酷Q机器人Windows部署


简介

酷Q是一个QQ机器人,可以接入QQ中进行收发消息权限管理等,目前有两个版本:

  • 酷Q Air 继承了老版本(酷Q Lite)简单快速、扩展性强的特点。使用了更强大的 V9 应用机制,并坚持免费,是一个轻巧、免费、高效的机器人核心,功能需要安装“应用”实现。
  • 酷Q Pro的功能更加强大,捐助开发者可以获取授权时长

可惜我的服务器Centos版本老旧,支持不了Docker,故现在Windows上试试水。
两者功能对比:

环境安装

  1. 酷Q
  2. CoolQ HTTP API 插件
  3. NoneBot
     pip install nonebot

使用方法

  1. 将CoolQ HTTP API 插件最新的 cpk 文件放到 酷Q 的 app 文件夹,然后启用即可。由于要上报事件、接受调用请求,因此需要所有权限。首次启用酷Q可以按步骤进行新手教程。

  2. 使用编辑器或 IDE,创建一个名为 bot.py 的文件,内容如下:

     import nonebot
    
     if __name__ == '__main__':
         nonebot.init()
         nonebot.load_builtin_plugins()
         nonebot.run(host='127.0.0.1', port=8080)

    if __name__ == '__main__' 语句块的这几行代码将依次:

    1. 使用默认配置初始化 NoneBot 包
    2. 加载 NoneBot 内置的插件
    3. 在地址 127.0.0.1:8080 运行 NoneBot

    运行后会产生如下日志:

    [2019-01-26 14:24:15,984 nonebot] INFO: Succeeded to import "nonebot.plugins.base"
    [2019-01-26 14:24:15,987 nonebot] INFO: Running on 127.0.0.1:8080
    Running on https://127.0.0.1:8080 (CTRL + C to quit)

    除此之外可能有一些红色的警告信息和 ASGI Framework Lifespan error 等,可以忽略。

  3. 启用CoolQ HTTP API后插件将开启一个 HTTP 服务器来接收请求,默认监听 0.0.0.0:5700,首次启用会生成一个默认配置文件,在 酷Q 的 data\app\io.github.richardchien.coolqhttpapi\config 文件夹中,文件名为 <user_id>.json<user_id> 为登录的 QQ 号),使用 JSON 格式填写,详见配置。修改这个文件,修改如下配置项(如果不存在相应字段则添加):

    {
       "ws_reverse_api_url": "ws://127.0.0.1:8080/ws/api/",
       "ws_reverse_event_url": "ws://127.0.0.1:8080/ws/event/",
       "use_ws_reverse": true
    }

    如果配置文件中需要使用中文或其它非 ASCII 字符,则必须使用 UTF-8 without BOM 编码保存文件。

    修改之后,在 酷Q 的应用菜单中重启 CoolQ HTTP API 插件,或直接重启 酷Q,以使新的配置文件生效。

    一旦新的配置文件正确生效之后,NoneBot 所在的控制台(如果正在运行的话)应该会输出类似下面的内容(两条访问日志):

     [2019-01-26 16:23:17,159] 172.29.84.18:50639 GET /ws/api/ 1.1 101 - 986
     [2019-01-26 16:23:17,201] 172.29.84.18:53839 GET /ws/event/ 1.1 101 - 551

    这表示 CoolQ HTTP API 插件已经成功地连接上了 NoneBot,与此同时,插件的日志文件中也会输出反向 WebSocket 连接成功的日志。

  4. 现在,尝试向你的 QQ 机器人账号发送如下内容:

    /echo 你好,世界

    到这里如果一切都没有问题,你应该会收到机器人给你回复了你好,世界。这一历史性的对话标志着你已经成功地运行了一个 NoneBot 的最小实例。进阶操作可以参照官方文档。

运行机制

我们已经运行了一个最小的 NoneBot 实例,在看着 QQ 机器人回复了自己的消息的同时,这是如何实现的?具体来说,NoneBot、CoolQ HTTP API 插件、酷Q,这三者是如何协同工作的?本章将对这个问题做一个初步解答。

一切从酷Q开始

酷Q扮演着「无头 QQ 客户端」的角色,一切的消息、通知、请求的发送和接收,最根本上都是由它来完成的,我们的最小 NoneBot 实例也不例外。

首先,我们向机器人发送的 /echo 你好,世界 进入腾讯的服务器,后者随后会把消息推送给 酷Q,就像推送给一个真正的 QQ 客户端一样。到这里,酷Q 就已经收到了我们发送的消息了。

