From b172a6d08f50dde0ef97d8a82f39490a06cd0611 Mon Sep 17 00:00:00 2001 From: DDSRem <73049927+DDSRem@users.noreply.github.com> Date: Tue, 12 May 2026 20:57:31 +0800 Subject: [PATCH] fix(telegram): handle caption messages in group chat mention detection (#5761) * fix(telegram): handle caption messages in group chat @mention detection Telegram media messages (photos, videos, etc.) store their text in `message.caption` and mention entities in `message.caption_entities`, not `message.text` / `message.entities`. The previous code only checked `message.text`, so commands and @mentions sent with media were silently skipped with "No text..." in the debug log. Co-Authored-By: Claude Sonnet 4.6 * fix(telegram): use correct entity field pairing and UTF-16 offsets for mention detection - Explicitly pair message.entities with text messages and caption_entities with media messages, avoiding false fallthrough on empty entity lists - Decode mention text via UTF-16-LE encoding to respect Telegram's UTF-16 based offset/length values, fixing incorrect slicing when emojis are present Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 --- app/modules/telegram/telegram.py | 38 ++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/app/modules/telegram/telegram.py b/app/modules/telegram/telegram.py index ca872b82..ad55c9d8 100644 --- a/app/modules/telegram/telegram.py +++ b/app/modules/telegram/telegram.py @@ -276,9 +276,12 @@ class Telegram: logger.debug(f"处理私聊消息:用户 {message.from_user.id}") return True + # 消息内容:文本消息用 text,媒体消息的说明文字用 caption + message_text = message.text or message.caption or "" + # 群聊中的命令消息总是处理(以/开头) - if message.text and message.text.startswith("/"): - logger.debug(f"处理群聊命令消息:{message.text[:20]}...") + if message_text.startswith("/"): + logger.debug(f"处理群聊命令消息:{message_text[:20]}...") return True # 群聊中检查是否@了机器人 @@ -288,27 +291,28 @@ class Telegram: logger.debug("未获取到bot用户名,处理所有群聊消息") return True - # 检查消息文本中是否包含@bot_username - if message.text and f"@{self._bot_username}" in message.text: + # 检查消息文本或说明文字中是否包含@bot_username + if f"@{self._bot_username}" in message_text: logger.debug(f"检测到@{self._bot_username},处理群聊消息") return True - # 检查消息实体中是否有提及bot - if message.entities: - for entity in message.entities: - if entity.type == "mention": - mention_text = message.text[ - entity.offset: entity.offset + entity.length - ] - if mention_text == f"@{self._bot_username}": - logger.debug( - f"通过实体检测到@{self._bot_username},处理群聊消息" - ) - return True + # 检查消息实体(文本消息用 entities,媒体消息用 caption_entities) + entities = (message.entities if message.text is not None else message.caption_entities) or [] + for entity in entities: + if entity.type == "mention": + # Telegram offset/length 基于 UTF-16 代码单元,需用字节编码处理含 emoji 的消息 + mention_text = message_text.encode('utf-16-le')[ + entity.offset * 2: (entity.offset + entity.length) * 2 + ].decode('utf-16-le') + if mention_text == f"@{self._bot_username}": + logger.debug( + f"通过实体检测到@{self._bot_username},处理群聊消息" + ) + return True # 群聊中没有@机器人,不处理 logger.debug( - f"群聊消息未@机器人,跳过处理:{message.text[:30] if message.text else 'No text'}..." + f"群聊消息未@机器人,跳过处理:{message_text[:30] if message_text else 'No text'}..." ) return False