From 467f1cdbe769b5f77eac1c8ca0f225165e8d5ce3 Mon Sep 17 00:00:00 2001 From: Belugary <53219544+Belugary@users.noreply.github.com> Date: Fri, 5 Jun 2026 14:18:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B8=B2=E6=9F=93=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E9=87=8C=E7=8B=AC=E7=AB=8B=E7=9A=84=E8=A7=86=E9=A2=91=E5=8F=B7?= =?UTF-8?q?=E5=88=86=E4=BA=AB=20(appmsg=20type=3D51)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 独立的视频号分享(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) --- mcp_server.py | 19 ++++++++++ tests/test_finder_message.py | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 tests/test_finder_message.py diff --git a/mcp_server.py b/mcp_server.py index ce98920..3871843 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -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 ': <简介>` 一行。 + +fixture 全部合成,无任何真实视频号昵称 / 简介 / id。 +""" +import unittest +import xml.etree.ElementTree as ET + +import mcp_server + + +def _appmsg(inner): + return ET.fromstring(f'{inner}') + + +class FormatFinderTextTests(unittest.TestCase): + def test_nickname_and_desc(self): + appmsg = _appmsg( + '示例标题' + '示例视频号' + '这是一条示例视频简介' + ) + out = mcp_server._format_finder_message_text(appmsg, '示例标题') + self.assertEqual(out, '[视频号] 示例视频号: 这是一条示例视频简介') + + def test_nickname_only(self): + appmsg = _appmsg('示例视频号') + 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'N{long_desc}' + ) + 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('无昵称') + out = mcp_server._format_finder_message_text(appmsg, '示例标题') + self.assertEqual(out, '[视频号] 示例标题') + + def test_missing_finderfeed_and_title_bare_label(self): + appmsg = _appmsg('x') + 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 = ( + '51示例标题' + '示例视频号' + '示例简介' + ) + 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()