From 027e054a17e28ea9d3e2f96223c0ab0e106830f2 Mon Sep 17 00:00:00 2001 From: Tranquil-Flow Date: Sat, 25 Apr 2026 08:49:47 +1000 Subject: [PATCH] fix(gateway): route forum supergroup General topic messages by including 'supergroup' chat type (#13607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forum supergroups always have chat.type == SUPERGROUP in the Telegram API, but the General topic fallback in _build_message_event() only checked for chat_type == "group". While the current mapping happens to map SUPERGROUP to "group", this is fragile — other methods (e.g. _is_group_chat) already distinguish the two types, and any refactor to the mapping would silently break General topic routing. Extend the check to accept both "group" and "supergroup", and add a debug log when the fallback fires to aid future diagnosis. --- gateway/platforms/telegram.py | 6 +- .../gateway/test_telegram_thread_fallback.py | 80 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/gateway/platforms/telegram.py b/gateway/platforms/telegram.py index be1bf494c5..254bc23d8a 100644 --- a/gateway/platforms/telegram.py +++ b/gateway/platforms/telegram.py @@ -2989,8 +2989,12 @@ class TelegramAdapter(BasePlatformAdapter): # Resolve DM topic name and skill binding thread_id_raw = message.message_thread_id thread_id_str = str(thread_id_raw) if thread_id_raw is not None else None - if chat_type == "group" and thread_id_str is None and getattr(chat, "is_forum", False): + if chat_type in ("group", "supergroup") and thread_id_str is None and getattr(chat, "is_forum", False): thread_id_str = self._GENERAL_TOPIC_THREAD_ID + logger.debug( + "Forum %s message without thread_id — routing to General topic (thread=%s)", + chat_type, thread_id_str, + ) chat_topic = None topic_skill = None diff --git a/tests/gateway/test_telegram_thread_fallback.py b/tests/gateway/test_telegram_thread_fallback.py index 4930467bfe..84a5fca735 100644 --- a/tests/gateway/test_telegram_thread_fallback.py +++ b/tests/gateway/test_telegram_thread_fallback.py @@ -132,6 +132,86 @@ def test_forum_general_topic_without_message_thread_id_keeps_thread_context(): assert event.source.thread_id == "1" +def test_forum_group_general_topic_fallback(): + """Forum GROUP chat without thread_id should also fall back to General topic.""" + from gateway.platforms import telegram as telegram_mod + + adapter = _make_adapter() + message = SimpleNamespace( + text="hello from group forum General", + caption=None, + chat=SimpleNamespace( + id=-100999, + type=telegram_mod.ChatType.GROUP, + is_forum=True, + title="Group forum", + ), + from_user=SimpleNamespace(id=789, full_name="Bob"), + message_thread_id=None, + reply_to_message=None, + message_id=20, + date=None, + ) + + event = adapter._build_message_event(message, msg_type=SimpleNamespace(value="text")) + + assert event.source.chat_id == "-100999" + assert event.source.chat_type == "group" + assert event.source.thread_id == "1" + + +def test_forum_supergroup_with_thread_id_preserves_it(): + """Forum supergroup messages WITH a thread_id should keep the original value.""" + from gateway.platforms import telegram as telegram_mod + + adapter = _make_adapter() + message = SimpleNamespace( + text="hello from a named topic", + caption=None, + chat=SimpleNamespace( + id=-100123, + type=telegram_mod.ChatType.SUPERGROUP, + is_forum=True, + title="Forum group", + ), + from_user=SimpleNamespace(id=456, full_name="Alice"), + message_thread_id=42, + reply_to_message=None, + message_id=30, + date=None, + ) + + event = adapter._build_message_event(message, msg_type=SimpleNamespace(value="text")) + + assert event.source.thread_id == "42" + + +def test_non_forum_supergroup_without_thread_id_stays_none(): + """Non-forum supergroup messages without thread_id should NOT get General topic.""" + from gateway.platforms import telegram as telegram_mod + + adapter = _make_adapter() + message = SimpleNamespace( + text="hello from a regular supergroup", + caption=None, + chat=SimpleNamespace( + id=-100555, + type=telegram_mod.ChatType.SUPERGROUP, + is_forum=False, + title="Regular supergroup", + ), + from_user=SimpleNamespace(id=456, full_name="Alice"), + message_thread_id=None, + reply_to_message=None, + message_id=40, + date=None, + ) + + event = adapter._build_message_event(message, msg_type=SimpleNamespace(value="text")) + + assert event.source.thread_id is None + + @pytest.mark.asyncio async def test_send_omits_general_topic_thread_id(): """Telegram sends to forum General should omit message_thread_id=1."""