官方QQ群机器人开发环境搭建(使用webhook方式)

使用 webhook 方式搭建QQ群机器人

最近突然想开发一个 QQ 群机器人,于是就去找了相关资料,发现有 websocket 和 webhook 两种方式,但是 websocket 方式将慢慢弃用转向 webhook 方式
既然都弃用了,那肯定要选新的方式了,于是就尝试使用 webhook 方式来搭建一个 QQ 群机器人
这篇文章用于记录机器人的开发环境搭建

创建机器人

首先根据文档的描述,注册一个账号,然后在QQ开放平台创建一个机器人
机器人创建好之后,找一个自己是群主或者管理员的少于20个人的群,在沙箱配置中设置该群,然后在 QQ 群中将机器人加入群聊

创建机器人之后,在开发管理中查看机器人的 AppID 和 Token,并生成 AppSecret,记好备用

准备环境

为了搭建官方 QQ 群机器人,需要一个经过 ICP 备案的域名,并将这个域名指向一台国内的服务器
域名指向服务器后,需要申请 SSL 证书,如果是国内的提供商,一般有免费的 SSL 证书可以直接申请,也可以使用 acme 申请证书
申请 SSL 证书后,将证书上传到服务器以备后续使用

开发环境搭建

机器人框架我使用的是 NoneBot,需要 Python3.9 以上的版本,Ubuntu 可以直接安装

1
sudo apt install python3.9 python3.9-venv python3.9-dev

然后创建一个虚拟环境

1
2
3
4
5
6
7
mkdir QQ_BOT
cd QQ_BOT
python3.9 -m venv .venv

source .venv/bin/activate
pip install pipx
pipx install nb-cli

按照文档安装 nonebot2 以及驱动器,为了使用 webhook 方式,需要安装 fastapi 和 httpx 这两个驱动器

1
2
nb driver install nonebot2[fastapi]
nb driver install nonebot2[httpx]

再安装适配器,这里使用的官方 QQ 的适配器

1
nb adapter install nonebot-adapter-qq

配置反向代理

官方 QQ 群机器人必须使用 HTTPS,所以需要安装 nginx 来配置反向代理

1
sudo apt install nginx

创建配置文件 /etc/nginx/sites-available/域名.conf,并编辑如下配置,其中的域名请替换为自己的域名,自定义端口可以随意设置,只要与后面的机器人配置的端口一致即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server {
listen 80;
server_name 域名;
return 301 https://$host$request_uri; # 强制HTTP跳转到HTTPS
}

server {
listen 443 ssl http2;
server_name 域名;

# SSL证书路径
ssl_certificate /path/to/your/domain.crt;
ssl_certificate_key /path/to/your/domain.key;

# SSL协议和加密套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;

# 反向代理配置
location /qq/webhook {
proxy_pass http://127.0.0.1:自定义端口/qq/webhook;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

保存并退出后,使用命令链接配置文件

1
sudo ln -sf /etc/nginx/sites-available/域名.conf /etc/nginx/sites-enabled/

测试配置文件是否正确,并重载 nginx 服务

1
2
sudo nginx -t
sudo systemctl reload nginx

配置机器人

在 QQ_BOT 目录下创建一个 .env 文件,并编辑如下内容,其中的 id , token , secret 分别为前面开发管理中获取到的AppID 和 Token,和生成的 AppSecret

1
2
3
4
5
6
7
8
9
10
11
12
HOST=0.0.0.0
PORT=自定义端口,与nginx配置文件中的端口一致
COMMAND_START=["/", ""]
COMMAND_SEP=[".", " "]
DRIVER=~fastapi+~httpx
LOG_LEVEL=DEBUG
API_TIMEOUT=10.0
NICKNAME=["机器人昵称1", "机器人昵称2"]
SESSION_EXPIRE_TIMEOUT=00:02:00
QQ_IS_SANDBOX=true

QQ_BOTS=[{"id":"xxx","token":"xxx","secret":"xxx","intent":{"c2c_group_at_messages":true},"use_websocket":false}]

测试机器人

写一个简单的小功能测试机器人是否搭建完成
在 QQ_BOT 下创建机器人主文件 bot.py,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
import nonebot
from nonebot.adapters.qq import Adapter as QQAdapter

nonebot.init()

driver = nonebot.get_driver()
driver.register_adapter(QQAdapter)

nonebot.load_plugins("plugins/my_bot")

if __name__ == "__main__":
nonebot.run()

在 QQ_BOT 下创建一个目录 plugins,在 plugins 目录下创建一个 my_bot 目录,再在这个目录下创建一个 repeater.py 文件,内容如下

1
2
3
4
5
6
7
8
9
10
from nonebot import on_message
from nonebot.adapters.qq import MessageEvent, MessageSegment

# 捕获所有消息事件
repeater = on_message()

@repeater.handle()
async def repeat(event: MessageEvent):
msg = event.get_plaintext()
await repeater.send(MessageSegment.text(msg))

目录结构如下

1
2
3
4
5
6
QQ_BOT/
├── bot.py
├── .env
├── plugins/
│ └── my_bot/
│ │ └── repeater.py

这段代码可以使机器人重复发送所有收到的消息,使用如下命令启动机器人

1
2
source .venv/bin/activate
python bot.py

启动之后,在 QQ 开放平台的机器人页面中,回调配置地址设置为 https://your_domain/qq/webhook/

在沙箱群中,测试机器人是否正常运行
测试成功


突然奇想想开发一个机器人,小时候用过一键脚本搭建过机器人,那时候还什么技术都不懂,只知道这样很好玩,现在长大了,学了很多技术了,可以尝试自己实现一个想要的功能了(★O∀O*)◇+。