Skip to content

fix: 私聊引用消息 reply 段丢失,records 命中时直接用 msgId 构造并携带被引用文本 - #2016

Open
eolynya wants to merge 1 commit into
NapNeko:mainfrom
eolynya:fix/private-reply-quote
Open

fix: 私聊引用消息 reply 段丢失,records 命中时直接用 msgId 构造并携带被引用文本#2016
eolynya wants to merge 1 commit into
NapNeko:mainfrom
eolynya:fix/private-reply-quote

Conversation

@eolynya

@eolynya eolynya commented Aug 16, 2026

Copy link
Copy Markdown

问题描述

私聊中引用(回复)消息时,OneBot 事件里丢失 reply 段——message 数组只剩 text 段,下游框架收不到引用信息(如 reply_to_id=None)。群聊不受影响。

复现步骤

  1. BOT 账号(或任意账号)在私聊发一条消息
  2. 对方引用该消息并发送(带或不带文字均可)
  3. 查看 OneBot 事件:message 数组中没有 {"type":"reply",...} 段,raw_message 也只剩纯文本

根因分析

引用消息的原始 replyElement 中,replayMsgSeq 被解析为 "0"(引用 bot 或自己发的消息时尤甚,peerUin 同样为 0),而 replyElement 的转换逻辑依赖 replayMsgSeq 走三种查询方法 + 协议兜底:

方法1查询失败,序号: 0, 消息数: 1
方法2查询失败,序号: 0, 消息数: 0
方法3查询失败,序号: 0, 消息数: 1
所有查找方法均失败,获取不到带记录的引用消息 0
协议兜底未找到匹配的引用消息

全部失败后 return null,reply 段被静默丢弃

但同一事件的 records[]sourceMsgIdInRecords 字段携带了被引用消息的完整记录(真实 msgId、发送者、时间、文本内容)。现有代码只在 records.peerUin 属于两个特定账号(284840486/1094950020)时才直接用 records.msgId 构造 reply 段——其他账号走必然失败的 seq 查询链。

相关 issue:#1508(BOT发起的私聊消息被引用回复时获取不到引用消息)、#477(私聊引用丢 reply 段)。

修复方案

records 命中(msgId === sourceMsgIdInRecords)且 msgId 有效时,直接用 records.msgId 构造 reply 段,不再依赖 seq 查询;同时从 sourceMsgTextElems 提取被引用文本,作为可选 text 字段携带(下游可直接使用,无需二次查询——NapCat 的 get_msg 对 bot 消息等场景同样会查不到)。

  • replyElement:把「特定账号捷径」推广为「records 命中即直用」(records.msgId 即被引用消息的真实 msgId,查询链本就多余)
  • createReplyData:新增可选 text 参数
  • OB11MessageReplySchema:data 新增可选 text 字段(向后兼容,不改变现有字段语义)

测试结果

  • 环境:NapCat docker(2026-08 镜像)+ 私聊引用 bot 消息
  • 修复前:100% 丢 reply 段(连续 51 次「所有查找方法均失败」日志)
  • 修复后:message 数组正确输出 {"type":"reply","data":{"id":"<shortId>","text":"<被引用文本>"}},下游 reply_to_id/reply_to_text 均正常

兼容性

  • text 为 Optional 新字段,不发送时行为与原来完全一致
  • 原 seq 查询链保留(records 未命中时仍走原逻辑)
  • 群聊引用路径不变(同样受益于 records 直用,行为一致)

@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown

✅ NapCat 构建成功

Success


📦 构建产物

包名 状态 下载
NapCat.Framework ✅ 成功 📥 下载
NapCat.Shell ✅ 成功 📥 下载

📋 构建信息

项目
🏷️ 版本号 4.18.19-pr.2016.768+3313df7
📝 提交 3313df7
🔗 构建日志 查看详情
🕐 完成时间 2026-08-16 05:49:47 UTC

🚀 快速安装 (Linux)

直连(需要能访问 GitHub)

curl -sSL https://github.com/NapNeko/napcat-pr-release/releases/download/pr-2016-3313df7/install.sh | bash

加速(国内推荐,ghfast.top)

curl -sSL https://gh.llkk.cc/https://github.com/NapNeko/napcat-pr-release/releases/download/pr-2016-3313df7/install.sh | bash

📦 查看 Release 页面
⚠️ 此为 PR 测试版本,约 5 天后会被自动清理。


🎉 所有构建均已成功完成!

点击上方下载链接获取构建产物进行测试

私聊中引用消息的 replayMsgSeq 常被解析为 0,原有三种查询方法+协议兜底必然全部失败,
reply 段被静默丢弃(NapNeko#1508 同场景)。而同一事件 records[]/sourceMsgIdInRecords 已携带
被引用消息完整记录(真实 msgId、文本),原实现仅对两个特定账号走此捷径。
现将捷径推广为 records 命中即直用 msgId,并携带 sourceMsgTextElems 文本作为可选 text 字段。
@eolynya
eolynya force-pushed the fix/private-reply-quote branch from 61c6e84 to 3313df7 Compare August 16, 2026 05:46
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown

✅ Docker 测试镜像就绪

Success


📋 构建信息

项目
📝 提交 3313df7
🔗 PR #2016
🕐 完成时间 2026-08-16 05:54:12 UTC

🚀 快速使用

拉取镜像

docker pull mlikiowa/napcat-docker:pr-2016-3313df7

启动容器

docker run -d \
  --name napcat-pr-test \
  -e NAPCAT_UID=$(id -u) \
  -e NAPCAT_GID=$(id -g) \
  -e WEBUI_TOKEN=napcat \
  -p 6099:6099 \
  -p 3000:3000 \
  -p 3001:3001 \
  -v ./napcat/config:/app/napcat/config \
  -v ./napcat/QQ:/app/.config/QQ \
  mlikiowa/napcat-docker:pr-2016-3313df7
变量 说明 默认值
WEBUI_TOKEN WebUI 登录 Token napcat
ACCOUNT 自动登录的 QQ 号 (空则手动扫码)
NAPCAT_UID / NAPCAT_GID 容器内运行用户的 UID/GID 0
MODE 预设连接模式(ws / astrbot 等) (空)

⚠️ 此为 PR 测试镜像,保留 5 天后自动清理。


🎉 Docker 测试镜像已就绪!

使用上方命令拉取镜像进行测试

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant