feat: 渲染聊天里独立的视频号分享 (appmsg type=51)

独立的视频号分享(appmsg type=51)在 get_chat_history 里走 generic 分支,渲染成
无信息的 [链接/文件];而同一条视频号被引用回复(type=57 → inner 51)嵌套时反而有
[视频号] 标签(_INNER_APPMSG_TYPE_LABEL['51']),两条路径体验不一致。

新增 _format_finder_message_text(appmsg, title),把合并转发记录
_format_record_dataitem 的 datatype == '22' 已用的 finderFeed 读法接到独立消息
dispatch:

- [视频号] <昵称>: <简介>(简介截断 80 字符,与 datatype==22 行为一致)
- 缺 nickname → [视频号] {title} 兜底

在 _format_app_message_text 的 app_type == 5 之后接 app_type == 51 分支。只用上游
原生 _collapse_text + findtext,不引入新依赖。

新增 tests/test_finder_message.py(6 个用例):昵称+简介、仅昵称、简介截断、缺昵称
fallback、bare label、dispatch 端到端。fixture 全部合成。

只碰聊天侧 mcp_server.py 渲染分支。不碰 sns / 朋友圈代码路径。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BelugaryandClaude Opus 4.8 authored and ylytdeng committed 2026-06-10 11:14:15 +08:00
1 parent f80bdada3f
commit 467f1cdbe7
2 files changed
+87

No files matched your search

+19
View File
@@ -909,6 +909,8 @@ def _format_app_message_text(content, local_type, is_group, chat_username, chat_
return f"[文件] {title}" if title else "[文件]"
if app_type == 5:
return f"[链接] {title}" if title else "[链接]"
if app_type == 51:
return _format_finder_message_text(appmsg, title)
if app_type in (33, 36, 44):
return f"[小程序] {title}" if title else "[小程序]"
if title:
@@ -1261,6 +1263,23 @@ def _format_redpacket_message_text(appmsg, title):
return ' '.join(parts)
def _format_finder_message_text(appmsg, title):
"""渲染视频号分享(appmsg type=51)一行展示文本。
现状:独立视频号分享走 _format_app_message_text 的 generic 分支,渲染成无信息的
[链接/文件];而同一条视频号被引用回复嵌套时反而有 [视频号] 标签
(见 _INNER_APPMSG_TYPE_LABEL['51']),两条路径体验不一致。本 helper 把合并转发
记录 _format_record_dataitem 的 datatype==22 已用的 finderFeed 读法接到独立消息。
fallback:缺 nickname → [视频号] {title};title 也缺 → [视频号]。
"""
nickname = _collapse_text(appmsg.findtext('finderFeed/nickname') or '')
desc = _collapse_text(appmsg.findtext('finderFeed/desc') or '')
if nickname:
return f"[视频号] {nickname}: {desc[:80]}" if desc else f"[视频号] {nickname}"
return f"[视频号] {title}" if title else "[视频号]"
def _format_voip_message_text(content):
if not content or '<voip' not in content:
return None
+68
View File
@@ -0,0 +1,68 @@
"""测试 appmsg type=51(视频号分享)解析与渲染。
此前独立视频号分享走 _format_app_message_text 的 generic 分支,渲染成无信息的
`[链接/文件]`;而同一条视频号被引用回复嵌套时反而有 [视频号] 标签,两条路径
体验不一致。本组用例钉住新行为:`[视频号] <昵称>: <简介>` 一行。
fixture 全部合成,无任何真实视频号昵称 / 简介 / id。
"""
import unittest
import xml.etree.ElementTree as ET
import mcp_server
def _appmsg(inner):
return ET.fromstring(f'<appmsg>{inner}</appmsg>')
class FormatFinderTextTests(unittest.TestCase):
def test_nickname_and_desc(self):
appmsg = _appmsg(
'<title>示例标题</title>'
'<finderFeed><nickname>示例视频号</nickname>'
'<desc>这是一条示例视频简介</desc></finderFeed>'
)
out = mcp_server._format_finder_message_text(appmsg, '示例标题')
self.assertEqual(out, '[视频号] 示例视频号: 这是一条示例视频简介')
def test_nickname_only(self):
appmsg = _appmsg('<finderFeed><nickname>示例视频号</nickname></finderFeed>')
out = mcp_server._format_finder_message_text(appmsg, 'ignored')
self.assertEqual(out, '[视频号] 示例视频号')
def test_desc_truncated_to_80_chars(self):
long_desc = '甲' * 100
appmsg = _appmsg(
f'<finderFeed><nickname>N</nickname><desc>{long_desc}</desc></finderFeed>'
)
out = mcp_server._format_finder_message_text(appmsg, 't')
self.assertEqual(out, '[视频号] N: ' + '甲' * 80)
def test_missing_nickname_falls_back_to_title(self):
appmsg = _appmsg('<finderFeed><desc>无昵称</desc></finderFeed>')
out = mcp_server._format_finder_message_text(appmsg, '示例标题')
self.assertEqual(out, '[视频号] 示例标题')
def test_missing_finderfeed_and_title_bare_label(self):
appmsg = _appmsg('<des>x</des>')
self.assertEqual(mcp_server._format_finder_message_text(appmsg, ''), '[视频号]')
def test_type51_dispatches_to_helper(self):
# _format_app_message_text 的 type=51 分支必须走 _format_finder_message_text,
# 不再掉进 generic [链接/文件] 兜底。
content = (
'<msg><appmsg><type>51</type><title>示例标题</title>'
'<finderFeed><nickname>示例视频号</nickname>'
'<desc>示例简介</desc></finderFeed></appmsg></msg>'
)
out = mcp_server._format_app_message_text(
content, local_type=49, is_group=False,
chat_username='wxid_synth_a', chat_display_name='Sender A', names={},
)
self.assertEqual(out, '[视频号] 示例视频号: 示例简介')
self.assertNotIn('链接/文件', out)
if __name__ == '__main__':
unittest.main()