diff --git a/plugins/platforms/telegram/adapter.py b/plugins/platforms/telegram/adapter.py index 674a49d2be947..e88685dd18eac 100644 --- a/plugins/platforms/telegram/adapter.py +++ b/plugins/platforms/telegram/adapter.py @@ -4852,6 +4852,7 @@ async def edit_message( chat_id=normalize_telegram_chat_id(chat_id), message_id=int(message_id), text=content, + **self._link_preview_kwargs(), ) if _saturated_preview: self._last_overflow_preview[_preview_key] = content @@ -4864,6 +4865,7 @@ async def edit_message( message_id=int(message_id), text=formatted, parse_mode=ParseMode.MARKDOWN_V2, + **self._link_preview_kwargs(), ) except Exception as fmt_err: # "Message is not modified" is a no-op, not an error @@ -4881,6 +4883,7 @@ async def edit_message( chat_id=normalize_telegram_chat_id(chat_id), message_id=int(message_id), text=_plain, + **self._link_preview_kwargs(), ) return SendResult(success=True, message_id=message_id) except Exception as e: @@ -4909,6 +4912,7 @@ async def edit_message( chat_id=normalize_telegram_chat_id(chat_id), message_id=int(message_id), text=truncated, + **self._link_preview_kwargs(), ) self._last_overflow_preview[_preview_key] = truncated return SendResult(success=True, message_id=message_id) @@ -4934,6 +4938,7 @@ async def edit_message( chat_id=normalize_telegram_chat_id(chat_id), message_id=int(message_id), text=content, + **self._link_preview_kwargs(), ) return SendResult(success=True, message_id=message_id) except Exception as retry_err: @@ -5041,6 +5046,7 @@ async def _edit_overflow_split( message_id=int(message_id), text=formatted, parse_mode=ParseMode.MARKDOWN_V2, + **self._link_preview_kwargs(), ) except Exception as fmt_err: if "not modified" not in str(fmt_err).lower(): @@ -5053,12 +5059,14 @@ async def _edit_overflow_split( chat_id=normalize_telegram_chat_id(chat_id), message_id=int(message_id), text=_strip_mdv2(first_chunk), + **self._link_preview_kwargs(), ) else: await self._bot.edit_message_text( chat_id=normalize_telegram_chat_id(chat_id), message_id=int(message_id), text=first_chunk, + **self._link_preview_kwargs(), ) except Exception as e: err_str = str(e).lower() diff --git a/tests/gateway/test_telegram_format.py b/tests/gateway/test_telegram_format.py index ab6fb4d4996c0..e278f78205b97 100644 --- a/tests/gateway/test_telegram_format.py +++ b/tests/gateway/test_telegram_format.py @@ -486,7 +486,64 @@ async def _fake_send_message(**kwargs): class TestEditMessageStreamingSafety: + @staticmethod + def _assert_link_previews_disabled(kwargs): + assert ( + kwargs.get("disable_web_page_preview") is True + or kwargs.get("link_preview_options") is not None + ) + + @pytest.mark.asyncio + async def test_non_final_edit_disables_link_preview_when_configured(self): + adapter = TelegramAdapter( + PlatformConfig( + enabled=True, + token="fake-token", + extra={"disable_link_previews": True}, + ) + ) + adapter._bot = MagicMock() + adapter._bot.edit_message_text = AsyncMock() + + result = await adapter.edit_message( + "123", + "456", + "partial https://example.com", + finalize=False, + ) + + assert result.success is True + kwargs = adapter._bot.edit_message_text.await_args.kwargs + self._assert_link_previews_disabled(kwargs) + + @pytest.mark.asyncio + async def test_final_edit_disables_link_preview_on_markdown_and_plain_fallback( + self, + ): + adapter = TelegramAdapter( + PlatformConfig( + enabled=True, + token="fake-token", + extra={"disable_link_previews": True}, + ) + ) + adapter._bot = MagicMock() + adapter._bot.edit_message_text = AsyncMock( + side_effect=[Exception("bad markdown"), None] + ) + + result = await adapter.edit_message( + "123", + "456", + "final https://example.com **bold**", + finalize=True, + ) + assert result.success is True + first_call = adapter._bot.edit_message_text.await_args_list[0].kwargs + second_call = adapter._bot.edit_message_text.await_args_list[1].kwargs + self._assert_link_previews_disabled(first_call) + self._assert_link_previews_disabled(second_call) @pytest.mark.asyncio async def test_message_too_long_splits_into_continuations_not_silent_truncation(self): @@ -525,6 +582,35 @@ async def _fake_send(**kwargs): # Continuations were sent threaded as replies for visual grouping. assert adapter._bot.send_message.await_count == len(result.continuation_message_ids) + @pytest.mark.asyncio + async def test_message_too_long_first_chunk_edit_disables_link_preview(self): + adapter = TelegramAdapter( + PlatformConfig( + enabled=True, + token="fake-token", + extra={"disable_link_previews": True}, + ) + ) + adapter._bot = MagicMock() + adapter._bot.edit_message_text = AsyncMock() + _next_id = [1000] + + async def _fake_send(**kwargs): + _next_id[0] += 1 + return SimpleNamespace(message_id=_next_id[0]) + + adapter._bot.send_message = AsyncMock(side_effect=_fake_send) + + result = await adapter.edit_message( + "123", + "456", + "https://example.com " + ("x" * 6000), + finalize=True, + ) + + assert result.success is True + first_edit = adapter._bot.edit_message_text.await_args_list[0].kwargs + self._assert_link_previews_disabled(first_edit) @pytest.mark.asyncio async def test_mid_stream_overflow_truncates_instead_of_splitting(self):