钩子与多渠道支持

奶狗 发表于 4 周前 浏览 30 字数 1374 阅读时长 7分钟

5. 钩子与多渠道支持

5.1 钩子系统(被动监听)

除了 onMessage 主动处理消息,插件还能通过 lib/hooks 在「特定时机」被动订阅,而不用改核心代码:

const hooks = require('../../lib/hooks');

// 在插件模块加载时订阅(建议在文件顶层或 meta 之前的模块作用域)
hooks.on('group_message', async ({ msg, ctx, bot }) => {
  // 群消息到达时触发,即使本插件未命中命令也会执行
});

hooks.on('user_first_seen', async ({ botId, groupId, userId, nickname }) => {
  // 某成员首次被机器人识别到(QQ 群被动识别成员用)
});

hooks.on('command', async ({ msg, ctx, command, args }) => {
  // 命中命令前缀时
});
事件 payload 触发时机
message { msg, ctx, bot } 任意消息到达
group_message { msg, ctx, bot } 群消息到达(msg.group_id 非空)
c2c_message { msg, ctx, bot } 私聊消息到达
user_first_seen { botId, groupId, userId, nickname } 成员首次被识别(QQ 群被动识别)
command { msg, ctx, command, args } 命中命令前缀

hooks.on 返回取消订阅函数。钩子内抛错不影响主流程和其他订阅者。

5.2 多渠道:微信 & QQ

插件默认支持微信(wechat)渠道。QQ 渠道走 qqbot 内置模块管线,仅当插件在 QQ 白名单或显式声明 channels 时才标记支持。

// 规则(lib/plugins.js resolveChannels):
// 1. 若 meta.channels 显式声明 → 使用声明(但微信始终被加入)
// 2. 否则:id 在 QQ_SUPPORTED 白名单 → ['wechat','qq'],否则 ['wechat']
meta: {
  channels: ['wechat', 'qq'],
},

QQ 白名单默认包含:replyrsssmartreminderdelta-passwordweatherdouyinhoroscopelookupima-knowledgeopenclawanniversaryrecipegold-pricemailhome-assistantpushmcphot-search 等。

5.3 统一发送能力

微信与 QQ 共用同一套 ctx.sendText / ctx.sendMedia

  • 文本:两者都支持 sendText
  • 图片/文件/视频sendMedia(filePath, type) 在两条渠道下都已实现(QQ 侧走分片上传 CDN,微信侧走 iLink 网关)。

因此一个用 commandPrefix + ctx.sendMedia 的插件(如 AI 绘图 /draw)可同时在 QQ 群、QQ 私聊、微信中触发并出图,无需分开写。

5.4 QQ 群成员被动识别

QQ 群中用户不是每次主动发消息,插件可通过 hooks.on('user_first_seen', ...) 在成员首次被 qqbot 网关识别到时拿到 groupId / userId / nickname,用于建群成员库、欢迎语等。