From dae94fa6526dec0c7660276a4d875cebc6e344f6 Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Sun, 10 May 2026 00:19:19 +0530 Subject: [PATCH] fix: follow-up for salvaged PR #22263 - Restore allowed_chats gate before thread_id check so ignored_threads applies universally (even to guest mentions). - Compute _message_mentions_bot once in _should_process_message to eliminate redundant second entity scan when guest_mode=true and the message does not mention the bot. - Remove redundant _is_group_chat from _is_guest_mention (caller already verified the message is a group chat). - Update _telegram_allowed_chats docstring to note guest_mode exception. - Add test coverage: bot_command entity, text_mention entity, caption_entities, and ignored_threads + guest_mode interaction. - Add nik1t7n to AUTHOR_MAP. --- gateway/platforms/telegram.py | 25 +++++++++----- scripts/release.py | 1 + tests/gateway/test_telegram_format.py | 37 +++++++++++++++++++++ tests/gateway/test_telegram_group_gating.py | 17 ++++++++++ 4 files changed, 71 insertions(+), 9 deletions(-) diff --git a/gateway/platforms/telegram.py b/gateway/platforms/telegram.py index 2aac6c706cf..191c794401d 100644 --- a/gateway/platforms/telegram.py +++ b/gateway/platforms/telegram.py @@ -3147,8 +3147,9 @@ class TelegramAdapter(BasePlatformAdapter): def _telegram_allowed_chats(self) -> set[str]: """Return the whitelist of group/supergroup chat IDs the bot will respond in. - When non-empty, group messages from chats NOT in this set are silently - ignored — even if the bot is @mentioned. DMs are never filtered. + When non-empty, group messages from chats NOT in this set are + silently ignored unless ``guest_mode`` is enabled and the bot is + explicitly @mentioned. DMs are never filtered. Empty set means no restriction (fully backward compatible). """ raw = self.config.extra.get("allowed_chats") @@ -3296,12 +3297,12 @@ class TelegramAdapter(BasePlatformAdapter): return False def _is_guest_mention(self, message: Message) -> bool: - """Return True for the narrow guest-mode bypass: group + explicit bot mention.""" - return ( - self._telegram_guest_mode() - and self._is_group_chat(message) - and self._message_mentions_bot(message) - ) + """Return True for the narrow guest-mode bypass: explicit bot mention. + + The caller (:meth:`_should_process_message`) has already verified + the message is a group chat, so that check is not repeated here. + """ + return self._telegram_guest_mode() and self._message_mentions_bot(message) def _clean_bot_trigger_text(self, text: Optional[str]) -> Optional[str]: if not text or not self._bot or not getattr(self._bot, "username", None): @@ -3344,6 +3345,9 @@ class TelegramAdapter(BasePlatformAdapter): logger.warning("[%s] Ignoring non-numeric Telegram message_thread_id: %r", self.name, thread_id) chat_id_str = str(getattr(getattr(message, "chat", None), "id", "")) + + # Resolve guest-mode mention bypass once so _message_mentions_bot + # is not called redundantly in the normal flow below. guest_mention = self._is_guest_mention(message) # allowed_chats check (whitelist). When set, group messages from chats @@ -3352,6 +3356,7 @@ class TelegramAdapter(BasePlatformAdapter): allowed = self._telegram_allowed_chats() if allowed and chat_id_str not in allowed: return guest_mention + if guest_mention: return True if chat_id_str in self._telegram_free_response_chats(): @@ -3360,7 +3365,9 @@ class TelegramAdapter(BasePlatformAdapter): return True if self._is_reply_to_bot(message): return True - if self._message_mentions_bot(message): + # When guest_mode is True, _is_guest_mention already called + # _message_mentions_bot above — skip the redundant second call. + if not self._telegram_guest_mode() and self._message_mentions_bot(message): return True return self._message_matches_mention_patterns(message) diff --git a/scripts/release.py b/scripts/release.py index f77059466f3..2011085f010 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -76,6 +76,7 @@ AUTHOR_MAP = { "ngusev@astralinux.ru": "NikolayGusev-astra", "liuguangyong201@hellobike.com": "liuguangyong93", "2093036+exiao@users.noreply.github.com": "exiao", + "20nik.nosov21@gmail.com": "nik1t7n", "thunderggnn@gmail.com": "ggnnggez", "haozhe4547@gmail.com": "ehz0ah", "kevyan1998@gmail.com": "kyan12", diff --git a/tests/gateway/test_telegram_format.py b/tests/gateway/test_telegram_format.py index dcb6568ecb7..1cd09f2e7db 100644 --- a/tests/gateway/test_telegram_format.py +++ b/tests/gateway/test_telegram_format.py @@ -827,3 +827,40 @@ class TestTelegramGuestMentionGating: ) assert adapter._should_process_message(message) is False + + def test_guest_mode_allows_bot_command_entity_outside_allowed_chats(self): + """``/cmd@botname`` is a ``bot_command`` entity, not ``mention``.""" + adapter = _guest_test_adapter(guest_mode=True, allowed_chats=["-100200"]) + text = "/status@hermes_bot" + message = _guest_group_message( + text, + chat_id=-100201, + entities=[SimpleNamespace(type="bot_command", offset=0, length=len(text))], + ) + + assert adapter._should_process_message(message) is True + + def test_guest_mode_allows_text_mention_entity_outside_allowed_chats(self): + """MessageEntity(type=text_mention) tags a user by ID — recognised as mention.""" + adapter = _guest_test_adapter(guest_mode=True, allowed_chats=["-100200"]) + message = _guest_group_message( + "hey there", + chat_id=-100201, + entities=[SimpleNamespace(type="text_mention", offset=0, length=3, user=SimpleNamespace(id=999))], + ) + + assert adapter._should_process_message(message) is True + + def test_guest_mode_allows_mention_in_caption_outside_allowed_chats(self): + """Media caption @mention should bypass allowed_chats via guest_mode.""" + adapter = _guest_test_adapter(guest_mode=True, allowed_chats=["-100200"]) + text = "look @hermes_bot" + message = _guest_group_message( + text="", + chat_id=-100201, + entities=[], + ) + message.caption = text + message.caption_entities = [_guest_mention_entity(text)] + + assert adapter._should_process_message(message) is True diff --git a/tests/gateway/test_telegram_group_gating.py b/tests/gateway/test_telegram_group_gating.py index ebf77d3ad14..282320ad10f 100644 --- a/tests/gateway/test_telegram_group_gating.py +++ b/tests/gateway/test_telegram_group_gating.py @@ -186,6 +186,23 @@ def test_guest_mode_defaults_to_false_for_allowed_chat_bypass(): assert adapter._should_process_message(mentioned) is False +def test_guest_mode_mention_dropped_in_ignored_thread(): + """A guest mention in an ignored thread is still dropped — thread gate runs first.""" + adapter = _make_adapter( + require_mention=True, + allowed_chats=["-200"], + guest_mode=True, + ignored_threads=[42], + ) + mentioned = _group_message( + "hi @hermes_bot", + chat_id=-201, + entities=[_mention_entity("hi @hermes_bot")], + thread_id=42, + ) + assert adapter._should_process_message(mentioned) is False + + def test_ignored_threads_drop_group_messages_before_other_gates(): adapter = _make_adapter(require_mention=False, free_response_chats=["-200"], ignored_threads=[31, "42"])