diff --git a/.gitignore b/.gitignore index bc390f6..9433141 100644 --- a/.gitignore +++ b/.gitignore @@ -147,4 +147,4 @@ package-lock.json # OpenCode .sisyphus -.omo \ No newline at end of file +.omozh/manual/adapters/LuckyLiliiaDoc/ diff --git a/.vitepress/sidebar/en.ts b/.vitepress/sidebar/en.ts index 68d12f7..346a5d0 100644 --- a/.vitepress/sidebar/en.ts +++ b/.vitepress/sidebar/en.ts @@ -159,6 +159,7 @@ export const sidebar: DefaultTheme.Sidebar = { { text: 'NapCat QQ Connection', link: '/en/manual/adapters/napcat' }, { text: 'GoCQ Adapter', link: '/en/manual/adapters/gocq' }, { text: 'SnowLuma Adapter', link: '/en/manual/adapters/snowluma' }, + { text: 'QQ Official Adapter', link: '/en/manual/adapters/qq-official-adapter' }, { text: 'Telegram Adapter', link: '/en/manual/adapters/telegram' }, { text: 'Discord Adapter', link: '/en/manual/adapters/discord' }, ] diff --git a/.vitepress/sidebar/zh.ts b/.vitepress/sidebar/zh.ts index 6e4b8e2..f10f5b6 100644 --- a/.vitepress/sidebar/zh.ts +++ b/.vitepress/sidebar/zh.ts @@ -118,6 +118,7 @@ export const sidebar: DefaultTheme.Sidebar = { { text: 'NapCat QQ 连接', link: '/manual/adapters/napcat' }, { text: 'GoCQ 适配器', link: '/manual/adapters/gocq' }, { text: 'SnowLuma 适配器', link: '/manual/adapters/snowluma' }, + { text: 'QQ 官方适配器', link: '/manual/adapters/qq-official-adapter' }, { text: 'Telegram 适配器', link: '/manual/adapters/telegram' }, { text: 'Discord 适配器', link: '/manual/adapters/discord' }, ] diff --git a/en/manual/adapters/index.md b/en/manual/adapters/index.md index a6cfd63..f8123e8 100644 --- a/en/manual/adapters/index.md +++ b/en/manual/adapters/index.md @@ -12,6 +12,7 @@ Adapters are responsible for connecting messaging platforms such as QQ, Telegram - [NapCat](./napcat.md) (Recommended) — The QQ adapter officially maintained by MaiBot, supporting both the plugin version and the standalone version. The plugin version is the currently recommended solution. - [GoCQ](./gocq.md) (Available, outdated) — QQ adaptation solution based on go-cqhttp / AstralGocq, suitable for existing GoCQ environments or specific needs. - [SnowLuma](./snowluma.md) (Available, in testing) — Next-generation QQ adaptation solution. +- [QQ Official Adapter](./qq-official-adapter.md) (Available) — Adapter based on the QQ official open platform API v2, outbound-only connection, no public IP needed. **Other platforms** — Community adaptations - [Telegram](./telegram.md) — Telegram platform adaptation solution diff --git a/en/manual/adapters/qq-official-adapter.md b/en/manual/adapters/qq-official-adapter.md new file mode 100644 index 0000000..61f03d3 --- /dev/null +++ b/en/manual/adapters/qq-official-adapter.md @@ -0,0 +1,200 @@ +--- +title: QQ Official Adapter +--- +# QQ Official Adapter + +The QQ Official Adapter connects MaiBot to the QQ platform through the [QQ Official Bot Open Platform](https://q.qq.com), sending and receiving messages in direct chats, group chats, text channels and channel DMs. + +::: info Outbound-only connection +The QQ Official Adapter actively connects to QQ's official WebSocket gateway and Open Platform API from MaiBot. It is an **outbound-only** connection — no public IP, port mapping, or callback URL is required. +::: + +::: warning Different ID system +The UserID / GroupID used by this adapter come from QQ's official OpenID system (`user_openid` / `member_openid` / `group_openid`), not numeric QQ numbers and group numbers. They cannot be mixed with OneBot v11 IDs. +::: + +## Overview + +The QQ Official Adapter is a MaiBot plugin that integrates with the API v2 of QQ's official bot open platform. It actively connects to QQ's official WebSocket gateway to receive messages and sends replies through the Open Platform REST API: + +- **Inbound**: QQ's official WebSocket gateway pushes events to the adapter, which converts and injects them into MaiBot +- **Outbound**: replies generated by MaiBot are converted by the adapter and sent through the QQ official API + +Unlike OneBot-based adapters such as NapCat and GoCQ, the QQ Official Adapter only uses QQ's official capabilities. It does not depend on third-party protocols or services, and there is no separate network connection between the adapter and MaiBot to maintain. + +Message flow: **QQ official gateway → adapter plugin (inside MaiBot) → MaiBot** + +### Adapter Repository + +Source code of the QQ Official Adapter: [WhiteCloudOL/qq-official-adapter](https://github.com/WhiteCloudOL/qq-official-adapter) + +## Installation + +### Step 1: Create a QQ Bot + +Open the [QQ Bot Open Platform](https://q.qq.com/qqbot/openclaw/), create a bot, and keep its **AppID** and **AppSecret**. + +::: tip AppSecret is the bot password +AppSecret is equivalent to the bot password. Store it securely, never commit it to a code repository or share it. If you suspect it has leaked, reset it on the open platform immediately. +::: + +### Step 2: Get the Adapter + +Clone the adapter repository into MaiBot's `plugins/` folder: + +::: code-group + +```bash [Bash ~vscode-icons:file-type-shell~] +# Enter MaiBot's plugins directory +cd MaiBot/plugins + +# Clone the repository +git clone https://github.com/WhiteCloudOL/qq-official-adapter.git +``` + +::: + +MaiBot installs the dependencies automatically based on the plugin manifest. + +### Step 3: Fill in the Plugin Config + +The plugin is **disabled by default** after installation. In the MaiBot WebUI plugin config, find **"QQ 官方机器人适配器"** and fill in the following: + +- **Enable adapter** — On +- **AppID** — The AppID shown on the QQ open platform +- **AppSecret** — The AppSecret matching the AppID + +The chat-list filter is off by default, so you can use it without configuring anything. If you need to restrict which groups or users can connect, enable the "chat filter" and fill in QQ official OpenIDs (see the [config reference](#configuration-reference) below). + +Alternatively, you can edit the plugin's config file `plugins/qq-official-adapter/config.toml` directly, set `enabled` to `true` and fill in the credentials — the effect is the same. + +### Step 4: Set the MaiBot Main Account + +Start MaiBot once and let the plugin connect to the QQ gateway, then find this line in the logs: + +```text +QQ 官方 WebSocket 已就绪: self_id=机器人自身ID +``` + +Then fill in the following in MaiBot's `config/bot_config.toml`: + +::: code-group + +```toml [TOML ~vscode-icons:file-type-toml~] +[bot] +platform = "qq" +qq_account = "日志中的 self_id" +``` + +::: + +::: warning Don't fill in the wrong account +`qq_account` must be the `self_id` from the logs (the bot's own ID in the WebSocket `READY` event). **Do not** fill in the AppID, the QQ number, or a OneBot v11 bot QQ number. MaiBot uses it to mark messages sent by the bot itself. +::: + +The bot's display nickname is read automatically from `bot.nickname` (default `"麦麦"`). When mentioned in a group, it enters the chat context as `@nickname`, so there is no need to fill in the bot ID in the plugin config again. + +### Step 5: Enable Full Group Messages (group chats only) + +To use group chat features, the **group owner** must open the QQ group settings, select the bot being used, and set the "机器人可获取的群聊消息范围" (range of group messages the bot can receive) to "获取群内全部消息" (get all messages in the group). Without this, the bot only receives messages within the platform-allowed scope and cannot fully participate in group chats. + +> This setting can only be operated by the group owner and must be set separately for each group that uses the bot. + +### Step 6: Restart and Verify + +Restart MaiBot and confirm the logs show **"QQ 官方 WebSocket 已就绪"**. It is recommended to test in order: + +1. Send plain text in a direct chat. +2. @ the bot in a group chat and send text. +3. Send a normal image and a QQ emoji / sticker. +4. Have MaiBot reply with a pure image, a pure emoji, and a text-plus-image message. + +## Configuration Reference + +The plugin's config file is located at `plugins/qq-official-adapter/config.toml` and contains the following three sections. + +### Plugin Settings (`[plugin]`) + +- **`enabled`** — Whether to enable the QQ Official Adapter. When off, the plugin only registers the message gateway and does not connect to the QQ WebSocket. Default: off +- **`config_version`** — The current config structure version (managed automatically, usually no need to change it manually). Default: "1.1.0" + +### Bot Credentials (`[credentials]`) + +- **`appid`** — The bot's AppID on the QQ open platform (obtained from `https://q.qq.com`). Default: empty +- **`app_secret`** — The AppSecret paired with the AppID, used to obtain the access token. Default: empty +- **`sandbox`** — Whether to use the sandbox environment. When enabled, the WebSocket gateway and message sending use the sandbox address, which is convenient for testing. Default: off + +### Chat Filter (`[chat]`) + +- **`enable_chat_list_filter`** — Whether to enable the group and private chat list filter. When off, `group_list` / `private_list` are ignored and only the `ban_user_id` rule applies. Default: off +- **`show_dropped_chat_list_messages`** — Whether to log messages dropped by the chat list filter. Default: off +- **`group_list_type`** — Group list mode. Whitelist only accepts the groups in the list; blacklist ignores the groups in the list. Default: "whitelist" +- **`group_list`** — The group list, filled with `group_openid` (deduplicated automatically). Default: empty +- **`private_list_type`** — Private chat list mode. Whitelist only accepts the private chats in the list; blacklist ignores the private chats in the list. Default: "whitelist" +- **`private_list`** — The private chat list, filled with `user_openid` (deduplicated automatically). Default: empty +- **`ban_user_id`** — The globally blocked user list, filled with `user_openid` or `member_openid`. Messages from these users are dropped before entering MaiBot. Default: empty + +::: tip The list expects OpenIDs +The chat lists are filled with QQ official OpenIDs (`group_openid` / `user_openid` / `member_openid`), not numeric group numbers / QQ numbers. You can find the OpenID of a given event in the debug logs. +::: + +### Complete Config Example + +::: code-group + +```toml [TOML ~vscode-icons:file-type-toml~] +[plugin] +enabled = true +config_version = "1.1.0" + +[credentials] +appid = "你的AppID" +app_secret = "你的AppSecret" +sandbox = false + +[chat] +enable_chat_list_filter = false +show_dropped_chat_list_messages = false +group_list_type = "whitelist" +group_list = [] +private_list_type = "whitelist" +private_list = [] +ban_user_id = [] +``` + +::: + +## Message Capabilities + +The QQ Official Adapter supports the following message scenarios: + +- **QQ direct chats** — Receives text, images, emoji, voice, video and files; can send text, images, emoji, voice, video, files and structured messages +- **QQ group chats** — Receives @-mentions, full messages and attachments; can send text, images, emoji, voice, video, files and structured messages +- **Text channels** — Receives @-mentions, full messages and attachments; can send text, images, Markdown, Ark and Embed +- **Channel DMs** — Receives text and attachments; can send text, images, Markdown, Ark and Embed + +Emoji in QQ groups and direct chats are sent as image rich media, so they never appear as invalid `[表情]` text; pure image or pure emoji replies also do not send extra `[图片]` / `[表情]` placeholder text. Inbound images and emoji keep their original binary for MaiBot to recognize: images that appear for the first time are recognized in the background and injected into the chat context afterwards, and the same image reuses the cached description. + +The adapter automatically judges whether a group message really @-mentions the bot (combining the event type, the WebSocket self ID, structured mentions and message elements) and auto-learns the bot's OpenID within the group scope, so there is no need to fill in the bot ID in the plugin config again. + +## Verification and Troubleshooting + +### Verify the Connection + +How do you know it is connected? Check these places: + +1. **MaiBot logs**: look for the `QQ 官方 WebSocket 已就绪` message +2. **WebUI plugin list**: the QQ Official Adapter plugin shows as loaded +3. **Send a test message**: send a message in a QQ direct chat / group and see whether MaiBot replies + +### The bot is @-mentioned in a group but MaiBot doesn't recognize it + +First confirm the logs received `GROUP_AT_MESSAGE_CREATE` or `GROUP_MESSAGE_CREATE`. If the logs show the adapter recognized it but MaiBot still cannot send a reply, check whether `qq_account` in `bot_config.toml` equals the `self_id` in the ready log. + +### Can't receive group chat or channel messages + +Confirm the bot has the permission for the corresponding scenario and has enabled the corresponding message capability on the open platform. If the quick-creation page says "暂不支持进入群聊" (group chats are not supported yet), the plugin cannot bypass the platform limit. For group chat scenarios, the group owner must also enable "获取群内全部消息". + +### 401 or authentication failure + +Check that the AppID and AppSecret belong to the same bot. After resetting the AppSecret, update the plugin config accordingly and restart. diff --git a/zh/manual/adapters/index.md b/zh/manual/adapters/index.md index dbad9ee..df9af51 100644 --- a/zh/manual/adapters/index.md +++ b/zh/manual/adapters/index.md @@ -12,6 +12,7 @@ title: 适配器概览 - [NapCat](./napcat.md)(推荐使用)— 麦麦官方维护的 QQ 适配器,支持插件版和独立版,插件版是当前推荐方案 - [GoCQ](./gocq.md)(可用,偏旧)— 基于 go-cqhttp / AstralGocq 的 QQ 适配方案,适合已有 GoCQ 环境或特定需求 - [SnowLuma](./snowluma.md)(可用,测试中)— 新一代 QQ 适配方案 +- [QQ 官方适配器](./qq-official-adapter.md)(可用)— 基于 QQ 官方开放平台 API v2 的适配器,纯出站连接,无需公网 IP **其他平台** — 社区适配 - [Telegram](./telegram.md) — Telegram 平台适配方案 diff --git a/zh/manual/adapters/qq-official-adapter.md b/zh/manual/adapters/qq-official-adapter.md new file mode 100644 index 0000000..bc3632d --- /dev/null +++ b/zh/manual/adapters/qq-official-adapter.md @@ -0,0 +1,200 @@ +--- +title: QQ 官方适配器 +--- +# QQ 官方适配器 + +QQ 官方适配器让 MaiBot 通过 [QQ 官方机器人开放平台](https://q.qq.com) 接入 QQ 平台,在单聊、群聊、文字子频道和频道私信中收发消息。 + +::: info 纯出站连接 +QQ 官方适配器由 MaiBot 主动连接 QQ 官方的 WebSocket 网关和开放平台 API,是**纯出站**连接,不需要公网 IP、端口映射或回调地址。 +::: + +::: warning ID 体系不同 +本适配器的 UserID / GroupID 来自 QQ 官方 OpenID 体系(`user_openid` / `member_openid` / `group_openid`),不是数字 QQ 号和群号,不能与 OneBot v11 的 ID 混用。 +::: + +## 简介 + +QQ 官方适配器是一个 MaiBot 插件,对接 QQ 官方机器人开放平台的 API v2。它主动连接 QQ 官方的 WebSocket 网关接收消息,并通过开放平台 REST API 发送回复: + +- **入站**:QQ 官方 WebSocket 网关推送事件到适配器,适配器转换后注入 MaiBot +- **出站**:MaiBot 生成的回复经适配器转换后,通过 QQ 官方 API 发送出去 + +与 NapCat、GoCQ 等基于 OneBot 协议的适配器不同,QQ 官方适配器只对接 QQ 官方能力,不依赖第三方协议或服务,也不需要维护适配器与 MaiBot 之间的网络连接。 + +消息流转:**QQ 官方网关 → 适配器插件(MaiBot 内部)→ MaiBot** + +### 适配器仓库 + +QQ 官方适配器的源码:[WhiteCloudOL/qq-official-adapter](https://github.com/WhiteCloudOL/qq-official-adapter) + +## 安装 + +### 第一步:创建 QQ 机器人 + +打开 [QQ 机器人开放平台](https://q.qq.com/qqbot/openclaw/),创建机器人,并保存它的 **AppID** 与 **AppSecret**。 + +::: tip AppSecret 是机器人密码 +AppSecret 等同于机器人密码,请妥善保存,不要提交到代码仓库或分享给别人。一旦怀疑泄露,应立即在开放平台重置。 +::: + +### 第二步:获取适配器 + +克隆适配器仓库到 MaiBot 的 `plugins/` 文件夹中: + +::: code-group + +```bash [Bash ~vscode-icons:file-type-shell~] +# 进入 MaiBot 的 plugins 目录 +cd MaiBot/plugins + +# 克隆仓库 +git clone https://github.com/WhiteCloudOL/qq-official-adapter.git +``` + +::: + +MaiBot 会根据插件清单自动安装依赖。 + +### 第三步:填写插件配置 + +插件安装后**默认是禁用的**。在 MaiBot WebUI 的插件配置中找到 **"QQ 官方机器人适配器"**,填写以下内容: + +- **启用适配器** — 开启 +- **AppID** — QQ 开放平台显示的 AppID +- **AppSecret** — 与 AppID 对应的 AppSecret + +聊天名单过滤默认关闭,不配置即可正常使用。需要限制允许接入的群或用户时,再启用"聊天过滤"并填写 QQ 官方 OpenID(详见下方[配置参考](#配置参考))。 + +也可以直接编辑插件的配置文件 `plugins/qq-official-adapter/config.toml`,把 `enabled` 设为 `true` 并填入凭据,效果相同。 + +### 第四步:设置 MaiBot 主账号 + +先启动一次 MaiBot,让插件连接上 QQ 网关,然后在日志中找到: + +```text +QQ 官方 WebSocket 已就绪: self_id=机器人自身ID +``` + +随后在 MaiBot 的 `config/bot_config.toml` 中填写: + +::: code-group + +```toml [TOML ~vscode-icons:file-type-toml~] +[bot] +platform = "qq" +qq_account = "日志中的 self_id" +``` + +::: + +::: warning 不要填错账号 +`qq_account` 必须填日志里的 `self_id`(即 WebSocket `READY` 事件中的机器人自身 ID)。**不要**填 AppID、QQ 号或 OneBot v11 的机器人 QQ 号。MaiBot 主程序会用它标记机器人自己发送的消息。 +::: + +机器人显示昵称会自动读取 `[bot]` 的 `nickname`(默认 `"麦麦"`),群聊中被 @ 时会以 `@昵称` 进入聊天上下文,无需在插件配置中重复填写机器人 ID。 + +### 第五步:开启群聊全量消息(仅群聊需要) + +如需使用群聊功能,需要由**群主**进入 QQ 群设置,选择当前使用的机器人,将"机器人可获取的群聊消息范围"设置为"获取群内全部消息"。未开启时,机器人只能收到平台允许范围内的消息,无法正常参与完整群聊。 + +> 该设置只能由群主操作,并且需要对每个使用机器人的群分别设置。 + +### 第六步:重启并验证 + +重启 MaiBot,确认日志出现 **"QQ 官方 WebSocket 已就绪"**。建议依次测试: + +1. 单聊发送普通文字。 +2. 群聊艾特机器人并发送文字。 +3. 发送普通图片和 QQ 表情/贴纸。 +4. 让 MaiBot 分别回复纯图片、纯表情和图文消息。 + +## 配置参考 + +插件的配置文件位于 `plugins/qq-official-adapter/config.toml`,包含以下三个分组。 + +### 插件设置 (`[plugin]`) + +- **`enabled`** — 是否启用 QQ 官方适配器。关闭时插件只注册消息网关,不会连接 QQ WebSocket。默认关闭 +- **`config_version`** — 当前配置结构版本(自动管理,一般不需要手动修改)。默认 "1.1.0" + +### 机器人凭据 (`[credentials]`) + +- **`appid`** — QQ 开放平台机器人的 AppID(在 `https://q.qq.com` 获取)。默认为空 +- **`app_secret`** — 与 AppID 配对的 AppSecret,用于获取访问令牌。默认为空 +- **`sandbox`** — 是否使用沙箱环境。开启后 WebSocket 网关与消息发送走沙箱地址,便于测试。默认关闭 + +### 聊天过滤 (`[chat]`) + +- **`enable_chat_list_filter`** — 是否启用群聊与私聊名单过滤。关闭后忽略 `group_list` / `private_list`,仅保留 `ban_user_id` 规则。默认关闭 +- **`show_dropped_chat_list_messages`** — 是否记录未通过聊天名单过滤而被丢弃的消息。默认关闭 +- **`group_list_type`** — 群聊名单模式。白名单只接收列表内群聊,黑名单则忽略列表内群聊。默认 "whitelist" +- **`group_list`** — 群聊名单,填写 `group_openid`(自动去重)。默认为空 +- **`private_list_type`** — 私聊名单模式。白名单只接收列表内私聊,黑名单则忽略列表内私聊。默认 "whitelist" +- **`private_list`** — 私聊名单,填写 `user_openid`(自动去重)。默认为空 +- **`ban_user_id`** — 全局屏蔽的用户列表,填写 `user_openid` 或 `member_openid`,这些用户的消息会在进入 MaiBot 之前被直接丢弃。默认为空 + +::: tip 名单里填的是 OpenID +聊天名单填写的都是 QQ 官方 OpenID(`group_openid` / `user_openid` / `member_openid`),不是数字群号 / QQ 号,可以在日志的调试信息中查看对应事件的 OpenID。 +::: + +### 完整配置示例 + +::: code-group + +```toml [TOML ~vscode-icons:file-type-toml~] +[plugin] +enabled = true +config_version = "1.1.0" + +[credentials] +appid = "你的AppID" +app_secret = "你的AppSecret" +sandbox = false + +[chat] +enable_chat_list_filter = false +show_dropped_chat_list_messages = false +group_list_type = "whitelist" +group_list = [] +private_list_type = "whitelist" +private_list = [] +ban_user_id = [] +``` + +::: + +## 消息能力 + +QQ 官方适配器支持以下消息场景: + +- **QQ 单聊** — 接收文字、图片、表情、语音、视频和文件;可发送文字、图片、表情、语音、视频、文件和结构化消息 +- **QQ 群聊** — 接收艾特消息、全量消息及附件;可发送文字、图片、表情、语音、视频、文件和结构化消息 +- **文字子频道** — 接收艾特消息、全量消息及附件;可发送文字、图片、Markdown、Ark 和 Embed +- **频道私信** — 接收文字及附件;可发送文字、图片、Markdown、Ark 和 Embed + +QQ 群与单聊中的表情以图片富媒体发送,不会显示为无效的 `[表情]` 文本;纯图片或纯表情回复也不会额外发送 `[图片]`、`[表情]` 占位文字。入站图片和表情会保留原始二进制供 MaiBot 识别,首次出现的图片会后台识别后补入聊天上下文,相同图片复用缓存描述。 + +适配器会自动判断群聊消息是否真正艾特当前机器人(结合事件类型、WebSocket 自身 ID、结构化 mentions 与消息元素),并自动学习群聊范围内的机器人 OpenID,无需在插件配置中重复填写机器人 ID。 + +## 验证与排查 + +### 验证连接 + +怎么知道连上了?看这几个地方: + +1. **MaiBot 日志**:看到 `QQ 官方 WebSocket 已就绪` 的提示 +2. **WebUI 插件列表**:能看到 QQ 官方适配器插件已加载 +3. **发消息测试**:在 QQ 单聊 / 群里发消息,看 MaiBot 有没有回复 + +### 群里艾特机器人,但 MaiBot 没有识别 + +先确认日志收到的是 `GROUP_AT_MESSAGE_CREATE` 或 `GROUP_MESSAGE_CREATE`。若日志显示插件已识别,但 MaiBot 仍无法发送回复,检查 `bot_config.toml` 的 `qq_account` 是否等于就绪日志里的 `self_id`。 + +### 收不到群聊或频道消息 + +确认机器人已获得对应场景权限,并在开放平台启用了相应消息能力。如果快速创建页面显示"暂不支持进入群聊",插件无法绕过平台限制。群聊场景还需要群主开启"获取群内全部消息"。 + +### 返回 401 或鉴权失败 + +核对 AppID 与 AppSecret 是否属于同一个机器人。重置 AppSecret 后,需要同步更新插件配置并重启。