QQ 官方机器人私聊自定义菜单插件
在 AstrBot WebUI 中按机器人配置私聊自定义菜单。插件自带可视化 Dashboard,可查看同步状态、逐机器人编辑菜单,并把旧版全局配置保留在「兼容性」页。
- 按机器人独立配置:每台机器人拥有自己的 AppID、ClientSecret、平台类型和菜单内容,保存在
data/plugin_data/astrbot_plugin_qq_custom_menu/menu_config.json - 私聊菜单:写入
GET/PUT /v2/menu,支持发送消息、链接、子菜单和开关 - 兼容性配置:旧版
qq_platforms+menu继续可用,并与新版配置按 AppID 合并;新版接管同 AppID 后,旧配置不再影响该机器人 - 从兼容配置导入:可在「机器人」页按 AppID 导入旧机器人,导入后仍可继续编辑
- 同步状态可视化:Dashboard 状态页展示每个平台的
已同步 / 待同步 / 尚未同步 / 同步已关闭状态 - 实时同步进度:手动同步通过 SSE 推送逐平台、逐场景进度与日志,某个机器人失败不会中断其余机器人
- 实时日志面板:Dashboard 日志页支持等级筛选、搜索、暂停与堆栈展开,可查看本插件当前进程最近 1000 条日志,常见凭据字段会先脱敏
- 凭证安全:Dashboard 只展示
ClientSecret掩码;保存时留空表示沿用已保存的密钥 - 链接自动归一化:省略协议或误用
http://的链接会统一补全为 QQ 要求的https:// - 变更检测:本地摘要记录上次成功同步的菜单,远端与配置一致时跳过
PUT,不信任过期摘要 - 国际化:运行期日志与 Dashboard 均提供简体中文 / English / Русский / 日本語
插件面向 QQ 官方机器人(qq_official / qq_official_webhook),需要自行准备机器人的 AppID 与 ClientSecret。
- 插件市场(推荐):在 AstrBot WebUI 的插件市场搜索
astrbot_plugin_qq_custom_menu,或直接打开插件主页安装。 - 手动安装:从 Releases 下载 zip,解压到 AstrBot 的
data/plugins/下(解压后应得到一个包含main.py与metadata.yaml的插件目录),再重启 AstrBot 或在插件页重载插件;依赖会由插件管理器按requirements.txt安装。 - 安装完成后打开本插件的可视化视图,按下面的「Dashboard」与「配置说明」维护菜单。
- 在 AstrBot 中安装并启用本插件。
- 打开插件可视化视图,进入「机器人」页新增机器人并填写
AppID与ClientSecret。 - 在机器人编辑器里维护「私聊」菜单,点击「保存并同步」。
- 到「状态概览」页查看同步进度与每个平台的状态。
- 旧版全局配置可在「兼容性」页继续维护,也可以在 AstrBot 插件配置页编辑。
插件启动时会自动同步一次。修改配置后可以重启 AstrBot / 重载插件,或在 Dashboard 里手动同步。
Dashboard 构建产物提交在 pages/dashboard/,AstrBot 会把它作为插件视图加载。
| 页面 | 能力 |
|---|---|
| 状态概览 | 机器人统计、私聊菜单状态、手动同步与实时进度 |
| 机器人 | 逐机器人维护私聊自定义菜单,支持新增、编辑、删除、导入兼容配置 |
| 日志 | 实时查看本插件日志,支持等级筛选、搜索、暂停、自动滚动与堆栈展开 |
| 兼容性 | 维护旧版全局 qq_platforms 与私聊 menu,仅对未被新版接管的 AppID 生效 |
| 设置 | 日志语言、启动同步开关、插件版本与仓库入口 |
说明:
- 新版机器人凭证保存在
menu_config.json;兼容配置只使用兼容性页(或插件配置页)填写并由插件保存的凭证。 - 兼容配置的平台凭证为空时不会读取 AstrBot 平台配置,也不会因此触发同步。
- 日志页只展示本插件源码产生的日志;日志仅保存在当前进程内存中,插件重启后会重新累计。
- 本地
pnpm dev没有 AstrBot bridge,页面会显示明确标注的 mock 数据,保存与同步不会伪装成功。
- 类型:
string - 可选:
zh-CN、en-US、ru-RU、ja-JP - 默认值:
zh-CN - 含义:插件运行期日志语言,不影响用户填写的菜单内容。
- 类型:
bool - 默认值:
true - 含义:是否在启动时同步私聊菜单。
- 关闭后:插件只通过
GET /v2/menu读取 QQ 当前菜单,不会覆盖线上内容;Dashboard 会显示「同步已关闭」。
- 类型:
template_list - 默认值:
[] - 含义:QQ 官方机器人平台凭证列表,每个条目包含:
appid:QQ 官方机器人AppIDsecret:QQ 官方机器人ClientSecretplatform:平台类型,可选qq_official/qq_official_webhook
- 留空时:不读取 AstrBot 平台配置,也不会同步未在插件中配置凭证的机器人。
- 多机器人场景下建议为每个机器人单独添加一条凭证。
- 类型:
template_list - 默认值:
[] - 含义:旧版全局 QQ 私聊自定义菜单内容,仅对未被
menu_config.json按 AppID 接管的机器人生效。 - 模板 key:
send_message:发送消息菜单项,字段为name/message/parentlink:跳转链接菜单项,字段为name/link/parentswitch:开关菜单项,字段为name/switch_id/defaultmenu:子菜单项,字段为name
- 子菜单项通过
parent字段引用母菜单名称,不内嵌。 - 一级菜单最多 10 个;每个子菜单最多 5 个子项。
link未填写协议时会自动归一化为https://开头。menu为空且sync_menu开启时,会清空 QQ 机器人当前的远程自定义菜单。
Dashboard 的「机器人」页把配置写入插件数据目录,不写进仓库:
{
"version": 2,
"robots": [
{
"id": "b7f6…",
"name": "主机器人",
"appid": "102xxxxxx",
"secret": "••••••••",
"platform": "qq_official",
"scenes": {
"c2c": {
"enabled": true,
"items": [
{ "type": "send_message", "name": "帮助", "message": "/help", "parent": "" }
]
}
}
}
]
}version 是乐观并发版本号,保存成功后会递增;页面提交旧版本时返回 HTTP 409,重新载入即可。
language: zh-CN
sync_menu: true
qq_platforms:
- appid: "102xxxxxx"
secret: "••••••••"
platform: qq_official
menu:
- __template_key: send_message
name: 帮助
message: /help
parent: ""
- __template_key: menu
name: 更多
- __template_key: link
name: 文档
link: https://docs.example.com
parent: 更多- 读取
menu_config.json,与兼容配置按 AppID 合并;新版配置优先接管同 AppID。 - 对私聊场景创建
QQClient,先换取access_token,再调用GET /v2/menu读取远端菜单。 sync_menu开启时,将配置转换为 QQ 菜单结构;远端与配置一致则跳过PUT,否则调用PUT /v2/menu整表覆盖。- 同步成功后把私聊菜单摘要写入
menu_state.yaml,供状态页判断是否已同步。 - 单个机器人失败只影响对应机器人,Dashboard 会展示失败原因,其余机器人继续同步。
- 私聊菜单为空且场景启用时,
PUT会清空该机器人的 QQ 自定义菜单。
插件通过 AstrBot 加载,功能测试仍需要在运行的 AstrBot 实例下进行;业务逻辑和 Dashboard 都可以跑离线测试。
pip install -r requirements.txt -r requirements-dev.txt
pytest -q
pytest --cov --cov-branch --cov-report=xml --junitxml=junit.xml -o junit_family=legacy
ruff check . --fix
ruff format --check .
pre-commit run --all-files # 可选,与 CI 同一套 hooks- 用例都在
tests/,tests/conftest.py会注入轻量 AstrBot stub,无需安装 AstrBot。 tests/test_main.py覆盖插件装配层;tests/test_web_api.py/tests/test_sync_runner.py覆盖 Dashboard 后端;tests/test_package_script.py/tests/test_bump_script.py覆盖发布脚本。- 异步用例直接写
async def(asyncio_mode = "auto")。
需要 Node ^22.12.0 || >=24 与 pnpm 9+(CI 使用 Node 24 + pnpm 12,见 package.json 的 engines)。源码在 web/dashboard/,构建产物提交在 pages/dashboard/:
cd web/dashboard
pnpm install
pnpm dev # 本地 dev server,没有 bridge,走 mock 并显式标注
pnpm build # vue-tsc 类型检查 + Vite 打包,直接写 pages/dashboard/
pnpm test # Vitest 单次运行
pnpm test:coverage # 覆盖率,阈值见 vitest.config.ts
pnpm test:report # 额外产出 test-report.junit.xml
pnpm test:codecov # 覆盖率 + JUnit,CI 用的入口pnpm build 会先执行 vue-tsc 类型检查,并直接生成 pages/dashboard/ 产物;不要手工编辑构建产物,改源码后重新构建即可。
python scripts/bump_version.py --check # 校验三处版本号一致
python scripts/bump_version.py minor # 同步 metadata.yaml / core/paths.py / web/dashboard/package.json
python scripts/package_plugin.py # 生成 dist/<插件名>-<版本>.zipmetadata.yaml 是唯一版本源,三处版本号必须一致,否则自动发布工作流会拒绝发布。推送到 master 且 metadata.yaml 有改动时,release.yml 会校验版本、用 scripts/package_plugin.py 打包、打 tag 并创建 Release;发布是幂等的,失败可在 Actions 里手动重跑。
- ci.yml:pre-commit lint + Python 3.10 / 3.11 / 3.12 / 3.13 Pytest 矩阵
- ci-dashboard.yml:Node 24 + pnpm 12 上跑 Vitest、构建 Dashboard,并校验
pages/dashboard无漂移 - codecov-core.yml / codecov-dashboard.yml:把覆盖率与 JUnit 测试报告上传到 Codecov,前后端分别使用 flag
unittests与dashboard
main.py 插件入口(@register / initialize / terminate)
core/ 业务逻辑:config、menu、qq_api、state、sync_runner、web_api、paths、i18n
_conf_schema.json WebUI 插件配置 schema
metadata.yaml 插件元数据(版本号唯一来源)
.astrbot-plugin/ WebUI 侧 i18n(metadata / config / views)
web/dashboard/ Dashboard 源码(Vue 3 + TypeScript + Vite + Vuetify + Vitest)
pages/dashboard/ Dashboard 构建产物(提交进仓库的生成文件)
tests/ 离线 pytest 套件
scripts/ bump_version.py、package_plugin.py
.github/ CI、Codecov、Release、Dependabot、Issue 模板
- 一级菜单最多 10 个。
- 每个子菜单最多 5 个子项。
- 子菜单仅支持
send_message/link。 link必须为https://开头。- 空菜单会清空远端自定义菜单。
- 本插件仅处理 C2C 单聊菜单;群聊功能由其他插件负责。
- 菜单同步只使用插件侧凭证(「机器人」或「兼容性」页填写),不会读取 AstrBot 平台配置。
- 菜单同步依赖 QQ 官方机器人开放平台的 Access Token 鉴权。
- 菜单展示效果受 QQ 官方机器人开放平台接口能力及当前适配器版本影响。
- Dashboard 的同步状态来自本地摘要,不会在每次打开页面时请求 QQ API;远端被外部修改后,状态可能仍显示「已同步」,下一次同步会以刚读取到的远端菜单为准。
- i18n 国际化(简体中文 / English / Русский / 日本語)
- 同步状态可视化 Dashboard
- 同步结果的状态持久化与变更检测
- 菜单编辑、机器人凭证维护与实时同步进度
- 实时日志面板、等级筛选与堆栈查看
- 按机器人配置私聊自定义菜单
- 频道 / 频道私信场景支持
- 连接测试与更细的同步诊断
本项目使用 AGPLv3 协议开源,详见 LICENSE 文件。