# Napcat Qq

> 为 openclaw 发送 QQ 消息（含图片/语音等媒体）时，强制使用 napcat 插件 API，并按照私聊/群聊规则生成与校验 sessionKey。适用于“发送QQ消息”“发群消息”“发QQ私聊”“发QQ图片”“发QQ语音”等请求。

- Skill: `propersama/napcat-qq` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add propersama/napcat-qq`
- Raw SKILL.md: https://api.skillmd.com/api/skills/propersama/napcat-qq/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: ProperSAMA (https://skillmd.com/u/propersama)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/propersama/napcat-qq

---


# 目标

确保 openclaw 发送 QQ 消息（文本与媒体）时只使用本插件的 API，并让 sessionKey 满足 napcat 插件要求。

# 工作流

1. NapCat 群聊可见回复（硬性规则）：
   - 当当前会话来自 NapCat 群聊，任何希望群里成员看到的文本回复都必须调用 `message` 工具：`action: "send"`。
   - 调用时必须显式指定 `channel: "napcat"`，并使用当前群的目标：`target: "session:napcat:group:<群号>"`（或 `target: "group:<群号>"`）。
   - 不要把普通最终回复当作群消息；群聊里的普通最终回复可能不会投递到 QQ。
   - 发送成功后，后续内部/最终回复保持简短，不重复已发送到群里的内容。
2. 识别消息类型：私聊或群聊。
3. 若用户未提供 QQ 号或群号，而是使用昵称、备注或群名指代目标，先调用搜索脚本：
   - `node scripts/qq-contact-search.js <关键词> [private|group|all]`
   - 若搜索结果为 1 个，直接采用该目标继续发送。
   - 若搜索结果多于 1 个，列出候选让用户选择编号后再发送。
   - 若没有结果，再询问更精确的昵称/备注/群名，或直接补充 QQ 号 / 群号。
4. 校验并构造 sessionKey：
   - 私聊：`session:napcat:private:<QQ号>`
   - 群聊：`session:napcat:group:<群号>`
5. 目标写法说明（重要）：
   - 群聊优先使用 `target: group:<群号>` 或 `target: session:napcat:group:<群号>`。
   - 纯数字 `target` 会被当作私聊用户 ID，容易导致“无法获取用户信息”。
6. 调用 message 工具时必须显式指定 `channel: "napcat"`，避免多通道场景下无法路由。
7. 通过 NapCat/QQ 发送文字时使用纯文本，不要使用 Markdown 标题、加粗、表格、代码块或 Markdown 链接语法。若需要表达层级，用普通换行和简短前缀即可。
8. 媒体发送规则：
   - 发送图片/媒体时，使用 `message` 工具并传 `mediaUrl`。
   - 可选传 `text` 作为媒体说明（caption）。
   - 语音可直接传 `.wav` 等音频 URL/路径到 `mediaUrl`，插件会按语音消息发送。
   - `mediaUrl` 需为 NapCat 可访问地址（通常是 `http/https` 局域网可达 URL）。

9. 语音生成与情绪策略（推荐约定，便于一致体验）：
   - 默认情绪策略：根据消息文本内容自动检测情绪/语气（由上游 TTS 侧实现）。
   - 显式覆盖规则：若用户明确指定情绪/语气（如“温柔/严肃/开心/激动”等），则覆盖自动检测结果。
   - 实践建议：将“默认音色/声线（voice profile）”作为**本地环境偏好**维护（见 `TOOLS.md`），避免在可分享的 skill 中绑定特定音色或语料路径。

10. 仅使用本插件的 API 完成发送，不要调用其他 QQ 发送途径。

## QQ 消息表情回应

- NapCat 通道支持 `message` 工具的 `react` 动作，可对 QQ 消息添加或撤销表情回应。
- 回应当前触发消息时可以省略 `messageId`；回应其他消息时必须显式提供 `messageId`。
- `emoji` 优先填写单个 Unicode Emoji；也可直接填写 QQ 数字表情 ID。
- 只保证 QQ 表情回应面板支持的 Emoji 可用；不支持的 Emoji 不要反复重试。
- 撤销机器人自己的回应时使用同一个 `emoji` 并传 `remove: true`。
- 只在轻量确认、表达情绪且无需额外文字时使用，避免对同一条消息连续添加多个回应。

# 入站上下文

- 当消息来自 NapCat 入站通道时，当前上下文会提供机器人自己的 QQ 号字段：`SelfId`、`BotId`、`BotQQ`、`NapCatSelfId`。
- 模型可见正文 `BodyForAgent` 会带有 `[NapCat context: bot QQ=<机器人QQ号>]` 前缀；需要判断“我现在用的是哪个 QQ 号”时优先读取这些上下文，不要猜。

# 交互规则

- 若用户未提供 QQ 号或群号，优先尝试用昵称/备注/群名搜索；搜索无结果时再询问并明确补全后发送。
- 若搜索返回多个候选，先让用户确认具体对象再发送。
- 若用户提供了 sessionKey 但格式不符合规则，改写为正确格式并说明已规范化。
- 若用户含糊描述（如“发消息给他”），优先确认私聊/群聊与目标 ID。

# 入站日志读取（排查/取证）

当用户要求“查看收到的消息”“排查某个 QQ/群的消息”时，按下面步骤执行：

1. 先确认日志目录配置：
   - 默认目录：`./logs/napcat-inbound`
   - 若插件配置了 `channels.napcat.inboundLogDir`，优先使用该目录
2. 根据会话类型选择日志文件：
   - 私聊：`qq-<QQ号>.log`
   - 群聊：`group-<群号>.log`
3. 日志为 JSON Lines（一行一条消息），常用字段：
   - `ts`、`message_type`、`user_id`、`group_id`、`message_id`、`raw_message`、`sender`
4. 读取日志时优先给出最近消息，再按用户要求扩展范围：
   - 例如先看最后 50 条，再按关键词/时间过滤
5. 重要行为约束：
   - 即使消息不在白名单中，日志里也可能有记录（因为是“先记录后过滤”）
   - 仅把日志用于排查与上下文理解，不要绕过白名单去触发自动处理

