diff --git a/docs/source/inclusions/bot_methods.rst b/docs/source/inclusions/bot_methods.rst
index df699e796aa..aff45cc164f 100644
--- a/docs/source/inclusions/bot_methods.rst
+++ b/docs/source/inclusions/bot_methods.rst
@@ -256,6 +256,35 @@
+.. raw:: html
+
+
+ Forum topic management
+
+.. list-table::
+ :align: left
+ :widths: 1 4
+
+ * - :meth:`~telegram.Bot.close_forum_topic`
+ - Used for closing a forum topic
+ * - :meth:`~telegram.Bot.create_forum_topic`
+ - Used to create a topic
+ * - :meth:`~telegram.Bot.delete_forum_topic`
+ - Used for deleting a forum topic
+ * - :meth:`~telegram.Bot.edit_forum_topic`
+ - Used to edit a topic
+ * - :meth:`~telegram.Bot.reopen_forum_topic`
+ - Used to reopen a topic
+ * - :meth:`~telegram.Bot.get_forum_topic_icon_stickers`
+ - Used to get custom emojis to use as topic icons
+ * - :meth:`~telegram.Bot.unpin_all_forum_topic_messages`
+ - Used to unpin all messages in a forum topic
+
+.. raw:: html
+
+
+
+
.. raw:: html
diff --git a/docs/substitutions/global.rst b/docs/substitutions/global.rst
index 46067cbc8a9..b06bb09db41 100644
--- a/docs/substitutions/global.rst
+++ b/docs/substitutions/global.rst
@@ -26,6 +26,8 @@
.. |chat_id_group| replace:: Unique identifier for the target chat or username of the target supergroup (in the format ``@supergroupusername``).
+.. |message_thread_id| replace:: Unique identifier for the target message thread of the forum topic.
+
.. |parse_mode| replace:: Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message. See the constants in :class:`telegram.constants.ParseMode` for the available modes.
.. |allow_sending_without_reply| replace:: Pass :obj:`True`, if the message should be sent even if the specified replied-to message is not found.
diff --git a/telegram/_bot.py b/telegram/_bot.py
index 72f1cc49ccd..d8825ef4881 100644
--- a/telegram/_bot.py
+++ b/telegram/_bot.py
@@ -6878,6 +6878,351 @@ async def create_invoice_link(
api_kwargs=api_kwargs,
)
+ @_log
+ async def get_forum_topic_icon_stickers(
+ self,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> List[Sticker]:
+ """Use this method to get custom emoji stickers, which can be used as a forum topic
+ icon by any user. Requires no parameters.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ List[:class:`telegram.Sticker`]
+
+ Raises:
+ :class:`telegram.error.TelegramError`
+
+ """
+ result = await self._post(
+ "getForumTopicIconStickers",
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+ return Sticker.de_list(result, self) # type: ignore[return-value, arg-type]
+
+ @_log
+ async def create_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ name: str,
+ icon_color: int,
+ icon_custom_emoji_id: str,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """
+ Use this method to create a topic in a forum supergroup chat. The bot must be
+ an administrator in the chat for this to work and must have
+ :paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
+
+ .. seealso:: :meth:`telegram.Message.create_forum_topic`,
+ :meth:`telegram.Chat.create_forum_topic`,
+
+ .. versionadded:: 20.0
+
+ Args:
+ chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
+ name (:obj:`str`): New topic name,
+ :tg-const:`telegram.constants.TopicLimit.MIN_NAME_LENGTH`-
+ :tg-const:`telegram.constants.TopicLimit.MAX_NAME_LENGTH` characters.
+ icon_color (:obj:`int`): Color of the topic icon in RGB format. Currently,
+ must be one of :attr:`telegram.constants.ForumIconColor.BLUE`,
+ :attr:`telegram.constants.ForumIconColor.YELLOW`,
+ :attr:`telegram.constants.ForumIconColor.PURPLE`,
+ :attr:`telegram.constants.ForumIconColor.GREEN`,
+ :attr:`telegram.constants.ForumIconColor.PINK`, or
+ :attr:`telegram.constants.ForumIconColor.RED`.
+ icon_custom_emoji_id (:obj:`str`): New unique identifier of the custom emoji shown as
+ the topic icon. Use :meth:`~telegram.Bot.get_forum_topic_icon_stickers` to get all
+ allowed custom emoji identifiers.
+
+ Returns:
+ :obj:`bool`: On success, :class:`telegram.ForumTopic` is returned.
+
+ Raises:
+ :class:`telegram.error.TelegramError`
+ """
+ data: JSONDict = {
+ "chat_id": chat_id,
+ "name": name,
+ "icon_color": icon_color,
+ "icon_custom_emoji_id": icon_custom_emoji_id,
+ }
+ # TODO: DO ForumTopic.de_json here!
+ return await self._post( # type: ignore[return-value]
+ "createForumTopic",
+ data,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ @_log
+ async def edit_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ name: str,
+ icon_custom_emoji_id: str,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """
+ Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must
+ be an administrator in the chat for this to work and must have
+ :paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights,
+ unless it is the creator of the topic.
+
+ .. seealso:: :meth:`telegram.Message.edit_forum_topic`,
+ :meth:`telegram.Chat.edit_forum_topic`,
+
+ .. versionadded:: 20.0
+
+ Args:
+ chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
+ message_thread_id (:obj:`int`): |message_thread_id|
+ name (:obj:`str`): New topic name,
+ :tg-const:`telegram.constants.TopicLimit.MIN_NAME_LENGTH`-
+ :tg-const:`telegram.constants.TopicLimit.MAX_NAME_LENGTH` characters.
+ icon_custom_emoji_id (:obj:`str`): New unique identifier of the custom emoji shown as
+ the topic icon. Use :meth:`~telegram.Bot.get_forum_topic_icon_stickers` to get all
+ allowed custom emoji identifiers.
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+
+ Raises:
+ :class:`telegram.error.TelegramError`
+
+ """
+ data: JSONDict = {
+ "chat_id": chat_id,
+ "message_thread_id": message_thread_id,
+ "name": name,
+ "icon_custom_emoji_id": icon_custom_emoji_id,
+ }
+ return await self._post( # type: ignore[return-value]
+ "editForumTopic",
+ data,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ @_log
+ async def close_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """
+ Use this method to close an open topic in a forum supergroup chat. The bot must
+ be an administrator in the chat for this to work and must have
+ :paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights,
+ unless it is the creator of the topic.
+
+ .. seealso:: :meth:`telegram.Message.close_forum_topic`,
+ :meth:`telegram.Chat.close_forum_topic`,
+
+ .. versionadded:: 20.0
+
+ Args:
+ chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
+ message_thread_id (:obj:`int`): |message_thread_id|
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+
+ Raises:
+ :class:`telegram.error.TelegramError`
+
+ """
+ data: JSONDict = {
+ "chat_id": chat_id,
+ "message_thread_id": message_thread_id,
+ }
+ return await self._post( # type: ignore[return-value]
+ "closeForumTopic",
+ data,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ @_log
+ async def reopen_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """
+ Use this method to reopen a closed topic in a forum supergroup chat. The bot must
+ be an administrator in the chat for this to work and must have
+ :paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights,
+ unless it is the creator of the topic.
+
+ .. seealso:: :meth:`telegram.Message.reopen_forum_topic`,
+ :meth:`telegram.Chat.reopen_forum_topic`,
+
+ .. versionadded:: 20.0
+
+ Args:
+ chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
+ message_thread_id (:obj:`int`): |message_thread_id|
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+
+ Raises:
+ :class:`telegram.error.TelegramError`
+
+ """
+ data: JSONDict = {
+ "chat_id": chat_id,
+ "message_thread_id": message_thread_id,
+ }
+ return await self._post( # type: ignore[return-value]
+ "reopenForumTopic",
+ data,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ @_log
+ async def delete_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """
+ Use this method to delete a forum topic along with all its messages in a forum supergroup
+ chat. The bot must be an administrator in the chat for this to work and must have
+ :paramref:`~telegram.ChatAdministratorRights.can_delete_messages` administrator rights,
+ unless it is the creator of the topic.
+
+ .. seealso:: :meth:`telegram.Message.delete_forum_topic`,
+ :meth:`telegram.Chat.delete_forum_topic`,
+
+ .. versionadded:: 20.0
+
+ Args:
+ chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
+ message_thread_id (:obj:`int`): |message_thread_id|
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+
+ Raises:
+ :class:`telegram.error.TelegramError`
+
+ """
+ data: JSONDict = {
+ "chat_id": chat_id,
+ "message_thread_id": message_thread_id,
+ }
+ return await self._post( # type: ignore[return-value]
+ "deleteForumTopic",
+ data,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ @_log
+ async def unpin_all_forum_topic_messages(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """
+ Use this method to clear the list of pinned messages in a forum topic. The bot must
+ be an administrator in the chat for this to work and must have
+ :paramref:`~telegram.ChatAdministratorRights.can_pin_messages` administrator rights
+ in the supergroup, unless it is the creator of the topic.
+
+ .. seealso:: :meth:`telegram.Message.unpin_all_forum_topic_messages`,
+ :meth:`telegram.Chat.unpin_all_forum_topic_messages`,
+
+ .. versionadded:: 20.0
+
+ Args:
+ chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
+ message_thread_id (:obj:`int`): |message_thread_id|
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+
+ Raises:
+ :class:`telegram.error.TelegramError`
+
+ """
+ data: JSONDict = {
+ "chat_id": chat_id,
+ "message_thread_id": message_thread_id,
+ }
+ return await self._post( # type: ignore[return-value]
+ "unpinAllForumTopicMessages",
+ data,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
def to_dict(self, recursive: bool = True) -> JSONDict: # skipcq: PYL-W0613
"""See :meth:`telegram.TelegramObject.to_dict`."""
data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name}
@@ -7070,3 +7415,17 @@ def __hash__(self) -> int:
"""Alias for :meth:`set_my_default_administrator_rights`"""
createInvoiceLink = create_invoice_link
"""Alias for :meth:`create_invoice_link`"""
+ getForumTopicIconStickers = get_forum_topic_icon_stickers
+ """Alias for :meth:`get_forum_topic_icon_stickers`"""
+ createForumTopic = create_forum_topic
+ """Alias for :meth:`create_forum_topic`"""
+ editForumTopic = edit_forum_topic
+ """Alias for :meth:`edit_forum_topic`"""
+ closeForumTopic = close_forum_topic
+ """Alias for :meth:`close_forum_topic`"""
+ reopenForumTopic = reopen_forum_topic
+ """Alias for :meth:`reopen_forum_topic`"""
+ deleteForumTopic = delete_forum_topic
+ """Alias for :meth:`delete_forum_topic`"""
+ unpinAllForumTopicMessages = unpin_all_forum_topic_messages
+ """Alias for :meth:`unpin_all_forum_topic_messages`"""
diff --git a/telegram/_chat.py b/telegram/_chat.py
index 85a51e0aece..91a751c53aa 100644
--- a/telegram/_chat.py
+++ b/telegram/_chat.py
@@ -2617,6 +2617,207 @@ async def set_menu_button(
api_kwargs=api_kwargs,
)
+ async def create_forum_topic(
+ self,
+ name: str,
+ icon_color: int,
+ icon_custom_emoji_id: str,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.create_forum_topic(chat_id=update.effective_chat.id, *args, **kwargs)
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.create_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().create_forum_topic(
+ chat_id=self.id,
+ name=name,
+ icon_color=icon_color,
+ icon_custom_emoji_id=icon_custom_emoji_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def edit_forum_topic(
+ self,
+ message_thread_id: int,
+ name: str,
+ icon_custom_emoji_id: str,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.edit_forum_topic(chat_id=update.effective_chat.id, *args, **kwargs)
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.edit_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().edit_forum_topic(
+ chat_id=self.id,
+ message_thread_id=message_thread_id,
+ name=name,
+ icon_custom_emoji_id=icon_custom_emoji_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def close_forum_topic(
+ self,
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.close_forum_topic(chat_id=update.effective_chat.id, *args, **kwargs)
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.close_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().close_forum_topic(
+ chat_id=self.id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def reopen_forum_topic(
+ self,
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.reopen_forum_topic(chat_id=update.effective_chat.id, *args, **kwargs)
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.reopen_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().reopen_forum_topic(
+ chat_id=self.id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def delete_forum_topic(
+ self,
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.delete_forum_topic(chat_id=update.effective_chat.id, *args, **kwargs)
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.delete_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().delete_forum_topic(
+ chat_id=self.id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def unpin_all_forum_topic_messages(
+ self,
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.unpin_all_forum_topic_messages(chat_id=update.effective_chat.id,
+ *args, **kwargs)
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.unpin_all_forum_topic_messages`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().unpin_all_forum_topic_messages(
+ chat_id=self.id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
async def get_menu_button(
self,
*,
diff --git a/telegram/_message.py b/telegram/_message.py
index e9d76b2ced4..f18e00973ea 100644
--- a/telegram/_message.py
+++ b/telegram/_message.py
@@ -2712,6 +2712,180 @@ async def unpin(
api_kwargs=api_kwargs,
)
+ async def edit_forum_topic(
+ self,
+ name: str,
+ icon_custom_emoji_id: str,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.edit_forum_topic(
+ chat_id=message.chat_id, message_thread_id=message.message_thread_id, *args,
+ **kwargs
+ )
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.edit_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().edit_forum_topic(
+ chat_id=self.chat_id,
+ message_thread_id=self.message_thread_id,
+ name=name,
+ icon_custom_emoji_id=icon_custom_emoji_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def close_forum_topic(
+ self,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.close_forum_topic(
+ chat_id=message.chat_id, message_thread_id=message.message_thread_id, *args,
+ **kwargs
+ )
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.close_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().close_forum_topic(
+ chat_id=self.chat_id,
+ message_thread_id=self.message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def reopen_forum_topic(
+ self,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.reopen_forum_topic(
+ chat_id=message.chat_id, message_thread_id=message.message_thread_id, *args,
+ **kwargs
+ )
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.reopen_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().reopen_forum_topic(
+ chat_id=self.chat_id,
+ message_thread_id=self.message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def delete_forum_topic(
+ self,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.delete_forum_topic(
+ chat_id=message.chat_id, message_thread_id=message.message_thread_id, *args,
+ **kwargs
+ )
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.delete_forum_topic`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().delete_forum_topic(
+ chat_id=self.chat_id,
+ message_thread_id=self.message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
+ async def unpin_all_forum_topic_messages(
+ self,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ ) -> bool:
+ """Shortcut for::
+
+ await bot.unpin_all_forum_topic_messages(
+ chat_id=message.chat_id, message_thread_id=message.message_thread_id, *args,
+ **kwargs
+ )
+
+ For the documentation of the arguments, please see
+ :meth:`telegram.Bot.unpin_all_forum_topic_messages`.
+
+ .. versionadded:: 20.0
+
+ Returns:
+ :obj:`bool`: On success, :obj:`True` is returned.
+ """
+ return await self.get_bot().unpin_all_forum_topic_messages(
+ chat_id=self.chat_id,
+ message_thread_id=self.message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=api_kwargs,
+ )
+
def parse_entity(self, entity: MessageEntity) -> str:
"""Returns the text from a given :class:`telegram.MessageEntity`.
diff --git a/telegram/constants.py b/telegram/constants.py
index b20f847dc52..1a5bb3e9405 100644
--- a/telegram/constants.py
+++ b/telegram/constants.py
@@ -46,6 +46,7 @@
"DiceEmoji",
"FileSizeLimit",
"FloodLimit",
+ "ForumIconColor",
"InlineKeyboardMarkupLimit",
"InlineQueryLimit",
"InlineQueryResultType",
@@ -63,6 +64,7 @@
"PollType",
"SUPPORTED_WEBHOOK_PORTS",
"StickerType",
+ "TopicLimit",
"WebhookLimit",
"UpdateType",
]
@@ -371,6 +373,66 @@ class FloodLimit(IntEnum):
"""
+class ForumIconColor(IntEnum):
+ """This enum contains the available colors for use in
+ :paramref:`telegram.Bot.create_forum_topic.icon_color`. The enum members of this enumeration
+ are instances of :class:`int` and can be treated as such.
+
+ .. versionadded:: 20.0
+ """
+
+ __slots__ = ()
+
+ BLUE = 0x6FB9F0
+ """:obj:`int`: An icon with a color which corresponds to blue.
+
+ .. raw:: html
+
+
+
+ """
+ YELLOW = 0xFFD67E
+ """:obj:`int`: An icon with a color which corresponds to yellow.
+
+ .. raw:: html
+
+
+
+ """
+ PURPLE = 0xCB86DB
+ """:obj:`int`: An icon with a color which corresponds to purple.
+
+ .. raw:: html
+
+
+
+ """
+ GREEN = 0x8EEE98
+ """:obj:`int`: An icon with a color which corresponds to green.
+
+ .. raw:: html
+
+
+
+ """
+ PINK = 0xFF93B2
+ """:obj:`int`: An icon with a color which corresponds to pink.
+
+ .. raw:: html
+
+
+
+ """
+ RED = 0xFB6F5F
+ """:obj:`int`: An icon with a color which corresponds to red.
+
+ .. raw:: html
+
+
+
+ """
+
+
class InlineKeyboardMarkupLimit(IntEnum):
"""This enum contains limitations for :class:`telegram.InlineKeyboardMarkup`/
:meth:`telegram.Bot.send_message` & friends. The enum
@@ -917,3 +979,18 @@ class ChatLimit(IntEnum):
""":obj:`int`: Minimum length of a new chat title."""
MAX_TITLE_LENGTH = 128
""":obj:`int`: Maximum length of a new chat title."""
+
+
+class TopicLimit(IntEnum):
+ """This enum contains limitations for :paramref:`telegram.Bot.edit_forum_topic.name`. The
+ enum members of this enumeration are instances of :class:`int` and can be treated as such.
+
+ .. versionadded:: 20.0
+ """
+
+ __slots__ = ()
+
+ MIN_NAME_LENGTH = 1
+ """:obj:`int`: Minimum length of the topic name."""
+ MAX_NAME_LENGTH = 128
+ """:obj:`int`: Maximum length of the topic name."""
diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py
index 7445c0bffd4..0ae8f88bcac 100644
--- a/telegram/ext/_extbot.py
+++ b/telegram/ext/_extbot.py
@@ -1107,6 +1107,28 @@ async def delete_chat_sticker_set(
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
+ async def delete_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ rate_limit_args: RLARGS = None,
+ ) -> bool:
+ return await super().delete_forum_topic(
+ chat_id=chat_id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
+ )
+
async def delete_message(
self,
chat_id: Union[str, int],
@@ -1221,6 +1243,32 @@ async def edit_chat_invite_link(
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
+ async def edit_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ name: str,
+ icon_custom_emoji_id: str,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ rate_limit_args: RLARGS = None,
+ ) -> bool:
+ return await super().edit_forum_topic(
+ chat_id=chat_id,
+ message_thread_id=message_thread_id,
+ name=name,
+ icon_custom_emoji_id=icon_custom_emoji_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
+ )
+
async def edit_message_caption(
self,
chat_id: Union[str, int] = None,
@@ -1533,6 +1581,24 @@ async def get_file(
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
+ async def get_forum_topic_icon_stickers(
+ self,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ rate_limit_args: RLARGS = None,
+ ) -> List[Sticker]:
+ return await super().get_forum_topic_icon_stickers(
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
+ )
+
async def get_game_high_scores(
self,
user_id: Union[int, str],
@@ -1757,6 +1823,54 @@ async def close(
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
+ async def close_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ rate_limit_args: RLARGS = None,
+ ) -> bool:
+ return await super().close_forum_topic(
+ chat_id=chat_id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
+ )
+
+ async def create_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ name: str,
+ icon_color: int,
+ icon_custom_emoji_id: str,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ rate_limit_args: RLARGS = None,
+ ) -> bool:
+ return await super().create_forum_topic(
+ chat_id=chat_id,
+ name=name,
+ icon_color=icon_color,
+ icon_custom_emoji_id=icon_custom_emoji_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
+ )
+
async def pin_chat_message(
self,
chat_id: Union[str, int],
@@ -1827,6 +1941,28 @@ async def promote_chat_member(
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
+ async def reopen_forum_topic(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ rate_limit_args: RLARGS = None,
+ ) -> bool:
+ return await super().reopen_forum_topic(
+ chat_id=chat_id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
+ )
+
async def restrict_chat_member(
self,
chat_id: Union[str, int],
@@ -3121,6 +3257,28 @@ async def unpin_chat_message(
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
+ async def unpin_all_forum_topic_messages(
+ self,
+ chat_id: Union[str, int],
+ message_thread_id: int,
+ *,
+ read_timeout: ODVInput[float] = DEFAULT_NONE,
+ write_timeout: ODVInput[float] = DEFAULT_NONE,
+ connect_timeout: ODVInput[float] = DEFAULT_NONE,
+ pool_timeout: ODVInput[float] = DEFAULT_NONE,
+ api_kwargs: JSONDict = None,
+ rate_limit_args: RLARGS = None,
+ ) -> bool:
+ return await super().unpin_all_forum_topic_messages(
+ chat_id=chat_id,
+ message_thread_id=message_thread_id,
+ read_timeout=read_timeout,
+ write_timeout=write_timeout,
+ connect_timeout=connect_timeout,
+ pool_timeout=pool_timeout,
+ api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
+ )
+
async def upload_sticker_file(
self,
user_id: Union[str, int],
@@ -3232,3 +3390,10 @@ async def upload_sticker_file(
getMyDefaultAdministratorRights = get_my_default_administrator_rights
setMyDefaultAdministratorRights = set_my_default_administrator_rights
createInvoiceLink = create_invoice_link
+ getForumTopicIconStickers = get_forum_topic_icon_stickers
+ createForumTopic = create_forum_topic
+ editForumTopic = edit_forum_topic
+ closeForumTopic = close_forum_topic
+ reopenForumTopic = reopen_forum_topic
+ deleteForumTopic = delete_forum_topic
+ unpinAllForumTopicMessages = unpin_all_forum_topic_messages
diff --git a/tests/test_bot.py b/tests/test_bot.py
index 85f9c59444b..8a40bc086cd 100644
--- a/tests/test_bot.py
+++ b/tests/test_bot.py
@@ -2568,6 +2568,9 @@ async def test_pin_and_unpin_message(self, bot, super_group_id):
# set_sticker_position_in_set, delete_sticker_from_set and get_custom_emoji_stickers
# are tested in the test_sticker module.
+ # get_forum_topic_icon_stickers, edit_forum_topic, etc...
+ # are tested in the test_forum module.
+
async def test_timeout_propagation_explicit(self, monkeypatch, bot, chat_id):
# Use BaseException that's not a subclass of Exception such that
# OkException should not be caught anywhere
diff --git a/tests/test_chat.py b/tests/test_chat.py
index 4f2305180b8..e8871deeedd 100644
--- a/tests/test_chat.py
+++ b/tests/test_chat.py
@@ -896,6 +896,128 @@ async def make_assertion(*_, **kwargs):
monkeypatch.setattr(chat.get_bot(), "decline_chat_join_request", make_assertion)
assert await chat.decline_join_request(user_id=42)
+ async def test_create_forum_topic(self, monkeypatch, chat):
+ async def make_assertion(*_, **kwargs):
+ return (
+ kwargs["chat_id"] == chat.id
+ and kwargs["name"] == "New Name"
+ and kwargs["icon_color"] == 0x6FB9F0
+ and kwargs["icon_custom_emoji_id"] == "12345"
+ )
+
+ assert check_shortcut_signature(
+ Chat.create_forum_topic, Bot.create_forum_topic, ["chat_id"], []
+ )
+ assert await check_shortcut_call(
+ chat.create_forum_topic,
+ chat.get_bot(),
+ "create_forum_topic",
+ shortcut_kwargs=["chat_id"],
+ )
+ assert await check_defaults_handling(chat.create_forum_topic, chat.get_bot())
+
+ monkeypatch.setattr(chat.get_bot(), "create_forum_topic", make_assertion)
+ assert await chat.create_forum_topic(
+ name="New Name", icon_color=0x6FB9F0, icon_custom_emoji_id="12345"
+ )
+
+ async def test_edit_forum_topic(self, monkeypatch, chat):
+ async def make_assertion(*_, **kwargs):
+ return (
+ kwargs["chat_id"] == chat.id
+ and kwargs["message_thread_id"] == 42
+ and kwargs["name"] == "New Name"
+ and kwargs["icon_custom_emoji_id"] == "12345"
+ )
+
+ assert check_shortcut_signature(
+ Chat.edit_forum_topic, Bot.edit_forum_topic, ["chat_id"], []
+ )
+ assert await check_shortcut_call(
+ chat.edit_forum_topic, chat.get_bot(), "edit_forum_topic", shortcut_kwargs=["chat_id"]
+ )
+ assert await check_defaults_handling(chat.edit_forum_topic, chat.get_bot())
+
+ monkeypatch.setattr(chat.get_bot(), "edit_forum_topic", make_assertion)
+ assert await chat.edit_forum_topic(
+ message_thread_id=42, name="New Name", icon_custom_emoji_id="12345"
+ )
+
+ async def test_close_forum_topic(self, monkeypatch, chat):
+ async def make_assertion(*_, **kwargs):
+ return kwargs["chat_id"] == chat.id and kwargs["message_thread_id"] == 42
+
+ assert check_shortcut_signature(
+ Chat.close_forum_topic, Bot.close_forum_topic, ["chat_id"], []
+ )
+ assert await check_shortcut_call(
+ chat.close_forum_topic,
+ chat.get_bot(),
+ "close_forum_topic",
+ shortcut_kwargs=["chat_id"],
+ )
+ assert await check_defaults_handling(chat.close_forum_topic, chat.get_bot())
+
+ monkeypatch.setattr(chat.get_bot(), "close_forum_topic", make_assertion)
+ assert await chat.close_forum_topic(message_thread_id=42)
+
+ async def test_reopen_forum_topic(self, monkeypatch, chat):
+ async def make_assertion(*_, **kwargs):
+ return kwargs["chat_id"] == chat.id and kwargs["message_thread_id"] == 42
+
+ assert check_shortcut_signature(
+ Chat.reopen_forum_topic, Bot.reopen_forum_topic, ["chat_id"], []
+ )
+ assert await check_shortcut_call(
+ chat.reopen_forum_topic,
+ chat.get_bot(),
+ "reopen_forum_topic",
+ shortcut_kwargs=["chat_id"],
+ )
+ assert await check_defaults_handling(chat.reopen_forum_topic, chat.get_bot())
+
+ monkeypatch.setattr(chat.get_bot(), "reopen_forum_topic", make_assertion)
+ assert await chat.reopen_forum_topic(message_thread_id=42)
+
+ async def test_delete_forum_topic(self, monkeypatch, chat):
+ async def make_assertion(*_, **kwargs):
+ return kwargs["chat_id"] == chat.id and kwargs["message_thread_id"] == 42
+
+ assert check_shortcut_signature(
+ Chat.delete_forum_topic, Bot.delete_forum_topic, ["chat_id"], []
+ )
+ assert await check_shortcut_call(
+ chat.delete_forum_topic,
+ chat.get_bot(),
+ "delete_forum_topic",
+ shortcut_kwargs=["chat_id"],
+ )
+ assert await check_defaults_handling(chat.delete_forum_topic, chat.get_bot())
+
+ monkeypatch.setattr(chat.get_bot(), "delete_forum_topic", make_assertion)
+ assert await chat.delete_forum_topic(message_thread_id=42)
+
+ async def test_unpin_all_forum_topic_messages(self, monkeypatch, chat):
+ async def make_assertion(*_, **kwargs):
+ return kwargs["chat_id"] == chat.id and kwargs["message_thread_id"] == 42
+
+ assert check_shortcut_signature(
+ Chat.unpin_all_forum_topic_messages,
+ Bot.unpin_all_forum_topic_messages,
+ ["chat_id"],
+ [],
+ )
+ assert await check_shortcut_call(
+ chat.unpin_all_forum_topic_messages,
+ chat.get_bot(),
+ "unpin_all_forum_topic_messages",
+ shortcut_kwargs=["chat_id"],
+ )
+ assert await check_defaults_handling(chat.unpin_all_forum_topic_messages, chat.get_bot())
+
+ monkeypatch.setattr(chat.get_bot(), "unpin_all_forum_topic_messages", make_assertion)
+ assert await chat.unpin_all_forum_topic_messages(message_thread_id=42)
+
def test_mention_html(self):
with pytest.raises(TypeError, match="Can not create a mention to a private group chat"):
chat = Chat(id=1, type="foo")
diff --git a/tests/test_message.py b/tests/test_message.py
index 3ad03e386cc..bb8aa8519c6 100644
--- a/tests/test_message.py
+++ b/tests/test_message.py
@@ -198,6 +198,7 @@ def message(bot):
]
},
{"web_app_data": WebAppData("some_data", "some_button_text")},
+ {"message_thread_id": 123},
],
ids=[
"forwarded_user",
@@ -251,6 +252,7 @@ def message(bot):
"has_protected_content",
"entities",
"web_app_data",
+ "message_thread_id",
],
)
def message_params(bot, request):
@@ -1693,6 +1695,124 @@ def test_default_quote(self, message):
finally:
message.get_bot()._defaults = None
+ async def test_edit_forum_topic(self, monkeypatch, message):
+ async def make_assertion(*_, **kwargs):
+ return (
+ kwargs["chat_id"] == message.chat_id
+ and kwargs["message_thread_id"] == message.message_thread_id
+ and kwargs["name"] == "New Name"
+ and kwargs["icon_custom_emoji_id"] == "12345"
+ )
+
+ assert check_shortcut_signature(
+ Message.edit_forum_topic, Bot.edit_forum_topic, ["chat_id", "message_thread_id"], []
+ )
+ assert await check_shortcut_call(
+ message.edit_forum_topic,
+ message.get_bot(),
+ "edit_forum_topic",
+ shortcut_kwargs=["chat_id", "message_thread_id"],
+ )
+ assert await check_defaults_handling(message.edit_forum_topic, message.get_bot())
+
+ monkeypatch.setattr(message.get_bot(), "edit_forum_topic", make_assertion)
+ assert await message.edit_forum_topic(name="New Name", icon_custom_emoji_id="12345")
+
+ async def test_close_forum_topic(self, monkeypatch, message):
+ async def make_assertion(*_, **kwargs):
+ return (
+ kwargs["chat_id"] == message.chat_id
+ and kwargs["message_thread_id"] == message.message_thread_id
+ )
+
+ assert check_shortcut_signature(
+ Message.close_forum_topic, Bot.close_forum_topic, ["chat_id", "message_thread_id"], []
+ )
+ assert await check_shortcut_call(
+ message.close_forum_topic,
+ message.get_bot(),
+ "close_forum_topic",
+ shortcut_kwargs=["chat_id", "message_thread_id"],
+ )
+ assert await check_defaults_handling(message.close_forum_topic, message.get_bot())
+
+ monkeypatch.setattr(message.get_bot(), "close_forum_topic", make_assertion)
+ assert await message.close_forum_topic()
+
+ async def test_reopen_forum_topic(self, monkeypatch, message):
+ async def make_assertion(*_, **kwargs):
+ return (
+ kwargs["chat_id"] == message.chat_id
+ and kwargs["message_thread_id"] == message.message_thread_id
+ )
+
+ assert check_shortcut_signature(
+ Message.reopen_forum_topic,
+ Bot.reopen_forum_topic,
+ ["chat_id", "message_thread_id"],
+ [],
+ )
+ assert await check_shortcut_call(
+ message.reopen_forum_topic,
+ message.get_bot(),
+ "reopen_forum_topic",
+ shortcut_kwargs=["chat_id", "message_thread_id"],
+ )
+ assert await check_defaults_handling(message.reopen_forum_topic, message.get_bot())
+
+ monkeypatch.setattr(message.get_bot(), "reopen_forum_topic", make_assertion)
+ assert await message.reopen_forum_topic()
+
+ async def test_delete_forum_topic(self, monkeypatch, message):
+ async def make_assertion(*_, **kwargs):
+ return (
+ kwargs["chat_id"] == message.chat_id
+ and kwargs["message_thread_id"] == message.message_thread_id
+ )
+
+ assert check_shortcut_signature(
+ Message.delete_forum_topic,
+ Bot.delete_forum_topic,
+ ["chat_id", "message_thread_id"],
+ [],
+ )
+ assert await check_shortcut_call(
+ message.delete_forum_topic,
+ message.get_bot(),
+ "delete_forum_topic",
+ shortcut_kwargs=["chat_id", "message_thread_id"],
+ )
+ assert await check_defaults_handling(message.delete_forum_topic, message.get_bot())
+
+ monkeypatch.setattr(message.get_bot(), "delete_forum_topic", make_assertion)
+ assert await message.delete_forum_topic()
+
+ async def test_unpin_all_forum_topic_messages(self, monkeypatch, message):
+ async def make_assertion(*_, **kwargs):
+ return (
+ kwargs["chat_id"] == message.chat_id
+ and kwargs["message_thread_id"] == message.message_thread_id
+ )
+
+ assert check_shortcut_signature(
+ Message.unpin_all_forum_topic_messages,
+ Bot.unpin_all_forum_topic_messages,
+ ["chat_id", "message_thread_id"],
+ [],
+ )
+ assert await check_shortcut_call(
+ message.unpin_all_forum_topic_messages,
+ message.get_bot(),
+ "unpin_all_forum_topic_messages",
+ shortcut_kwargs=["chat_id", "message_thread_id"],
+ )
+ assert await check_defaults_handling(
+ message.unpin_all_forum_topic_messages, message.get_bot()
+ )
+
+ monkeypatch.setattr(message.get_bot(), "unpin_all_forum_topic_messages", make_assertion)
+ assert await message.unpin_all_forum_topic_messages()
+
def test_equality(self):
id_ = 1
a = Message(