Nothing open on GitHub. Fix merged in #9530 on 14 Apr 2026. Check it covers your case.
The short answer
0open issues
0open PRs
3items grouped
- Known?
- Yes. 3 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #9530. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #9530. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These items all concern adding an ignored_threads configuration option to the Telegram gateway for filtering specific topics or threads. The group includes a feature request and related implementation pull requests.
Open issues0
Open PRs0
Fixes on record
-
#9530 feat(gateway): add ignored_threads config for Telegram
files:
gateway/config.py,gateway/platforms/telegram.py,tests/gateway/test_telegram_group_gating.pyShow the diff
-
gateway/config.py@@ -625,6 +625,11 @@ def load_gateway_config() -> GatewayConfig: if isinstance(frc, list): frc = ",".join(str(v) for v in frc) os.environ["TELEGRAM_FREE_RESPONSE_CHATS"] = str(frc) + ignored_threads = telegram_cfg.get("ignored_threads") + if ignored_threads is not None and not os.getenv("TELEGRAM_IGNORED_THREADS"): + if isinstance(ignored_threads, list): + ignored_threads = ",".join(str(v) for v in ignored_threads) + os.environ["TELEGRAM_IGNORED_THREADS"] = str(ignored_threads) if "reactions" in telegram_cfg and not os.getenv("TELEGRAM_REACTIONS"): os.environ["TELEGRAM_REACTIONS"] = str(telegram_cfg["reactions"]).lower() -
gateway/platforms/telegram.py@@ -1991,6 +1991,27 @@ def _telegram_free_response_chats(self) -> set[str]: return {str(part).strip() for part in raw if str(part).strip()} return {part.strip() for part in str(raw).split(",") if part.strip()} + def _telegram_ignored_threads(self) -> set[int]: + raw = self.config.extra.get("ignored_threads") + if raw is None: + raw = os.getenv("TELEGRAM_IGNORED_THREADS", "") + + if isinstance(raw, list): + values = raw + else: + values = str(raw).split(",") + + ignored: set[int] = set() + for value in values: + text = str(value).strip() + if not text: + continue + try: + ignored.add(int(text)) + except (TypeError, ValueError): + logger.warning("[%s] Ignoring invalid Telegram thread id: %r", self.name, value) + return ignored + def _compile_mention_patterns(self) -> List[re.Pattern]: """Compile optional regex wake-word patterns for group triggers.""" patterns = self.config.extra.get("mention_patterns") @@ -2102,6 +2123,13 @@ def _should_process_message(self, message: Message, *, is_command: bool = False) """ if not self._is_group_chat(message): return True + thread_id = getattr(message, "message_thread_id", None) + if thread_id is not None: + try: + if int(thread_id) in self._telegram_ignored_threads(): + return False + except (TypeError, ValueError): + logger.warning("[%s] Ignoring non-numeric Telegram message_thread_id: %r", self.name, thread_id) if str(getattr(getattr(message, "chat", None), "id", "")) in self._telegram_free_response_chats(): return True if not self._telegram_require_mention(): -
tests/gateway/test_telegram_group_gating.py@@ -5,7 +5,7 @@ from gateway.config import Platform, PlatformConfig, load_gateway_config -def _make_adapter(require_mention=None, free_response_chats=None, mention_patterns=None): +def _make_adapter(require_mention=None, free_response_chats=None, mention_patterns=None, ignored_threads=None): from gateway.platforms.telegram import TelegramAdapter extra = {} @@ -15,6 +15,8 @@ def _make_adapter(require_mention=None, free_response_chats=None, mention_patter extra["free_response_chats"] = free_response_chats if mention_patterns is not None: extra["mention_patterns"] = mention_patterns + if ignored_threads is not None: + extra["ignored_threads"] = ignored_threads adapter = object.__new__(TelegramAdapter) adapter.platform = Platform.TELEGRAM @@ -28,7 +30,16 @@ def _make_adapter(require_mention=None, free_response_chats=None, mention_patter return adapter -def _group_message(text="hello", *, chat_id=-100, reply_to_bot=False, entities=None, caption=None, caption_entities=None): +def _group_message( + text="hello", + *, + chat_id=-100, + thread_id=None, + reply_to_bot=False, + entities=None, + caption=None, + caption_entities=None, +): reply_to_message = None if reply_to_bot: reply_to_message = SimpleNamespace(from_user=SimpleNamespace(id=999)) @@ -37,6 +48,7 @@ def _group_message(text="hello", *, chat_id=-100, reply_to_bot=False, entities=N caption=caption, entities=entities or [], caption_entities=caption_entities or [], + message_thread_id=thread_id, chat=SimpleNamespace(id=chat_id, type="group"), reply_to_message=reply_to_message, ) @@ -69,6 +81,14 @@ def test_free_response_chats_bypass_mention_requirement(): assert adapter._should_process_message(_group_message("hello everyone", chat_id=-201)) 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"]) + + assert adapter._should_process_message(_group_message("hello everyone", chat_id=-200, thread_id=31)) is False + assert adapter._should_process_message(_group_message("hello everyone", chat_id=-200, thread_id=42)) is False + assert adapter._should_process_message(_group_message("hello everyone", chat_id=-200, thread_id=99)) is True + + def test_regex_mention_patterns_allow_custom_wake_words(): adapter = _make_adapter(require_mention=True, mention_patterns=[r"^\s*chompy\b"]) @@ -108,3 +128,23 @@ def test_config_bridges_telegram_group_settings(monkeypatch, tmp_path): assert __import__("os").environ["TELEGRAM_REQUIRE_MENTION"] == "true" assert json.loads(__import__("os").environ["TELEGRAM_MENTION_PATTERNS"]) == [r"^\s*chompy\b"] assert __import__("os").environ["TELEGRAM_FREE_RESPONSE_CHATS"] == "-123" + + +def test_config_bridges_telegram_ignored_threads(monkeypatch, tmp_path): + hermes_home = tmp_path / ".hermes" + hermes_home.mkdir() + (hermes_home / "config.yaml").write_text( + "telegram:\n" + " ignored_threads:\n" + " - 31\n" + " - \"42\"\n", + encoding="utf-8", + ) + + monkeypatch.setenv("HERMES_HOME", str(hermes_home)) + monkeypatch.delenv("TELEGRAM_IGNORED_THREADS", raising=False) + + config = load_gateway_config() + + assert config is not None + assert __import__("os").environ["TELEGRAM_IGNORED_THREADS"] == "31,42"
-
1 PR closed without merging
From the close comments: merged via another change 1
-
#9348 feat(gateway): add ignored_threads config for Telegram · merged via another change →
#9530
Closed issues · 1
- Closed#9208[Feature]: ignored_threads config for Telegram topic filtering
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Merged PRs
- #9530
- Closed issues
- 1
- Attempts
- 1 PR closed without merging
- Fix link checked
- 14 Apr 2026. This confirmation is old and may be out of date (a revert or reopen would not have invalidated it here); re-verify.