From 0349d89defe707aadeb67c449294e497368420b9 Mon Sep 17 00:00:00 2001 From: 2977094657 <2977094657@qq.com> Date: Wed, 31 Dec 2025 11:34:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(chat):=20=E5=9B=BE=E7=89=87=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E4=BC=98=E5=85=88=E4=BD=BF=E7=94=A8=E8=B5=84=E6=BA=90?= =?UTF-8?q?=20md5=20=E4=BF=AE=E5=A4=8D=20=5Ft.dat=20=E7=BC=A9=E7=95=A5?= =?UTF-8?q?=E5=9B=BE=E4=B8=8D=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 图片消息(local_type=3)优先使用 message_resource.db 的资源 md5,避免 XML md5 与本地 *_t.dat 基名不一致导致 /api/chat/media/image 404 - 同步覆盖消息合并/导出/列表三处解析路径 refs #12 --- src/wechat_decrypt_tool/routers/chat.py | 83 ++++++++++++++++--------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/src/wechat_decrypt_tool/routers/chat.py b/src/wechat_decrypt_tool/routers/chat.py index b55db16..fb7f589 100644 --- a/src/wechat_decrypt_tool/routers/chat.py +++ b/src/wechat_decrypt_tool/routers/chat.py @@ -483,6 +483,24 @@ def _append_full_messages_from_rows( if image_md5: break + # Prefer message_resource.db md5 for local files: XML md5 frequently differs from the on-disk *.dat basename + # (especially for *_t.dat thumbnails), causing the media endpoint to 404. + if resource_conn is not None: + try: + resource_md5 = _lookup_resource_md5( + resource_conn, + resource_chat_id, + message_local_type=local_type, + server_id=int(r["server_id"] or 0), + local_id=local_id, + create_time=create_time, + ) + except Exception: + resource_md5 = "" + resource_md5 = str(resource_md5 or "").strip().lower() + if len(resource_md5) == 32 and all(c in "0123456789abcdef" for c in resource_md5): + image_md5 = resource_md5 + # Extract CDN URL (some versions store a non-HTTP "file id" string here) _cdn_url_or_id = ( _extract_xml_attr(raw_text, "cdnthumburl") @@ -501,15 +519,6 @@ def _append_full_messages_from_rows( if (not image_url) and _cdn_url_or_id: image_file_id = _cdn_url_or_id - if (not image_md5) and resource_conn is not None: - image_md5 = _lookup_resource_md5( - resource_conn, - resource_chat_id, - message_local_type=local_type, - server_id=int(r["server_id"] or 0), - local_id=local_id, - create_time=create_time, - ) content_text = "[图片]" elif local_type == 34: render_type = "voice" @@ -1317,6 +1326,24 @@ def _collect_chat_messages( if image_md5: break + # Prefer message_resource.db md5 for local files: XML md5 frequently differs from the on-disk *.dat basename + # (especially for *_t.dat thumbnails), causing the media endpoint to 404. + if resource_conn is not None: + try: + resource_md5 = _lookup_resource_md5( + resource_conn, + resource_chat_id, + message_local_type=local_type, + server_id=int(r["server_id"] or 0), + local_id=local_id, + create_time=create_time, + ) + except Exception: + resource_md5 = "" + resource_md5 = str(resource_md5 or "").strip().lower() + if len(resource_md5) == 32 and all(c in "0123456789abcdef" for c in resource_md5): + image_md5 = resource_md5 + # Extract CDN URL (some versions store a non-HTTP "file id" string here) _cdn_url_or_id = ( _extract_xml_attr(raw_text, "cdnthumburl") @@ -1332,16 +1359,6 @@ def _collect_chat_messages( image_url = _cdn_url_or_id if _cdn_url_or_id.startswith(("http://", "https://")) else "" if (not image_url) and _cdn_url_or_id: image_file_id = _cdn_url_or_id - - if (not image_md5) and resource_conn is not None: - image_md5 = _lookup_resource_md5( - resource_conn, - resource_chat_id, - message_local_type=local_type, - server_id=int(r["server_id"] or 0), - local_id=local_id, - create_time=create_time, - ) content_text = "[图片]" elif local_type == 34: render_type = "voice" @@ -1841,6 +1858,24 @@ async def list_chat_messages( if image_md5: break + # Prefer message_resource.db md5 for local files: XML md5 frequently differs from the on-disk *.dat basename + # (especially for *_t.dat thumbnails), causing the media endpoint to 404. + if resource_conn is not None: + try: + resource_md5 = _lookup_resource_md5( + resource_conn, + resource_chat_id, + message_local_type=local_type, + server_id=int(r["server_id"] or 0), + local_id=local_id, + create_time=create_time, + ) + except Exception: + resource_md5 = "" + resource_md5 = str(resource_md5 or "").strip().lower() + if len(resource_md5) == 32 and all(c in "0123456789abcdef" for c in resource_md5): + image_md5 = resource_md5 + # Extract CDN URL (some versions store a non-HTTP "file id" string here) _cdn_url_or_id = ( _extract_xml_attr(raw_text, "cdnthumburl") @@ -1856,16 +1891,6 @@ async def list_chat_messages( image_url = _cdn_url_or_id if _cdn_url_or_id.startswith(("http://", "https://")) else "" if (not image_url) and _cdn_url_or_id: image_file_id = _cdn_url_or_id - - if (not image_md5) and resource_conn is not None: - image_md5 = _lookup_resource_md5( - resource_conn, - resource_chat_id, - message_local_type=local_type, - server_id=int(r["server_id"] or 0), - local_id=local_id, - create_time=create_time, - ) content_text = "[图片]" elif local_type == 34: render_type = "voice"