PicoClaw 接入 QQ:开放平台机器人配置指南与通道源码解析
【免费下载链接】picoclawTiny, Fast, and Deployable anywhere — automate the mundane, unleash your creativity项目地址: https://gitcode.com/gh_mirrors/pi/picoclaw
PicoClaw 通过 QQ 开放平台的官方机器人 Bot API 提供完整的 QQ 通道支持,支持私聊(C2C)与群聊 @ 消息的收发、图片/语音/文件等富媒体、输入状态提示与语音能力。本文以 docs/channels/qq/README.zh.md 为骨架,结合仓库内pkg/channels/qq的通道实现与 config/config.example.json 中的真实配置格式,完整讲解从凭证申请、配置写入、picoclaw gateway启动到消息收发与媒体发送的实战流程,并深入解析底层调用链,帮助你在 10 分钟内把 QQ 机器人接入 PicoClaw。
功能概述
QQ 通道基于 QQ 开放平台的官方机器人能力实现,无需自建服务端,机器人通过 WebSocket 长连接订阅消息事件。从 pkg/channels/qq/qq.go 的代码可以看到,通道注册了两类事件处理器:
handleC2CMessage():处理用户与机器人之间的私聊(C2C)消息;handleGroupATMessage():处理群聊中@ 机器人的消息。
发送侧则根据会话类型自动路由到PostGroupMessage(群消息)或PostC2CMessage(C2C 私聊消息)两个 OpenAPI 接口,并支持 Markdown 消息、富媒体上传(msg_type=7)、输入状态提示(msg_type=6)等扩展能力。
前置准备:获取 App ID 与 App Secret
接入 QQ 通道的核心凭证是App ID和App Secret,两者均由 QQ 开放平台下发。文档提供了两种获取方式。
快捷创建(推荐)
QQ 开放平台提供了一键创建机器人入口,适合快速验证:
- 打开 QQ 机器人快速创建入口,扫码登录;
- 系统自动创建机器人,页面展示App ID与App Secret,立即复制保存;
- 将凭证填入 PicoClaw 配置文件(下文详述);
- 运行
picoclaw gateway启动服务; - 打开 QQ,与机器人开始对话。
注意:App Secret 仅完整显示一次,请立即保存;再次查看会被强制重置。另外,通过快捷入口创建的机器人仅供创建人个人使用,暂不支持群聊;如需群聊功能,请在 QQ 开放平台为机器人配置沙箱模式。
手动创建
- 使用 QQ 账号登录 QQ 开放平台,注册开发者账号;
- 创建 QQ 机器人,自定义头像与名称;
- 在机器人设置页获取App ID与App Secret;
- 将凭证填入 PicoClaw 配置文件;
- 运行
picoclaw gateway启动服务; - 在 QQ 中搜索你的机器人,开始对话。
开发阶段建议开启沙箱模式,把测试用户和测试群加入沙箱,便于在受控范围内调试,避免误触线上用户。
配置文件详解
标准配置结构
以仓库根目录 config/config.example.json 中真实的 QQ 通道配置段为准,完整结构如下:
{ "channel_list": { "qq": { "enabled": false, "type": "qq", "allow_from": [], "reasoning_channel_id": "", "settings": { "app_id": "YOUR_QQ_APP_ID", "app_secret": "YOUR_QQ_APP_SECRET" } } } }启用时把enabled改为true,并将app_id、app_secret替换为开放平台下发的真实凭证即可。
字段说明
通道级字段与 settings 级字段分别对应 pkg/config/config.go#L573-L579 中定义的QQSettings结构体及其外层Channel配置:
| 字段 | 类型 | 必填 | 位置 | 描述 |
|---|---|---|---|---|
| enabled | bool | 是 | channel 级 | 是否启用 QQ 通道 |
| type | string | 是 | channel 级 | 固定为qq,用于匹配注册的通道工厂 |
| allow_from | array | 否 | channel 级 | 用户 ID 白名单,空数组表示允许所有用户 |
| reasoning_channel_id | string | 否 | channel 级 | 推理输出专用会话 ID,可配置为群 ID |
| app_id | string | 是 | settings | QQ 机器人应用的 App ID |
| app_secret | string | 是 | settings | QQ 机器人应用的 App Secret(敏感字段,加密存储) |
| max_message_length | int | 否 | settings | 单条消息最大长度限制 |
| max_base64_file_size_mib | int | 否 | settings | 本地文件转 base64 上传的最大体积(MiB),0表示不限制,仅影响本地文件,不影响 URL 直传 |
| send_markdown | bool | 否 | settings | 发送时是否使用 Markdown 消息类型 |
环境变量替代方案
从QQSettings的 struct tag 可以看到,所有 settings 级字段都支持通过环境变量注入,适合容器化或密钥管理场景:
PICOCLAW_CHANNELS_QQ_APP_IDPICOCLAW_CHANNELS_QQ_APP_SECRETPICOCLAW_CHANNELS_QQ_MAX_MESSAGE_LENGTHPICOCLAW_CHANNELS_QQ_MAX_BASE64_FILE_SIZE_MIBPICOCLAW_CHANNELS_QQ_SEND_MARKDOWN
其中app_secret在 pkg/config/config.go#L573 中使用SecureString类型,仓库的 安全配置测试 会验证这类敏感字段的脱敏与加密行为,切勿在日志或明文配置中泄露。
白名单与群触发
allow_from白名单在创建通道时通过channels.NewBaseChannel的bc.AllowFrom传入,空数组放行所有用户;如需限制为指定 QQ 用户,可填入对应的用户 ID 列表。group_trigger则控制群聊场景下的触发词过滤,配合群 @ 事件使用。
启动服务
配置写入后,运行 gateway 子命令启动服务:
picoclaw gateway该命令在 cmd/picoclaw/internal/gateway/command.go 中定义(用途说明为 "Start picoclaw gateway"),启动时会根据配置文件中的channel_list实例化所有已启用的通道,QQ 机器人随之建立 WebSocket 长连接并开始订阅消息事件。启动成功后,在 QQ 中搜索你的机器人即可开始对话。
源码实现原理
通道注册
QQ 通道通过工厂模式注册,见 pkg/channels/qq/init.go:init()中调用channels.RegisterFactory把config.ChannelQQ类型映射到NewQQChannel构造函数,配置文件中的settings块会被解码为*config.QQSettings后传入。这就是type字段必须为qq的原因。
WebSocket 连接与事件订阅
在Start()方法中(pkg/channels/qq/qq.go#L102-L174):
- 校验
app_id与app_secret是否已配置,缺失则直接报错; - 基于凭证构造
token.QQBotCredentials,创建 oauth2 token source,并启动后台协程自动刷新 Access Token; - 初始化 OpenAPI 客户端(5 秒超时);
- 注册 C2C 消息与群 @ 消息两类事件处理器,构建 Intent;
- 从
WS接口获取 WebSocket 网关信息,由botgo.NewSessionManager()建立长连接; - 额外启动一个去重清扫协程(dedup janitor),并在
reasoning_channel_id配置了群 ID 时预注册为 group 会话类型,保证纯出站路由正确。
这里使用了腾讯开源的tencent-connect/botgoSDK,底层事件分发的细节被封装在 botgo 中,PicoClaw 侧只需实现qqAPI接口(WS、PostGroupMessage、PostC2CMessage、Transport)即可完成收发。
消息去重
WebSocket 场景下事件可能重投递,通道在 pkg/channels/qq/qq.go#L909-L936 实现基于消息 ID 的 TTL 去重:默认 5 分钟窗口(dedupTTL),并对去重表设置 10000 条硬上限,超出时淘汰最旧条目;dedupJanitor每 60 秒清扫过期条目,避免内存无限增长。
会话路由与被动回复
通道内部维护chatType映射记录每个 chatID 是群聊还是私聊,未知 chatID 默认按群聊处理。同时记录每个会话最后一条入站消息 ID(lastMsgID),出站回复时通过applyPassiveReplyMetadata回填msg_id与递增的msg_seq,实现 QQ 开放平台要求的被动回复消息引用机制。
媒体发送:两步上传流程
SendMedia实现channels.MediaSender接口(pkg/channels/qq/qq.go#L326-L367),QQ 的富媒体发送是两步流程:
- 先将媒体上传到
/v2/groups/{group_id}/files或/v2/users/{user_id}/files(依会话类型而定),获得file_info; - 再以
msg_type=7的富媒体消息携带file_info发送。
媒体类型映射为qqFileType:图片=1、视频=2、音频=3、普通文件=4。对于本地文件,如果配置了max_base64_file_size_mib,会先os.Stat校验文件大小再以 base64 编码上传(见buildMediaUpload);URL 直传则不受该限制。音频还会做时长探测,超过 QQ 语音时长上限或无法探测时长时自动降级为普通文件发送。
输入状态提示
通道实现channels.TypingCapable接口的StartTyping:发送msg_type=6的 InputNotify 消息,并以 8 秒为间隔重发,模拟"对方正在输入"的状态,直到返回的停止函数被调用(幂等,可重复调用)。
群消息 URL 净化
为避免 QQ 对群消息的 URL 黑名单拦截,通道在群聊出站前会用sanitizeURLs将 URL 域名中的.替换为全角。(pkg/channels/qq/qq.go#L980-L1017)。该处理只作用于带http(s)://前缀的 URL,且只替换域名部分、保留路径与查询参数,避免对版本号之类的纯文本误伤。
语音能力
通道声明VoiceCapabilities{ASR: true, TTS: true}(pkg/channels/qq/qq.go#L1019-L1022),表明 QQ 通道同时支持语音识别(ASR)与语音合成(TTS),可用于语音交互类场景。
常见问题与排错提示
- 启动报 "app_id and app_secret not configured":说明配置文件中的
app_id/app_secret为空,请确认凭证已正确写入settings段。 - 私聊正常但群聊无响应:快捷创建入口创建的机器人不支持群聊,需在 QQ 开放平台配置沙箱模式,并把测试群加入沙箱。
- 凭证泄露风险:App Secret 属于敏感字段,仓库以
SecureString处理并在加密与脱敏逻辑中覆盖,生产环境建议通过PICOCLAW_CHANNELS_QQ_APP_SECRET环境变量注入。 - 群消息被拦截:QQ 对群内 URL 有黑名单策略,通道默认已做域名点号净化;如需外链直达,请结合实际开放平台规则调整发送内容。
若需进一步了解 PicoClaw 的整体架构与配置体系,可继续阅读 项目 README 与 配置文件指南。
【免费下载链接】picoclawTiny, Fast, and Deployable anywhere — automate the mundane, unleash your creativity项目地址: https://gitcode.com/gh_mirrors/pi/picoclaw
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考