diff --git a/plugins/platforms/telegram/adapter.py b/plugins/platforms/telegram/adapter.py index 3a986283239c..8ab596076365 100644 --- a/plugins/platforms/telegram/adapter.py +++ b/plugins/platforms/telegram/adapter.py @@ -1482,11 +1482,12 @@ class TelegramAdapter(BasePlatformAdapter): def _content_is_pipe_table_primary(self, content: str) -> bool: """True when pipe tables are the only rich construct in *content*. - Tables are auto-routed to ``sendRichMessage`` even when the full - ``rich_messages`` opt-in is off — MarkdownV2 has no table syntax and - the legacy path rewrites them into bullet lists, which reads like a - regression when users enable Telegram Topics and expect native tables. - Task lists, ``
``, and block math still require the full opt-in. + Used downstream to decide rendering strategy *after* the + ``rich_messages`` config gate has already approved rich delivery. + MarkdownV2 has no table syntax — the legacy path rewrites them into + bullet lists — so callers may choose native table rendering when the + opt-in is active. Task lists, ``
``, and block math indicate + composite rich content and return ``False``. """ if not content or not any( _TABLE_SEPARATOR_RE.match(line) for line in content.splitlines() @@ -1504,7 +1505,6 @@ class TelegramAdapter(BasePlatformAdapter): """Whether rich delivery is allowed for this payload.""" return bool( getattr(self, "_rich_messages_enabled", True) - or self._content_is_pipe_table_primary(content) ) def _rich_eligible(self, content: str) -> bool: diff --git a/tests/gateway/test_telegram_rich_messages.py b/tests/gateway/test_telegram_rich_messages.py index eb4a5b3802d8..3588442d64aa 100644 --- a/tests/gateway/test_telegram_rich_messages.py +++ b/tests/gateway/test_telegram_rich_messages.py @@ -582,21 +582,20 @@ async def test_notification_opt_in_drops_disable_flag(): @pytest.mark.asyncio -async def test_table_only_uses_rich_when_rich_messages_opt_out(): - """Pipe tables auto-route to sendRichMessage even without the full opt-in.""" +async def test_table_only_uses_legacy_when_rich_messages_opt_out(): + """Pipe tables respect the rich_messages: false config and stay on legacy.""" adapter = _make_adapter(extra={"rich_messages": False}) result = await adapter.send("12345", TABLE_ONLY_CONTENT) assert result.success is True - api_kwargs = _rich_api_kwargs(adapter) - assert api_kwargs["rich_message"]["markdown"] == TABLE_ONLY_CONTENT - adapter._bot.send_message.assert_not_called() + adapter._bot.do_api_request.assert_not_called() + adapter._bot.send_message.assert_awaited() @pytest.mark.asyncio -async def test_table_only_uses_rich_with_default_config(): - """Default config keeps task lists on legacy but upgrades bare tables.""" +async def test_table_only_uses_legacy_with_default_config(): + """Default config (rich_messages unset → False) keeps tables on legacy path.""" config = PlatformConfig(enabled=True, token="fake-token") adapter = TelegramAdapter(config) bot = MagicMock() @@ -608,13 +607,13 @@ async def test_table_only_uses_rich_with_default_config(): result = await adapter.send("12345", TABLE_ONLY_CONTENT) assert result.success is True - bot.do_api_request.assert_awaited_once() - bot.send_message.assert_not_called() + bot.do_api_request.assert_not_called() + bot.send_message.assert_awaited() @pytest.mark.asyncio -async def test_dm_topic_resumed_send_uses_rich_for_table_without_reply_anchor(): - """Resumed/synthetic DM-topic sends route tables via direct_messages_topic_id.""" +async def test_dm_topic_resumed_send_uses_legacy_for_table_when_opt_out(): + """Resumed DM-topic sends respect rich_messages: false for tables.""" adapter = _make_adapter(extra={"rich_messages": False}) result = await adapter.send( @@ -628,14 +627,13 @@ async def test_dm_topic_resumed_send_uses_rich_for_table_without_reply_anchor(): ) assert result.success is True - api_kwargs = _rich_api_kwargs(adapter) - assert api_kwargs["direct_messages_topic_id"] == 20189 - assert "reply_parameters" not in api_kwargs - assert api_kwargs["rich_message"]["markdown"] == TABLE_ONLY_CONTENT + adapter._bot.do_api_request.assert_not_called() + adapter._bot.send_message.assert_awaited() @pytest.mark.asyncio -async def test_finalize_edit_rich_includes_forum_topic_routing(): +async def test_finalize_edit_legacy_includes_forum_topic_routing(): + """With rich_messages: false, table edits use legacy path with topic routing.""" adapter = _make_adapter(extra={"rich_messages": False}) result = await adapter.edit_message( @@ -647,9 +645,8 @@ async def test_finalize_edit_rich_includes_forum_topic_routing(): ) assert result.success is True - api_kwargs = _rich_edit_kwargs(adapter) - assert api_kwargs["message_thread_id"] == 5 - assert api_kwargs["rich_message"]["markdown"] == TABLE_ONLY_CONTENT + adapter._bot.do_api_request.assert_not_called() + adapter._bot.edit_message_text.assert_awaited() @pytest.mark.asyncio