diff --git a/astrbot/core/platform/sources/telegram/tg_adapter.py b/astrbot/core/platform/sources/telegram/tg_adapter.py index 8ee361d77..342b61614 100644 --- a/astrbot/core/platform/sources/telegram/tg_adapter.py +++ b/astrbot/core/platform/sources/telegram/tg_adapter.py @@ -473,7 +473,10 @@ class TelegramPlatformAdapter(Platform): for entity in update.message.caption_entities: if entity.type == "mention": name = update.message.parse_caption_entity(entity)[1:] - message.message.append(Comp.At(qq=name, name=name)) + mention = Comp.At(qq=name, name=name) + if name.lower() == message.self_id.lower(): + mention.qq = message.self_id + message.message.append(mention) message = AstrBotMessage() message.session_id = str(update.message.chat.id) @@ -604,10 +607,12 @@ class TelegramPlatformAdapter(Platform): for entity in update.message.entities: if entity.type == "mention": name = update.message.parse_entity(entity)[1:] - message.message.append(Comp.At(qq=name, name=name)) - if name.lower() == context.bot.username.lower(): + mention = Comp.At(qq=name, name=name) + if name.lower() == message.self_id.lower(): + mention.qq = message.self_id text_parts.append(text_utf16[last_end : entity.offset * 2]) last_end = (entity.offset + entity.length) * 2 + message.message.append(mention) text_parts.append(text_utf16[last_end:]) plain_text = b"".join(text_parts).decode("utf-16-le") diff --git a/tests/test_telegram_adapter.py b/tests/test_telegram_adapter.py index fca7866be..28f2a4551 100644 --- a/tests/test_telegram_adapter.py +++ b/tests/test_telegram_adapter.py @@ -554,6 +554,63 @@ async def test_telegram_mentions_use_original_utf16_offsets( ) +@pytest.mark.asyncio +@pytest.mark.parametrize("in_caption", [False, True], ids=["text", "photo-caption"]) +@pytest.mark.parametrize( + "name", ["ExampleBot", "examplebot", "EXAMPLEBOT", "eXaMpLeBoT", "OtherBot"] +) +async def test_telegram_self_mention_is_case_insensitive(in_caption, name): + """Normalize self-mention IDs while preserving the original display name. + + Args: + in_caption: Whether the mention appears in a photo caption. + name: Username spelling used in the incoming mention. + """ + adapter = _load_telegram_adapter()( + make_platform_config("telegram"), {}, asyncio.Queue() + ) + context = _build_context() + context.bot.username = "ExampleBot" + text = f"😀 @{name} hello" + sdk_message = Message.de_json( + { + "message_id": 1, + "date": 0, + "chat": {"id": -100123, "type": "supergroup"}, + "caption" if in_caption else "text": text, + "caption_entities" if in_caption else "entities": [ + {"type": "mention", "offset": 3, "length": len(name) + 1} + ], + }, + bot=None, + ) + if in_caption: + update = create_mock_update( + message_text=None, + chat_type="supergroup", + photo=[create_mock_file()], + caption=text, + caption_entities=sdk_message.caption_entities, + ) + update.message.parse_caption_entity = sdk_message.parse_caption_entity + else: + update = create_mock_update( + message_text=text, chat_type="supergroup", entities=sdk_message.entities + ) + update.message.parse_entity = sdk_message.parse_entity + + result = await adapter.convert_message(update, context) + + assert result is not None + mentions = [part for part in result.message if isinstance(part, Comp.At)] + assert len(mentions) == 1 + is_self = name != "OtherBot" + assert mentions[0].qq == ("ExampleBot" if is_self else name) + assert mentions[0].name == name + assert (mentions[0].qq == result.self_id) is is_self + assert result.message_str == (text if in_caption or not is_self else "😀 hello") + + @pytest.mark.asyncio @pytest.mark.parametrize("media_type", ["photo", "document", "video"]) async def test_telegram_media_caption_mention_uses_utf16_offsets(media_type):