mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-19 07:35:19 +00:00
Full support for Bot API 9.5 (#5155)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com> Co-authored-by: OuYoung <212045739+ouyooung@users.noreply.github.com> Co-authored-by: Hethon <65696516+hethon@users.noreply.github.com> Co-authored-by: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com>
This commit is contained in:
+2
-2
@@ -11,7 +11,7 @@
|
||||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-9.4-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-9.5-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API version
|
||||
|
||||
@@ -77,7 +77,7 @@ After installing_ the library, be sure to check out the section on `working with
|
||||
Telegram API support
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All types and methods of the Telegram Bot API **9.4** are natively supported by this library.
|
||||
All types and methods of the Telegram Bot API **9.5** are natively supported by this library.
|
||||
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
|
||||
|
||||
Notable Features
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
features = "Full support for Bot API 9.5"
|
||||
[[pull_requests]]
|
||||
uid = "5155"
|
||||
author_uids = ["Poolitzer"]
|
||||
closes_threads = []
|
||||
@@ -183,6 +183,8 @@
|
||||
- Used for getting the list of boosts added to a chat
|
||||
* - :meth:`~telegram.Bot.leave_chat`
|
||||
- Used for leaving a chat
|
||||
* - :meth:`~telegram.Bot.set_chat_member_tag`
|
||||
- Used for setting the tag of a chat member
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
+61
-1
@@ -1218,10 +1218,14 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
api_kwargs: JSONDict | None = None,
|
||||
) -> bool:
|
||||
"""Use this method to stream a partial message to a user while the message is being
|
||||
generated; supported only for bots with forum topic mode enabled.
|
||||
generated.
|
||||
|
||||
.. versionadded:: 22.6
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
Now all bots can use this method.
|
||||
|
||||
|
||||
Args:
|
||||
chat_id (:obj:`int`): Unique identifier for the target private chat.
|
||||
draft_id (:obj:`int`): Unique identifier of the message draft; must be non-zero.
|
||||
@@ -5932,6 +5936,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
can_edit_stories: bool | None = None,
|
||||
can_delete_stories: bool | None = None,
|
||||
can_manage_direct_messages: bool | None = None,
|
||||
can_manage_tags: bool | None = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -6007,6 +6012,10 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
posts; for channels only
|
||||
|
||||
.. versionadded:: 22.4
|
||||
can_manage_tags (:obj:`bool`, optional): Pass :obj:`True`, if the administrator can
|
||||
edit the tags of regular members; for groups and supergroups only.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
@@ -6034,6 +6043,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
"can_edit_stories": can_edit_stories,
|
||||
"can_delete_stories": can_delete_stories,
|
||||
"can_manage_direct_messages": can_manage_direct_messages,
|
||||
"can_manage_tags": can_manage_tags,
|
||||
}
|
||||
|
||||
return await self._post(
|
||||
@@ -12019,6 +12029,54 @@ CHAT_ACTIVITY_TIMEOUT` seconds.
|
||||
|
||||
return UserProfileAudios.de_json(result, self)
|
||||
|
||||
async def set_chat_member_tag(
|
||||
self,
|
||||
chat_id: int | str,
|
||||
user_id: int,
|
||||
tag: str | None = None,
|
||||
*,
|
||||
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 = None,
|
||||
) -> bool:
|
||||
"""
|
||||
Use this method to set a tag for a regular member in a group or a supergroup. The bot must
|
||||
be an administrator in the chat for this to work and must have the
|
||||
:attr:`~telegram.ChatMemberAdministrator.can_manage_tags` administrator right.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Args:
|
||||
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
|
||||
user_id (:obj:`int`): Unique identifier of the target user.
|
||||
tag (:obj:`str`, optional): New tag for the member;
|
||||
0-:tg-const:`telegram.constants.TagLimit.MAX_TAG_LENGTH` characters, emoji are not
|
||||
allowed.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
|
||||
Raises:
|
||||
:class:`telegram.error.TelegramError`
|
||||
"""
|
||||
data: JSONDict = {
|
||||
"chat_id": chat_id,
|
||||
"user_id": user_id,
|
||||
"tag": tag,
|
||||
}
|
||||
|
||||
return await self._post(
|
||||
"setChatMemberTag",
|
||||
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: # noqa: ARG002
|
||||
"""See :meth:`telegram.TelegramObject.to_dict`."""
|
||||
data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name}
|
||||
@@ -12357,3 +12415,5 @@ CHAT_ACTIVITY_TIMEOUT` seconds.
|
||||
"""Alias for :meth:`set_my_profile_photo`"""
|
||||
getUserProfileAudios = get_user_profile_audios
|
||||
"""Alias for :meth:`get_user_profile_audios`"""
|
||||
setChatMemberTag = set_chat_member_tag
|
||||
"""Alias for :meth:`set_chat_member_tag`"""
|
||||
|
||||
@@ -619,6 +619,7 @@ class _ChatBase(TelegramObject):
|
||||
can_edit_stories: bool | None = None,
|
||||
can_delete_stories: bool | None = None,
|
||||
can_manage_direct_messages: bool | None = None,
|
||||
can_manage_tags: bool | None = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -670,6 +671,7 @@ class _ChatBase(TelegramObject):
|
||||
can_edit_stories=can_edit_stories,
|
||||
can_delete_stories=can_delete_stories,
|
||||
can_manage_direct_messages=can_manage_direct_messages,
|
||||
can_manage_tags=can_manage_tags,
|
||||
)
|
||||
|
||||
async def restrict_member(
|
||||
@@ -3995,6 +3997,41 @@ class _ChatBase(TelegramObject):
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
async def set_chat_member_tag(
|
||||
self,
|
||||
user_id: int,
|
||||
tag: str | None = None,
|
||||
*,
|
||||
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 = None,
|
||||
) -> bool:
|
||||
"""
|
||||
Shortcut for::
|
||||
|
||||
await bot.set_chat_member_tag(chat_id=update.effective_chat.id, *args, **kwargs)
|
||||
|
||||
For the documentation of the arguments, please see
|
||||
:meth:`telegram.Bot.set_chat_member_tag`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().set_chat_member_tag(
|
||||
chat_id=self.id,
|
||||
user_id=user_id,
|
||||
tag=tag,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
|
||||
class Chat(_ChatBase):
|
||||
"""This object represents a chat.
|
||||
|
||||
@@ -31,7 +31,8 @@ class ChatAdministratorRights(TelegramObject):
|
||||
:attr:`can_promote_members`, :attr:`can_change_info`, :attr:`can_invite_users`,
|
||||
:attr:`can_post_messages`, :attr:`can_edit_messages`, :attr:`can_pin_messages`,
|
||||
:attr:`can_manage_topics`, :attr:`can_post_stories`, :attr:`can_delete_stories`,
|
||||
:attr:`can_edit_stories` and :attr:`can_manage_direct_messages` are equal.
|
||||
:attr:`can_edit_stories`, :attr:`can_manage_direct_messages` and :attr:`can_manage_tags` are
|
||||
equal.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
@@ -52,6 +53,10 @@ class ChatAdministratorRights(TelegramObject):
|
||||
:attr:`can_manage_direct_messages` is considered as well when comparing objects of
|
||||
this type in terms of equality.
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
:attr:`can_manage_tags` is considered as well when comparing objects of this type in terms
|
||||
of equality.
|
||||
|
||||
Args:
|
||||
is_anonymous (:obj:`bool`): :obj:`True`, if the user's presence in the chat is hidden.
|
||||
can_manage_chat (:obj:`bool`): :obj:`True`, if the administrator can access the chat event
|
||||
@@ -104,6 +109,11 @@ class ChatAdministratorRights(TelegramObject):
|
||||
manage direct messages of the channel and decline suggested posts; for channels only.
|
||||
|
||||
.. versionadded:: 22.4
|
||||
can_manage_tags (:obj:`bool`, optional): :obj:`True`, if the administrator can edit the
|
||||
tags of regular members; for groups and supergroups only. If omitted defaults to the
|
||||
value of :attr:`can_pin_messages`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
is_anonymous (:obj:`bool`): :obj:`True`, if the user's presence in the chat is hidden.
|
||||
@@ -157,6 +167,11 @@ class ChatAdministratorRights(TelegramObject):
|
||||
manage direct messages of the channel and decline suggested posts; for channels only.
|
||||
|
||||
.. versionadded:: 22.4
|
||||
can_manage_tags (:obj:`bool`): Optional. :obj:`True`, if the administrator can edit the
|
||||
tags of regular members; for groups and supergroups only. If omitted defaults to the
|
||||
value of :attr:`can_pin_messages`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
@@ -168,6 +183,7 @@ class ChatAdministratorRights(TelegramObject):
|
||||
"can_invite_users",
|
||||
"can_manage_chat",
|
||||
"can_manage_direct_messages",
|
||||
"can_manage_tags",
|
||||
"can_manage_topics",
|
||||
"can_manage_video_chats",
|
||||
"can_pin_messages",
|
||||
@@ -196,6 +212,7 @@ class ChatAdministratorRights(TelegramObject):
|
||||
can_pin_messages: bool | None = None,
|
||||
can_manage_topics: bool | None = None,
|
||||
can_manage_direct_messages: bool | None = None,
|
||||
can_manage_tags: bool | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
) -> None:
|
||||
@@ -218,6 +235,7 @@ class ChatAdministratorRights(TelegramObject):
|
||||
self.can_pin_messages: bool | None = can_pin_messages
|
||||
self.can_manage_topics: bool | None = can_manage_topics
|
||||
self.can_manage_direct_messages: bool | None = can_manage_direct_messages
|
||||
self.can_manage_tags: bool | None = can_manage_tags
|
||||
|
||||
self._id_attrs = (
|
||||
self.is_anonymous,
|
||||
@@ -236,6 +254,7 @@ class ChatAdministratorRights(TelegramObject):
|
||||
self.can_edit_stories,
|
||||
self.can_delete_stories,
|
||||
self.can_manage_direct_messages,
|
||||
self.can_manage_tags,
|
||||
)
|
||||
|
||||
self._freeze()
|
||||
|
||||
@@ -257,6 +257,11 @@ class ChatMemberAdministrator(ChatMember):
|
||||
manage direct messages of the channel and decline suggested posts; for channels only.
|
||||
|
||||
.. versionadded:: 22.4
|
||||
can_manage_tags (:obj:`bool`, optional): :obj:`True`, if the administrator can edit the
|
||||
tags of regular members; for groups and supergroups only. If omitted defaults to the
|
||||
value of :attr:`can_pin_messages`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
status (:obj:`str`): The member's status in the chat,
|
||||
@@ -321,6 +326,11 @@ class ChatMemberAdministrator(ChatMember):
|
||||
manage direct messages of the channel and decline suggested posts; for channels only.
|
||||
|
||||
.. versionadded:: 22.4
|
||||
can_manage_tags (:obj:`bool`): Optional. :obj:`True`, if the administrator can edit the
|
||||
tags of regular members; for groups and supergroups only. If omitted defaults to the
|
||||
value of :attr:`can_pin_messages`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
@@ -333,6 +343,7 @@ class ChatMemberAdministrator(ChatMember):
|
||||
"can_invite_users",
|
||||
"can_manage_chat",
|
||||
"can_manage_direct_messages",
|
||||
"can_manage_tags",
|
||||
"can_manage_topics",
|
||||
"can_manage_video_chats",
|
||||
"can_pin_messages",
|
||||
@@ -365,6 +376,7 @@ class ChatMemberAdministrator(ChatMember):
|
||||
can_manage_topics: bool | None = None,
|
||||
custom_title: str | None = None,
|
||||
can_manage_direct_messages: bool | None = None,
|
||||
can_manage_tags: bool | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
@@ -389,6 +401,7 @@ class ChatMemberAdministrator(ChatMember):
|
||||
self.can_manage_topics: bool | None = can_manage_topics
|
||||
self.custom_title: str | None = custom_title
|
||||
self.can_manage_direct_messages: bool | None = can_manage_direct_messages
|
||||
self.can_manage_tags: bool | None = can_manage_tags
|
||||
|
||||
|
||||
class ChatMemberMember(ChatMember):
|
||||
@@ -404,6 +417,9 @@ class ChatMemberMember(ChatMember):
|
||||
expire.
|
||||
|
||||
.. versionadded:: 21.5
|
||||
tag (:obj:`str`, optional): Tag of the member.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
status (:obj:`str`): The member's status in the chat,
|
||||
@@ -413,21 +429,29 @@ class ChatMemberMember(ChatMember):
|
||||
expire.
|
||||
|
||||
.. versionadded:: 21.5
|
||||
tag (:obj:`str`): Optional. Tag of the member.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("until_date",)
|
||||
__slots__ = (
|
||||
"tag",
|
||||
"until_date",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
user: User,
|
||||
until_date: dtm.datetime | None = None,
|
||||
tag: str | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.MEMBER, user=user, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
self.until_date: dtm.datetime | None = until_date
|
||||
self.tag: str | None = tag
|
||||
|
||||
|
||||
class ChatMemberRestricted(ChatMember):
|
||||
@@ -490,6 +514,12 @@ class ChatMemberRestricted(ChatMember):
|
||||
notes.
|
||||
|
||||
.. versionadded:: 20.1
|
||||
can_edit_tag (:obj:`bool`): :obj:`True`, if the user is allowed to edit their own tag.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
tag (:obj:`str`, optional): Tag of the member.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
status (:obj:`str`): The member's status in the chat,
|
||||
@@ -540,12 +570,19 @@ class ChatMemberRestricted(ChatMember):
|
||||
notes.
|
||||
|
||||
.. versionadded:: 20.1
|
||||
can_edit_tag (:obj:`bool`): :obj:`True`, if the user is allowed to edit their own tag.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
tag (:obj:`str`): Optional. Tag of the member.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"can_add_web_page_previews",
|
||||
"can_change_info",
|
||||
"can_edit_tag",
|
||||
"can_invite_users",
|
||||
"can_manage_topics",
|
||||
"can_pin_messages",
|
||||
@@ -559,6 +596,7 @@ class ChatMemberRestricted(ChatMember):
|
||||
"can_send_videos",
|
||||
"can_send_voice_notes",
|
||||
"is_member",
|
||||
"tag",
|
||||
"until_date",
|
||||
)
|
||||
|
||||
@@ -581,6 +619,8 @@ class ChatMemberRestricted(ChatMember):
|
||||
can_send_videos: bool,
|
||||
can_send_video_notes: bool,
|
||||
can_send_voice_notes: bool,
|
||||
can_edit_tag: bool,
|
||||
tag: str | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
@@ -602,6 +642,8 @@ class ChatMemberRestricted(ChatMember):
|
||||
self.can_send_videos: bool = can_send_videos
|
||||
self.can_send_video_notes: bool = can_send_video_notes
|
||||
self.can_send_voice_notes: bool = can_send_voice_notes
|
||||
self.can_edit_tag: bool = can_edit_tag
|
||||
self.tag: str | None = tag
|
||||
|
||||
|
||||
class ChatMemberLeft(ChatMember):
|
||||
|
||||
@@ -35,8 +35,8 @@ class ChatPermissions(TelegramObject):
|
||||
:attr:`can_send_polls`, :attr:`can_send_other_messages`, :attr:`can_add_web_page_previews`,
|
||||
:attr:`can_change_info`, :attr:`can_invite_users`, :attr:`can_pin_messages`,
|
||||
:attr:`can_send_audios`, :attr:`can_send_documents`, :attr:`can_send_photos`,
|
||||
:attr:`can_send_videos`, :attr:`can_send_video_notes`, :attr:`can_send_voice_notes`, and
|
||||
:attr:`can_manage_topics` are equal.
|
||||
:attr:`can_send_videos`, :attr:`can_send_video_notes`, :attr:`can_send_voice_notes`,
|
||||
:attr:`can_manage_topics` and :attr:`can_edit_tag` are equal.
|
||||
|
||||
.. versionchanged:: 20.0
|
||||
:attr:`can_manage_topics` is considered as well when comparing objects of
|
||||
@@ -47,6 +47,9 @@ class ChatPermissions(TelegramObject):
|
||||
:attr:`can_send_videos`, :attr:`can_send_video_notes` and :attr:`can_send_voice_notes`
|
||||
are considered as well when comparing objects of this type in terms of equality.
|
||||
* Removed deprecated argument and attribute ``can_send_media_messages``.
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
:attr:`can_edit_tag` is considered as well when comparing objects of
|
||||
this type in terms of equality.
|
||||
|
||||
|
||||
Note:
|
||||
@@ -93,6 +96,10 @@ class ChatPermissions(TelegramObject):
|
||||
notes.
|
||||
|
||||
.. versionadded:: 20.1
|
||||
can_edit_tag (:obj:`bool`, optional): :obj:`True`, if the user is allowed to edit their own
|
||||
tag.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
can_send_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to send text
|
||||
@@ -134,12 +141,17 @@ class ChatPermissions(TelegramObject):
|
||||
notes.
|
||||
|
||||
.. versionadded:: 20.1
|
||||
can_edit_tag (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to edit their own
|
||||
tag.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"can_add_web_page_previews",
|
||||
"can_change_info",
|
||||
"can_edit_tag",
|
||||
"can_invite_users",
|
||||
"can_manage_topics",
|
||||
"can_pin_messages",
|
||||
@@ -170,6 +182,7 @@ class ChatPermissions(TelegramObject):
|
||||
can_send_videos: bool | None = None,
|
||||
can_send_video_notes: bool | None = None,
|
||||
can_send_voice_notes: bool | None = None,
|
||||
can_edit_tag: bool | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
@@ -189,6 +202,7 @@ class ChatPermissions(TelegramObject):
|
||||
self.can_send_videos: bool | None = can_send_videos
|
||||
self.can_send_video_notes: bool | None = can_send_video_notes
|
||||
self.can_send_voice_notes: bool | None = can_send_voice_notes
|
||||
self.can_edit_tag: bool | None = can_edit_tag
|
||||
|
||||
self._id_attrs = (
|
||||
self.can_send_messages,
|
||||
@@ -205,6 +219,7 @@ class ChatPermissions(TelegramObject):
|
||||
self.can_send_videos,
|
||||
self.can_send_video_notes,
|
||||
self.can_send_voice_notes,
|
||||
self.can_edit_tag,
|
||||
)
|
||||
|
||||
self._freeze()
|
||||
@@ -219,7 +234,7 @@ class ChatPermissions(TelegramObject):
|
||||
.. versionadded:: 20.0
|
||||
|
||||
"""
|
||||
return cls(*(14 * (True,)))
|
||||
return cls(*(True,) * len(cls.__slots__))
|
||||
|
||||
@classmethod
|
||||
def no_permissions(cls) -> "ChatPermissions":
|
||||
@@ -229,7 +244,7 @@ class ChatPermissions(TelegramObject):
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
return cls(*(14 * (False,)))
|
||||
return cls(*(False,) * len(cls.__slots__))
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "ChatPermissions":
|
||||
|
||||
@@ -74,7 +74,7 @@ from telegram._telegramobject import TelegramObject
|
||||
from telegram._uniquegift import UniqueGiftInfo
|
||||
from telegram._user import User
|
||||
from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp, to_timestamp
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE, DefaultValue
|
||||
from telegram._utils.entities import parse_message_entities, parse_message_entity
|
||||
from telegram._utils.strings import TextEncoding
|
||||
@@ -330,8 +330,8 @@ class Message(MaybeInaccessibleMessage):
|
||||
or as a scheduled message.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
media_group_id (:obj:`str`, optional): The unique identifier of a media message group this
|
||||
message belongs to.
|
||||
media_group_id (:obj:`str`, optional): The unique identifier inside this chat of a media
|
||||
message group this message belongs to.
|
||||
text (:obj:`str`, optional): For text messages, the actual UTF-8 text of the message,
|
||||
0-:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters.
|
||||
entities (Sequence[:class:`telegram.MessageEntity`], optional): For text messages, special
|
||||
@@ -684,6 +684,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
chat_owner_changed (:class:`telegram.ChatOwnerChanged`, optional): Service message: chat
|
||||
owner has changed.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
sender_tag (:obj:`str`, optional): Tag or custom title of the sender of the message; for
|
||||
supergroups only
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
@@ -726,8 +730,8 @@ class Message(MaybeInaccessibleMessage):
|
||||
or as a scheduled message.
|
||||
|
||||
.. versionadded:: 21.1
|
||||
media_group_id (:obj:`str`): Optional. The unique identifier of a media message group this
|
||||
message belongs to.
|
||||
media_group_id (:obj:`str`): Optional. The unique identifier inside this chat of a media
|
||||
message group this message belongs to.
|
||||
text (:obj:`str`): Optional. For text messages, the actual UTF-8 text of the message,
|
||||
0-:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters.
|
||||
entities (tuple[:class:`telegram.MessageEntity`]): Optional. For text messages, special
|
||||
@@ -1096,6 +1100,10 @@ class Message(MaybeInaccessibleMessage):
|
||||
chat_owner_changed (:class:`telegram.ChatOwnerChanged`): Optional. Service message: chat
|
||||
owner has changed.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
sender_tag (:obj:`str`): Optional. Tag or custom title of the sender of the message; for
|
||||
supergroups only
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
.. |custom_emoji_no_md1_support| replace:: Since custom emoji entities are not supported by
|
||||
@@ -1193,6 +1201,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
"sender_boost_count",
|
||||
"sender_business_bot",
|
||||
"sender_chat",
|
||||
"sender_tag",
|
||||
"show_caption_above_media",
|
||||
"sticker",
|
||||
"story",
|
||||
@@ -1327,6 +1336,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
gift_upgrade_sent: GiftInfo | None = None,
|
||||
chat_owner_changed: ChatOwnerChanged | None = None,
|
||||
chat_owner_left: ChatOwnerLeft | None = None,
|
||||
sender_tag: str | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
@@ -1456,6 +1466,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
self.gift_upgrade_sent: GiftInfo | None = gift_upgrade_sent
|
||||
self.chat_owner_changed: ChatOwnerChanged | None = chat_owner_changed
|
||||
self.chat_owner_left: ChatOwnerLeft | None = chat_owner_left
|
||||
self.sender_tag: str | None = sender_tag
|
||||
|
||||
self._effective_attachment = DEFAULT_NONE
|
||||
|
||||
@@ -5304,6 +5315,17 @@ class Message(MaybeInaccessibleMessage):
|
||||
insert = f'<span class="tg-spoiler">{escaped_text}</span>'
|
||||
elif entity.type == MessageEntity.CUSTOM_EMOJI:
|
||||
insert = f'<tg-emoji emoji-id="{entity.custom_emoji_id}">{escaped_text}</tg-emoji>'
|
||||
elif entity.type == MessageEntity.DATE_TIME:
|
||||
if entity.date_time_format:
|
||||
insert = (
|
||||
f'<tg-time unix="{to_timestamp(entity.unix_time)}" '
|
||||
f'format="{entity.date_time_format}">{escaped_text}</tg-time>'
|
||||
)
|
||||
else:
|
||||
insert = (
|
||||
f'<tg-time unix="{to_timestamp(entity.unix_time)}">'
|
||||
f"{escaped_text}</tg-time>"
|
||||
)
|
||||
else:
|
||||
insert = escaped_text
|
||||
|
||||
@@ -5443,6 +5465,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
MessageEntity.SPOILER,
|
||||
MessageEntity.STRIKETHROUGH,
|
||||
MessageEntity.UNDERLINE,
|
||||
MessageEntity.DATE_TIME,
|
||||
):
|
||||
if any(entity.type == entity_type for entity in entities):
|
||||
name = entity_type.name.title().replace("_", " ") # type:ignore[attr-defined]
|
||||
@@ -5535,6 +5558,14 @@ class Message(MaybeInaccessibleMessage):
|
||||
entity_type=MessageEntity.CUSTOM_EMOJI,
|
||||
)
|
||||
insert = f""
|
||||
elif entity.type == MessageEntity.DATE_TIME:
|
||||
if entity.date_time_format:
|
||||
insert = (
|
||||
f"}"
|
||||
f"&format={entity.date_time_format})"
|
||||
)
|
||||
else:
|
||||
insert = f"})"
|
||||
else:
|
||||
insert = escaped_text
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"""This module contains an object that represents a Telegram MessageEntity."""
|
||||
|
||||
import copy
|
||||
import datetime as dtm
|
||||
import itertools
|
||||
from collections.abc import Sequence
|
||||
from typing import TYPE_CHECKING, Final
|
||||
@@ -28,6 +29,7 @@ from telegram._telegramobject import TelegramObject
|
||||
from telegram._user import User
|
||||
from telegram._utils import enum
|
||||
from telegram._utils.argumentparsing import de_json_optional
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
|
||||
from telegram._utils.strings import TextEncoding
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
@@ -55,13 +57,17 @@ class MessageEntity(TelegramObject):
|
||||
(underlined text), :attr:`STRIKETHROUGH`, :attr:`SPOILER` (spoiler message),
|
||||
:attr:`BLOCKQUOTE` (block quotation), :attr:`CODE` (monowidth string), :attr:`PRE`
|
||||
(monowidth block), :attr:`TEXT_LINK` (for clickable text URLs), :attr:`TEXT_MENTION`
|
||||
(for users without usernames), :attr:`CUSTOM_EMOJI` (for inline custom emoji stickers).
|
||||
(for users without usernames), :attr:`CUSTOM_EMOJI` (for inline custom emoji stickers)
|
||||
or :attr:`DATE_TIME`(for formatted date and time).
|
||||
|
||||
.. versionadded:: 20.0
|
||||
Added inline custom emoji
|
||||
|
||||
.. versionadded:: 20.8
|
||||
Added block quotation
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
Added date_time
|
||||
offset (:obj:`int`): Offset in UTF-16 code units to the start of the entity.
|
||||
length (:obj:`int`): Length of the entity in UTF-16 code units.
|
||||
url (:obj:`str`, optional): For :attr:`TEXT_LINK` only, url that will be opened after
|
||||
@@ -75,6 +81,17 @@ class MessageEntity(TelegramObject):
|
||||
information about the sticker.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
date_time_format (:obj:`str`, optional): For :attr`DATE_TIME` only, the string that defines
|
||||
the formatting of the date and time. See `date-time entity formatting
|
||||
<https://core.telegram.org/bots/api#date-time-entity-formatting>`_ for more details and
|
||||
:tg-const:`telegram.constants.MessageEntityDateTimeFormats` for all possible formats.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
unix_time (:class:`datetime.datetime`, optional): For :attr:`DATE_TIME` only, the time
|
||||
associated with the entity.
|
||||
|datetime_localization|
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
Attributes:
|
||||
type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (``@username``),
|
||||
:attr:`HASHTAG` (``#hashtag`` or ``#hashtag@chatusername``), :attr:`CASHTAG` (``$USD``
|
||||
@@ -105,10 +122,31 @@ class MessageEntity(TelegramObject):
|
||||
information about the sticker.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
date_time_format (:obj:`str`): Optional. For :attr`DATE_TIME` only, the string that defines
|
||||
the formatting of the date and time. See `date-time entity formatting
|
||||
<https://core.telegram.org/bots/api#date-time-entity-formatting>`_ for more details and
|
||||
:tg-const:`telegram.constants.MessageEntityDateTimeFormats` for all possible formats.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
unix_time (:class:`datetime.datetime`): Optional. For :attr:`DATE_TIME` only, the time
|
||||
associated with the entity.
|
||||
|datetime_localization|
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("custom_emoji_id", "language", "length", "offset", "type", "url", "user")
|
||||
__slots__ = (
|
||||
"custom_emoji_id",
|
||||
"date_time_format",
|
||||
"language",
|
||||
"length",
|
||||
"offset",
|
||||
"type",
|
||||
"unix_time",
|
||||
"url",
|
||||
"user",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -119,6 +157,8 @@ class MessageEntity(TelegramObject):
|
||||
user: User | None = None,
|
||||
language: str | None = None,
|
||||
custom_emoji_id: str | None = None,
|
||||
date_time_format: str | None = None,
|
||||
unix_time: dtm.datetime | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
@@ -132,6 +172,8 @@ class MessageEntity(TelegramObject):
|
||||
self.user: User | None = user
|
||||
self.language: str | None = language
|
||||
self.custom_emoji_id: str | None = custom_emoji_id
|
||||
self.date_time_format: str | None = date_time_format
|
||||
self.unix_time: dtm.datetime | None = unix_time
|
||||
|
||||
self._id_attrs = (self.type, self.offset, self.length)
|
||||
|
||||
@@ -144,6 +186,10 @@ class MessageEntity(TelegramObject):
|
||||
|
||||
data["user"] = de_json_optional(data.get("user"), User, bot)
|
||||
|
||||
# Get the local timezone from the bot if it has defaults
|
||||
loc_tzinfo = extract_tzinfo_from_defaults(bot)
|
||||
data["unix_time"] = from_timestamp(data.get("unix_time"), tzinfo=loc_tzinfo)
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
@staticmethod
|
||||
@@ -376,6 +422,11 @@ class MessageEntity(TelegramObject):
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
DATE_TIME: Final[str] = constants.MessageEntityType.DATE_TIME
|
||||
""":const:`telegram.constants.MessageEntityType.DATE_TIME`
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
EMAIL: Final[str] = constants.MessageEntityType.EMAIL
|
||||
""":const:`telegram.constants.MessageEntityType.EMAIL`"""
|
||||
EXPANDABLE_BLOCKQUOTE: Final[str] = constants.MessageEntityType.EXPANDABLE_BLOCKQUOTE
|
||||
|
||||
@@ -2677,3 +2677,38 @@ class User(TelegramObject):
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
async def set_chat_member_tag(
|
||||
self,
|
||||
chat_id: int | str,
|
||||
tag: str | None = None,
|
||||
*,
|
||||
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 = None,
|
||||
) -> bool:
|
||||
"""
|
||||
Shortcut for::
|
||||
|
||||
await bot.set_chat_member_tag(user_id=update.effective_user.id, *args, **kwargs)
|
||||
|
||||
For the documentation of the arguments, please see
|
||||
:meth:`telegram.Bot.set_chat_member_tag`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().set_chat_member_tag(
|
||||
user_id=self.id,
|
||||
chat_id=chat_id,
|
||||
tag=tag,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@@ -91,6 +91,7 @@ __all__ = [
|
||||
"MediaGroupLimit",
|
||||
"MenuButtonType",
|
||||
"MessageAttachmentType",
|
||||
"MessageEntityDateTimeFormats",
|
||||
"MessageEntityType",
|
||||
"MessageLimit",
|
||||
"MessageOriginType",
|
||||
@@ -121,6 +122,7 @@ __all__ = [
|
||||
"SuggestedPost",
|
||||
"SuggestedPostInfoState",
|
||||
"SuggestedPostRefunded",
|
||||
"TagLimit",
|
||||
"TransactionPartnerType",
|
||||
"TransactionPartnerUser",
|
||||
"UniqueGiftInfoOrigin",
|
||||
@@ -179,7 +181,7 @@ class _AccentColor(NamedTuple):
|
||||
#: :data:`telegram.__bot_api_version_info__`.
|
||||
#:
|
||||
#: .. versionadded:: 20.0
|
||||
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=9, minor=4)
|
||||
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=9, minor=5)
|
||||
#: :obj:`str`: Telegram Bot API
|
||||
#: version supported by this version of `python-telegram-bot`. Also available as
|
||||
#: :data:`telegram.__bot_api_version__`.
|
||||
@@ -2017,6 +2019,11 @@ class MessageEntityType(StringEnum):
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
DATE_TIME = "date_time"
|
||||
""":obj:`str`: Message entities representing formatted date and time.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
EMAIL = "email"
|
||||
""":obj:`str`: Message entities representing a email."""
|
||||
EXPANDABLE_BLOCKQUOTE = "expandable_blockquote"
|
||||
@@ -2048,6 +2055,63 @@ class MessageEntityType(StringEnum):
|
||||
""":obj:`str`: Message entities representing a url."""
|
||||
|
||||
|
||||
class MessageEntityDateTimeFormats(StringEnum):
|
||||
"""This enum contains all possible formats for :attr:`telegram.MessageEntity.date_time_format`.
|
||||
Please read `date-time entity formatting
|
||||
<https://core.telegram.org/bots/api#date-time-entity-formatting>`_ for more details. The enum
|
||||
members of this enumeration are instances of :class:`str` and can be treated as such.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
RELATIVE = "r"
|
||||
""":obj:`str`: Displays the time relative to the current time."""
|
||||
LOCALIZED_WEEKDAY = "w"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language."""
|
||||
SHORT_DATE = "d"
|
||||
""":obj:`str`: Displays the date in short form (e.g., "17.03.22")."""
|
||||
LONG_DATE = "D"
|
||||
""":obj:`str`: Displays the date in long form (e.g., "March 17, 2022")."""
|
||||
SHORT_TIME = "t"
|
||||
""":obj:`str`: Displays the time in short form (e.g., "22:45")."""
|
||||
LONG_TIME = "T"
|
||||
""":obj:`str`: Displays the time in long form (e.g., "22:45:00")."""
|
||||
LOCALIZED_WEEKDAY_SHORT_DATE = "wd"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language and the date in
|
||||
short form."""
|
||||
LOCALIZED_WEEKDAY_LONG_DATE = "wD"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language and the date in
|
||||
long form."""
|
||||
LOCALIZED_WEEKDAY_SHORT_TIME = "wt"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language and the time in
|
||||
short form."""
|
||||
LOCALIZED_WEEKDAY_LONG_TIME = "wT"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language and the time in
|
||||
long form."""
|
||||
LOCALIZED_WEEKDAY_SHORT_DATE_SHORT_TIME = "wdt"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language, the date in
|
||||
short form and the time in short form."""
|
||||
LOCALIZED_WEEKDAY_SHORT_DATE_LONG_TIME = "wdT"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language, the date in
|
||||
short form and the time in long form."""
|
||||
LOCALIZED_WEEKDAY_LONG_DATE_SHORT_TIME = "wDt"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language, the date in
|
||||
long form and the time in short form."""
|
||||
LOCALIZED_WEEKDAY_LONG_DATE_LONG_TIME = "wDT"
|
||||
""":obj:`str`: Displays the day of the week in the user's localized language, the date in
|
||||
long form and the time in long form."""
|
||||
SHORT_DATE_SHORT_TIME = "dt"
|
||||
""":obj:`str`: Displays the date in short form and the time in short form."""
|
||||
SHORT_DATE_LONG_TIME = "dT"
|
||||
""":obj:`str`: Displays the date in short form and the time in long form."""
|
||||
LONG_DATE_SHORT_TIME = "Dt"
|
||||
""":obj:`str`: Displays the date in long form and the time in short form."""
|
||||
LONG_DATE_LONG_TIME = "DT"
|
||||
""":obj:`str`: Displays the date in long form and the time in long form."""
|
||||
|
||||
|
||||
class MessageLimit(IntEnum):
|
||||
"""This enum contains limitations for :class:`telegram.Message`/
|
||||
:class:`telegram.InputTextMessageContent`/
|
||||
@@ -3964,3 +4028,18 @@ class VerifyLimit(IntEnum):
|
||||
:paramref:`~telegram.Bot.verify_chat.custom_description` or
|
||||
:paramref:`~telegram.Bot.verify_user.custom_description` parameter.
|
||||
"""
|
||||
|
||||
|
||||
class TagLimit(IntEnum):
|
||||
"""This enum contains limitations for :meth:`~telegram.Bot.set_chat_member_tag`.
|
||||
The enum members of this enumeration are instances of :class:`int` and can be treated as such.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
MAX_TAG_LENGTH = 16
|
||||
""":obj:`int`: Maximum number of characters in a :obj:`str` passed as the
|
||||
:paramref:`~telegram.Bot.set_chat_member_tag.tag` parameter.
|
||||
"""
|
||||
|
||||
@@ -2367,6 +2367,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
can_edit_stories: bool | None = None,
|
||||
can_delete_stories: bool | None = None,
|
||||
can_manage_direct_messages: bool | None = None,
|
||||
can_manage_tags: bool | None = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2394,6 +2395,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
can_edit_stories=can_edit_stories,
|
||||
can_delete_stories=can_delete_stories,
|
||||
can_manage_direct_messages=can_manage_direct_messages,
|
||||
can_manage_tags=can_manage_tags,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
connect_timeout=connect_timeout,
|
||||
@@ -5485,6 +5487,30 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
|
||||
)
|
||||
|
||||
async def set_chat_member_tag(
|
||||
self,
|
||||
chat_id: int | str,
|
||||
user_id: int,
|
||||
tag: str | None = None,
|
||||
*,
|
||||
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 = None,
|
||||
rate_limit_args: RLARGS | None = None,
|
||||
) -> bool:
|
||||
return await super().set_chat_member_tag(
|
||||
chat_id=chat_id,
|
||||
user_id=user_id,
|
||||
tag=tag,
|
||||
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),
|
||||
)
|
||||
|
||||
# updated camelCase aliases
|
||||
getMe = get_me
|
||||
sendMessage = send_message
|
||||
@@ -5650,3 +5676,4 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
setMyProfilePhoto = set_my_profile_photo
|
||||
removeMyProfilePhoto = remove_my_profile_photo
|
||||
getUserProfileAudios = get_user_profile_audios
|
||||
setChatMemberTag = set_chat_member_tag
|
||||
|
||||
@@ -2835,6 +2835,18 @@ class TestBotWithoutRequest:
|
||||
limit="limit",
|
||||
)
|
||||
|
||||
# TODO if we have a group member id in every group we could test this
|
||||
async def test_set_chat_member_tag(self, offline_bot, monkeypatch):
|
||||
|
||||
async def make_assertion(url, request_data: RequestData, *args, **kwargs):
|
||||
assert request_data.parameters.get("chat_id") == 1234
|
||||
assert request_data.parameters.get("user_id") == 5678
|
||||
assert request_data.parameters.get("tag") == "This is a tag"
|
||||
|
||||
monkeypatch.setattr(offline_bot.request, "post", make_assertion)
|
||||
|
||||
await offline_bot.set_chat_member_tag(1234, 5678, "This is a tag")
|
||||
|
||||
|
||||
class TestBotWithRequest:
|
||||
"""
|
||||
@@ -3808,6 +3820,7 @@ class TestBotWithRequest:
|
||||
can_edit_stories=True,
|
||||
can_delete_stories=True,
|
||||
can_manage_direct_messages=True,
|
||||
can_manage_tags=True,
|
||||
)
|
||||
|
||||
# Test that we pass the correct params to TG
|
||||
@@ -3832,6 +3845,7 @@ class TestBotWithRequest:
|
||||
and data.get("can_edit_stories") == 14
|
||||
and data.get("can_delete_stories") == 15
|
||||
and data.get("can_manage_direct_messages") == 16
|
||||
and data.get("can_manage_tags") == 17
|
||||
)
|
||||
|
||||
monkeypatch.setattr(bot, "_post", make_assertion)
|
||||
@@ -3854,6 +3868,7 @@ class TestBotWithRequest:
|
||||
can_edit_stories=14,
|
||||
can_delete_stories=15,
|
||||
can_manage_direct_messages=16,
|
||||
can_manage_tags=17,
|
||||
)
|
||||
|
||||
async def test_export_chat_invite_link(self, bot, channel_id):
|
||||
|
||||
@@ -1548,6 +1548,25 @@ class TestChatWithoutRequest(ChatTestBase):
|
||||
monkeypatch.setattr(chat.get_bot(), "get_chat_gifts", make_assertion)
|
||||
assert await chat.get_gifts()
|
||||
|
||||
async def test_instance_method_set_chat_member_tag(self, monkeypatch, chat):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
return (
|
||||
kwargs["chat_id"] == chat.id
|
||||
and kwargs["user_id"] == "user_id"
|
||||
and kwargs["tag"] == "tag"
|
||||
)
|
||||
|
||||
assert check_shortcut_signature(
|
||||
Chat.set_chat_member_tag, Bot.set_chat_member_tag, ["chat_id"], []
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
chat.set_chat_member_tag, chat.get_bot(), "set_chat_member_tag"
|
||||
)
|
||||
assert await check_defaults_handling(chat.set_chat_member_tag, chat.get_bot())
|
||||
|
||||
monkeypatch.setattr(chat.get_bot(), "set_chat_member_tag", make_assertion)
|
||||
assert await chat.set_chat_member_tag(user_id="user_id", tag="tag")
|
||||
|
||||
def test_mention_html(self):
|
||||
chat = Chat(id=1, type="foo")
|
||||
with pytest.raises(TypeError, match="Can not create a mention to a private group chat"):
|
||||
|
||||
@@ -41,6 +41,7 @@ def chat_admin_rights():
|
||||
can_edit_stories=True,
|
||||
can_delete_stories=True,
|
||||
can_manage_direct_messages=True,
|
||||
can_manage_tags=True,
|
||||
)
|
||||
|
||||
|
||||
@@ -69,6 +70,7 @@ class TestChatAdministratorRightsWithoutRequest:
|
||||
"can_edit_stories": True,
|
||||
"can_delete_stories": True,
|
||||
"can_manage_direct_messages": True,
|
||||
"can_manage_tags": True,
|
||||
}
|
||||
chat_administrator_rights_de = ChatAdministratorRights.de_json(json_dict, offline_bot)
|
||||
assert chat_administrator_rights_de.api_kwargs == {}
|
||||
@@ -96,6 +98,7 @@ class TestChatAdministratorRightsWithoutRequest:
|
||||
assert admin_rights_dict["can_edit_stories"] == car.can_edit_stories
|
||||
assert admin_rights_dict["can_delete_stories"] == car.can_delete_stories
|
||||
assert admin_rights_dict["can_manage_direct_messages"] == car.can_manage_direct_messages
|
||||
assert admin_rights_dict["can_manage_tags"] == car.can_manage_tags
|
||||
|
||||
def test_equality(self):
|
||||
a = ChatAdministratorRights(
|
||||
@@ -147,6 +150,7 @@ class TestChatAdministratorRightsWithoutRequest:
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
)
|
||||
t = ChatAdministratorRights.all_rights()
|
||||
# if the dirs are the same, the attributes will all be there
|
||||
@@ -173,6 +177,7 @@ class TestChatAdministratorRightsWithoutRequest:
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
)
|
||||
t = ChatAdministratorRights.no_rights()
|
||||
# if the dirs are the same, the attributes will all be there
|
||||
|
||||
@@ -76,6 +76,9 @@ class ChatMemberTestBase:
|
||||
can_send_messages = True
|
||||
is_member = True
|
||||
can_manage_direct_messages = True
|
||||
can_manage_tags = True
|
||||
can_edit_tag = True
|
||||
tag = "test_tag"
|
||||
|
||||
|
||||
class TestChatMemberWithoutRequest(ChatMemberTestBase):
|
||||
@@ -172,6 +175,7 @@ def chat_member_administrator():
|
||||
TestChatMemberAdministratorWithoutRequest.custom_title,
|
||||
TestChatMemberAdministratorWithoutRequest.is_anonymous,
|
||||
TestChatMemberAdministratorWithoutRequest.can_manage_direct_messages,
|
||||
TestChatMemberAdministratorWithoutRequest.can_manage_tags,
|
||||
)
|
||||
|
||||
|
||||
@@ -205,6 +209,7 @@ class TestChatMemberAdministratorWithoutRequest(ChatMemberTestBase):
|
||||
"custom_title": self.custom_title,
|
||||
"is_anonymous": self.is_anonymous,
|
||||
"can_manage_direct_messages": self.can_manage_direct_messages,
|
||||
"can_manage_tags": self.can_manage_tags,
|
||||
}
|
||||
chat_member = ChatMemberAdministrator.de_json(data, offline_bot)
|
||||
|
||||
@@ -230,6 +235,7 @@ class TestChatMemberAdministratorWithoutRequest(ChatMemberTestBase):
|
||||
assert chat_member.custom_title == self.custom_title
|
||||
assert chat_member.is_anonymous == self.is_anonymous
|
||||
assert chat_member.can_manage_direct_messages == self.can_manage_direct_messages
|
||||
assert chat_member.can_manage_tags == self.can_manage_tags
|
||||
|
||||
def test_to_dict(self, chat_member_administrator):
|
||||
assert chat_member_administrator.to_dict() == {
|
||||
@@ -253,6 +259,7 @@ class TestChatMemberAdministratorWithoutRequest(ChatMemberTestBase):
|
||||
"custom_title": chat_member_administrator.custom_title,
|
||||
"is_anonymous": chat_member_administrator.is_anonymous,
|
||||
"can_manage_direct_messages": chat_member_administrator.can_manage_direct_messages,
|
||||
"can_manage_tags": chat_member_administrator.can_manage_tags,
|
||||
}
|
||||
|
||||
def test_equality(self, chat_member_administrator):
|
||||
@@ -272,6 +279,7 @@ class TestChatMemberAdministratorWithoutRequest(ChatMemberTestBase):
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
)
|
||||
c = ChatMemberAdministrator(
|
||||
User(1, "test_user", is_bot=False),
|
||||
@@ -288,6 +296,7 @@ class TestChatMemberAdministratorWithoutRequest(ChatMemberTestBase):
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
)
|
||||
d = Dice(5, "test")
|
||||
|
||||
@@ -566,6 +575,8 @@ def chat_member_restricted():
|
||||
can_send_voice_notes=TestChatMemberRestrictedWithoutRequest.can_send_voice_notes,
|
||||
is_member=TestChatMemberRestrictedWithoutRequest.is_member,
|
||||
until_date=TestChatMemberRestrictedWithoutRequest.until_date,
|
||||
can_edit_tag=TestChatMemberRestrictedWithoutRequest.can_edit_tag,
|
||||
tag=TestChatMemberRestrictedWithoutRequest.tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -597,6 +608,8 @@ class TestChatMemberRestrictedWithoutRequest(ChatMemberTestBase):
|
||||
"can_send_voice_notes": self.can_send_voice_notes,
|
||||
"is_member": self.is_member,
|
||||
"until_date": to_timestamp(self.until_date),
|
||||
"can_edit_tag": self.can_edit_tag,
|
||||
"tag": self.tag,
|
||||
# legacy argument
|
||||
"can_send_media_messages": False,
|
||||
}
|
||||
@@ -622,6 +635,8 @@ class TestChatMemberRestrictedWithoutRequest(ChatMemberTestBase):
|
||||
assert chat_member.can_send_voice_notes == self.can_send_voice_notes
|
||||
assert chat_member.is_member == self.is_member
|
||||
assert chat_member.until_date == self.until_date
|
||||
assert chat_member.can_edit_tag == self.can_edit_tag
|
||||
assert chat_member.tag == self.tag
|
||||
|
||||
def test_de_json_localization(self, tz_bot, offline_bot, raw_bot, chat_member_restricted):
|
||||
json_dict = chat_member_restricted.to_dict()
|
||||
@@ -660,6 +675,8 @@ class TestChatMemberRestrictedWithoutRequest(ChatMemberTestBase):
|
||||
"can_send_voice_notes": chat_member_restricted.can_send_voice_notes,
|
||||
"is_member": chat_member_restricted.is_member,
|
||||
"until_date": to_timestamp(chat_member_restricted.until_date),
|
||||
"can_edit_tag": chat_member_restricted.can_edit_tag,
|
||||
"tag": chat_member_restricted.tag,
|
||||
}
|
||||
|
||||
def test_equality(self, chat_member_restricted):
|
||||
@@ -683,6 +700,8 @@ class TestChatMemberRestrictedWithoutRequest(ChatMemberTestBase):
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
"tag",
|
||||
)
|
||||
d = Dice(5, "test")
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ def chat_permissions():
|
||||
can_send_videos=True,
|
||||
can_send_video_notes=True,
|
||||
can_send_voice_notes=True,
|
||||
can_edit_tag=True,
|
||||
)
|
||||
|
||||
|
||||
@@ -58,6 +59,7 @@ class ChatPermissionsTestBase:
|
||||
can_send_videos = True
|
||||
can_send_video_notes = False
|
||||
can_send_voice_notes = None
|
||||
can_edit_tag = None
|
||||
|
||||
|
||||
class TestChatPermissionsWithoutRequest(ChatPermissionsTestBase):
|
||||
@@ -83,6 +85,7 @@ class TestChatPermissionsWithoutRequest(ChatPermissionsTestBase):
|
||||
"can_send_videos": self.can_send_videos,
|
||||
"can_send_video_notes": self.can_send_video_notes,
|
||||
"can_send_voice_notes": self.can_send_voice_notes,
|
||||
"can_edit_tag": self.can_edit_tag,
|
||||
}
|
||||
permissions = ChatPermissions.de_json(json_dict, offline_bot)
|
||||
assert permissions.api_kwargs == {"can_send_media_messages": "can_send_media_messages"}
|
||||
@@ -101,6 +104,7 @@ class TestChatPermissionsWithoutRequest(ChatPermissionsTestBase):
|
||||
assert permissions.can_send_videos == self.can_send_videos
|
||||
assert permissions.can_send_video_notes == self.can_send_video_notes
|
||||
assert permissions.can_send_voice_notes == self.can_send_voice_notes
|
||||
assert permissions.can_edit_tag == self.can_edit_tag
|
||||
|
||||
def test_to_dict(self, chat_permissions):
|
||||
permissions_dict = chat_permissions.to_dict()
|
||||
@@ -125,6 +129,7 @@ class TestChatPermissionsWithoutRequest(ChatPermissionsTestBase):
|
||||
assert permissions_dict["can_send_videos"] == chat_permissions.can_send_videos
|
||||
assert permissions_dict["can_send_video_notes"] == chat_permissions.can_send_video_notes
|
||||
assert permissions_dict["can_send_voice_notes"] == chat_permissions.can_send_voice_notes
|
||||
assert permissions_dict["can_edit_tag"] == chat_permissions.can_edit_tag
|
||||
|
||||
def test_equality(self):
|
||||
a = ChatPermissions(
|
||||
@@ -153,6 +158,7 @@ class TestChatPermissionsWithoutRequest(ChatPermissionsTestBase):
|
||||
can_send_videos=True,
|
||||
can_send_video_notes=True,
|
||||
can_send_voice_notes=True,
|
||||
can_edit_tag=True,
|
||||
)
|
||||
f = ChatPermissions(
|
||||
can_send_messages=True,
|
||||
@@ -164,6 +170,7 @@ class TestChatPermissionsWithoutRequest(ChatPermissionsTestBase):
|
||||
can_send_videos=True,
|
||||
can_send_video_notes=True,
|
||||
can_send_voice_notes=True,
|
||||
can_edit_tag=True,
|
||||
)
|
||||
|
||||
assert a == b
|
||||
|
||||
@@ -198,6 +198,7 @@ class TestConstantsWithoutRequest:
|
||||
"reply_markup",
|
||||
"reply_to_message",
|
||||
"sender_chat",
|
||||
"sender_tag",
|
||||
"is_accessible",
|
||||
"quote",
|
||||
"external_reply",
|
||||
|
||||
+38
-6
@@ -19,6 +19,7 @@
|
||||
|
||||
import datetime as dtm
|
||||
from copy import copy, deepcopy
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -434,6 +435,7 @@ def message(bot):
|
||||
},
|
||||
{"chat_owner_changed": ChatOwnerChanged(new_owner=User(4, "Snow", False))},
|
||||
{"chat_owner_left": ChatOwnerLeft(new_owner=User(5, "Crash", False))},
|
||||
{"sender_tag": "This is a tag"},
|
||||
],
|
||||
ids=[
|
||||
"reply",
|
||||
@@ -527,6 +529,7 @@ def message(bot):
|
||||
"gift_upgrade_sent",
|
||||
"chat_owner_changed",
|
||||
"chat_owner_left",
|
||||
"sender_tag",
|
||||
],
|
||||
)
|
||||
def message_params(bot, request):
|
||||
@@ -585,11 +588,20 @@ class MessageTestBase:
|
||||
{"length": 34, "offset": 154, "type": "blockquote"},
|
||||
{"length": 6, "offset": 181, "type": "bold"},
|
||||
{"length": 33, "offset": 190, "type": "expandable_blockquote"},
|
||||
{"length": 4, "offset": 224, "type": "date_time", "unix_time": dtm.datetime(2000, 7, 28)},
|
||||
{
|
||||
"length": 14,
|
||||
"offset": 229,
|
||||
"type": "date_time",
|
||||
"unix_time": dtm.datetime(2000, 7, 28, tzinfo=ZoneInfo("Europe/Berlin")),
|
||||
"date_time_format": "r",
|
||||
},
|
||||
]
|
||||
test_text_v2 = (
|
||||
r"Test for <bold, ita_lic, \`code, links, text-mention and `\pre. "
|
||||
"http://google.com and bold nested in strk>trgh nested in italic. Python pre. Spoiled. "
|
||||
"👍.\nMultiline\nblock quote\nwith nested.\n\nMultiline\nexpandable\nblock quote."
|
||||
"👍.\nMultiline\nblock quote\nwith nested.\n\nMultiline\nexpandable\nblock quote.\ntime"
|
||||
"\ntime_formatted\n"
|
||||
)
|
||||
test_message = Message(
|
||||
message_id=1,
|
||||
@@ -957,7 +969,9 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
'<span class="tg-spoiler">Spoiled</span>. '
|
||||
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
|
||||
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>\n"
|
||||
'<tg-time unix="964742400">time</tg-time>\n'
|
||||
'<tg-time unix="964735200" format="r">time_formatted</tg-time>\n'
|
||||
)
|
||||
text_html = self.test_message_v2.text_html
|
||||
assert text_html == test_html_string
|
||||
@@ -979,7 +993,9 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
'<span class="tg-spoiler">Spoiled</span>. '
|
||||
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
|
||||
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>\n"
|
||||
'<tg-time unix="964742400">time</tg-time>\n'
|
||||
'<tg-time unix="964735200" format="r">time_formatted</tg-time>\n'
|
||||
)
|
||||
text_html = self.test_message_v2.text_html_urled
|
||||
assert text_html == test_html_string
|
||||
@@ -1007,6 +1023,8 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
"\n\n>Multiline\n"
|
||||
">expandable\n"
|
||||
r">block quote\.||"
|
||||
"\n\n"
|
||||
"\n"
|
||||
)
|
||||
text_markdown = self.test_message_v2.text_markdown_v2
|
||||
assert text_markdown == test_md_string
|
||||
@@ -1066,6 +1084,8 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
"\n\n>Multiline\n"
|
||||
">expandable\n"
|
||||
r">block quote\.||"
|
||||
"\n\n"
|
||||
"\n"
|
||||
)
|
||||
text_markdown = self.test_message_v2.text_markdown_v2_urled
|
||||
assert text_markdown == test_md_string
|
||||
@@ -1183,7 +1203,9 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
'<span class="tg-spoiler">Spoiled</span>. '
|
||||
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
|
||||
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>\n"
|
||||
'<tg-time unix="964742400">time</tg-time>\n'
|
||||
'<tg-time unix="964735200" format="r">time_formatted</tg-time>\n'
|
||||
)
|
||||
caption_html = self.test_message_v2.caption_html
|
||||
assert caption_html == test_html_string
|
||||
@@ -1205,7 +1227,9 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
'<span class="tg-spoiler">Spoiled</span>. '
|
||||
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
|
||||
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>\n"
|
||||
'<tg-time unix="964742400">time</tg-time>\n'
|
||||
'<tg-time unix="964735200" format="r">time_formatted</tg-time>\n'
|
||||
)
|
||||
caption_html = self.test_message_v2.caption_html_urled
|
||||
assert caption_html == test_html_string
|
||||
@@ -1233,6 +1257,8 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
"\n\n>Multiline\n"
|
||||
">expandable\n"
|
||||
r">block quote\.||"
|
||||
"\n\n"
|
||||
"\n"
|
||||
)
|
||||
caption_markdown = self.test_message_v2.caption_markdown_v2
|
||||
assert caption_markdown == test_md_string
|
||||
@@ -1267,6 +1293,8 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
"\n\n>Multiline\n"
|
||||
">expandable\n"
|
||||
r">block quote\.||"
|
||||
"\n\n"
|
||||
"\n"
|
||||
)
|
||||
caption_markdown = self.test_message_v2.caption_markdown_v2_urled
|
||||
assert caption_markdown == test_md_string
|
||||
@@ -1746,6 +1774,8 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
"\n\n>Multiline\n"
|
||||
">expandable\n"
|
||||
r">block quote\.||"
|
||||
"\n\n"
|
||||
"\n"
|
||||
)
|
||||
|
||||
async def make_assertion(*_, **kwargs):
|
||||
@@ -1803,7 +1833,9 @@ class TestMessageWithoutRequest(MessageTestBase):
|
||||
'<span class="tg-spoiler">Spoiled</span>. '
|
||||
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
|
||||
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
|
||||
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>\n"
|
||||
'<tg-time unix="964742400">time</tg-time>\n'
|
||||
'<tg-time unix="964735200" format="r">time_formatted</tg-time>\n'
|
||||
)
|
||||
|
||||
async def make_assertion(*_, **kwargs):
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
#
|
||||
# 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 as dtm
|
||||
import random
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import MessageEntity, User
|
||||
from telegram._utils.datetime import UTC, to_timestamp
|
||||
from telegram.constants import MessageEntityType
|
||||
from tests.auxil.slots import mro_slots
|
||||
|
||||
@@ -37,7 +39,25 @@ def message_entity(request):
|
||||
language = None
|
||||
if type_ == MessageEntity.PRE:
|
||||
language = "python"
|
||||
return MessageEntity(type_, 1, 3, url=url, user=user, language=language)
|
||||
custom_emoji_id = None
|
||||
if type_ == MessageEntity.CUSTOM_EMOJI:
|
||||
custom_emoji_id = "emoji_id"
|
||||
date_time_format = None
|
||||
unix_time = None
|
||||
if type_ == MessageEntity.DATE_TIME:
|
||||
date_time_format = "wDT"
|
||||
unix_time = dtm.datetime.now(tz=UTC)
|
||||
return MessageEntity(
|
||||
type_,
|
||||
1,
|
||||
3,
|
||||
url=url,
|
||||
user=user,
|
||||
language=language,
|
||||
custom_emoji_id=custom_emoji_id,
|
||||
date_time_format=date_time_format,
|
||||
unix_time=unix_time,
|
||||
)
|
||||
|
||||
|
||||
class MessageEntityTestBase:
|
||||
@@ -76,6 +96,11 @@ class TestMessageEntityWithoutRequest(MessageEntityTestBase):
|
||||
assert entity_dict["user"] == message_entity.user.to_dict()
|
||||
if message_entity.language:
|
||||
assert entity_dict["language"] == message_entity.language
|
||||
if message_entity.custom_emoji_id:
|
||||
assert entity_dict["custom_emoji_id"] == message_entity.custom_emoji_id
|
||||
if message_entity.date_time_format:
|
||||
assert entity_dict["date_time_format"] == message_entity.date_time_format
|
||||
assert entity_dict["unix_time"] == to_timestamp(message_entity.unix_time)
|
||||
|
||||
def test_enum_init(self):
|
||||
entity = MessageEntity(type="foo", offset=0, length=1)
|
||||
|
||||
@@ -887,3 +887,22 @@ class TestUserWithoutRequest(UserTestBase):
|
||||
|
||||
monkeypatch.setattr(user.get_bot(), "get_user_gifts", make_assertion)
|
||||
assert await user.get_gifts()
|
||||
|
||||
async def test_instance_method_set_chat_member_tag(self, monkeypatch, user):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
return (
|
||||
kwargs["user_id"] == user.id
|
||||
and kwargs["chat_id"] == "chat_id"
|
||||
and kwargs["tag"] == "tag"
|
||||
)
|
||||
|
||||
assert check_shortcut_signature(
|
||||
user.set_chat_member_tag, Bot.set_chat_member_tag, ["user_id"], []
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
user.set_chat_member_tag, user.get_bot(), "set_chat_member_tag"
|
||||
)
|
||||
assert await check_defaults_handling(user.set_chat_member_tag, user.get_bot())
|
||||
|
||||
monkeypatch.setattr(user.get_bot(), "set_chat_member_tag", make_assertion)
|
||||
assert await user.set_chat_member_tag(chat_id="chat_id", tag="tag")
|
||||
|
||||
Reference in New Issue
Block a user