Skip to content

开始编写模块包

ZiBuYuCHN edited this page Mar 4, 2019 · 6 revisions

我们将 modules/ 文件夹(该目录拥有 \kjBotModule\ 命名空间)下的所有文件夹视作模块包,推荐的目录格式是:modules/{$vendorName}/{$moduleName}/

我们以 样例模块包 为例:
样例模块包应该创建到 modules/kjBot_Dev/Demo,此时其 README 应位于 modules/kjBot_Dev/Demo/README.md

编写模块(Module)

每个模块都是一个继承了 kjBot\Framework\Module 的类。
同时必须实现其 process(array $args, kjBot\Framework\Event\MessageEvent $event) 方法。

modules/kjBot_Dev/Demo/DemoModule.php

<?php
namespace kjBotModule\kjBot_Dev\Demo;

use kjBot\Framework\Module;
use kjBot\Framework\Event\MessageEvent;

class DemoModule extends Module{
    public function process(array $args, MessageEvent $event){
        return $event->sendBack('Hello, world!');
    }
}

模块需要在 /modules.php 文件内声明自己处理什么命令,此处假定我们的样例要处理 你好
因此我们需要在 $Modules 数组内添加一行:'你好' => kjBotModule\kjBot_Dev\Demo\DemoModule::class,
框架会先将收到的消息用空格切割,选中第一个部分,将其视为命令,检查 $Modules 数组,反射对应的模块来处理。
之后,消息将被解析为一个个参数放在 $args 数组内,并将消息事件的对象 $event 一同传入模块的 process() 方法。
注:我们将 $args[0]称为命令,将数组内其他元素称为参数

在上述情况下,你好你好 世界,均会调用我们的 DemoModule 模块。 此处,模块对该事件的响应是:$event->sendBack('Hello, world!'),该方法会对该事件创建一个 Message 对象,将 Hello, world! 发送回发出的地方。(即私聊发回私聊,群聊发回群聊)
此处返回值的更多操作请参阅进阶文档

编写插件(Plugin)

每个模块都是一个继承了 kjBot\Framework\Plugin 的类。

框架接收到的所有事件都将经过所有插件,插件需要添加到 /plugins.php 才能启用。 此处我们添加一行 kjBotModule\kjBot_Dev\Demo\DemoPlugin::class,

modules/kjBot_Dev/Demo/DemoPlugin.php

<?php
namespace kjBotModule\kjBot_Dev\Demo;

use kjBot\Framework\Plugin;
use kjBot\Framework\Message;
use kjBot\Framework\Event\MessageEvent;

class DemoPlugin extends Plugin{
    public $handleDepth = 3; //捕获到最底层的事件
    public $handleQueue = true; //声明是否要捕获消息队列

    public function beforePostMessage(&$queue){} //若声明不需要捕获消息队列可不实现本方法
    //此处以正常群聊消息举例
    public function message_group_normal(MessageEvent $event): ?Message{
        if(false !== strpos($event->getMsg(), '你好')) return $event->sendBack('Hello, world!');
        else return NULL;
    }
}

这里声明了插件对消息捕获的粒度(深度)是3,不同粒度决定了插件在遇到不同事件时会被调用的方法,粒度的用法见进阶文档
此外还声明了需要捕获消息队列(使用引用传递),插件有权限在消息被发出前对该队列进行编辑,例如特定情况清除某些消息。

在上面的例子中,插件将会捕获到 post_type=message, message_type=group, sub_type=normal 的事件,各类事件对应的方法见进阶文档
我们的插件取出了该消息的内容,匹配其中的 你好,若匹配成功则添加一条 Hello, world! 的消息到消息队列。若匹配失败则返回 NULL

在模块处理完成后,因为声明了要捕获消息队列,我们又会进入插件的 beforePostMessage() 方法,这里什么也不做。

编写 README

一个模块包最好包含 README 以便其他开发者使用你的模块包。

  • 应简明介绍该模块包的功能,使用前需要的准备工作(例如某目录可能无法自动创建,需提醒开发者手动创建),并在介绍的末尾说明该模块包依赖哪些模块包。
  • 应使用二级标题## `composer.json` 来告知其他开发者需要往相应的文件添加什么内容。(比如需要一个 composer 包才能正常工作)
    • 如果存在模块包内部之间的依赖请通过注释说明某模块需要某模块才能正常工作。