fix(qq): fix local file outbound and add svg as image type (#2294)

- Fix _read_media_bytes treating local paths as URLs: local file
  handling code was dead code placed after an early return inside the
  HTTP try/except block. Restructure to check for local paths (plain
  path or file:// URI) before URL validation, so files like
  /home/.../.nanobot/workspace/generated_image.svg can be read and
  sent correctly.
- Add .svg to _IMAGE_EXTS so SVG files are uploaded as file_type=1
  (image) instead of file_type=4 (file).
- Add tests for local path, file:// URI, and missing file cases.

Fixes: https://github.com/HKUDS/nanobot/pull/1667#issuecomment-4096400955

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chen Junda
2026-03-20 16:42:46 +08:00
committed by chengyongru
parent d7373db419
commit 2db2cc18f1
2 changed files with 62 additions and 31 deletions

View File

@@ -1,11 +1,12 @@
import tempfile
from pathlib import Path
from types import SimpleNamespace
import pytest
from nanobot.bus.events import OutboundMessage
from nanobot.bus.queue import MessageBus
from nanobot.channels.qq import QQChannel
from nanobot.channels.qq import QQConfig
from nanobot.channels.qq import QQChannel, QQConfig
class _FakeApi:
@@ -124,3 +125,38 @@ async def test_send_group_message_uses_markdown_when_configured() -> None:
"msg_id": "msg1",
"msg_seq": 2,
}
@pytest.mark.asyncio
async def test_read_media_bytes_local_path() -> None:
channel = QQChannel(QQConfig(app_id="app", secret="secret"), MessageBus())
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f:
f.write(b"\x89PNG\r\n")
tmp_path = f.name
data, filename = await channel._read_media_bytes(tmp_path)
assert data == b"\x89PNG\r\n"
assert filename == Path(tmp_path).name
@pytest.mark.asyncio
async def test_read_media_bytes_file_uri() -> None:
channel = QQChannel(QQConfig(app_id="app", secret="secret"), MessageBus())
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as f:
f.write(b"JFIF")
tmp_path = f.name
data, filename = await channel._read_media_bytes(f"file://{tmp_path}")
assert data == b"JFIF"
assert filename == Path(tmp_path).name
@pytest.mark.asyncio
async def test_read_media_bytes_missing_file() -> None:
channel = QQChannel(QQConfig(app_id="app", secret="secret"), MessageBus())
data, filename = await channel._read_media_bytes("/nonexistent/path/image.png")
assert data is None
assert filename is None