diff --git a/CHANGES/1451.feature.rst b/CHANGES/1451.feature.rst new file mode 100644 index 00000000..42780540 --- /dev/null +++ b/CHANGES/1451.feature.rst @@ -0,0 +1 @@ +Added **message_thread_id** parameter to **message.get_url()**. diff --git a/aiogram/types/message.py b/aiogram/types/message.py index d04f3317..3d380e50 100644 --- a/aiogram/types/message.py +++ b/aiogram/types/message.py @@ -4027,13 +4027,16 @@ class Message(MaybeInaccessibleMessage): **kwargs, ).as_(self._bot) - def get_url(self, force_private: bool = False) -> Optional[str]: + def get_url( + self, force_private: bool = False, include_thread_id: bool = False + ) -> Optional[str]: """ Returns message URL. Cannot be used in private (one-to-one) chats. If chat has a username, returns URL like https://t.me/username/message_id Otherwise (or if {force_private} flag is set), returns https://t.me/c/shifted_chat_id/message_id :param force_private: if set, a private URL is returned even for a public chat + :param include_thread_id: if set, adds chat thread id to URL and returns like https://t.me/username/thread_id/message_id :return: string with full message URL """ if self.chat.type in ("private", "group"): @@ -4045,7 +4048,13 @@ class Message(MaybeInaccessibleMessage): else self.chat.username ) - return f"https://t.me/{chat_value}/{self.message_id}" + message_id_value = ( + f"{self.message_thread_id}/{self.message_id}" + if include_thread_id and self.message_thread_id and self.is_topic_message + else f"{self.message_id}" + ) + + return f"https://t.me/{chat_value}/{message_id_value}" def react( self, diff --git a/tests/test_api/test_methods/test_get_url.py b/tests/test_api/test_methods/test_get_url.py index 9eec1017..0c5cddc5 100644 --- a/tests/test_api/test_methods/test_get_url.py +++ b/tests/test_api/test_methods/test_get_url.py @@ -26,7 +26,7 @@ class TestGetMessageUrl: ["supergroup", -10012345678901, None, True, "https://t.me/c/12345678901/10"], ], ) - def test_method( + def test_get_url_non_topic_message( self, bot: MockedBot, chat_type: str, @@ -46,5 +46,61 @@ class TestGetMessageUrl: if expected_result is None: assert fake_message.get_url(force_private=force_private) is None + assert ( + fake_message.get_url(force_private=force_private, include_thread_id=True) is None + ) else: assert fake_message.get_url(force_private=force_private) == expected_result + assert ( + fake_message.get_url(force_private=force_private, include_thread_id=True) + == expected_result + ) + + @pytest.mark.parametrize( + "chat_username,force_private,include_thread_id,fake_thread_id_topic,expected_result", + [ + [None, False, False, None, "https://t.me/c/1234567890/10"], + [None, False, False, 3, "https://t.me/c/1234567890/10"], + [None, False, True, None, "https://t.me/c/1234567890/10"], + [None, False, True, 3, "https://t.me/c/1234567890/3/10"], + [None, True, False, None, "https://t.me/c/1234567890/10"], + [None, True, False, 3, "https://t.me/c/1234567890/10"], + [None, True, True, None, "https://t.me/c/1234567890/10"], + [None, True, True, 3, "https://t.me/c/1234567890/3/10"], + ["name", False, False, None, "https://t.me/name/10"], + ["name", False, False, 3, "https://t.me/name/10"], + ["name", False, True, None, "https://t.me/name/10"], + ["name", False, True, 3, "https://t.me/name/3/10"], + ["name", True, False, None, "https://t.me/c/1234567890/10"], + ["name", True, False, 3, "https://t.me/c/1234567890/10"], + ["name", True, True, None, "https://t.me/c/1234567890/10"], + ["name", True, True, 3, "https://t.me/c/1234567890/3/10"], + ], + ) + def test_get_url_if_topic_message( + self, + bot: MockedBot, + chat_username: Optional[str], + force_private: bool, + include_thread_id: bool, + fake_thread_id_topic: Optional[int], + expected_result: Optional[str], + ): + fake_message_id = 10 + fake_chat_id = -1001234567890 + fake_chat_type = "supergroup" + fake_chat_with_topics = Chat( + id=fake_chat_id, username=chat_username, type=fake_chat_type, is_forum=True + ) + fake_message_from_topic = Message( + message_id=fake_message_id, + date=datetime.datetime.now(), + text="test", + chat=fake_chat_with_topics, + is_topic_message=True, + message_thread_id=fake_thread_id_topic, + ) + actual_result = fake_message_from_topic.get_url( + force_private=force_private, include_thread_id=include_thread_id + ) + assert actual_result == expected_result