Nonebot对接QQ官方机器人
原来基于go-cqhttp的机器人在年初的时候登录不上失效了。因为之前用的就是Nonebot就想着改一改继续用。这里记录一下QQ官方API的对接方法。
QQ官方API支持文字子频道、频道私信、群聊、单聊。截止24年8月,个人开发者还不支持群聊。但是如果只是个人/小范围使用,可以与手动添加的成员私聊,或在一个少于 20
人的沙箱群中使用(另外频道应该很少人用吧)。
优点:不用一直担心风控,无需麻烦的登录流程。
缺点:个人开发者权限有限,主动消息次数仅 4
次/月。
个人用途:主要是对接ChatGPT方便访问,还有校园卡余额不足时主动提醒。
QQ开放平台设置
进入QQ开放平台https://q.qq.com/qqbot/#/home,注册一个公域机器人账号。这一步坑比较少,简略带过。
“沙箱配置”:根据需要,配置沙箱群/沙箱频道/频道私信成员/列表私信成员。
“开发设置”:获取AppID、Token、AppSecret。注意管理平台使用管理员QQ账号登录,否则权限不足无法生成机器人密钥。
Nonebot配置
这里使用nb-cli脚手架搭建。确保所有包都正确安装并更新。
pip uninstall nonebot
pip uninstall nonebot2
pip uninstall nb-cli
pip install nb-cli
进入项目文件夹,使用 nb create
创建项目。项目配置建议如下:
- 模板:simple
- 驱动器:HTTPX和websockets
- 适配器:QQ
- 插件:在“src”文件夹中
- 虚拟环境看自身需求。可以添加echo插件用来测试。
如果配置正确,项目文件夹下的pyproject.toml文件的adapters如下图。
踩坑:如果适配器是qqguild,这是老版本已经停止维护。请自行到适配器商店(适配器商店 | NoneBot)安装nonebot-adapters-qq。

接下来编辑.env文件。将下面这段代码粘贴到文件后,将id、token、secret更改为开发设置中自己机器人的信息。
QQ_IS_SANDBOX=flase
QQ_BOTS='
[
{
"id": "xxx",
"token": "xxx",
"secret": "xxx",
"intent": {
"c2c_group_at_messages": true
}
}
]
'
在项目文件夹下使用 nb run --reload
启动机器人(--reload
代表项目内文件有更改机器人就会热重载)。如果一切顺利,应该会见到如下画面。

如果不成功可以试试把 QQ_IS_SANDBOX 改成 true。
如果安装了echo插件,在单聊或频道私聊内,向机器人发送 /echo hello
,机器人将回复hello。 如果在群聊或子频道内,则需要发送 @机器人 /echo hello
。
插件开发
玩Nonebot的应该都是多多少少自己写插件的吧。
API文档:QQ 机器人 | QQ机器人文档
发送消息:发送消息 | QQ机器人文档
被动消息
- 用户发给机器人触发的回复消息。
- 需要携带上一条消息的msg_id(适配器自动实现)。
- 回复消息的有效期为
5
分钟。 - 每个消息最多回复
5
次。
Nonebot会根据被动消息触发的event类别选择不同的发送方法,所以不需要私信、频道等都分别实现。
这里放一个keyword触发的测试代码,发送的消息包含’test’就会返回当前的session_id。
from nonebot.plugin import on_keyword
from nonebot.adapters import Bot, Event
test = on_keyword(['test'], priority=5)
@test.handle()
async def test_handle(event: Event):
await test.send(event.get_session_id())
主动消息
网上很难找到有关于Nonebot主动发送消息的资料,主要还是得看nonebot-adapter-qq的源码。
adapter-qq/nonebot/adapters/qq at master · nonebot/adapter-qq · GitHub
- 机器人主动发送的消息,如定时消息。
- 主动发送消息会被官方限制频率:
- 文字子频道:
20
条/天;2
个子频道/天 - 频道私信:
2
条/天/用户;200
条/天/机器人 - 群聊:
4
条/月/群 - 单聊:
4
条/月/用户 - 主动推送消息在每个频道中,每天可以往
2
个子频道推送消息,超过后会被限制。
- 文字子频道:
文字子频道 | 频道私信 | 群聊 | 单聊 | |
session | guild+channel | guild+channel | group | friend |
adapter方法 | send_to_channel | send_to_dms | send_to_group | send_to_c2c |
发送目标 | channel_id | guild_id | group_openid | openid |
发送目标id与实际的QQ号、频道号、群号等不同。可以借助“被动消息”一节的测试代码,获取当前环境的id号。

这里放一个定时触发的测试代码,向指定openid的用户于每天 17:00
私聊发送主动消息‘test’。注意需要安装nonebot_plugin_apscheduler。
from nonebot import require, get_bot
from nonebot.adapters import Bot, Event
scheduler = require('nonebot_plugin_apscheduler').scheduler
@scheduler.scheduled_job('cron', hour=17, minute=0)
async def test_schedule():
bot = get_bot()
try:
await bot.send_to_c2c(openid='xxx', message='test')
except:
print("发送失败")