Skip to content

Commit 14ad7b2

Browse files
Qwintyteknium1
authored andcommitted
fix(telegram): preserve new DM topic lanes
1 parent 5b52e26 commit 14ad7b2

3 files changed

Lines changed: 22 additions & 15 deletions

File tree

gateway/run.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,13 +2272,14 @@ def _recover_telegram_topic_thread_id(
22722272
) -> Optional[str]:
22732273
"""Pin DM-topic routing to the user's last-active topic.
22742274

2275-
Telegram fragments topic-mode DMs two ways: a Reply on a message
2276-
in another topic delivers ``message_thread_id`` for *that* topic,
2277-
and ``_build_message_event`` strips the thread_id on plain replies
2278-
(#3206 — needed for non-topic users). Both route the user to the
2279-
wrong session. When topic mode is on, rewrite the thread_id to the
2280-
user's most-recent binding if the inbound id is missing/General or
2281-
not a known topic for this chat. Returns None to leave it alone.
2275+
Telegram can omit ``message_thread_id`` or surface General (``1``)
2276+
for some topic-mode DM replies. In those lobby-shaped cases, keep the
2277+
conversation attached to the user's most-recent bound topic.
2278+
2279+
Do not rewrite a non-lobby, previously-unbound thread id: a newly
2280+
created Telegram DM topic is also "unknown" until the first inbound
2281+
message is recorded, and rewriting it would send that brand-new topic's
2282+
answer into an older lane. Returns None to leave the source alone.
22822283
"""
22832284
if (
22842285
source.platform != Platform.TELEGRAM
@@ -2288,6 +2289,14 @@ def _recover_telegram_topic_thread_id(
22882289
or not self._telegram_topic_mode_enabled(source)
22892290
):
22902291
return None
2292+
inbound = str(source.thread_id or "")
2293+
is_lobby = not inbound or inbound in self._TELEGRAM_GENERAL_TOPIC_IDS
2294+
if not is_lobby:
2295+
# A non-lobby, unknown thread_id is most likely the first message in
2296+
# a brand-new Telegram DM topic. Preserve it so it can be recorded
2297+
# as a new independent lane below instead of hijacking the latest
2298+
# existing topic binding.
2299+
return None
22912300
session_db = getattr(self, "_session_db", None)
22922301
if session_db is None:
22932302
return None
@@ -2300,11 +2309,6 @@ def _recover_telegram_topic_thread_id(
23002309
return None
23012310
if not bindings:
23022311
return None
2303-
inbound = str(source.thread_id or "")
2304-
is_lobby = not inbound or inbound in self._TELEGRAM_GENERAL_TOPIC_IDS
2305-
known = {str(b.get("thread_id") or "") for b in bindings}
2306-
if not is_lobby and inbound in known:
2307-
return None
23082312
user_id = str(source.user_id)
23092313
for b in bindings: # newest-first
23102314
if str(b.get("user_id") or "") == user_id:

tests/gateway/test_telegram_thread_fallback.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ def __init__(self, media, caption=None, **kwargs):
9898
_fake_telegram_ext.CommandHandler = object
9999
_fake_telegram_ext.CallbackQueryHandler = object
100100
_fake_telegram_ext.MessageHandler = object
101+
_fake_telegram_ext.TypeHandler = object
101102
_fake_telegram_ext.ContextTypes = SimpleNamespace(DEFAULT_TYPE=object)
102103
_fake_telegram_ext.filters = object
103104
_fake_telegram_request = types.ModuleType("telegram.request")

tests/gateway/test_telegram_topic_mode.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,13 +1175,15 @@ def test_recover_returns_none_for_known_topic(tmp_path):
11751175
assert runner._recover_telegram_topic_thread_id(_make_source(thread_id="222")) is None
11761176

11771177

1178-
def test_recover_rewrites_unknown_thread_id_to_most_recent(tmp_path):
1179-
# Cross-topic Reply leak: inbound thread_id is a Telegram-only id we never bound.
1178+
def test_recover_preserves_unknown_thread_id_for_new_topic(tmp_path):
1179+
# A newly-created Telegram DM topic arrives with a real, previously-unbound
1180+
# message_thread_id. It must become its own session lane rather than being
1181+
# rewritten to whichever older topic was most recently active.
11801182
db = SessionDB(db_path=tmp_path / "state.db")
11811183
_seed_two_topic_bindings(db)
11821184
runner = _make_runner(session_db=db)
11831185

1184-
assert runner._recover_telegram_topic_thread_id(_make_source(thread_id="9999")) == "222"
1186+
assert runner._recover_telegram_topic_thread_id(_make_source(thread_id="9999")) is None
11851187

11861188

11871189
def test_recover_rewrites_lobby_thread_id_to_most_recent(tmp_path):

0 commit comments

Comments
 (0)