基于nonebotV2go-cqhttp,写一个属于自己的QQ机器人

介绍

要写一个属于自己的QQ机器人,首先要了解QQ机器人的组成原理,不同组件实现的功能以及实现方式。

组件名 作用 描述
go-cqhttp 无头客户端 与QQ服务器连接,模拟真实QQ客户端,与自己的后端逻辑框架(即头)进行交互,实现各种消息通知的收发
nonebot2 “头骨” 接受无头客户端发送来的消息,提供封装好的方法供开发者编写处理逻辑,相当于“头骨”,起框架作用

这篇文章 (个系列) 会基于以上框架,自行编写处理逻辑,实现自己想要的功能

注意

nonebot是使用python3来编写的框架,后续的所有相关代码都是基于在nonebot可以运行的python环境(python3 >= 3.7)下编写与测试。虽然python相对比较容易入门,编写这样的机器人还是需要有少许编程基础知识的,完全没有任何相关概念的人尽早右上退出吧(~虽然我自己也就是个半吊子水平~)。

环境

编写环境是Windows10,amd64,python3.8

本文编写时所使用框架版本:nonebot 2.0.0a9,go-cqhttp v0.9.39

安装所需环境:

nonebot:

pip3 install nonebot

go-cqhttp:

https://github.com/Mrs4s/go-cqhttp/releases
注意根据自己的系统、处理器架构来挑选对应的可执行文件
例如:
Windows系统,AMD64架构,则下载后缀为windows-amd64.exe的文件
Linux系统,I386架构,则下载后缀为linux-i386的文件

go-cqhttp配置

在go-cqhttp可执行文件同目录下创建config.hjson,按照如下模板修改信息配置

/*
    go-cqhttp 默认配置文件
*/

{
    // QQ号
    uin: 12345678
    // QQ密码
    password: "这里填机器人QQ密码"
    // 是否启用密码加密
    encrypt_password: false
    // 加密后的密码, 如未启用密码加密将为空, 请勿随意修改.
    password_encrypted: ""
    // 是否启用内置数据库
    // 启用将会增加10-20MB的内存占用和一定的磁盘空间
    // 关闭将无法使用 撤回 回复 get_msg 等上下文相关功能
    enable_db: true
    // 访问密钥, 强烈推荐在公网的服务器设置
    access_token: ""
    // 重连设置
    relogin: {
        // 是否启用自动重连
        // 如不启用掉线后将不会自动重连
        enabled: true
        // 重连延迟, 单位秒
        relogin_delay: 3
        // 最大重连次数, 0为无限制
        max_relogin_times: 0
    }
    // API限速设置
    // 该设置为全局生效
    // 原 cqhttp 虽然启用了 rate_limit 后缀, 但是基本没插件适配
    // 目前该限速设置为令牌桶算法, 请参考: 
    // https://baike.baidu.com/item/%E4%BB%A4%E7%89%8C%E6%A1%B6%E7%AE%97%E6%B3%95/6597000?fr=aladdin
    _rate_limit: {
        // 是否启用限速
        enabled: false
        // 令牌回复频率, 单位秒
        frequency: 1
        // 令牌桶大小
        bucket_size: 1
    }
    // 是否忽略无效的CQ码
    // 如果为假将原样发送
    ignore_invalid_cqcode: false
    // 是否强制分片发送消息
    // 分片发送将会带来更快的速度
    // 但是兼容性会有些问题
    force_fragmented: false
    // 心跳频率, 单位秒
    // -1 为关闭心跳
    heartbeat_interval: 0
    // HTTP设置
    http_config: {
        // 是否启用正向HTTP服务器
        enabled: false
        // 服务端监听地址
        host: 0.0.0.0
        // 服务端监听端口
        port: 5700
        // 反向HTTP超时时间, 单位秒
        // 最小值为5,小于5将会忽略本项设置
        timeout: 0
        // 反向HTTP POST地址列表
        // 格式: 
        // {
        //    地址: secret
        // }
        post_urls: {}
    }
    // 正向WS设置
    ws_config: {
        // 是否启用正向WS服务器
        enabled: false
        // 正向WS服务器监听地址
        host: 0.0.0.0
        // 正向WS服务器监听端口
        port: 6700
    }
    // 反向WS设置
    ws_reverse_servers: [
        // 可以添加多个反向WS推送
        {
            // 是否启用该推送
            enabled: true
            // 反向WS Universal 地址
            // 注意 设置了此项地址后下面两项将会被忽略
            // 留空请使用 ""
            reverse_url: ws://127.0.0.1:8080/cqhttp/ws
            // 反向WS API 地址
            reverse_api_url: ws://you_websocket_api.server
            // 反向WS Event 地址
            reverse_event_url: ws://you_websocket_event.server
            // 重连间隔 单位毫秒
            reverse_reconnect_interval: 3000
        }
    ]
    // 上报数据类型
    // 可选: string array
    post_message_format: array
    // 是否使用服务器下发的新地址进行重连
    // 注意, 此设置可能导致在海外服务器上连接情况更差
    use_sso_address: false
    // 是否启用 DEBUG
    debug: true
    // 日志等级
    log_level: ""
    // WebUi 设置
    web_ui: {
        // 是否启用 WebUi
        enabled: false
        // 监听地址
        host: 127.0.0.1
        // 监听端口
        web_ui_port: 9999
        // 是否接收来自web的输入
        web_input: true
    }
}

其中要注意的是反向WS相关设置

原理: nonebot框架与无头客户端的连接逻辑是nonebot启动一个Websocket服务端,然后QQ无头客户端主动连接至nonebot开启的WS服务端,并通过WS协议推送消息、调用API,对于无头客户端来说,主动连接至已有的WS服务器就算作是反向WS服务端,所以要根据nonebot的相关信息配置好反向WS相关配置

配置项 说明
enabled 开关,当然是填true啊,否则下列配置直接就是无意义的
reverse_url 目标服务器的url,如果你的nonebot与go-cqhttp运行在同一台主机上,这里就可以填写为ws://运行nonebot机器的地址:端口号/适配器名称/ws,如果是同一台机器,地址可以填为127.0.0.1端口号与适配器名称取决于nonebot的配置,后文会写。

运行go-cqhttp

以上配置文件配置完毕后,运行go-cqhttp的可执行文件:
Windows下:使用powershell终端 ~(真别用CMD了)~ 打开可执行文件所在目录,执行./文件名

如果出现类似设备锁、安全验证等提示,按照提示完成步骤即可。出现成功提示后,代表你的QQ无头客户端已经成功运行了。

运行一个最小的nonebot实例

在要编写机器人处理程序的目录下新建文件,名为bot.py,内容如下填写

import nonebot
from nonebot.adapters.cqhttp import Bot as CQHTTPBot

nonebot.init()
driver = nonebot.get_driver()
driver.register_adapter("cqhttp", CQHTTPBot) # 这里的第一个参数即为前文提到的“适配器名称”,要相互对应
nonebot.load_builtin_plugins()

if __name__ == "__main__":
nonebot.run(host="0.0.0.0",port=8080) 
# 第一个参数代表监听地址,如果你的nonebot与go-cqhttp运行在同一个机器上,这里可以填写为127.0.0.1
# 如果在同一局域网则可以填写局域网所在网段网络号,例如`192.168.1.0`
# 而如果两个程序相互处于公网状态,则填写`0.0.0.0`吧,表示监听所有地址。
# 第二个参数代表端口号,与前文go-cqhttp配置中的端口号相对应。

如果没有出错,python3 bot.py运行nonebot,nonebot 所在的控制台应该会输出类似下面的内容(两条访问日志):

09-14 21:31:16 [INFO] uvicorn | ('127.0.0.1', 12345) - "WebSocket /cqhttp/ws" [accepted]
09-14 21:31:16 [INFO] nonebot | WebSocket Connection from CQHTTP Bot 你的QQ号 Accepted!

这表示 CQHTTP 协议端已经成功地使用 CQHTTP 协议连接上了 NoneBot。

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

/echo hello world!

到这里如果一切 OK,你应该会收到机器人给你回复了 你好,世界。这一历史性的对话标志着你已经成功地运行了一个 NoneBot 的最小实例。

结束

基本机器人的创建教程到此为止,后续文章会尝试从编写第一个自己的插件来记录。

未完待续

Last modification:February 3, 2021
觉得有帮助的话,打赏一个呗~