From 474f9c96938e7481a342ff94cfe233243d0665bf Mon Sep 17 00:00:00 2001 From: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:32:39 +0200 Subject: [PATCH] Make `Message.reply_*` Reply in the Same Topic by Default (#4170) Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> --- telegram/_message.py | 231 ++++++++++++++++++++++++++++++++++++++---- tests/test_message.py | 150 +++++++++++++++++++++++++++ 2 files changed, 362 insertions(+), 19 deletions(-) diff --git a/telegram/_message.py b/telegram/_message.py index 5e2f60247..18ee981c2 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -824,6 +824,9 @@ class Message(MaybeInaccessibleMessage): .. |blockquote_no_md1_support| replace:: Since block quotation entities are not supported by :attr:`~telegram.constants.ParseMode.MARKDOWN`, this method now raises a :exc:`ValueError` when encountering a block quotation. + + .. |reply_same_thread| replace:: If :paramref:`message_thread_id` is not provided, + this will reply to the same thread (topic) of the original message. """ # fmt: on @@ -1535,6 +1538,15 @@ class Message(MaybeInaccessibleMessage): return chat_id, effective_reply_parameters + def _parse_message_thread_id( + self, + chat_id: Union[str, int], + message_thread_id: Optional[int] = None, + ) -> Optional[int]: + return message_thread_id or ( + self.message_thread_id if chat_id in {self.chat_id, self.chat.username} else None + ) + async def reply_text( self, text: str, @@ -1560,10 +1572,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_message(update.effective_message.chat_id, *args, **kwargs) + await bot.send_message( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_message`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -1581,6 +1601,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_message( chat_id=chat_id, text=text, @@ -1627,6 +1648,7 @@ class Message(MaybeInaccessibleMessage): await bot.send_message( update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, parse_mode=ParseMode.MARKDOWN, *args, **kwargs, @@ -1636,6 +1658,9 @@ class Message(MaybeInaccessibleMessage): For the documentation of the arguments, please see :meth:`telegram.Bot.send_message`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Note: :tg-const:`telegram.constants.ParseMode.MARKDOWN` is a legacy mode, retained by Telegram for backward compatibility. You should use :meth:`reply_markdown_v2` instead. @@ -1656,6 +1681,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_message( chat_id=chat_id, text=text, @@ -1702,6 +1728,7 @@ class Message(MaybeInaccessibleMessage): await bot.send_message( update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, parse_mode=ParseMode.MARKDOWN_V2, *args, **kwargs, @@ -1711,6 +1738,9 @@ class Message(MaybeInaccessibleMessage): For the documentation of the arguments, please see :meth:`telegram.Bot.send_message`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -1727,6 +1757,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_message( chat_id=chat_id, text=text, @@ -1773,6 +1804,7 @@ class Message(MaybeInaccessibleMessage): await bot.send_message( update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, parse_mode=ParseMode.HTML, *args, **kwargs, @@ -1782,6 +1814,9 @@ class Message(MaybeInaccessibleMessage): For the documentation of the arguments, please see :meth:`telegram.Bot.send_message`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -1798,6 +1833,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_message( chat_id=chat_id, text=text, @@ -1843,10 +1879,18 @@ class Message(MaybeInaccessibleMessage): ) -> Tuple["Message", ...]: """Shortcut for:: - await bot.send_media_group(update.effective_message.chat_id, *args, **kwargs) + await bot.send_media_group( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_media_group`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -1866,6 +1910,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_media_group( chat_id=chat_id, media=media, @@ -1910,10 +1955,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_photo(update.effective_message.chat_id, *args, **kwargs) + await bot.send_photo( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_photo`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -1931,6 +1984,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_photo( chat_id=chat_id, photo=photo, @@ -1981,10 +2035,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_audio(update.effective_message.chat_id, *args, **kwargs) + await bot.send_audio( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_audio`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2002,6 +2064,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_audio( chat_id=chat_id, audio=audio, @@ -2053,10 +2116,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_document(update.effective_message.chat_id, *args, **kwargs) + await bot.send_document( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_document`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2074,6 +2145,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_document( chat_id=chat_id, document=document, @@ -2126,10 +2198,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_animation(update.effective_message.chat_id, *args, **kwargs) + await bot.send_animation( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_animation`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2147,6 +2227,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_animation( chat_id=chat_id, animation=animation, @@ -2194,10 +2275,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_sticker(update.effective_message.chat_id, *args, **kwargs) + await bot.send_sticker( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_sticker`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2215,6 +2304,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_sticker( chat_id=chat_id, sticker=sticker, @@ -2263,10 +2353,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_video(update.effective_message.chat_id, *args, **kwargs) + await bot.send_video( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_video`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2284,6 +2382,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_video( chat_id=chat_id, video=video, @@ -2335,10 +2434,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_video_note(update.effective_message.chat_id, *args, **kwargs) + await bot.send_video_note( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_video_note`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2356,6 +2463,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_video_note( chat_id=chat_id, video_note=video_note, @@ -2402,10 +2510,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_voice(update.effective_message.chat_id, *args, **kwargs) + await bot.send_voice( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_voice`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2423,6 +2539,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_voice( chat_id=chat_id, voice=voice, @@ -2471,10 +2588,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_location(update.effective_message.chat_id, *args, **kwargs) + await bot.send_location( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_location`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2492,6 +2617,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_location( chat_id=chat_id, latitude=latitude, @@ -2543,10 +2669,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_venue(update.effective_message.chat_id, *args, **kwargs) + await bot.send_venue( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_venue`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2564,6 +2698,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_venue( chat_id=chat_id, latitude=latitude, @@ -2613,10 +2748,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_contact(update.effective_message.chat_id, *args, **kwargs) + await bot.send_contact( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_contact`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2634,6 +2777,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_contact( chat_id=chat_id, phone_number=phone_number, @@ -2686,10 +2830,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_poll(update.effective_message.chat_id, *args, **kwargs) + await bot.send_poll( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_poll`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2707,6 +2859,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_poll( chat_id=chat_id, question=question, @@ -2755,10 +2908,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_dice(update.effective_message.chat_id, *args, **kwargs) + await bot.send_dice( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_dice`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2776,6 +2937,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_dice( chat_id=chat_id, disable_notification=disable_notification, @@ -2805,10 +2967,18 @@ class Message(MaybeInaccessibleMessage): ) -> bool: """Shortcut for:: - await bot.send_chat_action(update.effective_message.chat_id, *args, **kwargs) + await bot.send_chat_action( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_chat_action`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + .. versionadded:: 13.2 Returns: @@ -2817,7 +2987,7 @@ class Message(MaybeInaccessibleMessage): """ return await self.get_bot().send_chat_action( chat_id=self.chat_id, - message_thread_id=message_thread_id, + message_thread_id=self._parse_message_thread_id(self.chat_id, message_thread_id), action=action, read_timeout=read_timeout, write_timeout=write_timeout, @@ -2847,10 +3017,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_game(update.effective_message.chat_id, *args, **kwargs) + await bot.send_game( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_game`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -2870,6 +3048,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_game( chat_id=chat_id, # type: ignore[arg-type] game_short_name=game_short_name, @@ -2927,10 +3106,18 @@ class Message(MaybeInaccessibleMessage): ) -> "Message": """Shortcut for:: - await bot.send_invoice(update.effective_message.chat_id, *args, **kwargs) + await bot.send_invoice( + update.effective_message.chat_id, + message_thread_id=update.effective_message.message_thread_id, + *args, + **kwargs, + ) For the documentation of the arguments, please see :meth:`telegram.Bot.send_invoice`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Warning: As of API 5.2 :paramref:`start_parameter ` is an optional argument and therefore the @@ -2960,6 +3147,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().send_invoice( chat_id=chat_id, title=title, @@ -3130,6 +3318,7 @@ class Message(MaybeInaccessibleMessage): await bot.copy_message( chat_id=message.chat.id, + message_thread_id=update.effective_message.message_thread_id, message_id=message_id, *args, **kwargs @@ -3137,6 +3326,9 @@ class Message(MaybeInaccessibleMessage): For the documentation of the arguments, please see :meth:`telegram.Bot.copy_message`. + .. versionchanged:: NEXT.VERSION + |reply_same_thread| + Keyword Args: quote (:obj:`bool`, optional): |reply_quote| @@ -3155,6 +3347,7 @@ class Message(MaybeInaccessibleMessage): chat_id, effective_reply_parameters = await self._parse_quote_arguments( do_quote, quote, reply_to_message_id, reply_parameters ) + message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id) return await self.get_bot().copy_message( chat_id=chat_id, from_chat_id=from_chat_id, diff --git a/tests/test_message.py b/tests/test_message.py index b98f36b45..d0db5aeb2 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -482,6 +482,48 @@ class TestMessageWithoutRequest(TestMessageBase): if reply_parameters is None or reply_parameters.message_id != 42: pytest.fail(f"reply_parameters is {reply_parameters} but should be 42") + @staticmethod + async def check_thread_id_parsing( + message: Message, method, bot_method_name: str, args, monkeypatch + ): + """Used in testing reply_* below. Makes sure that meassage_thread_id is parsed + correctly.""" + + async def extract_message_thread_id(*args, **kwargs): + return kwargs.get("message_thread_id") + + monkeypatch.setattr(message.get_bot(), bot_method_name, extract_message_thread_id) + + message.message_thread_id = None + message_thread_id = await method(*args) + assert message_thread_id is None + + message.message_thread_id = 99 + message_thread_id = await method(*args) + assert message_thread_id == 99 + + message_thread_id = await method(*args, message_thread_id=50) + assert message_thread_id == 50 + + if bot_method_name == "send_chat_action": + return + + message_thread_id = await method( + *args, + do_quote=message.build_reply_arguments( + target_chat_id=123, + ), + ) + assert message_thread_id is None + + message_thread_id = await method( + *args, + do_quote=message.build_reply_arguments( + target_chat_id=message.chat_id, + ), + ) + assert message_thread_id == message.message_thread_id + def test_slot_behaviour(self): message = Message( message_id=TestMessageBase.id_, @@ -1361,6 +1403,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_text, "send_message", ["test"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_text, "send_message", ["test"], monkeypatch + ) + async def test_reply_markdown(self, monkeypatch, message): test_md_string = ( r"Test for <*bold*, _ita_\__lic_, `code`, " @@ -1395,6 +1441,10 @@ class TestMessageWithoutRequest(TestMessageBase): monkeypatch.setattr(message.get_bot(), "send_message", make_assertion) assert await message.reply_markdown(self.test_message.text_markdown) + await self.check_thread_id_parsing( + message, message.reply_markdown, "send_message", ["test"], monkeypatch + ) + async def test_reply_markdown_v2(self, monkeypatch, message): test_md_string = ( r"__Test__ for <*bold*, _ita\_lic_, `\\\`code`, " @@ -1436,6 +1486,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_markdown_v2, "send_message", [test_md_string], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_markdown_v2, "send_message", ["test"], monkeypatch + ) + async def test_reply_html(self, monkeypatch, message): test_html_string = ( "Test for <bold, ita_lic, " @@ -1479,6 +1533,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_html, "send_message", [test_html_string], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_html, "send_message", ["test"], monkeypatch + ) + async def test_reply_media_group(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1509,6 +1567,14 @@ class TestMessageWithoutRequest(TestMessageBase): monkeypatch, ) + await self.check_thread_id_parsing( + message, + message.reply_media_group, + "send_media_group", + ["reply_media_group"], + monkeypatch, + ) + async def test_reply_photo(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1535,6 +1601,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_photo, "send_photo", ["test_photo"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_photo, "send_photo", ["test_photo"], monkeypatch + ) + async def test_reply_audio(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1561,6 +1631,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_audio, "send_audio", ["test_audio"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_audio, "send_audio", ["test_audio"], monkeypatch + ) + async def test_reply_document(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1587,6 +1661,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_document, "send_document", ["test_document"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_document, "send_document", ["test_document"], monkeypatch + ) + async def test_reply_animation(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1613,6 +1691,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_animation, "send_animation", ["test_animation"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_animation, "send_animation", ["test_animation"], monkeypatch + ) + async def test_reply_sticker(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1639,6 +1721,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_sticker, "send_sticker", ["test_sticker"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_sticker, "send_sticker", ["test_sticker"], monkeypatch + ) + async def test_reply_video(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1665,6 +1751,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_video, "send_video", ["test_video"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_video, "send_video", ["test_video"], monkeypatch + ) + async def test_reply_video_note(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1691,6 +1781,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_video_note, "send_video_note", ["test_video_note"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_video_note, "send_video_note", ["test_video_note"], monkeypatch + ) + async def test_reply_voice(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1717,6 +1811,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_voice, "send_voice", ["test_voice"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_voice, "send_voice", ["test_voice"], monkeypatch + ) + async def test_reply_location(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1743,6 +1841,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_location, "send_location", ["test_location"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_location, "send_location", ["test_location"], monkeypatch + ) + async def test_reply_venue(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1769,6 +1871,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_venue, "send_venue", ["test_venue"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_venue, "send_venue", ["test_venue"], monkeypatch + ) + async def test_reply_contact(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1795,6 +1901,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_contact, "send_contact", ["test_contact"], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_contact, "send_contact", ["test_contact"], monkeypatch + ) + async def test_reply_poll(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1819,6 +1929,10 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_poll, "send_poll", ["test_poll", ["1", "2", "3"]], monkeypatch ) + await self.check_thread_id_parsing( + message, message.reply_poll, "send_poll", ["test_poll", ["1", "2", "3"]], monkeypatch + ) + async def test_reply_dice(self, monkeypatch, message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1846,6 +1960,10 @@ class TestMessageWithoutRequest(TestMessageBase): monkeypatch, ) + await self.check_thread_id_parsing( + message, message.reply_dice, "send_dice", [], monkeypatch + ) + async def test_reply_action(self, monkeypatch, message: Message): async def make_assertion(*_, **kwargs): id_ = kwargs["chat_id"] == message.chat_id @@ -1863,6 +1981,14 @@ class TestMessageWithoutRequest(TestMessageBase): monkeypatch.setattr(message.get_bot(), "send_chat_action", make_assertion) assert await message.reply_chat_action(action=ChatAction.TYPING) + await self.check_thread_id_parsing( + message, + message.reply_chat_action, + "send_chat_action", + [ChatAction.TYPING], + monkeypatch, + ) + async def test_reply_game(self, monkeypatch, message): async def make_assertion(*_, **kwargs): return ( @@ -1886,6 +2012,14 @@ class TestMessageWithoutRequest(TestMessageBase): message, message.reply_game, "send_game", ["test_game"], monkeypatch ) + await self.check_thread_id_parsing( + message, + message.reply_game, + "send_game", + ["test_game"], + monkeypatch, + ) + async def test_reply_invoice(self, monkeypatch, message): async def make_assertion(*_, **kwargs): title = kwargs["title"] == "title" @@ -1928,6 +2062,14 @@ class TestMessageWithoutRequest(TestMessageBase): monkeypatch, ) + await self.check_thread_id_parsing( + message, + message.reply_invoice, + "send_invoice", + ["title", "description", "payload", "provider_token", "currency", "prices"], + monkeypatch, + ) + @pytest.mark.parametrize(("disable_notification", "protected"), [(False, True), (True, False)]) async def test_forward(self, monkeypatch, message, disable_notification, protected): async def make_assertion(*_, **kwargs): @@ -2042,6 +2184,14 @@ class TestMessageWithoutRequest(TestMessageBase): monkeypatch, ) + await self.check_thread_id_parsing( + message, + message.reply_copy, + "copy_message", + [123456, 456789], + monkeypatch, + ) + async def test_edit_text(self, monkeypatch, message): async def make_assertion(*_, **kwargs): chat_id = kwargs["chat_id"] == message.chat_id