进入 CoolQ HTTP API 插件

酷Q 在收到消息之后,按优先级依次将消息转交给已启用的各插件处理,在我们的例子中,只有一个插件,就是 CoolQ HTTP API 插件。

CoolQ HTTP API 插件收到消息后,会将其包装为一个统一的事件格式,并对消息内容进行一个初步的处理,例如编码转换、数组化、CQ 码增强等,这里的细节目前为止不需要完全明白,在需要的时候,可以去参考 CoolQ HTTP API 插件的文档。

接着,插件把包装好的事件转换成 JSON 格式,并通过「反向 WebSocket」发送给 NoneBot。这里的「反向 WebSocket」,连接的就是我们在 CoolQ HTTP API 插件的配置中指定的 ws_reverse_url,即 NoneBot 监听的 WebSocket 入口。

提示

「反向 WebSocket」是 CoolQ HTTP API 插件的一种通信方式,表示插件作为客户端,主动去连接配置文件中指定的 ws_reverse_url。除此之外还有 HTTP、(正向)WebSocket 等方式。

NoneBot 出场

CoolQ HTTP API 插件通过反向 WebSocket 将消息事件发送到 NoneBot 后,NoneBot 就开始了它的处理流程。

初步处理

首先 NoneBot 利用底层的 aiocqhttp 区分事件类型,并通知到相应的函数,本例中,相应的函数就是负责处理消息的函数。

负责处理消息的函数会尝试把消息作为一个命令来解析,根据默认配置,它发现消息内容 /echo 你好,世界 符合命令的一个特征——以 / 开头,剥离掉这个起始字符之后,消息变为 echo 你好,世界,紧接着,它读取第一个空白字符之前的内容,即 echo,将其理解为命令的名字。

提示

实际上,它还会使用配置中的分隔符对 echo 做一个分割,不过这里分割完也只有一个部分,所以实际命令名字为 ('echo',),形式是一个 Python 元组;而如果我们发送的命令是 note.add,分割之后就是 ('note', 'add')

理解最小实例的代码

import nonebot

if __name__ == '__main__':
    nonebot.init()
    nonebot.load_builtin_plugins()
    nonebot.run(host='127.0.0.1', port=8080)

第 4 行的 nonebot.init() 首先初始化 nonebot 包,这是无论如何都需要写的一行代码,并且必须在使用 NoneBot 的任何功能之前调用。

随后,nonebot.load_builtin_plugins() 加载了 NoneBot 的内置插件,这一步不是必须的,尤其在你编写了自己的插件之后,可能会不再需要内置插件。

NoneBot 的内置插件只包含了两个命令,echosay,两者的功能都是重复发送者的话,区别在于,echo 命令任何人都可以调用(不限制权限),但只能原样重复消息,不能手动指定要发送的 CQ 码,say 命令只有超级用户(通常是你自己,需要在配置中指定)可以调用,可以在消息中指定要发送的 CQ 码。

可以通过在配置中设置SUPERUSERS = {QQid}来获取超级用户权限。

最后,nonebot.run(host='127.0.0.1', port=8080) 让 NoneBot 跑在了地址 127.0.0.1:8080 上,向 CoolQ HTTP API 插件提供 //ws//ws/event//ws/api/ 四个入口,在我们的反向 WebSocket 配置中,插件利用了第二个入口。

命令处理器

echo 命令处理器的代码其实非常简单,如下:

@on_command('echo')
async def echo(session: CommandSession):
    await session.send(session.state.get('message') or session.current_arg)

消息处理函数将剩余部分(你好,世界)当做命令的参数,并通过命令名获取到对应的命令处理器,然后把参数、消息事件中附带的其它信息一起打包成一个 Session 对象(具体来说,是一个 CommandSession 类的对象),传给命令处理器来调用它。

再次进入 CoolQ HTTP API 插件

命令处理器在调用 session.send() 之后,NoneBot 把消息内容发送给了 CoolQ HTTP API 插件那边已连接的反向 WebSocket 客户端,同时告诉它要把消息发送到和收到消息相同的地方(即接收到消息所在的群组、讨论组或私聊)。CoolQ HTTP API 插件明白了 NoneBot 的要求之后,会对消息做一些必要的处理,然后按照指示调用 酷Q 提供的相应接口。

一切又在 酷Q 结束

酷Q 收到 CoolQ HTTP API 插件的接口调用之后,将消息内容发送给腾讯的服务器,就像一个真正的 QQ 客户端一样,于是你就收到了 QQ 机器人发来的消息了。

参考资料


评论
  目录