mirror of
https://github.com/LifeArchiveProject/WeChatDataAnalysis.git
synced 2026-06-18 15:54:08 +08:00
64e8cf6718
补充 Finder/视频号类型 app message 的 objectId、objectNonceId 解析 在聊天消息接口、搜索结果和导出链路中透传上述字段 前端消息归一化增加 objectId、objectNonceId 字段 新增对应测试,覆盖 type=51 场景
194 lines
9.4 KiB
Python
194 lines
9.4 KiB
Python
import sys
|
||
import unittest
|
||
from pathlib import Path
|
||
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
sys.path.insert(0, str(ROOT / "src"))
|
||
|
||
from wechat_decrypt_tool.chat_helpers import _parse_app_message
|
||
|
||
|
||
class TestParseAppMessage(unittest.TestCase):
|
||
def test_mini_program_type_33_parses_as_link(self):
|
||
# 小程序分享是 appmsg type=33/36。部分 payload 会在 <weappinfo> 内嵌一个 <type>0</type>,
|
||
# 并且出现在外层 <type>33</type> 之前,因此解析必须避免被嵌套 <type> 误导。
|
||
raw_text = (
|
||
"<msg><appmsg appid='' sdkver='0'>"
|
||
"<title>锦城苑房源详情分享给你,点击查看哦~</title>"
|
||
"<des></des>"
|
||
"<weappinfo>"
|
||
"<type>0</type>"
|
||
"<username><![CDATA[gh_xxx@app]]></username>"
|
||
"<weappiconurl><![CDATA[https://example.com/icon.png]]></weappiconurl>"
|
||
"</weappinfo>"
|
||
"<type>33</type>"
|
||
"<url></url>"
|
||
"<thumburl>https://example.com/thumb.jpg</thumburl>"
|
||
"<sourcedisplayname><![CDATA[成都购房通]]></sourcedisplayname>"
|
||
"</appmsg></msg>"
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("renderType"), "link")
|
||
self.assertEqual(parsed.get("linkType"), "mini_program")
|
||
self.assertEqual(parsed.get("title"), "锦城苑房源详情分享给你,点击查看哦~")
|
||
self.assertEqual(parsed.get("from"), "成都购房通")
|
||
self.assertEqual(parsed.get("fromUsername"), "gh_xxx@app")
|
||
self.assertEqual(parsed.get("thumbUrl"), "https://example.com/thumb.jpg")
|
||
|
||
def test_quote_type_57_nested_refermsg_uses_inner_title(self):
|
||
raw_text = (
|
||
'<msg><appmsg appid="" sdkver="0">'
|
||
'<title>一松一紧</title><des></des><action></action><type>57</type>'
|
||
'<showtype>0</showtype><soundtype>0</soundtype><mediatagname></mediatagname>'
|
||
'<messageext></messageext><messageaction></messageaction><content></content>'
|
||
'<url></url><appattach><totallen>0</totallen><attachid></attachid><fileext></fileext></appattach>'
|
||
'<extinfo></extinfo><sourceusername></sourceusername><sourcedisplayname></sourcedisplayname>'
|
||
'<commenturl></commenturl><refermsg>'
|
||
'<type>57</type><svrid>1173057991425172913</svrid>'
|
||
'<fromusr>44372432598@chatroom</fromusr><chatusr>44372432598@chatroom</chatusr>'
|
||
'<displayname><![CDATA[ㅤ磁父]]></displayname>'
|
||
'<content><![CDATA[<msg><appmsg appid="" sdkver="0"><title>那里紧?哪里张?</title><des></des>'
|
||
'<action></action><type>57</type><showtype>0</showtype><soundtype>0</soundtype>'
|
||
'<mediatagname></mediatagname><messageext></messageext><messageaction></messageaction>'
|
||
'<content></content><url></url><appattach><totallen>0</totallen><attachid></attachid>'
|
||
'<fileext></fileext></appattach><extinfo></extinfo><sourceusername></sourceusername>'
|
||
'<sourcedisplayname></sourcedisplayname><commenturl></commenturl></appmsg></msg>]]></content>'
|
||
'</refermsg></appmsg></msg>'
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("renderType"), "quote")
|
||
self.assertEqual(parsed.get("content"), "一松一紧")
|
||
self.assertEqual(parsed.get("quoteType"), "57")
|
||
self.assertEqual(parsed.get("quoteContent"), "那里紧?哪里张?")
|
||
|
||
def test_quote_type_57_plain_text_refermsg_keeps_text(self):
|
||
raw_text = (
|
||
'<msg><appmsg appid="" sdkver="0">'
|
||
'<title>回复</title><type>57</type>'
|
||
'<refermsg><type>57</type><content><![CDATA[普通文本引用]]></content></refermsg>'
|
||
'</appmsg></msg>'
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("renderType"), "quote")
|
||
self.assertEqual(parsed.get("quoteContent"), "普通文本引用")
|
||
|
||
def test_quote_type_49_nested_xml_refermsg_uses_inner_title(self):
|
||
raw_text = (
|
||
'<msg><appmsg appid="" sdkver="0">'
|
||
'<title>这种傻逼公众号怎么还在看</title><type>57</type>'
|
||
'<refermsg><type>49</type><displayname><![CDATA[水豚喧喧]]></displayname>'
|
||
'<content><![CDATA[wxid_gryaI8aopjio22: <?xml version="1.0"?><msg><appmsg appid="" sdkver="0">'
|
||
'<title>为自己的美丽漂亮善良知性发声😊</title><des></des>'
|
||
'<type>5</type><url>https://mp.weixin.qq.com/s/example</url>'
|
||
'<thumburl>https://mmbiz.qpic.cn/some-thumb.jpg</thumburl>'
|
||
'</appmsg></msg>]]></content></refermsg></appmsg></msg>'
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("renderType"), "quote")
|
||
self.assertEqual(parsed.get("quoteType"), "49")
|
||
self.assertEqual(parsed.get("quoteTitle"), "水豚喧喧")
|
||
self.assertEqual(parsed.get("quoteContent"), "[链接] 为自己的美丽漂亮善良知性发声😊")
|
||
self.assertEqual(parsed.get("quoteThumbUrl"), "https://mmbiz.qpic.cn/some-thumb.jpg")
|
||
|
||
def test_public_account_link_exposes_link_type_and_style(self):
|
||
raw_text = (
|
||
'<msg><appmsg appid="" sdkver="0">'
|
||
'<title>为自己的美丽漂亮善良知性发声😊</title>'
|
||
'<des>#日常穿搭灵感 #白色蕾丝裙穿搭 #知性美女</des>'
|
||
'<type>5</type>'
|
||
'<url>http://mp.weixin.qq.com/s?__biz=xx&mid=1</url>'
|
||
'<thumburl>http://mmbiz.qpic.cn/abc/640?wx_fmt=jpeg</thumburl>'
|
||
'<sourceusername>gh_0cef8eaa987d</sourceusername>'
|
||
'<sourcedisplayname>草莓不甜芒果甜</sourcedisplayname>'
|
||
'</appmsg></msg>'
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("renderType"), "link")
|
||
self.assertEqual(parsed.get("linkType"), "official_article")
|
||
self.assertEqual(parsed.get("linkStyle"), "cover")
|
||
|
||
def test_finder_type_51_uses_nested_desc_and_cover(self):
|
||
raw_text = (
|
||
'<msg><appmsg appid="" sdkver="0">'
|
||
'<title>当前版本不支持展示该内容,请升级至最新版本。</title>'
|
||
'<des></des>'
|
||
'<type>51</type>'
|
||
'<url></url>'
|
||
'<finderFeed>'
|
||
'<nickname><![CDATA[央视新闻]]></nickname>'
|
||
'<username><![CDATA[finder_cctv_news]]></username>'
|
||
'<desc><![CDATA[微信视频号全金融行业今公布发布]]></desc>'
|
||
'<mediaList><media>'
|
||
'<coverUrl><![CDATA[https://finder.video.qq.com/cover.jpg]]></coverUrl>'
|
||
'<url><![CDATA[https://channels.weixin.qq.com/web/pages/feed?feedid=abc]]></url>'
|
||
'</media></mediaList>'
|
||
'</finderFeed>'
|
||
'</appmsg></msg>'
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("renderType"), "link")
|
||
self.assertEqual(parsed.get("linkType"), "finder")
|
||
self.assertEqual(parsed.get("title"), "微信视频号全金融行业今公布发布")
|
||
self.assertEqual(parsed.get("content"), "微信视频号全金融行业今公布发布")
|
||
self.assertEqual(parsed.get("from"), "央视新闻")
|
||
self.assertEqual(parsed.get("fromUsername"), "finder_cctv_news")
|
||
self.assertEqual(parsed.get("thumbUrl"), "https://finder.video.qq.com/cover.jpg")
|
||
self.assertEqual(parsed.get("url"), "https://channels.weixin.qq.com/web/pages/feed?feedid=abc")
|
||
|
||
def test_finder_type_51_exposes_object_fields(self):
|
||
raw_text = (
|
||
'<msg><appmsg appid="" sdkver="0">'
|
||
'<title>当前版本不支持展示该内容,请升级至最新版本。</title>'
|
||
'<des></des>'
|
||
'<type>51</type>'
|
||
'<finderFeed>'
|
||
'<nickname><![CDATA[央视新闻]]></nickname>'
|
||
'<objectId><![CDATA[1234567890]]></objectId>'
|
||
'<objectNonceId><![CDATA[nonce-abc]]></objectNonceId>'
|
||
'</finderFeed>'
|
||
'</appmsg></msg>'
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("linkType"), "finder")
|
||
self.assertEqual(parsed.get("objectId"), "1234567890")
|
||
self.assertEqual(parsed.get("objectNonceId"), "nonce-abc")
|
||
|
||
def test_quote_type_5_nested_xml_refermsg_uses_inner_title(self):
|
||
raw_text = (
|
||
'<msg><appmsg appid="" sdkver="0">'
|
||
'<title>这个年龄有点大啊</title><type>57</type>'
|
||
'<refermsg><type>5</type><displayname><![CDATA[水豚噜噜]]></displayname>'
|
||
'<content><![CDATA[wxid_qrval8aopiio22:\n<?xml version="1.0"?>\n<msg><appmsg appid="" sdkver="0">'
|
||
'<title>谁说冬天不能穿裙子?</title><des></des><type>5</type>'
|
||
'<thumburl>https://mmbiz.qpic.cn/some-thumb2.jpg</thumburl>'
|
||
'<url>https://mp.weixin.qq.com/s/example2</url>'
|
||
'</appmsg></msg>]]></content></refermsg></appmsg></msg>'
|
||
)
|
||
|
||
parsed = _parse_app_message(raw_text)
|
||
|
||
self.assertEqual(parsed.get("renderType"), "quote")
|
||
self.assertEqual(parsed.get("quoteType"), "5")
|
||
self.assertEqual(parsed.get("quoteTitle"), "水豚噜噜")
|
||
self.assertEqual(parsed.get("quoteContent"), "[链接] 谁说冬天不能穿裙子?")
|
||
self.assertEqual(parsed.get("quoteThumbUrl"), "https://mmbiz.qpic.cn/some-thumb2.jpg")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|