文档同步
本页由 plugins/adapters/icqq/README.md 自动生成。请修改包内 README 后运行 pnpm sync:adapter-docs。
@zhin.js/adapter-icqq
ICQQ Plugin Runtime 适配器 — 进程内直接使用 @icqqjs/icqq Client
功能特性
- 群聊 / 私聊 / 群临时会话 / QQ 频道消息
- 入站:ICQQ Client 原始事件经
Endpoint.emit(...)唯一入口上送;文本与图片 / 语音 / 视频 / 文件统一归一为 canonicalSegment+MediaRef - 出站:canonical Segment 直接投影为 ICQQ 原生
Sendable,再由sendGroupMsg/sendPrivateMsg/ …发送 - 群聊 reaction:
control.addReaction/removeReaction(协议 ACK 失败不阻塞后续发送) - Agent 工具:包根
tools/(@zhin.js/toolFeature;模型侧名为icqq__send_user_like等) - Console Endpoint 管理:
src/endpoint.ts显式实现EndpointManagement(好友/群/群成员列表、请求审批、删好友、踢人、禁言、设管理)
安装
pnpm add @zhin.js/adapter-icqq @icqqjs/icqq
# 可选:未配置 signApiAddr 时走本地签名
pnpm add @icqqjs/qqsign@icqqjs/icqq 是适配器的可选对等依赖(peerDependencies + optional)。应用侧需自行安装;monorepo 内另在 devDependencies 声明以便构建/测试。
@icqqjs/* 发布在 GitHub Packages,需:
@icqqjs:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}并设置具有 read:packages 权限的 NPM_TOKEN(CI 使用仓库 secret PERSONAL_TOKEN)。
签名:未配置 signApiAddr 时,若已安装 @icqqjs/qqsign 则自动走本地签名。
前置条件
- 准备可登录的 QQ 账号,并选择远程
signApiAddr或安装本地@icqqjs/qqsign。 - 确保运行目录可持久化设备与登录状态;容器部署应挂载对应数据目录。
- 首次登录可能要求二维码、滑块或设备确认,可在 Console 登录待办或终端完成。
配置(Plugin Runtime)
plugins:
icqq:
master: "1659488338" # 必填,顶层共享(/approve 与 master 角色)
autoReconnect: true
endpoints:
- id: "${ICQQ_ACCOUNT}" # QQ 号
# password: "${ICQQ_PASSWORD}" # 可选;不填则扫码登录多账号:一个插件实例挂多个 endpoint(endpoints 数组逐项覆盖顶层字段,id 必填):
plugins:
icqq:
master: "1659488338"
endpoints:
- id: "${ICQQ_ACCOUNT}"
- id: "${ICQQ_ACCOUNT_2}"
- id: "${ICQQ_ACCOUNT_3}"Send conversation
| 类型 | conversation |
|---|---|
| 私聊 | { kind: 'private', id: uin } |
| 群聊 | { kind: 'group', id: gid } |
| 群临时会话 | { kind: 'private', id: uin, parent: { kind: 'group', id: gid } } |
| 频道 | { kind: 'channel', id: channelId, parent: { kind: 'channel', id: guildId } } |
直接使用完整 ICQQ Client
适配器把 icqq 注册为 @icqqjs/icqq.Client 与 SDK EventMap 的类型判别项。 所有 Feature 都使用同一个 adapter 字段完成类型缩窄与运行时过滤:
import { defineHandler } from 'zhin.js/handler'
import '@zhin.js/adapter-icqq'
export default defineHandler({
adapter: 'icqq',
event: 'request.group.add',
async handle({ client, event }) {
await client.setGroupAddRequest(event.flag, true)
},
})client 就是当前账号的真实 ICQQ SDK 实例,不是 Endpoint facade。未知扩展事件可显式使用 event: '*';此时 Client 类型保持完整,事件 payload 为 unknown。普通消息回复仍应走 Message.$reply;群管理、请求审批与 ICQQ 专属查询可直接调用当前事件的 client。
Command context 的 $client 是按需读取的 getter:
export default defineCommand({
adapter: 'icqq',
async execute(context) {
await context.$client.sendLike(Number(context.sender!.id), 10)
return 'ok'
},
})Middleware 使用同一个判别字段;不声明 adapter 时 $client 的类型是 unknown:
export default defineMiddleware<Message>({
target: 'inbound',
adapter: 'icqq',
async handle(context, next) {
console.log(context.$client.uin, context.input.content)
await next()
},
})Agent tool 的 IM turn 同样直接读取当前 Client:
export default defineAgentTool({
adapter: 'icqq',
description: '获取群列表',
async execute(_input, context) {
return context.$client.getGroupList()
},
})adapter 缺失时 $client 静态类型为 unknown;声明后若实际 operation 不属于 ICQQ, 运行时会在执行前拒绝。Client 只能在当前 operation 内使用。task、schedule 或 Host 等脱离 IM turn 的场景,才使用 icqqClient.get(context, endpointId) 显式选择账号。
架构
plugin.ts+adapters/icqq.ts(defineAdapter)- Client token:
src/client.ts(直接引用 ICQQClient/EventMap) - Endpoint:
src/endpoint.ts(组合 ICQQClient,负责账号 transport 与 Zhin lifecycle) - 协议常量 / 配置:
src/protocol.ts - Agent 工具:
tools/*.ts;权限说明见agent/PERMITS.md
Plugin Runtime 迁移说明
- 不再经过
@icqqjs/cliIPC 守护进程;登录态与协议栈都在本进程。 autoReconnect:Client 断线后按配置自动重连(stop()为主动断开,不触发重连)。outboundMedia: file | base64:file在发送期间把 segment base64 物化为临时文件并于发送结束清理;base64使用 ICQQ 原生支持的base64://file 参数。- ICQQ 的语音、视频、文件是独立消息元素;它们与其他段混发时适配器会明确拒绝,避免协议栈静默丢段。
- 入站语音 / 视频在 Endpoint 持有原生 Client 时解析可下载 URL;解析失败则保留真实平台引用,不伪造或丢弃媒体。
- Console 社交/群管 RPC 已接线:endpoint 把好友/群/群成员列表、请求审批和群管操作归一化为冻结的
EndpointManagement。Host 只消费该语义端口。 - 好友/入群请求与通知:经 the unified
Endpoint.emit(...)ingress 分发到handlers(notice.receive/request.receive);审批走Request.$approve/EndpointManagement.approveRequest。Consolerequest.list优先读management.listRequests()(getSystemMsg),不再写入unified_inbox_request/notice。 system.*(登录扫码等)分发到system.receive。- 登录辅助:
system.login.qrcode|slider|device|auth经loginAssistToken(LoginAssist)挂起待办;刷新后可用 Consolelogin.list/login.submit或终端 stdin 继续(对齐 icqq 官方 stdin 流程)。system.online/login.error会清理该 endpoint 待办。
故障排查
| 现象 | 排查 |
|---|---|
| 一直停在登录中 | 打开 Console 登录待办,完成二维码、滑块或设备确认 |
| 签名失败 | 检查 signApiAddr;本地模式确认 @icqqjs/qqsign 已安装且版本匹配 |
| 重启后重复登录 | 持久化设备与会话数据目录,避免每次生成新设备 |
| 请求或通知未显示 | 在 Endpoint 详情检查请求视图;ICQQ 优先读取平台请求列表 |
License
MIT