Skip to content

feat(group): 支持群昵称/群名片展示#23

Open
hqhq1025 wants to merge 1 commit intojackwener:mainfrom
hqhq1025:codex/group-nicknames
Open

feat(group): 支持群昵称/群名片展示#23
hqhq1025 wants to merge 1 commit intojackwener:mainfrom
hqhq1025:codex/group-nicknames

Conversation

@hqhq1025
Copy link
Copy Markdown

@hqhq1025 hqhq1025 commented May 1, 2026

背景

微信群成员在不同群里经常会设置不同的群昵称/群名片。当前 wx members 只从 contact.nick_name / contact.remark 生成 display,群聊消息里的 sender / last_sender / stats.top_senders 也只会回退到联系人名或 username。

实际使用时,这会让大群里的发言人很难对应到群内身份,比如同一个联系人在不同群里的展示名不同,或者联系人备注和群名片不是同一套命名规则。

改动

  • contact/contact.dbchat_room.ext_buffer 解析群昵称,生成 member_username -> group_nickname 映射
  • wx members --json 每个成员新增/补齐:
    • display:展示名,优先使用群昵称
    • contact_display:联系人备注或微信昵称
    • group_nickname:群昵称;本地没有记录时为空字符串
    • is_owner:是否群主
  • 群聊里的 sender / last_sender / stats.top_senders 优先使用群昵称,缺失时回退到联系人备注、微信昵称或 username
  • README.md / SKILL.md 同步说明群昵称显示规则和 members 输出字段

实现要点

  • 不新增依赖。ext_buffer 按 protobuf-like wire format 只读解析,支持 varint、fixed32、fixed64、length-delimited 字段跳过/提取
  • 解析时优先用 chatroom_member 里的当前成员 username 作为锚点,避免把其它字符串误判成成员 ID
  • members 主路径直接复用同一个 contact.db 连接读取 chatroom_memberext_buffer
  • 全局 search 会批量加载涉及群聊的昵称表,并用 Arc 在各 DB 分组任务间共享,避免重复打开 contact.db 和深拷贝大 map
  • 整个改动只读本地解密缓存,不写微信数据库,也不改变密钥/解密流程

兼容性

  • 非群聊行为不变
  • 群聊没有 ext_buffer、没有群昵称,或解析不到稳定成员映射时,会回退到原来的联系人显示名/username
  • membersdisplay 在有群昵称时会更贴近微信群内显示;需要旧联系人名语义的调用方可以读 contact_display
  • JSON 字段是向后增加;原来的 username / display / is_owner 仍保留

局限

chat_room.ext_buffer 不是公开 schema,这里按本地数据和 protobuf-like 结构做了保守解析。为了降低误判,解析会用当前群成员 username 做锚点,并过滤控制字符、超长字符串和明显 username-like 的昵称候选。

历史消息里如果 sender 已经不在当前 chatroom_member 里,仍可能只能回退到联系人名或 username。这属于本地成员表快照和历史消息之间的天然差异。

验证

项目级验证:

cargo check
bash /Users/haoqing/.agents/skills/check/scripts/run-tests.sh

结果:43 个单测全过。新增 2 个群昵称解析单测,覆盖 protobuf-like member chunk 解析和 target username 锚定。

本地真实数据抽检,不输出真实群名/昵称/消息内容:

  • 最近 500 个会话里 124 个群全部跑 wx members,0 个命令失败、0 个 schema 异常、0 个 display 优先级异常、0 个空 display
  • 124 个群共 13,631 个成员,解析到 4,478 个非空 group_nickname,93 个群有群昵称数据
  • 高覆盖的 12 个群交叉验证 members / history / search / stats,绝大多数 sender 能落回当前 members.display;少量不在成员表里的 sender 主要是历史成员/退群成员形态
  • 8 个高覆盖群重复运行 membershistory,规范化 JSON 哈希完全一致
  • 热态性能抽检:members 平均 0.055s,history -n 300 平均 0.53s,search --in 平均 0.47s,stats 平均 0.29s
  • 边界路径验证:无群昵称群正常回退到联系人名;私聊调用 members 正常拒绝;unreadnew-messages、全局 search 均能跑通

未跑完整 cross-target check:当前 macOS 本机缺 Linux/Windows C 交叉工具链,zstd-sys / libsqlite3-sys 会在 C 编译阶段卡住。本 PR 没有新增平台分支或 C 依赖。

@hqhq1025 hqhq1025 marked this pull request as ready for review May 1, 2026 16:48
@hqhq1025
Copy link
Copy Markdown
Author

hqhq1025 commented May 4, 2026

补一条本地真实数据验证,确认群昵称功能在 members 和群聊 history 两条路径上都能成立。

出于隐私原因,这里不贴真实群名、成员标识或群昵称,只保留验证方法和结论。

我在本机把群昵称分支和 appmsg 分支一起整合后,先 wx daemon stop 清掉旧后台进程,再分别执行:

wx members "<group>" --json
wx history "<group>" --json -n 8

对一个本地确实存在群昵称映射的活跃群做验证。

结果里:

  • members 输出能同时区分 contact_display / group_nickname / display 三个字段,且 display 会优先使用群昵称
  • 同一个群的最新 history 中,发送者展示已经与 members.display 对齐,显示为群昵称而不是联系人名
  • 验证过程中一度看到旧显示名,最后确认是旧 wx-daemon 仍在复用 socket,导致查询吃到了旧进程结果;停止 daemon 后重新查询即可稳定复现正确行为

也就是说,这条功能链本身是通的,之前的问题出在本地验证时复用了旧后台进程。

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