mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2024-12-22 14:35:00 +01:00
API 6.4 (#3449)
Co-authored-by: poolitzer <github@poolitzer.eu> Co-authored-by: Dmitry Kolomatskiy <58207913+lemontree210@users.noreply.github.com> Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
This commit is contained in:
parent
f408b1a2dd
commit
606773d8f0
33 changed files with 1379 additions and 59 deletions
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
File diff suppressed because one or more lines are too long
|
@ -14,7 +14,7 @@
|
|||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.3-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.4-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
|
||||
|
@ -93,7 +93,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
|||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **6.2** are supported.
|
||||
All types and methods of the Telegram Bot API **6.4** are supported.
|
||||
|
||||
Installing
|
||||
==========
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
:target: https://pypi.org/project/python-telegram-bot-raw/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.3-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.4-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
|
||||
|
@ -89,7 +89,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
|||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **6.2** are supported.
|
||||
All types and methods of the Telegram Bot API **6.4** are supported.
|
||||
|
||||
Installing
|
||||
==========
|
||||
|
|
|
@ -267,16 +267,26 @@
|
|||
|
||||
* - :meth:`~telegram.Bot.close_forum_topic`
|
||||
- Used for closing a forum topic
|
||||
* - :meth:`~telegram.Bot.close_general_forum_topic`
|
||||
- Used for closing the general 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.edit_general_forum_topic`
|
||||
- Used to edit the general topic
|
||||
* - :meth:`~telegram.Bot.get_forum_topic_icon_stickers`
|
||||
- Used to get custom emojis to use as topic icons
|
||||
* - :meth:`~telegram.Bot.hide_general_forum_topic`
|
||||
- Used to hide the general topic
|
||||
* - :meth:`~telegram.Bot.unhide_general_forum_topic`
|
||||
- Used to unhide the general topic
|
||||
* - :meth:`~telegram.Bot.reopen_forum_topic`
|
||||
- Used to reopen a topic
|
||||
* - :meth:`~telegram.Bot.reopen_general_forum_topic`
|
||||
- Used to reopen the general topic
|
||||
* - :meth:`~telegram.Bot.unpin_all_forum_topic_messages`
|
||||
- Used to unpin all messages in a forum topic
|
||||
|
||||
|
|
|
@ -39,7 +39,10 @@ Available Types
|
|||
telegram.forumtopic
|
||||
telegram.forumtopicclosed
|
||||
telegram.forumtopiccreated
|
||||
telegram.forumtopicedited
|
||||
telegram.forumtopicreopened
|
||||
telegram.generalforumtopichidden
|
||||
telegram.generalforumtopicunhidden
|
||||
telegram.inlinekeyboardbutton
|
||||
telegram.inlinekeyboardmarkup
|
||||
telegram.inputfile
|
||||
|
@ -84,4 +87,5 @@ Available Types
|
|||
telegram.webappdata
|
||||
telegram.webappinfo
|
||||
telegram.webhookinfo
|
||||
telegram.writeaccessallowed
|
||||
|
||||
|
|
6
docs/source/telegram.forumtopicedited.rst
Normal file
6
docs/source/telegram.forumtopicedited.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
telegram.ForumTopicEdited
|
||||
=========================
|
||||
|
||||
.. autoclass:: telegram.ForumTopicEdited
|
||||
:members:
|
||||
:show-inheritance:
|
6
docs/source/telegram.generalforumtopichidden.rst
Normal file
6
docs/source/telegram.generalforumtopichidden.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
telegram.GeneralForumTopicHidden
|
||||
================================
|
||||
|
||||
.. autoclass:: telegram.GeneralForumTopicHidden
|
||||
:members:
|
||||
:show-inheritance:
|
6
docs/source/telegram.generalforumtopicunhidden.rst
Normal file
6
docs/source/telegram.generalforumtopicunhidden.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
telegram.GeneralForumTopicUnhidden
|
||||
==================================
|
||||
|
||||
.. autoclass:: telegram.GeneralForumTopicUnhidden
|
||||
:members:
|
||||
:show-inheritance:
|
6
docs/source/telegram.writeaccessallowed.rst
Normal file
6
docs/source/telegram.writeaccessallowed.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
telegram.WriteAccessAllowed
|
||||
===========================
|
||||
|
||||
.. autoclass:: telegram.WriteAccessAllowed
|
||||
:members:
|
||||
:show-inheritance:
|
|
@ -50,4 +50,4 @@
|
|||
|
||||
.. |sequenceargs| replace:: Accepts any :class:`collections.abc.Sequence` as input instead of just a list.
|
||||
|
||||
.. |captionentitiesattr| replace:: Tuple of special entities that appear in the caption, which can be specified instead of ``parse_mode``.
|
||||
.. |captionentitiesattr| replace:: Tuple of special entities that appear in the caption, which can be specified instead of ``parse_mode``.
|
||||
|
|
|
@ -70,9 +70,12 @@ __all__ = ( # Keep this alphabetically ordered
|
|||
"ForumTopic",
|
||||
"ForumTopicClosed",
|
||||
"ForumTopicCreated",
|
||||
"ForumTopicEdited",
|
||||
"ForumTopicReopened",
|
||||
"Game",
|
||||
"GameHighScore",
|
||||
"GeneralForumTopicHidden",
|
||||
"GeneralForumTopicUnhidden",
|
||||
"helpers",
|
||||
"IdDocumentData",
|
||||
"InlineKeyboardButton",
|
||||
|
@ -176,6 +179,7 @@ __all__ = ( # Keep this alphabetically ordered
|
|||
"WebAppData",
|
||||
"WebAppInfo",
|
||||
"WebhookInfo",
|
||||
"WriteAccessAllowed",
|
||||
)
|
||||
|
||||
|
||||
|
@ -234,7 +238,15 @@ from ._files.video import Video
|
|||
from ._files.videonote import VideoNote
|
||||
from ._files.voice import Voice
|
||||
from ._forcereply import ForceReply
|
||||
from ._forumtopic import ForumTopic, ForumTopicClosed, ForumTopicCreated, ForumTopicReopened
|
||||
from ._forumtopic import (
|
||||
ForumTopic,
|
||||
ForumTopicClosed,
|
||||
ForumTopicCreated,
|
||||
ForumTopicEdited,
|
||||
ForumTopicReopened,
|
||||
GeneralForumTopicHidden,
|
||||
GeneralForumTopicUnhidden,
|
||||
)
|
||||
from ._games.callbackgame import CallbackGame
|
||||
from ._games.game import Game
|
||||
from ._games.gamehighscore import GameHighScore
|
||||
|
@ -326,6 +338,7 @@ from ._videochat import (
|
|||
from ._webappdata import WebAppData
|
||||
from ._webappinfo import WebAppInfo
|
||||
from ._webhookinfo import WebhookInfo
|
||||
from ._writeaccessallowed import WriteAccessAllowed
|
||||
|
||||
#: :obj:`str`: The version of the `python-telegram-bot` library as string.
|
||||
#: To get detailed information about the version number, please use :data:`__version_info__`
|
||||
|
|
273
telegram/_bot.py
273
telegram/_bot.py
|
@ -919,6 +919,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -973,6 +974,10 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
:class:`ReplyKeyboardRemove` | :class:`ForceReply`, optional):
|
||||
Additional interface options. An object for an inline keyboard, custom reply
|
||||
keyboard, instructions to remove reply keyboard or to force a reply from the user.
|
||||
has_spoiler (:obj:`bool`, optional): Pass :obj:`True` if the photo needs to be covered
|
||||
with a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Keyword Args:
|
||||
filename (:obj:`str`, optional): Custom file name for the photo, when uploading a
|
||||
|
@ -991,6 +996,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
data: JSONDict = {
|
||||
"chat_id": chat_id,
|
||||
"photo": self._parse_file_input(photo, PhotoSize, filename=filename),
|
||||
"has_spoiler": has_spoiler,
|
||||
}
|
||||
|
||||
return await self._send_message(
|
||||
|
@ -1363,6 +1369,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -1438,6 +1445,10 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
.. versionchanged:: 20.0
|
||||
File paths as input is also accepted for bots *not* running in
|
||||
:paramref:`~telegram.Bot.local_mode`.
|
||||
has_spoiler (:obj:`bool`, optional): Pass :obj:`True` if the video needs to be covered
|
||||
with a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Keyword Args:
|
||||
filename (:obj:`str`, optional): Custom file name for the video, when uploading a
|
||||
|
@ -1461,6 +1472,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
"height": height,
|
||||
"supports_streaming": supports_streaming,
|
||||
"thumb": self._parse_file_input(thumb, attach=True) if thumb else None,
|
||||
"has_spoiler": has_spoiler,
|
||||
}
|
||||
|
||||
return await self._send_message(
|
||||
|
@ -1617,6 +1629,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -1687,6 +1700,10 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
:class:`ReplyKeyboardRemove` | :class:`ForceReply`, optional):
|
||||
Additional interface options. An object for an inline keyboard, custom reply
|
||||
keyboard, instructions to remove reply keyboard or to force a reply from the user.
|
||||
has_spoiler (:obj:`bool`, optional): Pass :obj:`True` if the animation needs to be
|
||||
covered with a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Keyword Args:
|
||||
filename (:obj:`str`, optional): Custom file name for the animation, when uploading a
|
||||
|
@ -1709,6 +1726,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
"width": width,
|
||||
"height": height,
|
||||
"thumb": self._parse_file_input(thumb, attach=True) if thumb else None,
|
||||
"has_spoiler": has_spoiler,
|
||||
}
|
||||
|
||||
return await self._send_message(
|
||||
|
@ -2553,6 +2571,7 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
self,
|
||||
chat_id: Union[str, int],
|
||||
action: str,
|
||||
message_thread_id: int = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2574,6 +2593,9 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
action(:obj:`str`): Type of action to broadcast. Choose one, depending on what the user
|
||||
is about to receive. For convenience look at the constants in
|
||||
:class:`telegram.constants.ChatAction`.
|
||||
message_thread_id (:obj:`int`, optional): |message_thread_id_arg|
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
@ -2582,7 +2604,11 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
:class:`telegram.error.TelegramError`
|
||||
|
||||
"""
|
||||
data: JSONDict = {"chat_id": chat_id, "action": action}
|
||||
data: JSONDict = {
|
||||
"chat_id": chat_id,
|
||||
"action": action,
|
||||
"message_thread_id": message_thread_id,
|
||||
}
|
||||
result = await self._post(
|
||||
"sendChatAction",
|
||||
data,
|
||||
|
@ -3913,7 +3939,8 @@ class Bot(TelegramObject, AbstractAsyncContextManager):
|
|||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
) -> ChatMember:
|
||||
"""Use this method to get information about a member of a chat.
|
||||
"""Use this method to get information about a member of a chat. The method is guaranteed
|
||||
to work only if the bot is an administrator in the chat.
|
||||
|
||||
.. seealso:: :meth:`telegram.Chat.get_member`
|
||||
|
||||
|
@ -6970,8 +6997,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
self,
|
||||
chat_id: Union[str, int],
|
||||
message_thread_id: int,
|
||||
name: str,
|
||||
icon_custom_emoji_id: str,
|
||||
name: str = None,
|
||||
icon_custom_emoji_id: str = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -6993,12 +7020,14 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
Args:
|
||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
|
||||
message_thread_id (:obj:`int`): |message_thread_id|
|
||||
name (:obj:`str`): New topic name,
|
||||
name (:obj:`str`, optional): New topic name,
|
||||
:tg-const:`telegram.constants.ForumTopicLimit.MIN_NAME_LENGTH`-
|
||||
:tg-const:`telegram.constants.ForumTopicLimit.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.
|
||||
:tg-const:`telegram.constants.ForumTopicLimit.MAX_NAME_LENGTH` characters. If
|
||||
not specified or empty, the current name of the topic will be kept.
|
||||
icon_custom_emoji_id (:obj:`str`, optional): 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.Pass an empty string to remove the
|
||||
icon. If not specified, the current icon will be kept.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
@ -7214,6 +7243,222 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@_log
|
||||
async def edit_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, int],
|
||||
name: 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 the name of the 'General' topic in a forum supergroup chat. The bot
|
||||
must be an administrator in the chat for this to work and must have
|
||||
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
|
||||
|
||||
.. seealso:: :meth:`telegram.Chat.edit_general_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.ForumTopicLimit.MIN_NAME_LENGTH`-
|
||||
:tg-const:`telegram.constants.ForumTopicLimit.MAX_NAME_LENGTH` characters.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.error.TelegramError`
|
||||
|
||||
"""
|
||||
data: JSONDict = {"chat_id": chat_id, "name": name}
|
||||
|
||||
return await self._post(
|
||||
"editGeneralForumTopic",
|
||||
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_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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 'General' topic in a forum supergroup chat. The bot must
|
||||
be an administrator in the chat for this to work and must have
|
||||
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
|
||||
|
||||
.. seealso:: :meth:`telegram.Chat.close_general_forum_topic`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Args:
|
||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.error.TelegramError`
|
||||
|
||||
"""
|
||||
data: JSONDict = {"chat_id": chat_id}
|
||||
|
||||
return await self._post(
|
||||
"closeGeneralForumTopic",
|
||||
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_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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 'General' topic in a forum supergroup chat. The bot must
|
||||
be an administrator in the chat for this to work and must have
|
||||
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
|
||||
The topic will be automatically unhidden if it was hidden.
|
||||
|
||||
.. seealso:: :meth:`telegram.Chat.reopen_general_forum_topic`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Args:
|
||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.error.TelegramError`
|
||||
|
||||
"""
|
||||
data: JSONDict = {"chat_id": chat_id}
|
||||
|
||||
return await self._post(
|
||||
"reopenGeneralForumTopic",
|
||||
data,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@_log
|
||||
async def hide_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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 hide the 'General' topic in a forum supergroup chat. The bot must
|
||||
be an administrator in the chat for this to work and must have
|
||||
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
|
||||
The topic will be automatically closed if it was open.
|
||||
|
||||
.. seealso:: :meth:`telegram.Chat.hide_general_forum_topic`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Args:
|
||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.error.TelegramError`
|
||||
|
||||
"""
|
||||
data: JSONDict = {"chat_id": chat_id}
|
||||
|
||||
return await self._post(
|
||||
"hideGeneralForumTopic",
|
||||
data,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@_log
|
||||
async def unhide_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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 unhide the 'General' topic in a forum supergroup chat. The bot must
|
||||
be an administrator in the chat for this to work and must have
|
||||
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
|
||||
|
||||
.. seealso:: :meth:`telegram.Chat.unhide_general_forum_topic`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Args:
|
||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.error.TelegramError`
|
||||
|
||||
"""
|
||||
data: JSONDict = {"chat_id": chat_id}
|
||||
|
||||
return await self._post(
|
||||
"unhideGeneralForumTopic",
|
||||
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}
|
||||
|
@ -7422,3 +7667,13 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
|||
"""Alias for :meth:`delete_forum_topic`"""
|
||||
unpinAllForumTopicMessages = unpin_all_forum_topic_messages
|
||||
"""Alias for :meth:`unpin_all_forum_topic_messages`"""
|
||||
editGeneralForumTopic = edit_general_forum_topic
|
||||
"""Alias for :meth:`edit_general_forum_topic`"""
|
||||
closeGeneralForumTopic = close_general_forum_topic
|
||||
"""Alias for :meth:`close_general_forum_topic`"""
|
||||
reopenGeneralForumTopic = reopen_general_forum_topic
|
||||
"""Alias for :meth:`reopen_general_forum_topic`"""
|
||||
hideGeneralForumTopic = hide_general_forum_topic
|
||||
"""Alias for :meth:`hide_general_forum_topic`"""
|
||||
unhideGeneralForumTopic = unhide_general_forum_topic
|
||||
"""Alias for :meth:`unhide_general_forum_topic`"""
|
||||
|
|
|
@ -164,6 +164,16 @@ class Chat(TelegramObject):
|
|||
status of the other party in a private chat. Returned only in
|
||||
:meth:`telegram.Bot.get_chat`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
has_aggressive_anti_spam_enabled (:obj:`bool`, optional): :obj:`True`, if aggressive
|
||||
anti-spam checks are enabled in the supergroup. The field is only available to chat
|
||||
administrators. Returned only in :meth:`telegram.Bot.get_chat`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
has_hidden_members (:obj:`bool`, optional): :obj:`True`, if non-administrators can only
|
||||
get the list of bots and administrators in the chat. Returned only in
|
||||
:meth:`telegram.Bot.get_chat`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Attributes:
|
||||
|
@ -247,6 +257,16 @@ class Chat(TelegramObject):
|
|||
status of the other party in a private chat. Returned only in
|
||||
:meth:`telegram.Bot.get_chat`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
has_aggressive_anti_spam_enabled (:obj:`bool`): Optional. :obj:`True`, if aggressive
|
||||
anti-spam checks are enabled in the supergroup. The field is only available to chat
|
||||
administrators. Returned only in :meth:`telegram.Bot.get_chat`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
has_hidden_members (:obj:`bool`): Optional. :obj:`True`, if non-administrators can only
|
||||
get the list of bots and administrators in the chat. Returned only in
|
||||
:meth:`telegram.Bot.get_chat`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
.. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups
|
||||
|
@ -279,6 +299,8 @@ class Chat(TelegramObject):
|
|||
"is_forum",
|
||||
"active_usernames",
|
||||
"emoji_status_custom_emoji_id",
|
||||
"has_hidden_members",
|
||||
"has_aggressive_anti_spam_enabled",
|
||||
)
|
||||
|
||||
SENDER: ClassVar[str] = constants.ChatType.SENDER
|
||||
|
@ -323,6 +345,8 @@ class Chat(TelegramObject):
|
|||
is_forum: bool = None,
|
||||
active_usernames: Sequence[str] = None,
|
||||
emoji_status_custom_emoji_id: str = None,
|
||||
has_aggressive_anti_spam_enabled: bool = None,
|
||||
has_hidden_members: bool = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
):
|
||||
|
@ -357,6 +381,8 @@ class Chat(TelegramObject):
|
|||
self.is_forum = is_forum
|
||||
self.active_usernames = parse_sequence_arg(active_usernames)
|
||||
self.emoji_status_custom_emoji_id = emoji_status_custom_emoji_id
|
||||
self.has_aggressive_anti_spam_enabled = has_aggressive_anti_spam_enabled
|
||||
self.has_hidden_members = has_hidden_members
|
||||
|
||||
self._id_attrs = (self.id,)
|
||||
|
||||
|
@ -1330,6 +1356,7 @@ class Chat(TelegramObject):
|
|||
async def send_chat_action(
|
||||
self,
|
||||
action: str,
|
||||
message_thread_id: int = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -1350,6 +1377,7 @@ class Chat(TelegramObject):
|
|||
return await self.get_bot().send_chat_action(
|
||||
chat_id=self.id,
|
||||
action=action,
|
||||
message_thread_id=message_thread_id,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
|
@ -1372,6 +1400,7 @@ class Chat(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -1408,6 +1437,7 @@ class Chat(TelegramObject):
|
|||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def send_contact(
|
||||
|
@ -1818,6 +1848,7 @@ class Chat(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -1858,6 +1889,7 @@ class Chat(TelegramObject):
|
|||
filename=filename,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def send_sticker(
|
||||
|
@ -1977,6 +2009,7 @@ class Chat(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2018,6 +2051,7 @@ class Chat(TelegramObject):
|
|||
filename=filename,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def send_video_note(
|
||||
|
@ -2663,8 +2697,8 @@ class Chat(TelegramObject):
|
|||
async def edit_forum_topic(
|
||||
self,
|
||||
message_thread_id: int,
|
||||
name: str,
|
||||
icon_custom_emoji_id: str,
|
||||
name: str = None,
|
||||
icon_custom_emoji_id: str = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2825,6 +2859,164 @@ class Chat(TelegramObject):
|
|||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
async def edit_general_forum_topic(
|
||||
self,
|
||||
name: 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_general_forum_topic(
|
||||
chat_id=update.effective_chat.id, *args, **kwargs
|
||||
)
|
||||
|
||||
For the documentation of the arguments, please see
|
||||
:meth:`telegram.Bot.edit_general_forum_topic`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().edit_general_forum_topic(
|
||||
chat_id=self.id,
|
||||
name=name,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
async def close_general_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_general_forum_topic(chat_id=update.effective_chat.id, *args, **kwargs)
|
||||
|
||||
For the documentation of the arguments, please see
|
||||
:meth:`telegram.Bot.close_general_forum_topic`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().close_general_forum_topic(
|
||||
chat_id=self.id,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
async def reopen_general_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_general_forum_topic(
|
||||
chat_id=update.effective_chat.id, *args, **kwargs
|
||||
)
|
||||
|
||||
For the documentation of the arguments, please see
|
||||
:meth:`telegram.Bot.reopen_general_forum_topic`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().reopen_general_forum_topic(
|
||||
chat_id=self.id,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
async def hide_general_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.hide_general_forum_topic(chat_id=update.effective_chat.id, *args, **kwargs)
|
||||
|
||||
For the documentation of the arguments, please see
|
||||
:meth:`telegram.Bot.hide_general_forum_topic`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().hide_general_forum_topic(
|
||||
chat_id=self.id,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
async def unhide_general_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.unhide_general_forum_topic (
|
||||
chat_id=update.effective_chat.id, *args, **kwargs
|
||||
)
|
||||
|
||||
For the documentation of the arguments, please see
|
||||
:meth:`telegram.Bot.unhide_general_forum_topic`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().unhide_general_forum_topic(
|
||||
chat_id=self.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,
|
||||
*,
|
||||
|
|
|
@ -150,6 +150,10 @@ class InputMediaAnimation(InputMedia):
|
|||
width (:obj:`int`, optional): Animation width.
|
||||
height (:obj:`int`, optional): Animation height.
|
||||
duration (:obj:`int`, optional): Animation duration in seconds.
|
||||
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the animation needs to be covered
|
||||
with a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.ANIMATION`.
|
||||
|
@ -168,10 +172,13 @@ class InputMediaAnimation(InputMedia):
|
|||
width (:obj:`int`): Optional. Animation width.
|
||||
height (:obj:`int`): Optional. Animation height.
|
||||
duration (:obj:`int`): Optional. Animation duration in seconds.
|
||||
has_spoiler (:obj:`bool`): Optional. :obj:`True`, if the animation is covered with a
|
||||
spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
__slots__ = ("duration", "height", "thumb", "width")
|
||||
__slots__ = ("duration", "height", "thumb", "width", "has_spoiler")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -184,6 +191,7 @@ class InputMediaAnimation(InputMedia):
|
|||
duration: int = None,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
):
|
||||
|
@ -210,6 +218,7 @@ class InputMediaAnimation(InputMedia):
|
|||
self.width = width
|
||||
self.height = height
|
||||
self.duration = duration
|
||||
self.has_spoiler = has_spoiler
|
||||
|
||||
|
||||
class InputMediaPhoto(InputMedia):
|
||||
|
@ -237,6 +246,10 @@ class InputMediaPhoto(InputMedia):
|
|||
|
||||
.. versionchanged:: 20.0
|
||||
|sequenceclassargs|
|
||||
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the photo needs to be covered
|
||||
with a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.PHOTO`.
|
||||
|
@ -251,10 +264,13 @@ class InputMediaPhoto(InputMedia):
|
|||
|
||||
* |tupleclassattrs|
|
||||
* |alwaystuple|
|
||||
has_spoiler (:obj:`bool`): Optional. :obj:`True`, if the photo is covered with a
|
||||
spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
__slots__ = ("has_spoiler",)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -263,6 +279,7 @@ class InputMediaPhoto(InputMedia):
|
|||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
):
|
||||
|
@ -278,7 +295,8 @@ class InputMediaPhoto(InputMedia):
|
|||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
self._freeze()
|
||||
with self._unfrozen():
|
||||
self.has_spoiler = has_spoiler
|
||||
|
||||
|
||||
class InputMediaVideo(InputMedia):
|
||||
|
@ -325,6 +343,10 @@ class InputMediaVideo(InputMedia):
|
|||
|
||||
.. versionchanged:: 13.2
|
||||
Accept :obj:`bytes` as input.
|
||||
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the video needs to be covered
|
||||
with a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.VIDEO`.
|
||||
|
@ -345,10 +367,13 @@ class InputMediaVideo(InputMedia):
|
|||
supports_streaming (:obj:`bool`): Optional. :obj:`True`, if the uploaded video is
|
||||
suitable for streaming.
|
||||
thumb (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
|
||||
has_spoiler (:obj:`bool`): Optional. :obj:`True`, if the video is covered with a
|
||||
spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
__slots__ = ("duration", "height", "thumb", "supports_streaming", "width")
|
||||
__slots__ = ("duration", "height", "thumb", "supports_streaming", "width", "has_spoiler")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -362,6 +387,7 @@ class InputMediaVideo(InputMedia):
|
|||
thumb: FileInput = None,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
):
|
||||
|
@ -390,6 +416,7 @@ class InputMediaVideo(InputMedia):
|
|||
self.duration = duration
|
||||
self.thumb = self._parse_thumb_input(thumb)
|
||||
self.supports_streaming = supports_streaming
|
||||
self.has_spoiler = has_spoiler
|
||||
|
||||
|
||||
class InputMediaAudio(InputMedia):
|
||||
|
|
|
@ -142,3 +142,73 @@ class ForumTopicReopened(TelegramObject):
|
|||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
self._freeze()
|
||||
|
||||
|
||||
class ForumTopicEdited(TelegramObject):
|
||||
"""
|
||||
This object represents a service message about an edited forum topic.
|
||||
|
||||
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||
considered equal, if their :attr:`name` and :attr:`icon_custom_emoji_id` are equal.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Args:
|
||||
name (:obj:`str`, optional): New name of the topic, if it was edited.
|
||||
icon_custom_emoji_id (:obj:`str`, optional): New identifier of the custom emoji shown as
|
||||
the topic icon, if it was edited; an empty string if the icon was removed.
|
||||
|
||||
Attributes:
|
||||
name (:obj:`str`): Optional. New name of the topic, if it was edited.
|
||||
icon_custom_emoji_id (:obj:`str`): Optional. New identifier of the custom emoji shown as
|
||||
the topic icon, if it was edited; an empty string if the icon was removed.
|
||||
"""
|
||||
|
||||
__slots__ = ("name", "icon_custom_emoji_id")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str = None,
|
||||
icon_custom_emoji_id: str = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.name = name
|
||||
self.icon_custom_emoji_id = icon_custom_emoji_id
|
||||
|
||||
self._id_attrs = (self.name, self.icon_custom_emoji_id)
|
||||
|
||||
self._freeze()
|
||||
|
||||
|
||||
class GeneralForumTopicHidden(TelegramObject):
|
||||
"""
|
||||
This object represents a service message about General forum topic hidden in the chat.
|
||||
Currently holds no information.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, *, api_kwargs: JSONDict = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
self._freeze()
|
||||
|
||||
|
||||
class GeneralForumTopicUnhidden(TelegramObject):
|
||||
"""
|
||||
This object represents a service message about General forum topic unhidden in the chat.
|
||||
Currently holds no information.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, *, api_kwargs: JSONDict = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
self._freeze()
|
||||
|
|
|
@ -36,7 +36,14 @@ from telegram._files.venue import Venue
|
|||
from telegram._files.video import Video
|
||||
from telegram._files.videonote import VideoNote
|
||||
from telegram._files.voice import Voice
|
||||
from telegram._forumtopic import ForumTopicClosed, ForumTopicCreated, ForumTopicReopened
|
||||
from telegram._forumtopic import (
|
||||
ForumTopicClosed,
|
||||
ForumTopicCreated,
|
||||
ForumTopicEdited,
|
||||
ForumTopicReopened,
|
||||
GeneralForumTopicHidden,
|
||||
GeneralForumTopicUnhidden,
|
||||
)
|
||||
from telegram._games.game import Game
|
||||
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
|
||||
from telegram._messageautodeletetimerchanged import MessageAutoDeleteTimerChanged
|
||||
|
@ -59,6 +66,7 @@ from telegram._videochat import (
|
|||
VideoChatStarted,
|
||||
)
|
||||
from telegram._webappdata import WebAppData
|
||||
from telegram._writeaccessallowed import WriteAccessAllowed
|
||||
from telegram.constants import MessageAttachmentType, ParseMode
|
||||
from telegram.helpers import escape_markdown
|
||||
|
||||
|
@ -277,15 +285,35 @@ class Message(TelegramObject):
|
|||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_created (:class:`telegram.ForumTopicCreated`, optional): Service message:
|
||||
forum topic created
|
||||
forum topic created.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_closed (:class:`telegram.ForumTopicClosed`, optional): Service message:
|
||||
forum topic closed
|
||||
forum topic closed.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_reopened (:class:`telegram.ForumTopicReopened`, optional): Service message:
|
||||
forum topic reopened
|
||||
forum topic reopened.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_edited (:class:`telegram.ForumTopicEdited`, optional): Service message:
|
||||
forum topic edited.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
general_forum_topic_hidden (:class:`telegram.GeneralForumTopicHidden`, optional):
|
||||
Service message: General forum topic hidden.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
general_forum_topic_unhidden (:class:`telegram.GeneralForumTopicUnhidden`, optional):
|
||||
Service message: General forum topic unhidden.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
write_access_allowed (:class:`telegram.WriteAccessAllowed`, optional): Service message:
|
||||
the user allowed the bot added to the attachment menu to write messages.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
has_media_spoiler (:obj:`bool`, optional): :obj:`True`, if the message media is covered
|
||||
by a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
|
@ -484,15 +512,35 @@ class Message(TelegramObject):
|
|||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_created (:class:`telegram.ForumTopicCreated`): Optional. Service message:
|
||||
forum topic created
|
||||
forum topic created.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_closed (:class:`telegram.ForumTopicClosed`): Optional. Service message:
|
||||
forum topic closed
|
||||
forum topic closed.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_reopened (:class:`telegram.ForumTopicReopened`): Optional. Service message:
|
||||
forum topic reopened
|
||||
forum topic reopened.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
forum_topic_edited (:class:`telegram.ForumTopicEdited`): Optional. Service message:
|
||||
forum topic edited.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
general_forum_topic_hidden (:class:`telegram.GeneralForumTopicHidden`): Optional.
|
||||
Service message: General forum topic hidden.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
general_forum_topic_unhidden (:class:`telegram.GeneralForumTopicUnhidden`): Optional.
|
||||
Service message: General forum topic unhidden.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
write_access_allowed (:class:`telegram.WriteAccessAllowed`): Optional. Service message:
|
||||
the user allowed the bot added to the attachment menu to write messages.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
has_media_spoiler (:obj:`bool`): Optional. :obj:`True`, if the message media is covered
|
||||
by a spoiler animation.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
|
@ -567,6 +615,11 @@ class Message(TelegramObject):
|
|||
"forum_topic_created",
|
||||
"forum_topic_closed",
|
||||
"forum_topic_reopened",
|
||||
"forum_topic_edited",
|
||||
"general_forum_topic_hidden",
|
||||
"general_forum_topic_unhidden",
|
||||
"write_access_allowed",
|
||||
"has_media_spoiler",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
|
@ -635,6 +688,11 @@ class Message(TelegramObject):
|
|||
forum_topic_created: ForumTopicCreated = None,
|
||||
forum_topic_closed: ForumTopicClosed = None,
|
||||
forum_topic_reopened: ForumTopicReopened = None,
|
||||
forum_topic_edited: ForumTopicEdited = None,
|
||||
general_forum_topic_hidden: GeneralForumTopicHidden = None,
|
||||
general_forum_topic_unhidden: GeneralForumTopicUnhidden = None,
|
||||
write_access_allowed: WriteAccessAllowed = None,
|
||||
has_media_spoiler: bool = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
):
|
||||
|
@ -706,6 +764,11 @@ class Message(TelegramObject):
|
|||
self.forum_topic_created = forum_topic_created
|
||||
self.forum_topic_closed = forum_topic_closed
|
||||
self.forum_topic_reopened = forum_topic_reopened
|
||||
self.forum_topic_edited = forum_topic_edited
|
||||
self.general_forum_topic_hidden = general_forum_topic_hidden
|
||||
self.general_forum_topic_unhidden = general_forum_topic_unhidden
|
||||
self.write_access_allowed = write_access_allowed
|
||||
self.has_media_spoiler = has_media_spoiler
|
||||
|
||||
self._effective_attachment = DEFAULT_NONE
|
||||
|
||||
|
@ -805,6 +868,16 @@ class Message(TelegramObject):
|
|||
data["forum_topic_reopened"] = ForumTopicReopened.de_json(
|
||||
data.get("forum_topic_reopened"), bot
|
||||
)
|
||||
data["forum_topic_edited"] = ForumTopicEdited.de_json(data.get("forum_topic_edited"), bot)
|
||||
data["general_forum_topic_hidden"] = GeneralForumTopicHidden.de_json(
|
||||
data.get("general_forum_topic_hidden"), bot
|
||||
)
|
||||
data["general_forum_topic_unhidden"] = GeneralForumTopicUnhidden.de_json(
|
||||
data.get("general_forum_topic_unhidden"), bot
|
||||
)
|
||||
data["write_access_allowed"] = WriteAccessAllowed.de_json(
|
||||
data.get("write_access_allowed"), bot
|
||||
)
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
|
@ -1203,6 +1276,7 @@ class Message(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
quote: bool = None,
|
||||
|
@ -1246,6 +1320,7 @@ class Message(TelegramObject):
|
|||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def reply_audio(
|
||||
|
@ -1390,6 +1465,7 @@ class Message(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
quote: bool = None,
|
||||
|
@ -1438,6 +1514,7 @@ class Message(TelegramObject):
|
|||
filename=filename,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def reply_sticker(
|
||||
|
@ -1506,6 +1583,7 @@ class Message(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
quote: bool = None,
|
||||
|
@ -1554,6 +1632,7 @@ class Message(TelegramObject):
|
|||
filename=filename,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def reply_video_note(
|
||||
|
@ -1980,6 +2059,7 @@ class Message(TelegramObject):
|
|||
async def reply_chat_action(
|
||||
self,
|
||||
action: str,
|
||||
message_thread_id: int = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2001,6 +2081,7 @@ class Message(TelegramObject):
|
|||
"""
|
||||
return await self.get_bot().send_chat_action(
|
||||
chat_id=self.chat_id,
|
||||
message_thread_id=message_thread_id,
|
||||
action=action,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
|
@ -2815,8 +2896,8 @@ class Message(TelegramObject):
|
|||
|
||||
async def edit_forum_topic(
|
||||
self,
|
||||
name: str,
|
||||
icon_custom_emoji_id: str,
|
||||
name: str = None,
|
||||
icon_custom_emoji_id: str = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
|
|
@ -68,6 +68,11 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
characters.
|
||||
|
||||
.. versionadded:: 13.7
|
||||
is_persistent (:obj:`bool`, optional): Requests clients to always show the keyboard when
|
||||
the regular keyboard is hidden. Defaults to :obj:`False`, in which case the custom
|
||||
keyboard can be hidden and opened with a keyboard icon.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Attributes:
|
||||
keyboard (Tuple[Tuple[:class:`telegram.KeyboardButton`]]): Array of button rows,
|
||||
|
@ -97,6 +102,11 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
characters.
|
||||
|
||||
.. versionadded:: 13.7
|
||||
is_persistent (:obj:`bool`): Optional. Requests clients to always show the keyboard when
|
||||
the regular keyboard is hidden. If :obj:`False`, the custom keyboard can be hidden and
|
||||
opened with a keyboard icon.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
"""
|
||||
|
||||
|
@ -106,6 +116,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
"resize_keyboard",
|
||||
"one_time_keyboard",
|
||||
"input_field_placeholder",
|
||||
"is_persistent",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
|
@ -115,6 +126,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
one_time_keyboard: bool = None,
|
||||
selective: bool = None,
|
||||
input_field_placeholder: str = None,
|
||||
is_persistent: bool = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
):
|
||||
|
@ -136,6 +148,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
self.one_time_keyboard = one_time_keyboard
|
||||
self.selective = selective
|
||||
self.input_field_placeholder = input_field_placeholder
|
||||
self.is_persistent = is_persistent
|
||||
|
||||
self._id_attrs = (self.keyboard,)
|
||||
|
||||
|
@ -149,6 +162,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
one_time_keyboard: bool = False,
|
||||
selective: bool = False,
|
||||
input_field_placeholder: str = None,
|
||||
is_persistent: bool = None,
|
||||
**kwargs: object,
|
||||
) -> "ReplyKeyboardMarkup":
|
||||
"""Shortcut for::
|
||||
|
@ -182,6 +196,11 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
field when the reply is active.
|
||||
|
||||
.. versionadded:: 13.7
|
||||
is_persistent (:obj:`bool`): Optional. Requests clients to always show the keyboard
|
||||
when the regular keyboard is hidden. Defaults to :obj:`False`, in which case the
|
||||
custom keyboard can be hidden and opened with a keyboard icon.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
return cls(
|
||||
[[button]],
|
||||
|
@ -189,6 +208,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
one_time_keyboard=one_time_keyboard,
|
||||
selective=selective,
|
||||
input_field_placeholder=input_field_placeholder,
|
||||
is_persistent=is_persistent,
|
||||
**kwargs, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
|
@ -200,6 +220,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
one_time_keyboard: bool = False,
|
||||
selective: bool = False,
|
||||
input_field_placeholder: str = None,
|
||||
is_persistent: bool = None,
|
||||
**kwargs: object,
|
||||
) -> "ReplyKeyboardMarkup":
|
||||
"""Shortcut for::
|
||||
|
@ -236,6 +257,11 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
field when the reply is active.
|
||||
|
||||
.. versionadded:: 13.7
|
||||
is_persistent (:obj:`bool`): Optional. Requests clients to always show the keyboard
|
||||
when the regular keyboard is hidden. Defaults to :obj:`False`, in which case the
|
||||
custom keyboard can be hidden and opened with a keyboard icon.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
"""
|
||||
return cls(
|
||||
|
@ -244,6 +270,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
one_time_keyboard=one_time_keyboard,
|
||||
selective=selective,
|
||||
input_field_placeholder=input_field_placeholder,
|
||||
is_persistent=is_persistent,
|
||||
**kwargs, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
|
@ -255,6 +282,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
one_time_keyboard: bool = False,
|
||||
selective: bool = False,
|
||||
input_field_placeholder: str = None,
|
||||
is_persistent: bool = None,
|
||||
**kwargs: object,
|
||||
) -> "ReplyKeyboardMarkup":
|
||||
"""Shortcut for::
|
||||
|
@ -291,6 +319,11 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
field when the reply is active.
|
||||
|
||||
.. versionadded:: 13.7
|
||||
is_persistent (:obj:`bool`): Optional. Requests clients to always show the keyboard
|
||||
when the regular keyboard is hidden. Defaults to :obj:`False`, in which case the
|
||||
custom keyboard can be hidden and opened with a keyboard icon.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
"""
|
||||
button_grid = [[button] for button in button_column]
|
||||
|
@ -300,6 +333,7 @@ class ReplyKeyboardMarkup(TelegramObject):
|
|||
one_time_keyboard=one_time_keyboard,
|
||||
selective=selective,
|
||||
input_field_placeholder=input_field_placeholder,
|
||||
is_persistent=is_persistent,
|
||||
**kwargs, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
|
|
|
@ -427,6 +427,7 @@ class User(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -463,6 +464,7 @@ class User(TelegramObject):
|
|||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def send_media_group(
|
||||
|
@ -575,6 +577,7 @@ class User(TelegramObject):
|
|||
async def send_chat_action(
|
||||
self,
|
||||
action: str,
|
||||
message_thread_id: int = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -595,6 +598,7 @@ class User(TelegramObject):
|
|||
return await self.get_bot().send_chat_action(
|
||||
chat_id=self.id,
|
||||
action=action,
|
||||
message_thread_id=message_thread_id,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
|
@ -955,6 +959,7 @@ class User(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -995,6 +1000,7 @@ class User(TelegramObject):
|
|||
filename=filename,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def send_sticker(
|
||||
|
@ -1056,6 +1062,7 @@ class User(TelegramObject):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -1097,6 +1104,7 @@ class User(TelegramObject):
|
|||
filename=filename,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
)
|
||||
|
||||
async def send_venue(
|
||||
|
|
37
telegram/_writeaccessallowed.py
Normal file
37
telegram/_writeaccessallowed.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2022
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains objects related to the write access allowed service message."""
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
|
||||
class WriteAccessAllowed(TelegramObject):
|
||||
"""
|
||||
This object represents a service message about a user allowing a bot added to the attachment
|
||||
menu to write messages. Currently holds no information.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, *, api_kwargs: JSONDict = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
self._freeze()
|
|
@ -111,7 +111,7 @@ class _BotAPIVersion(NamedTuple):
|
|||
#: :data:`telegram.__bot_api_version_info__`.
|
||||
#:
|
||||
#: .. versionadded:: 20.0
|
||||
BOT_API_VERSION_INFO = _BotAPIVersion(major=6, minor=3)
|
||||
BOT_API_VERSION_INFO = _BotAPIVersion(major=6, minor=4)
|
||||
#: :obj:`str`: Telegram Bot API
|
||||
#: version supported by this version of `python-telegram-bot`. Also available as
|
||||
#: :data:`telegram.__bot_api_version__`.
|
||||
|
@ -1568,14 +1568,22 @@ class ForumTopicLimit(IntEnum):
|
|||
__slots__ = ()
|
||||
|
||||
MIN_NAME_LENGTH = 1
|
||||
""":obj:`int`: Minimum length of a :obj:`str` passed as the
|
||||
:paramref:`~telegram.Bot.create_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.create_forum_topic` and :paramref:`~telegram.Bot.edit_forum_topic.name`
|
||||
parameter of :meth:`telegram.Bot.edit_forum_topic`.
|
||||
""":obj:`int`: Minimum length of a :obj:`str` passed as:
|
||||
|
||||
* :paramref:`~telegram.Bot.create_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.create_forum_topic`
|
||||
* :paramref:`~telegram.Bot.edit_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.edit_forum_topic`
|
||||
* :paramref:`~telegram.Bot.edit_general_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.edit_general_forum_topic`
|
||||
"""
|
||||
MAX_NAME_LENGTH = 128
|
||||
""":obj:`int`: Maximum length of a :obj:`str` passed as the
|
||||
:paramref:`~telegram.Bot.create_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.create_forum_topic` and :paramref:`~telegram.Bot.edit_forum_topic.name`
|
||||
parameter of :meth:`telegram.Bot.edit_forum_topic`.
|
||||
""":obj:`int`: Maximum length of a :obj:`str` passed as:
|
||||
|
||||
* :paramref:`~telegram.Bot.create_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.create_forum_topic`
|
||||
* :paramref:`~telegram.Bot.edit_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.edit_forum_topic`
|
||||
* :paramref:`~telegram.Bot.edit_general_forum_topic.name` parameter of
|
||||
:meth:`telegram.Bot.edit_general_forum_topic`
|
||||
"""
|
||||
|
|
|
@ -1264,8 +1264,8 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
self,
|
||||
chat_id: Union[str, int],
|
||||
message_thread_id: int,
|
||||
name: str,
|
||||
icon_custom_emoji_id: str,
|
||||
name: str = None,
|
||||
icon_custom_emoji_id: str = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -1286,6 +1286,28 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
||||
)
|
||||
|
||||
async def edit_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, int],
|
||||
name: 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_general_forum_topic(
|
||||
chat_id=chat_id,
|
||||
name=name,
|
||||
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,
|
||||
|
@ -1862,6 +1884,26 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
||||
)
|
||||
|
||||
async def close_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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_general_forum_topic(
|
||||
chat_id=chat_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],
|
||||
|
@ -1888,6 +1930,66 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
||||
)
|
||||
|
||||
async def reopen_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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_general_forum_topic(
|
||||
chat_id=chat_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 hide_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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().hide_general_forum_topic(
|
||||
chat_id=chat_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 unhide_general_forum_topic(
|
||||
self,
|
||||
chat_id: Union[str, 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().unhide_general_forum_topic(
|
||||
chat_id=chat_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],
|
||||
|
@ -2045,6 +2147,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2070,6 +2173,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
caption_entities=caption_entities,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
filename=filename,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
|
@ -2132,6 +2236,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
self,
|
||||
chat_id: Union[str, int],
|
||||
action: str,
|
||||
message_thread_id: int = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2143,6 +2248,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
return await super().send_chat_action(
|
||||
chat_id=chat_id,
|
||||
action=action,
|
||||
message_thread_id=message_thread_id,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
|
@ -2519,6 +2625,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2540,6 +2647,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
caption_entities=caption_entities,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
filename=filename,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
|
@ -2706,6 +2814,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
has_spoiler: bool = None,
|
||||
*,
|
||||
filename: str = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
@ -2732,6 +2841,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
caption_entities=caption_entities,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
filename=filename,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
|
@ -3414,3 +3524,8 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
reopenForumTopic = reopen_forum_topic
|
||||
deleteForumTopic = delete_forum_topic
|
||||
unpinAllForumTopicMessages = unpin_all_forum_topic_messages
|
||||
editGeneralForumTopic = edit_general_forum_topic
|
||||
closeGeneralForumTopic = close_general_forum_topic
|
||||
reopenGeneralForumTopic = reopen_general_forum_topic
|
||||
hideGeneralForumTopic = hide_general_forum_topic
|
||||
unhideGeneralForumTopic = unhide_general_forum_topic
|
||||
|
|
|
@ -58,6 +58,7 @@ __all__ = (
|
|||
"FORWARDED",
|
||||
"ForwardedFrom",
|
||||
"GAME",
|
||||
"HAS_MEDIA_SPOILER",
|
||||
"HAS_PROTECTED_CONTENT",
|
||||
"INVOICE",
|
||||
"IS_AUTOMATIC_FORWARD",
|
||||
|
@ -1383,6 +1384,20 @@ GAME = _Game(name="filters.GAME")
|
|||
"""Messages that contain :attr:`telegram.Message.game`."""
|
||||
|
||||
|
||||
class _HasMediaSpoiler(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
return bool(message.has_media_spoiler)
|
||||
|
||||
|
||||
HAS_MEDIA_SPOILER = _HasMediaSpoiler(name="filters.HAS_MEDIA_SPOILER")
|
||||
"""Messages that contain :attr:`telegram.Message.has_media_spoiler`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
|
||||
class _HasProtectedContent(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
|
@ -1721,6 +1736,10 @@ class StatusUpdate:
|
|||
or StatusUpdate.FORUM_TOPIC_CREATED.check_update(update)
|
||||
or StatusUpdate.FORUM_TOPIC_CLOSED.check_update(update)
|
||||
or StatusUpdate.FORUM_TOPIC_REOPENED.check_update(update)
|
||||
or StatusUpdate.FORUM_TOPIC_EDITED.check_update(update)
|
||||
or StatusUpdate.GENERAL_FORUM_TOPIC_HIDDEN.check_update(update)
|
||||
or StatusUpdate.GENERAL_FORUM_TOPIC_UNHIDDEN.check_update(update)
|
||||
or StatusUpdate.WRITE_ACCESS_ALLOWED.check_update(update)
|
||||
)
|
||||
|
||||
ALL = _All(name="filters.StatusUpdate.ALL")
|
||||
|
@ -1783,6 +1802,18 @@ class StatusUpdate:
|
|||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
class _ForumTopicEdited(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
return bool(message.forum_topic_edited)
|
||||
|
||||
FORUM_TOPIC_EDITED = _ForumTopicEdited(name="filters.StatusUpdate.FORUM_TOPIC_EDITED")
|
||||
"""Messages that contain :attr:`telegram.Message.forum_topic_edited`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
class _ForumTopicReopened(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
|
@ -1795,6 +1826,34 @@ class StatusUpdate:
|
|||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
class _GeneralForumTopicHidden(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
return bool(message.general_forum_topic_hidden)
|
||||
|
||||
GENERAL_FORUM_TOPIC_HIDDEN = _GeneralForumTopicHidden(
|
||||
name="filters.StatusUpdate.GENERAL_FORUM_TOPIC_HIDDEN"
|
||||
)
|
||||
"""Messages that contain :attr:`telegram.Message.general_forum_topic_hidden`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
class _GeneralForumTopicUnhidden(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
return bool(message.general_forum_topic_unhidden)
|
||||
|
||||
GENERAL_FORUM_TOPIC_UNHIDDEN = _GeneralForumTopicUnhidden(
|
||||
name="filters.StatusUpdate.GENERAL_FORUM_TOPIC_UNHIDDEN"
|
||||
)
|
||||
"""Messages that contain :attr:`telegram.Message.general_forum_topic_unhidden`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
class _LeftChatMember(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
|
@ -1945,6 +2004,18 @@ class StatusUpdate:
|
|||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
class _WriteAccessAllowed(MessageFilter):
|
||||
__slots__ = ()
|
||||
|
||||
def filter(self, message: Message) -> bool:
|
||||
return bool(message.write_access_allowed)
|
||||
|
||||
WRITE_ACCESS_ALLOWED = _WriteAccessAllowed(name="filters.StatusUpdate.WRITE_ACCESS_ALLOWED")
|
||||
"""Messages that contain :attr:`telegram.Message.write_access_allowed`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
|
||||
class Sticker:
|
||||
"""Filters messages which contain a sticker.
|
||||
|
|
|
@ -27,15 +27,15 @@ import random
|
|||
# purposes than testing.
|
||||
FALLBACKS = (
|
||||
"W3sidG9rZW4iOiAiNTc5Njk0NzE0OkFBRnBLOHc2emtrVXJENHhTZVl3RjNNTzhlLTRHcm1jeTdjIiwgInBheW1lbnRfc"
|
||||
"HJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TmpRME5qWmxOekk1WWpKaSIsICJjaGF0X2lkIjogIjY3NTY2Nj"
|
||||
"IyNCIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTMxMDkxMTEzNSIsICJmb3J1bV9ncm91cF9pZCI6ICItMTAwMTYxOTE"
|
||||
"1OTQwNCIsICJjaGFubmVsX2lkIjogIkBweXRob250ZWxlZ3JhbWJvdHRlc3RzIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0"
|
||||
"cyBmYWxsYmFjayAxIiwgImJvdF91c2VybmFtZSI6ICJAcHRiX2ZhbGxiYWNrXzFfYm90In0sIHsidG9rZW4iOiAiNTU4M"
|
||||
"Tk0MDY2OkFBRndEUElGbHpHVWxDYVdIdFRPRVg0UkZyWDh1OURNcWZvIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOi"
|
||||
"AiMjg0Njg1MDYzOlRFU1Q6WWpFd09EUXdNVEZtTkRjeSIsICJjaGF0X2lkIjogIjY3NTY2NjIyNCIsICJzdXBlcl9ncm9"
|
||||
"1cF9pZCI6ICItMTAwMTIyMTIxNjgzMCIsICJmb3J1bV9ncm91cF9pZCI6ICItMTAwMTYxOTE1OTQwNCIsICJjaGFubmVs"
|
||||
"X2lkIjogIkBweXRob250ZWxlZ3JhbWJvdHRlc3RzIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0cyBmYWxsYmFjayAyIiwgI"
|
||||
"mJvdF91c2VybmFtZSI6ICJAcHRiX2ZhbGxiYWNrXzJfYm90In1d "
|
||||
"HJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TmpRME5qWmxOekk1WWpKaSIsICJjaGF0X2 lkIjogIjY3NTY2N"
|
||||
"jIyNCIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTMxMDkxMTEzNSIsICJmb3J1bV9ncm91cF9pZCI6ICItMTAwMTgzOD"
|
||||
"AwNDU3NyIsICJjaGFubmVsX2lkIjogIkBweXRob250ZWxlZ3JhbWJvdHRlc3RzIi wgIm5hbWUiOiAiUFRCIHRlc3RzIG"
|
||||
"ZhbGxiYWNrIDEiLCAidXNlcm5hbWUiOiAiQHB0Yl9mYWxsYmFja18xX2JvdCJ9LCB7InRva2VuIjogIjU1ODE5NDA2Njp"
|
||||
"BQUZ3RFBJRmx6R1VsQ2FXSHRUT0VYNFJGclg4dTlETXFmbyIsIC JwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY"
|
||||
"4NTA2MzpURVNUOllqRXdPRFF3TVRGbU5EY3kiLCAiY2hhdF9pZCI6ICI2NzU2NjYyMjQiLCAic3VwZXJfZ3JvdXBfaWQi"
|
||||
"OiAiLTEwMDEyMjEyMTY4MzAiLCAiZm9ydW1fZ3 JvdXBfaWQiOiAiLTEwMDE4NTc4NDgzMTQiLCAiY2hhbm5lbF9pZCI6"
|
||||
"ICJAcHl0aG9udGVsZWdyYW1ib3R0ZXN0cyIsICJuYW1lIjogIlBUQiB0ZXN0cyBmYWxsYmFjayAyIiwgInVzZXJuYW1lI"
|
||||
"jogIkBwdGJfZmFsbGJhY2tfMl9ib3QifV0="
|
||||
)
|
||||
|
||||
GITHUB_ACTION = os.getenv("GITHUB_ACTION", None)
|
||||
|
|
|
@ -93,6 +93,7 @@ class TestAnimation:
|
|||
disable_notification=False,
|
||||
protect_content=True,
|
||||
thumb=thumb_file,
|
||||
has_spoiler=True,
|
||||
)
|
||||
|
||||
assert isinstance(message.animation, Animation)
|
||||
|
@ -106,6 +107,10 @@ class TestAnimation:
|
|||
assert message.animation.thumb.width == self.width
|
||||
assert message.animation.thumb.height == self.height
|
||||
assert message.has_protected_content
|
||||
try:
|
||||
assert message.has_media_spoiler
|
||||
except AssertionError:
|
||||
pytest.xfail("This is a bug on Telegram's end")
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
async def test_send_animation_custom_filename(self, bot, chat_id, animation_file, monkeypatch):
|
||||
|
|
|
@ -967,6 +967,18 @@ class TestBot:
|
|||
with pytest.raises(BadRequest, match="Wrong parameter action"):
|
||||
await bot.send_chat_action(chat_id, "unknown action")
|
||||
|
||||
async def test_send_chat_action_all_args(self, bot, chat_id, provider_token, monkeypatch):
|
||||
async def make_assertion(*args, **_):
|
||||
kwargs = args[1]
|
||||
return (
|
||||
kwargs["chat_id"] == chat_id
|
||||
and kwargs["action"] == "action"
|
||||
and kwargs["message_thread_id"] == 1
|
||||
)
|
||||
|
||||
monkeypatch.setattr(bot, "_post", make_assertion)
|
||||
assert await bot.send_chat_action(chat_id, "action", 1)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_answer_web_app_query(self, bot, raw_bot, monkeypatch):
|
||||
params = False
|
||||
|
@ -2525,7 +2537,7 @@ class TestBot:
|
|||
# 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...
|
||||
# get_forum_topic_icon_stickers, edit_forum_topic, general_forum etc...
|
||||
# are tested in the test_forum module.
|
||||
|
||||
async def test_timeout_propagation_explicit(self, monkeypatch, bot, chat_id):
|
||||
|
|
|
@ -51,6 +51,8 @@ def chat(bot):
|
|||
is_forum=True,
|
||||
active_usernames=TestChat.active_usernames,
|
||||
emoji_status_custom_emoji_id=TestChat.emoji_status_custom_emoji_id,
|
||||
has_aggressive_anti_spam_enabled=TestChat.has_aggressive_anti_spam_enabled,
|
||||
has_hidden_members=TestChat.has_hidden_members,
|
||||
)
|
||||
chat.set_bot(bot)
|
||||
chat._unfreeze()
|
||||
|
@ -82,6 +84,8 @@ class TestChat:
|
|||
is_forum = True
|
||||
active_usernames = ["These", "Are", "Usernames!"]
|
||||
emoji_status_custom_emoji_id = "VeryUniqueCustomEmojiID"
|
||||
has_aggressive_anti_spam_enabled = True
|
||||
has_hidden_members = True
|
||||
|
||||
def test_slot_behaviour(self, chat, mro_slots):
|
||||
for attr in chat.__slots__:
|
||||
|
@ -112,6 +116,8 @@ class TestChat:
|
|||
"is_forum": self.is_forum,
|
||||
"active_usernames": self.active_usernames,
|
||||
"emoji_status_custom_emoji_id": self.emoji_status_custom_emoji_id,
|
||||
"has_aggressive_anti_spam_enabled": self.has_aggressive_anti_spam_enabled,
|
||||
"has_hidden_members": self.has_hidden_members,
|
||||
}
|
||||
chat = Chat.de_json(json_dict, bot)
|
||||
|
||||
|
@ -141,6 +147,8 @@ class TestChat:
|
|||
assert chat.is_forum == self.is_forum
|
||||
assert chat.active_usernames == tuple(self.active_usernames)
|
||||
assert chat.emoji_status_custom_emoji_id == self.emoji_status_custom_emoji_id
|
||||
assert chat.has_aggressive_anti_spam_enabled == self.has_aggressive_anti_spam_enabled
|
||||
assert chat.has_hidden_members == self.has_hidden_members
|
||||
|
||||
def test_to_dict(self, chat):
|
||||
chat_dict = chat.to_dict()
|
||||
|
@ -166,6 +174,10 @@ class TestChat:
|
|||
assert chat_dict["is_forum"] == chat.is_forum
|
||||
assert chat_dict["active_usernames"] == list(chat.active_usernames)
|
||||
assert chat_dict["emoji_status_custom_emoji_id"] == chat.emoji_status_custom_emoji_id
|
||||
assert (
|
||||
chat_dict["has_aggressive_anti_spam_enabled"] == chat.has_aggressive_anti_spam_enabled
|
||||
)
|
||||
assert chat_dict["has_hidden_members"] == chat.has_hidden_members
|
||||
|
||||
def test_always_tuples_attributes(self):
|
||||
chat = Chat(
|
||||
|
@ -1032,6 +1044,111 @@ class TestChat:
|
|||
monkeypatch.setattr(chat.get_bot(), "unpin_all_forum_topic_messages", make_assertion)
|
||||
assert await chat.unpin_all_forum_topic_messages(message_thread_id=42)
|
||||
|
||||
async def test_edit_general_forum_topic(self, monkeypatch, chat):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
return kwargs["chat_id"] == chat.id and kwargs["name"] == "WhatAName"
|
||||
|
||||
assert check_shortcut_signature(
|
||||
Chat.edit_general_forum_topic,
|
||||
Bot.edit_general_forum_topic,
|
||||
["chat_id"],
|
||||
[],
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
chat.edit_general_forum_topic,
|
||||
chat.get_bot(),
|
||||
"edit_general_forum_topic",
|
||||
shortcut_kwargs=["chat_id"],
|
||||
)
|
||||
assert await check_defaults_handling(chat.edit_general_forum_topic, chat.get_bot())
|
||||
|
||||
monkeypatch.setattr(chat.get_bot(), "edit_general_forum_topic", make_assertion)
|
||||
assert await chat.edit_general_forum_topic(name="WhatAName")
|
||||
|
||||
async def test_close_general_forum_topic(self, monkeypatch, chat):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
return kwargs["chat_id"] == chat.id
|
||||
|
||||
assert check_shortcut_signature(
|
||||
Chat.close_general_forum_topic,
|
||||
Bot.close_general_forum_topic,
|
||||
["chat_id"],
|
||||
[],
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
chat.close_general_forum_topic,
|
||||
chat.get_bot(),
|
||||
"close_general_forum_topic",
|
||||
shortcut_kwargs=["chat_id"],
|
||||
)
|
||||
assert await check_defaults_handling(chat.close_general_forum_topic, chat.get_bot())
|
||||
|
||||
monkeypatch.setattr(chat.get_bot(), "close_general_forum_topic", make_assertion)
|
||||
assert await chat.close_general_forum_topic()
|
||||
|
||||
async def test_reopen_general_forum_topic(self, monkeypatch, chat):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
return kwargs["chat_id"] == chat.id
|
||||
|
||||
assert check_shortcut_signature(
|
||||
Chat.reopen_general_forum_topic,
|
||||
Bot.reopen_general_forum_topic,
|
||||
["chat_id"],
|
||||
[],
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
chat.reopen_general_forum_topic,
|
||||
chat.get_bot(),
|
||||
"reopen_general_forum_topic",
|
||||
shortcut_kwargs=["chat_id"],
|
||||
)
|
||||
assert await check_defaults_handling(chat.reopen_general_forum_topic, chat.get_bot())
|
||||
|
||||
monkeypatch.setattr(chat.get_bot(), "reopen_general_forum_topic", make_assertion)
|
||||
assert await chat.reopen_general_forum_topic()
|
||||
|
||||
async def test_hide_general_forum_topic(self, monkeypatch, chat):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
return kwargs["chat_id"] == chat.id
|
||||
|
||||
assert check_shortcut_signature(
|
||||
Chat.hide_general_forum_topic,
|
||||
Bot.hide_general_forum_topic,
|
||||
["chat_id"],
|
||||
[],
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
chat.hide_general_forum_topic,
|
||||
chat.get_bot(),
|
||||
"hide_general_forum_topic",
|
||||
shortcut_kwargs=["chat_id"],
|
||||
)
|
||||
assert await check_defaults_handling(chat.hide_general_forum_topic, chat.get_bot())
|
||||
|
||||
monkeypatch.setattr(chat.get_bot(), "hide_general_forum_topic", make_assertion)
|
||||
assert await chat.hide_general_forum_topic()
|
||||
|
||||
async def test_unhide_general_forum_topic(self, monkeypatch, chat):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
return kwargs["chat_id"] == chat.id
|
||||
|
||||
assert check_shortcut_signature(
|
||||
Chat.unhide_general_forum_topic,
|
||||
Bot.unhide_general_forum_topic,
|
||||
["chat_id"],
|
||||
[],
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
chat.unhide_general_forum_topic,
|
||||
chat.get_bot(),
|
||||
"unhide_general_forum_topic",
|
||||
shortcut_kwargs=["chat_id"],
|
||||
)
|
||||
assert await check_defaults_handling(chat.unhide_general_forum_topic, chat.get_bot())
|
||||
|
||||
monkeypatch.setattr(chat.get_bot(), "unhide_general_forum_topic", make_assertion)
|
||||
assert await chat.unhide_general_forum_topic()
|
||||
|
||||
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")
|
||||
|
|
|
@ -1026,6 +1026,26 @@ class TestFilters:
|
|||
assert filters.StatusUpdate.FORUM_TOPIC_REOPENED.check_update(update)
|
||||
update.message.forum_topic_reopened = None
|
||||
|
||||
update.message.forum_topic_edited = "topic_edited"
|
||||
assert filters.StatusUpdate.ALL.check_update(update)
|
||||
assert filters.StatusUpdate.FORUM_TOPIC_EDITED.check_update(update)
|
||||
update.message.forum_topic_edited = None
|
||||
|
||||
update.message.general_forum_topic_hidden = "topic_hidden"
|
||||
assert filters.StatusUpdate.ALL.check_update(update)
|
||||
assert filters.StatusUpdate.GENERAL_FORUM_TOPIC_HIDDEN.check_update(update)
|
||||
update.message.general_forum_topic_hidden = None
|
||||
|
||||
update.message.general_forum_topic_unhidden = "topic_unhidden"
|
||||
assert filters.StatusUpdate.ALL.check_update(update)
|
||||
assert filters.StatusUpdate.GENERAL_FORUM_TOPIC_UNHIDDEN.check_update(update)
|
||||
update.message.general_forum_topic_unhidden = None
|
||||
|
||||
update.message.write_access_allowed = "allowed"
|
||||
assert filters.StatusUpdate.ALL.check_update(update)
|
||||
assert filters.StatusUpdate.WRITE_ACCESS_ALLOWED.check_update(update)
|
||||
update.message.write_access_allowed = None
|
||||
|
||||
def test_filters_forwarded(self, update):
|
||||
assert not filters.FORWARDED.check_update(update)
|
||||
update.message.forward_date = datetime.datetime.utcnow()
|
||||
|
@ -1815,6 +1835,11 @@ class TestFilters:
|
|||
update.message.is_topic_message = True
|
||||
assert filters.IS_TOPIC_MESSAGE.check_update(update)
|
||||
|
||||
def test_filters_has_media_spoiler(self, update):
|
||||
assert not filters.HAS_MEDIA_SPOILER.check_update(update)
|
||||
update.message.has_media_spoiler = True
|
||||
assert filters.HAS_MEDIA_SPOILER.check_update(update)
|
||||
|
||||
def test_filters_has_protected_content(self, update):
|
||||
assert not filters.HAS_PROTECTED_CONTENT.check_update(update)
|
||||
update.message.has_protected_content = True
|
||||
|
|
|
@ -16,9 +16,20 @@
|
|||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import ForumTopic, ForumTopicClosed, ForumTopicCreated, ForumTopicReopened, Sticker
|
||||
from telegram import (
|
||||
ForumTopic,
|
||||
ForumTopicClosed,
|
||||
ForumTopicCreated,
|
||||
ForumTopicEdited,
|
||||
ForumTopicReopened,
|
||||
GeneralForumTopicHidden,
|
||||
GeneralForumTopicUnhidden,
|
||||
Sticker,
|
||||
)
|
||||
|
||||
TEST_MSG_TEXT = "Topics are forever"
|
||||
TEST_TOPIC_ICON_COLOR = 0x6FB9F0
|
||||
|
@ -139,7 +150,9 @@ class TestForumTopic:
|
|||
assert a != e
|
||||
assert hash(a) != hash(e)
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
class TestForumMethods:
|
||||
async def test_create_forum_topic(self, real_topic):
|
||||
result = real_topic
|
||||
assert isinstance(result, ForumTopic)
|
||||
|
@ -161,7 +174,6 @@ class TestForumTopic:
|
|||
)
|
||||
assert result is True, "Failed to delete forum topic"
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
async def test_get_forum_topic_icon_stickers(self, bot):
|
||||
emoji_sticker_list = await bot.get_forum_topic_icon_stickers()
|
||||
first_sticker = emoji_sticker_list[0]
|
||||
|
@ -194,7 +206,6 @@ class TestForumTopic:
|
|||
assert result is True, "Failed to edit forum topic"
|
||||
# no way of checking the edited name, just the boolean result
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
async def test_send_message_to_topic(self, bot, forum_group_id, real_topic):
|
||||
message_thread_id = real_topic.message_thread_id
|
||||
|
||||
|
@ -223,7 +234,6 @@ class TestForumTopic:
|
|||
)
|
||||
assert result is True, "Failed to reopen forum topic"
|
||||
|
||||
@pytest.mark.xfail(reason="Can fail due to race conditions in GH actions CI")
|
||||
async def test_unpin_all_forum_topic_messages(self, bot, forum_group_id, real_topic):
|
||||
message_thread_id = real_topic.message_thread_id
|
||||
|
||||
|
@ -244,6 +254,43 @@ class TestForumTopic:
|
|||
)
|
||||
assert result is True, "Failed to unpin all the messages in forum topic"
|
||||
|
||||
async def test_edit_general_forum_topic(self, bot, forum_group_id):
|
||||
result = await bot.edit_general_forum_topic(
|
||||
chat_id=forum_group_id,
|
||||
name=f"GENERAL_{datetime.datetime.now().timestamp()}",
|
||||
)
|
||||
assert result is True, "Failed to edit general forum topic"
|
||||
# no way of checking the edited name, just the boolean result
|
||||
|
||||
async def test_close_and_reopen_general_forum_topic(self, bot, forum_group_id):
|
||||
result = await bot.close_general_forum_topic(
|
||||
chat_id=forum_group_id,
|
||||
)
|
||||
assert result is True, "Failed to close general forum topic"
|
||||
|
||||
result = await bot.reopen_general_forum_topic(
|
||||
chat_id=forum_group_id,
|
||||
)
|
||||
assert result is True, "Failed to reopen general forum topic"
|
||||
|
||||
async def test_hide_and_unhide_general_forum_topic(self, bot, forum_group_id):
|
||||
|
||||
result = await bot.hide_general_forum_topic(
|
||||
chat_id=forum_group_id,
|
||||
)
|
||||
assert result is True, "Failed to hide general forum topic"
|
||||
|
||||
result = await bot.unhide_general_forum_topic(
|
||||
chat_id=forum_group_id,
|
||||
)
|
||||
assert result is True, "Failed to unhide general forum topic"
|
||||
|
||||
# hiding the general topic also closes it, so we reopen it
|
||||
result = await bot.reopen_general_forum_topic(
|
||||
chat_id=forum_group_id,
|
||||
)
|
||||
assert result is True, "Failed to reopen general forum topic"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def topic_created():
|
||||
|
@ -333,3 +380,95 @@ class TestForumTopicReopened:
|
|||
action = ForumTopicReopened()
|
||||
action_dict = action.to_dict()
|
||||
assert action_dict == {}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def topic_edited(emoji_id):
|
||||
return ForumTopicEdited(name=TEST_TOPIC_NAME, icon_custom_emoji_id=emoji_id)
|
||||
|
||||
|
||||
class TestForumTopicEdited:
|
||||
def test_slot_behaviour(self, topic_edited, mro_slots):
|
||||
for attr in topic_edited.__slots__:
|
||||
assert getattr(topic_edited, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
assert len(mro_slots(topic_edited)) == len(set(mro_slots(topic_edited))), "duplicate slot"
|
||||
|
||||
def test_expected_values(self, topic_edited, emoji_id):
|
||||
assert topic_edited.name == TEST_TOPIC_NAME
|
||||
assert topic_edited.icon_custom_emoji_id == emoji_id
|
||||
|
||||
def test_de_json(self, bot, emoji_id):
|
||||
assert ForumTopicEdited.de_json(None, bot=bot) is None
|
||||
|
||||
json_dict = {"name": TEST_TOPIC_NAME, "icon_custom_emoji_id": emoji_id}
|
||||
action = ForumTopicEdited.de_json(json_dict, bot)
|
||||
assert action.api_kwargs == {}
|
||||
|
||||
assert action.name == TEST_TOPIC_NAME
|
||||
assert action.icon_custom_emoji_id == emoji_id
|
||||
# special test since it is mentioned in the docs that icon_custom_emoji_id can be an
|
||||
# empty string
|
||||
json_dict = {"icon_custom_emoji_id": ""}
|
||||
action = ForumTopicEdited.de_json(json_dict, bot)
|
||||
assert action.icon_custom_emoji_id == ""
|
||||
|
||||
def test_to_dict(self, topic_edited, emoji_id):
|
||||
action_dict = topic_edited.to_dict()
|
||||
|
||||
assert isinstance(action_dict, dict)
|
||||
assert action_dict["name"] == TEST_TOPIC_NAME
|
||||
assert action_dict["icon_custom_emoji_id"] == emoji_id
|
||||
|
||||
def test_equality(self, emoji_id):
|
||||
a = ForumTopicEdited(name=TEST_TOPIC_NAME, icon_custom_emoji_id="")
|
||||
b = ForumTopicEdited(
|
||||
name=TEST_TOPIC_NAME,
|
||||
icon_custom_emoji_id="",
|
||||
)
|
||||
c = ForumTopicEdited(name=f"{TEST_TOPIC_NAME}!", icon_custom_emoji_id=emoji_id)
|
||||
d = ForumTopicEdited(icon_custom_emoji_id="")
|
||||
|
||||
assert a == b
|
||||
assert hash(a) == hash(b)
|
||||
|
||||
assert a != c
|
||||
assert hash(a) != hash(c)
|
||||
|
||||
assert a != d
|
||||
assert hash(a) != hash(d)
|
||||
|
||||
|
||||
class TestGeneralForumTopicHidden:
|
||||
def test_slot_behaviour(self, mro_slots):
|
||||
action = GeneralForumTopicHidden()
|
||||
for attr in action.__slots__:
|
||||
assert getattr(action, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
assert len(mro_slots(action)) == len(set(mro_slots(action))), "duplicate slot"
|
||||
|
||||
def test_de_json(self):
|
||||
action = GeneralForumTopicHidden.de_json({}, None)
|
||||
assert action.api_kwargs == {}
|
||||
assert isinstance(action, GeneralForumTopicHidden)
|
||||
|
||||
def test_to_dict(self):
|
||||
action = GeneralForumTopicHidden()
|
||||
action_dict = action.to_dict()
|
||||
assert action_dict == {}
|
||||
|
||||
|
||||
class TestGeneralForumTopicUnhidden:
|
||||
def test_slot_behaviour(self, mro_slots):
|
||||
action = GeneralForumTopicUnhidden()
|
||||
for attr in action.__slots__:
|
||||
assert getattr(action, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
assert len(mro_slots(action)) == len(set(mro_slots(action))), "duplicate slot"
|
||||
|
||||
def test_de_json(self):
|
||||
action = GeneralForumTopicUnhidden.de_json({}, None)
|
||||
assert action.api_kwargs == {}
|
||||
assert isinstance(action, GeneralForumTopicUnhidden)
|
||||
|
||||
def test_to_dict(self):
|
||||
action = GeneralForumTopicUnhidden()
|
||||
action_dict = action.to_dict()
|
||||
assert action_dict == {}
|
||||
|
|
|
@ -68,6 +68,7 @@ def input_media_video(class_thumb_file):
|
|||
caption_entities=TestInputMediaVideo.caption_entities,
|
||||
thumb=class_thumb_file,
|
||||
supports_streaming=TestInputMediaVideo.supports_streaming,
|
||||
has_spoiler=TestInputMediaVideo.has_spoiler,
|
||||
)
|
||||
|
||||
|
||||
|
@ -78,6 +79,7 @@ def input_media_photo(class_thumb_file):
|
|||
caption=TestInputMediaPhoto.caption,
|
||||
parse_mode=TestInputMediaPhoto.parse_mode,
|
||||
caption_entities=TestInputMediaPhoto.caption_entities,
|
||||
has_spoiler=TestInputMediaPhoto.has_spoiler,
|
||||
)
|
||||
|
||||
|
||||
|
@ -92,6 +94,7 @@ def input_media_animation(class_thumb_file):
|
|||
height=TestInputMediaAnimation.height,
|
||||
thumb=class_thumb_file,
|
||||
duration=TestInputMediaAnimation.duration,
|
||||
has_spoiler=TestInputMediaAnimation.has_spoiler,
|
||||
)
|
||||
|
||||
|
||||
|
@ -142,6 +145,7 @@ class TestInputMediaVideo:
|
|||
parse_mode = "HTML"
|
||||
supports_streaming = True
|
||||
caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
|
||||
has_spoiler = True
|
||||
|
||||
def test_slot_behaviour(self, input_media_video, mro_slots):
|
||||
inst = input_media_video
|
||||
|
@ -160,6 +164,7 @@ class TestInputMediaVideo:
|
|||
assert input_media_video.caption_entities == tuple(self.caption_entities)
|
||||
assert input_media_video.supports_streaming == self.supports_streaming
|
||||
assert isinstance(input_media_video.thumb, InputFile)
|
||||
assert input_media_video.has_spoiler == self.has_spoiler
|
||||
|
||||
def test_caption_entities_always_tuple(self):
|
||||
input_media_video = InputMediaVideo(self.media)
|
||||
|
@ -178,6 +183,7 @@ class TestInputMediaVideo:
|
|||
ce.to_dict() for ce in input_media_video.caption_entities
|
||||
]
|
||||
assert input_media_video_dict["supports_streaming"] == input_media_video.supports_streaming
|
||||
assert input_media_video_dict["has_spoiler"] == input_media_video.has_spoiler
|
||||
|
||||
def test_with_video(self, video): # noqa: F811
|
||||
# fixture found in test_video
|
||||
|
@ -210,6 +216,7 @@ class TestInputMediaPhoto:
|
|||
caption = "My Caption"
|
||||
parse_mode = "Markdown"
|
||||
caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
|
||||
has_spoiler = True
|
||||
|
||||
def test_slot_behaviour(self, input_media_photo, mro_slots):
|
||||
inst = input_media_photo
|
||||
|
@ -223,6 +230,7 @@ class TestInputMediaPhoto:
|
|||
assert input_media_photo.caption == self.caption
|
||||
assert input_media_photo.parse_mode == self.parse_mode
|
||||
assert input_media_photo.caption_entities == tuple(self.caption_entities)
|
||||
assert input_media_photo.has_spoiler == self.has_spoiler
|
||||
|
||||
def test_caption_entities_always_tuple(self):
|
||||
input_media_photo = InputMediaPhoto(self.media)
|
||||
|
@ -237,6 +245,7 @@ class TestInputMediaPhoto:
|
|||
assert input_media_photo_dict["caption_entities"] == [
|
||||
ce.to_dict() for ce in input_media_photo.caption_entities
|
||||
]
|
||||
assert input_media_photo_dict["has_spoiler"] == input_media_photo.has_spoiler
|
||||
|
||||
def test_with_photo(self, photo): # noqa: F811
|
||||
# fixture found in test_photo
|
||||
|
@ -266,6 +275,7 @@ class TestInputMediaAnimation:
|
|||
width = 30
|
||||
height = 30
|
||||
duration = 1
|
||||
has_spoiler = True
|
||||
|
||||
def test_slot_behaviour(self, input_media_animation, mro_slots):
|
||||
inst = input_media_animation
|
||||
|
@ -280,6 +290,7 @@ class TestInputMediaAnimation:
|
|||
assert input_media_animation.parse_mode == self.parse_mode
|
||||
assert input_media_animation.caption_entities == tuple(self.caption_entities)
|
||||
assert isinstance(input_media_animation.thumb, InputFile)
|
||||
assert input_media_animation.has_spoiler == self.has_spoiler
|
||||
|
||||
def test_caption_entities_always_tuple(self):
|
||||
input_media_animation = InputMediaAnimation(self.media)
|
||||
|
@ -297,6 +308,7 @@ class TestInputMediaAnimation:
|
|||
assert input_media_animation_dict["width"] == input_media_animation.width
|
||||
assert input_media_animation_dict["height"] == input_media_animation.height
|
||||
assert input_media_animation_dict["duration"] == input_media_animation.duration
|
||||
assert input_media_animation_dict["has_spoiler"] == input_media_animation.has_spoiler
|
||||
|
||||
def test_with_animation(self, animation): # noqa: F811
|
||||
# fixture found in test_animation
|
||||
|
@ -621,6 +633,22 @@ class TestSendMediaGroup:
|
|||
)
|
||||
assert all(mes.has_protected_content for mes in messages)
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
async def test_send_media_group_with_spoiler(
|
||||
self, bot, chat_id, photo_file, video_file # noqa: F811
|
||||
):
|
||||
# Media groups can't contain Animations, so that is tested in test_animation.py
|
||||
media = [
|
||||
InputMediaPhoto(photo_file, has_spoiler=True),
|
||||
InputMediaVideo(video_file, has_spoiler=True),
|
||||
]
|
||||
messages = await bot.send_media_group(chat_id, media)
|
||||
assert isinstance(messages, tuple)
|
||||
assert len(messages) == 2
|
||||
assert all(isinstance(mes, Message) for mes in messages)
|
||||
assert all(mes.media_group_id == messages[0].media_group_id for mes in messages)
|
||||
assert all(mes.has_media_spoiler for mes in messages)
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
async def test_send_media_group_custom_filename(
|
||||
self,
|
||||
|
|
|
@ -107,6 +107,7 @@ class TestPhoto:
|
|||
disable_notification=False,
|
||||
protect_content=True,
|
||||
parse_mode="Markdown",
|
||||
has_spoiler=True,
|
||||
)
|
||||
|
||||
assert isinstance(message.photo[-2], PhotoSize)
|
||||
|
@ -123,6 +124,7 @@ class TestPhoto:
|
|||
|
||||
assert message.caption == TestPhoto.caption.replace("*", "")
|
||||
assert message.has_protected_content
|
||||
assert message.has_media_spoiler
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
async def test_send_photo_custom_filename(self, bot, chat_id, photo_file, monkeypatch):
|
||||
|
|
|
@ -29,6 +29,7 @@ def reply_keyboard_markup():
|
|||
resize_keyboard=TestReplyKeyboardMarkup.resize_keyboard,
|
||||
one_time_keyboard=TestReplyKeyboardMarkup.one_time_keyboard,
|
||||
selective=TestReplyKeyboardMarkup.selective,
|
||||
is_persistent=TestReplyKeyboardMarkup.is_persistent,
|
||||
)
|
||||
|
||||
|
||||
|
@ -37,6 +38,7 @@ class TestReplyKeyboardMarkup:
|
|||
resize_keyboard = True
|
||||
one_time_keyboard = True
|
||||
selective = True
|
||||
is_persistent = True
|
||||
|
||||
def test_slot_behaviour(self, reply_keyboard_markup, mro_slots):
|
||||
inst = reply_keyboard_markup
|
||||
|
@ -103,6 +105,7 @@ class TestReplyKeyboardMarkup:
|
|||
assert reply_keyboard_markup.resize_keyboard == self.resize_keyboard
|
||||
assert reply_keyboard_markup.one_time_keyboard == self.one_time_keyboard
|
||||
assert reply_keyboard_markup.selective == self.selective
|
||||
assert reply_keyboard_markup.is_persistent == self.is_persistent
|
||||
|
||||
def test_wrong_keyboard_inputs(self):
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -134,6 +137,7 @@ class TestReplyKeyboardMarkup:
|
|||
== reply_keyboard_markup.one_time_keyboard
|
||||
)
|
||||
assert reply_keyboard_markup_dict["selective"] == reply_keyboard_markup.selective
|
||||
assert reply_keyboard_markup_dict["is_persistent"] == reply_keyboard_markup.is_persistent
|
||||
|
||||
def test_equality(self):
|
||||
a = ReplyKeyboardMarkup.from_column(["button1", "button2", "button3"])
|
||||
|
|
|
@ -105,6 +105,7 @@ class TestVideo:
|
|||
height=video.height,
|
||||
parse_mode="Markdown",
|
||||
thumb=thumb_file,
|
||||
has_spoiler=True,
|
||||
)
|
||||
|
||||
assert isinstance(message.video, Video)
|
||||
|
@ -125,6 +126,7 @@ class TestVideo:
|
|||
|
||||
assert message.video.file_name == self.file_name
|
||||
assert message.has_protected_content
|
||||
assert message.has_media_spoiler
|
||||
|
||||
@pytest.mark.flaky(3, 1)
|
||||
async def test_send_video_custom_filename(self, bot, chat_id, video_file, monkeypatch):
|
||||
|
|
37
tests/test_writeaccessallowed.py
Normal file
37
tests/test_writeaccessallowed.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2022
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
from telegram import WriteAccessAllowed
|
||||
|
||||
|
||||
class TestWriteAccessAllowed:
|
||||
def test_slot_behaviour(self, mro_slots):
|
||||
action = WriteAccessAllowed()
|
||||
for attr in action.__slots__:
|
||||
assert getattr(action, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
assert len(mro_slots(action)) == len(set(mro_slots(action))), "duplicate slot"
|
||||
|
||||
def test_de_json(self):
|
||||
action = WriteAccessAllowed.de_json({}, None)
|
||||
assert action.api_kwargs == {}
|
||||
assert isinstance(action, WriteAccessAllowed)
|
||||
|
||||
def test_to_dict(self):
|
||||
action = WriteAccessAllowed()
|
||||
action_dict = action.to_dict()
|
||||
assert action_dict == {}
|
Loading…
Reference in a new issue