From bd0ba745dd016e923853575ffff45e4eed8fa482 Mon Sep 17 00:00:00 2001 From: 04cb <0x04cb@gmail.com> Date: Tue, 12 May 2026 08:38:11 +0800 Subject: [PATCH] fix(wecom): preserve real filename from SDK when payload omits name (#3737) --- nanobot/channels/wecom.py | 9 +++++---- tests/channels/test_wecom_channel.py | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/nanobot/channels/wecom.py b/nanobot/channels/wecom.py index 2dd9f8856..8fd360526 100644 --- a/nanobot/channels/wecom.py +++ b/nanobot/channels/wecom.py @@ -292,17 +292,18 @@ class WecomChannel(BaseChannel): file_info = body.get("file", {}) file_url = file_info.get("url", "") aes_key = file_info.get("aeskey", "") - file_name = file_info.get("name", "unknown") + file_name = file_info.get("name") or None if file_url and aes_key: file_path = await self._download_and_save_media(file_url, aes_key, "file", file_name) if file_path: - content_parts.append(f"[file: {file_name}]") + display_name = os.path.basename(file_path) + content_parts.append(f"[file: {display_name}]") media_paths.append(file_path) else: - content_parts.append(f"[file: {file_name}: download failed]") + content_parts.append(f"[file: {file_name or 'unknown'}: download failed]") else: - content_parts.append(f"[file: {file_name}: download failed]") + content_parts.append(f"[file: {file_name or 'unknown'}: download failed]") elif msg_type == "mixed": # Mixed content contains multiple message items diff --git a/tests/channels/test_wecom_channel.py b/tests/channels/test_wecom_channel.py index 7cb61ab82..cc0bbf29f 100644 --- a/tests/channels/test_wecom_channel.py +++ b/tests/channels/test_wecom_channel.py @@ -552,6 +552,26 @@ async def test_process_file_message() -> None: os.unlink(p) +@pytest.mark.asyncio +async def test_process_file_message_uses_sdk_filename_when_name_missing(tmp_path: Path) -> None: + """Without `file.name`, fall back to SDK fname instead of saving as 'unknown' (#3737).""" + channel = WecomChannel(WecomConfig(bot_id="b", secret="s", allow_from=["user1"]), MessageBus()) + client = _FakeWeComClient() + client.download_file.return_value = (b"%PDF-1.4 fake", "real_name.pdf") + channel._client = client + + with patch("nanobot.channels.wecom.get_media_dir", return_value=tmp_path): + frame = _FakeFrame(body={ + "msgid": "msg_file_2", "chatid": "chat1", "from": {"userid": "user1"}, + "file": {"url": "https://example.com/x", "aeskey": "key456"}, + }) + await channel._process_message(frame, "file") + + msg = await channel.bus.consume_inbound() + assert msg.media == [str(tmp_path / "real_name.pdf")] + assert "[file: real_name.pdf]" in msg.content + + @pytest.mark.asyncio async def test_process_voice_message() -> None: """Voice message: transcribed text is included in content."""