fix(telegram): match bot mentions case-insensitively (#10399)

This commit is contained in:
Wei Chengqian
2026-10-06 12:41:02 +08:00
committed by GitHub
parent 42972e932a
commit 3861730f5a
2 changed files with 65 additions and 3 deletions
@@ -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")
+57
View File
@@ -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):