From 564b30a1c06dcf4e5c3220099b90257e602b01fb Mon Sep 17 00:00:00 2001 From: Trainingdlu Date: Sun, 9 Aug 2026 17:25:54 +0900 Subject: [PATCH] fix(telegram): use static thumbnail for animated stickers --- .../platform/sources/telegram/tg_adapter.py | 16 +++-- tests/test_telegram_adapter.py | 72 +++++++++++++++++++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/astrbot/core/platform/sources/telegram/tg_adapter.py b/astrbot/core/platform/sources/telegram/tg_adapter.py index d8efd7f5d8..ff1b05170b 100644 --- a/astrbot/core/platform/sources/telegram/tg_adapter.py +++ b/astrbot/core/platform/sources/telegram/tg_adapter.py @@ -596,10 +596,18 @@ def _apply_caption() -> None: elif update.message.sticker: # 将sticker当作图片处理 - file = await update.message.sticker.get_file() - message.message.append(Comp.Image(file=file.file_path, url=file.file_path)) - if update.message.sticker.emoji: - sticker_text = f"Sticker: {update.message.sticker.emoji}" + sticker = update.message.sticker + if sticker.is_animated or sticker.is_video: + # .tgs/.webm stickers are not bitmaps; use the static thumbnail. + file = await sticker.thumbnail.get_file() if sticker.thumbnail else None + else: + file = await sticker.get_file() + if file: + message.message.append( + Comp.Image(file=file.file_path, url=file.file_path) + ) + if sticker.emoji: + sticker_text = f"Sticker: {sticker.emoji}" message.message_str = sticker_text message.message.append(Comp.Plain(sticker_text)) diff --git a/tests/test_telegram_adapter.py b/tests/test_telegram_adapter.py index 17fe60f111..cc135578d5 100644 --- a/tests/test_telegram_adapter.py +++ b/tests/test_telegram_adapter.py @@ -215,6 +215,78 @@ async def test_telegram_video_caption_populates_message_text_and_plain(): ) +_STICKER_URL = "https://api.telegram.org/file/test/sticker_1.webp" +_ANIMATED_URL = "https://api.telegram.org/file/test/sticker_1.tgs" +_VIDEO_URL = "https://api.telegram.org/file/test/sticker_1.webm" +_THUMBNAIL_URL = "https://api.telegram.org/file/test/thumb_1.webp" + + +def _make_sticker( + file_path: str, + *, + is_animated: bool = False, + is_video: bool = False, + thumbnail_path: str | None = None, +): + sticker = create_mock_file(file_path) + sticker.emoji = "🙄" + sticker.is_animated = is_animated + sticker.is_video = is_video + sticker.thumbnail = ( + create_mock_file(thumbnail_path) if thumbnail_path is not None else None + ) + return sticker + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + ("file_path", "flags", "expected_url"), + [ + (_STICKER_URL, {}, _STICKER_URL), + (_ANIMATED_URL, {"is_animated": True}, _THUMBNAIL_URL), + (_VIDEO_URL, {"is_video": True}, _THUMBNAIL_URL), + ], + ids=["static", "animated", "video"], +) +async def test_telegram_sticker_uses_thumbnail_only_when_animated( + file_path, flags, expected_url +): + TelegramPlatformAdapter = _load_telegram_adapter() + adapter = TelegramPlatformAdapter( + make_platform_config("telegram"), + {}, + asyncio.Queue(), + ) + sticker = _make_sticker(file_path, thumbnail_path=_THUMBNAIL_URL, **flags) + update = create_mock_update(message_text=None, sticker=sticker) + + result = await adapter.convert_message(update, _build_context()) + + assert result is not None + images = [c for c in result.message if isinstance(c, Comp.Image)] + assert len(images) == 1 + assert images[0].url == expected_url + assert result.message_str == "Sticker: 🙄" + + +@pytest.mark.asyncio +async def test_telegram_animated_sticker_without_thumbnail_skips_image(): + TelegramPlatformAdapter = _load_telegram_adapter() + adapter = TelegramPlatformAdapter( + make_platform_config("telegram"), + {}, + asyncio.Queue(), + ) + sticker = _make_sticker(_ANIMATED_URL, is_animated=True, thumbnail_path=None) + update = create_mock_update(message_text=None, sticker=sticker) + + result = await adapter.convert_message(update, _build_context()) + + assert result is not None + assert not any(isinstance(c, Comp.Image) for c in result.message) + assert result.message_str == "Sticker: 🙄" + + @pytest.mark.asyncio async def test_telegram_voice_message_creates_record_component(tmp_path): TelegramPlatformAdapter = _load_telegram_adapter()