Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions astrbot/core/platform/sources/telegram/tg_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
72 changes: 72 additions & 0 deletions tests/test_telegram_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading