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

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

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

创建机器人

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

创建机器人之后,在开发管理中查看机器人的 AppIDToken,并生成 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 分别为前面开发管理中获取到的AppIDToken,和生成的 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("my_bot/plugins")

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

QQ_BOT 下创建一个目录,并再在其下创建一个 plugins 目录,在 plugins 目录下创建一个 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
├── my_bot/
│ └── plugins/
│ │ └── repeater.py

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

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

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

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


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