@saukkojs/plugin-qq
v0.1.0
Published
QQ official bot adapter plugin for Saukko
Maintainers
Readme
@saukkojs/plugin-qq
Saukko 的 QQ 官方机器人适配器插件,基于 QQ 开放平台 API v2(WebSocket 网关 + OpenAPI)。
适用于 Saukko 0.2.x 版本。
要求
- Node.js >= 22(依赖内置的全局
WebSocket与fetch) - 已在 QQ 开放平台 创建机器人,取得 AppID 与 ClientSecret
安装与配置
pnpm add @saukkojs/plugin-qq在项目的 saukko.toml 中配置(插件名 qq):
[plugin.config.qq]
appId = "你的 AppID"
secret = "你的 ClientSecret"
sandbox = false
intents = ["GROUP_AND_C2C_EVENT", "PUBLIC_GUILD_MESSAGES", "GUILDS", "GUILD_MEMBERS"]appId / secret 也可用环境变量 QQ_APP_ID / QQ_SECRET 提供(配置优先)。
完整配置项:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| appId | string | 必填。开放平台管理端获取 |
| secret | string | 必填。开放平台管理端获取 |
| intents | number | string[] | 事件订阅位掩码或事件名数组,缺省为 GUILDS \| GUILD_MEMBERS \| PUBLIC_GUILD_MESSAGES \| GROUP_AND_C2C_EVENT(均无需额外申请权限) |
| sandbox | boolean | 是否使用沙箱环境,默认 false |
| endpoint | string | 自定义 OpenAPI 域名 |
| shard | [number, number] | 分片设置,默认 [0, 1] |
| reconnect | boolean | 断线自动重连,默认 true |
事件
所有事件通过 context.on(...) 订阅,回调参数为 { name, data, bot }。
| 事件名 | 来源(QQ 网关事件) | 说明 |
| --- | --- | --- |
| meta.connect | READY | 会话建立,data.version 为适配器版本信息 |
| meta.status_update | 连接状态变化 | data.status: { good, online } |
| message.private | C2C_MESSAGE_CREATE / DIRECT_MESSAGE_CREATE | 私聊消息;频道私信时 sub_type 为 'direct' 且带 guild_id |
| message.group | GROUP_AT_MESSAGE_CREATE / GROUP_MESSAGE_CREATE | 群消息,group_id 为群 openid |
| message.channel | AT_MESSAGE_CREATE / MESSAGE_CREATE | 频道消息,带 guild_id / channel_id |
| notice.friend_increase / notice.friend_decrease | FRIEND_ADD / FRIEND_DEL | 用户添加 / 删除机器人 |
| notice.private_message_delete | DIRECT_MESSAGE_DELETE | 私信撤回 |
| notice.group_member_increase / notice.group_member_decrease | GROUP_ADD_ROBOT / GROUP_DEL_ROBOT | 机器人被拉入 / 移出群聊 |
| notice.guild_member_increase / notice.guild_member_decrease | GUILD_MEMBER_ADD / GUILD_MEMBER_REMOVE | 频道成员增减 |
| notice.channel_create / notice.channel_delete | CHANNEL_CREATE / CHANNEL_DELETE | 子频道新建 / 删除 |
| notice.channel_message_delete | MESSAGE_DELETE / PUBLIC_MESSAGE_DELETE | 频道消息撤回 |
| qq.raw | 全部网关事件 | 原始事件透传:{ id, event, seq, data } |
消息事件 data 字段包括:message_id、message(消息段数组)、alt_message(纯文本替代表示)、user_id、group_id / guild_id / channel_id 等,另附 raw 保留平台原始事件体。
消息段
接收方向:text、mention、mention_all、image、voice、video、file、face(频道表情)、channel(子频道提及)、ark(卡片,扩展段)。
发送方向接受纯字符串或消息段数组,支持 text、mention、mention_all(仅频道)、image / voice / video / file(data.url 为公网可访问地址,群聊/单聊会自动上传转存)、markdown(data 即平台 markdown 对象)、keyboard、reply、ark、embed(后两者仅频道)。
使用示例
// plugins/echo.ts(在 saukko.toml 的 plugin.files 中登记)
import type { PluginContext } from '@saukkojs/core';
import type { QQBot } from '@saukkojs/plugin-qq';
export const name = 'echo';
export default function (context: PluginContext) {
context.on('message.group', async ({ data, bot }) => {
if (data.alt_message.trim() === 'ping') {
// reply 自动按事件来源选择目标,并携带 msg_id 作为被动回复
await (bot as QQBot).reply(data, 'pong');
}
});
}也可以通过依赖注入拿到 bot 实例(inject: ['qq'],注入对象即 QQBot),或从 context.bots 中查找。
Bot API
| 方法 | 说明 |
| --- | --- |
| sendPrivateMessage(userOpenid, message, options?) | 发送 QQ 单聊消息 |
| sendGroupMessage(groupOpenid, message, options?) | 发送群聊消息 |
| sendChannelMessage(channelId, message, options?) | 发送子频道消息 |
| sendDirectMessage(guildId, message, options?) | 发送频道私信(guildId 为私信会话 id) |
| createDirectSession(userId, sourceGuildId) | 建立频道私信会话 |
| reply(event, message, options?) | 快捷被动回复一条消息事件 |
| recallPrivateMessage / recallGroupMessage / recallChannelMessage / recallDirectMessage | 撤回消息 |
| api.uploadC2CFile / api.uploadGroupFile | 富媒体上传(获取 file_info) |
| api.request(method, path, body?) | 直接调用任意 OpenAPI 接口 |
options:{ msgId?, eventId?, reference?, keyboard? }。填写 msgId / eventId 即为被动回复(5 分钟内有效,同一条消息最多回复 5 次,多次回复的 msg_seq 由适配器自动递增)。
注意事项
- 群聊 / 单聊不支持图文混排:文本(或 Markdown)与每个富媒体会拆分为多条消息依次发送。
- Markdown 与纯文本互斥(平台限制),同一条消息中提供
markdown段时文本将被忽略。 - 频道私信需先
createDirectSession(或使用DIRECT_MESSAGE_CREATE事件中的guild_id)。 - 订阅
GUILD_MESSAGES、FORUMS_EVENT等私域事件需要平台权限,请按需配置intents,否则网关会拒绝连接。
开发
pnpm install
pnpm build # 输出到 lib/
pnpm test # 单元测试 + 模拟网关集成测试