diff --git a/plugins/platforms/telegram/adapter.py b/plugins/platforms/telegram/adapter.py index 239b26de171..40f1ab09423 100644 --- a/plugins/platforms/telegram/adapter.py +++ b/plugins/platforms/telegram/adapter.py @@ -902,13 +902,6 @@ class TelegramAdapter(BasePlatformAdapter): reply_to = metadata.get("telegram_reply_to_message_id") return int(reply_to) if reply_to is not None else None - @staticmethod - def _looks_like_private_chat_id(chat_id: str) -> bool: - try: - return int(chat_id) > 0 - except (TypeError, ValueError): - return False - @classmethod def _is_private_dm_topic_send( cls, @@ -926,10 +919,8 @@ class TelegramAdapter(BasePlatformAdapter): return False return bool( thread_id - and ( - metadata and metadata.get("telegram_dm_topic_reply_fallback") - or cls._looks_like_private_chat_id(chat_id) - ) + and metadata + and metadata.get("telegram_dm_topic_reply_fallback") ) @staticmethod diff --git a/tests/gateway/test_telegram_thread_fallback.py b/tests/gateway/test_telegram_thread_fallback.py index 3f5b7da420c..41dbcc001d3 100644 --- a/tests/gateway/test_telegram_thread_fallback.py +++ b/tests/gateway/test_telegram_thread_fallback.py @@ -458,6 +458,81 @@ async def test_send_private_dm_topic_uses_direct_messages_topic_id(): assert call_log[0]["direct_messages_topic_id"] == 99999 +@pytest.mark.asyncio +async def test_private_chat_explicit_thread_id_uses_message_thread_id_without_anchor(): + """Cron-resolved private-chat forum topics route by message_thread_id.""" + adapter = _make_adapter() + call_log = [] + + async def mock_send_message(**kwargs): + call_log.append(dict(kwargs)) + return SimpleNamespace(message_id=270454) + + adapter._bot = SimpleNamespace(send_message=mock_send_message) + + result = await adapter.send( + chat_id="775566675", + content="cron topic delivery", + metadata={"thread_id": "270453"}, + ) + + assert result.success is True + assert call_log[0]["reply_to_message_id"] is None + assert call_log[0]["message_thread_id"] == 270453 + assert "direct_messages_topic_id" not in call_log[0] + + +@pytest.mark.asyncio +async def test_private_chat_explicit_direct_messages_topic_id_uses_direct_topic_without_anchor(): + """Explicit Bot API Direct Messages topics do not need a reply anchor.""" + adapter = _make_adapter() + call_log = [] + + async def mock_send_message(**kwargs): + call_log.append(dict(kwargs)) + return SimpleNamespace(message_id=270454) + + adapter._bot = SimpleNamespace(send_message=mock_send_message) + + result = await adapter.send( + chat_id="775566675", + content="direct topic delivery", + metadata={"direct_messages_topic_id": "270453"}, + ) + + assert result.success is True + assert call_log[0]["reply_to_message_id"] is None + assert call_log[0]["message_thread_id"] is None + assert call_log[0]["direct_messages_topic_id"] == 270453 + + +@pytest.mark.asyncio +async def test_private_dm_topic_reply_fallback_without_anchor_fails_loud(): + """Anchor-required DM topic fallback must not silently send elsewhere.""" + adapter = _make_adapter() + call_log = [] + + async def mock_send_message(**kwargs): + call_log.append(dict(kwargs)) + return SimpleNamespace(message_id=270454) + + adapter._bot = SimpleNamespace(send_message=mock_send_message) + + result = await adapter.send( + chat_id="775566675", + content="missing anchor", + metadata={ + "thread_id": "270453", + "telegram_dm_topic_reply_fallback": True, + }, + ) + + assert result.success is False + assert result.retryable is False + assert result.error == adapter._dm_topic_missing_anchor_error() + assert call_log == [] + + def test_base_gateway_metadata_marks_telegram_dm_topics_as_reply_fallback(): source = SimpleNamespace( platform=Platform.TELEGRAM,