From 51e5bedbea153caa4644bbb04c86d497c22b51b9 Mon Sep 17 00:00:00 2001 From: Harshil <37377066+harshil21@users.noreply.github.com> Date: Tue, 21 May 2024 13:27:01 -0400 Subject: [PATCH 1/5] Introduce _ChatBase --- docs/auxil/sphinx_hooks.py | 1 + docs/source/conf.py | 2 +- docs/source/telegram.chat.rst | 2 + docs/source/telegram.chatfullinfo.rst | 4 +- docs/source/telegram.photosize.rst | 2 +- telegram/_bot.py | 8 +- telegram/_chat.py | 999 +++----------------------- telegram/_chatfullinfo.py | 471 ++++++++++-- telegram/_message.py | 2 +- telegram/constants.py | 5 +- tests/test_chat.py | 248 +------ tests/test_chatfullinfo.py | 202 ++++-- tests/test_official/exceptions.py | 5 +- 13 files changed, 693 insertions(+), 1258 deletions(-) diff --git a/docs/auxil/sphinx_hooks.py b/docs/auxil/sphinx_hooks.py index 3074ac7afb3..2cfbfe14049 100644 --- a/docs/auxil/sphinx_hooks.py +++ b/docs/auxil/sphinx_hooks.py @@ -46,6 +46,7 @@ "_BaseThumbedMedium": "TelegramObject", "_BaseMedium": "TelegramObject", "_CredentialsBase": "TelegramObject", + "_ChatBase": "TelegramObject", } diff --git a/docs/source/conf.py b/docs/source/conf.py index a50e3dbdb05..947479ba4d9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,7 @@ release = "21.2" # telegram.__version__ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "6.1.3" +needs_sphinx = "7.3.7" # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom diff --git a/docs/source/telegram.chat.rst b/docs/source/telegram.chat.rst index 3ef9672472f..d69b08b60e8 100644 --- a/docs/source/telegram.chat.rst +++ b/docs/source/telegram.chat.rst @@ -1,6 +1,8 @@ Chat ==== +.. Also lists methods of _ChatBase, but not the ones of TelegramObject .. autoclass:: telegram.Chat :members: :show-inheritance: + :inherited-members: TelegramObject diff --git a/docs/source/telegram.chatfullinfo.rst b/docs/source/telegram.chatfullinfo.rst index f15dbeedaa1..3bbc9fa9e18 100644 --- a/docs/source/telegram.chatfullinfo.rst +++ b/docs/source/telegram.chatfullinfo.rst @@ -1,6 +1,8 @@ ChatFullInfo ============ +.. Also lists methods of _ChatBase, but not the ones of TelegramObject .. autoclass:: telegram.ChatFullInfo :members: - :show-inheritance: \ No newline at end of file + :show-inheritance: + :inherited-members: TelegramObject \ No newline at end of file diff --git a/docs/source/telegram.photosize.rst b/docs/source/telegram.photosize.rst index d36e6e27fe4..be044f1164b 100644 --- a/docs/source/telegram.photosize.rst +++ b/docs/source/telegram.photosize.rst @@ -1,6 +1,6 @@ PhotoSize ========= -.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject +.. Also lists methods of _BaseMedium, but not the ones of TelegramObject .. autoclass:: telegram.PhotoSize :members: diff --git a/telegram/_bot.py b/telegram/_bot.py index cf08284c7fe..3ae0ce5f17d 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -1152,7 +1152,7 @@ async def forward_message( Note: Since the release of Bot API 5.5 it can be impossible to forward messages from some chats. Use the attributes :attr:`telegram.Message.has_protected_content` and - :attr:`telegram.Chat.has_protected_content` to check this. + :attr:`telegram.ChatFullInfo.has_protected_content` to check this. As a workaround, it is still possible to use :meth:`copy_message`. However, this behaviour is undocumented and might be changed by Telegram. @@ -4610,8 +4610,8 @@ async def set_chat_sticker_set( ) -> bool: """Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate - admin rights. Use the field :attr:`telegram.Chat.can_set_sticker_set` optionally returned - in :meth:`get_chat` requests to check if the bot can use this method. + admin rights. Use the field :attr:`telegram.ChatFullInfo.can_set_sticker_set` optionally + returned in :meth:`get_chat` requests to check if the bot can use this method. Args: chat_id (:obj:`int` | :obj:`str`): |chat_id_group| @@ -4644,7 +4644,7 @@ async def delete_chat_sticker_set( ) -> bool: """Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. - Use the field :attr:`telegram.Chat.can_set_sticker_set` optionally returned in + Use the field :attr:`telegram.ChatFullInfo.can_set_sticker_set` optionally returned in :meth:`get_chat` requests to check if the bot can use this method. Args: diff --git a/telegram/_chat.py b/telegram/_chat.py index b94d006e141..8250a8f179b 100644 --- a/telegram/_chat.py +++ b/telegram/_chat.py @@ -20,36 +20,25 @@ """This module contains an object that represents a Telegram Chat.""" from datetime import datetime from html import escape -from typing import TYPE_CHECKING, Any, Final, Optional, Sequence, Tuple, Union +from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union from telegram import constants -from telegram._birthdate import Birthdate -from telegram._chatlocation import ChatLocation from telegram._chatpermissions import ChatPermissions -from telegram._files.chatphoto import ChatPhoto from telegram._forumtopic import ForumTopic from telegram._menubutton import MenuButton from telegram._reaction import ReactionType from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg -from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import CorrectOptionID, FileInput, JSONDict, ODVInput, ReplyMarkup -from telegram._utils.warnings import warn from telegram.helpers import escape_markdown from telegram.helpers import mention_html as helpers_mention_html from telegram.helpers import mention_markdown as helpers_mention_markdown -from telegram.warnings import PTBDeprecationWarning if TYPE_CHECKING: from telegram import ( Animation, Audio, - Bot, - BusinessIntro, - BusinessLocation, - BusinessOpeningHours, ChatInviteLink, ChatMember, Contact, @@ -77,735 +66,13 @@ ) -_deprecated_attrs = ( - "accent_color_id", - "active_usernames", - "available_reactions", - "background_custom_emoji_id", - "bio", - "birthdate", - "business_intro", - "business_location", - "business_opening_hours", - "can_set_sticker_set", - "custom_emoji_sticker_set_name", - "description", - "emoji_status_custom_emoji_id", - "emoji_status_expiration_date", - "has_aggressive_anti_spam_enabled", - "has_hidden_members", - "has_private_forwards", - "has_protected_content", - "has_restricted_voice_and_video_messages", - "has_visible_history", - "invite_link", - "join_by_request", - "join_to_send_messages", - "linked_chat_id", - "location", - "message_auto_delete_time", - "permissions", - "personal_chat", - "photo", - "pinned_message", - "profile_accent_color_id", - "profile_background_custom_emoji_id", - "slow_mode_delay", - "sticker_set_name", - "unrestrict_boost_count", -) - - -class Chat(TelegramObject): - """This object represents a chat. - - Objects of this class are comparable in terms of equality. Two objects of this class are - considered equal, if their :attr:`id` is equal. - - .. versionchanged:: 20.0 - - * Removed the deprecated methods ``kick_member`` and ``get_members_count``. - * The following are now keyword-only arguments in Bot methods: - ``location``, ``filename``, ``contact``, ``{read, write, connect, pool}_timeout``, - ``api_kwargs``. Use a named argument for those, - and notice that some positional arguments changed position as a result. - - .. versionchanged:: 20.0 - Removed the attribute ``all_members_are_administrators``. As long as Telegram provides - this field for backwards compatibility, it is available through - :attr:`~telegram.TelegramObject.api_kwargs`. - - Args: - id (:obj:`int`): Unique identifier for this chat. This number may be greater than 32 bits - and some programming languages may have difficulty/silent defects in interpreting it. - But it is smaller than 52 bits, so a signed 64-bit integer or double-precision float - type are safe for storing this identifier. - type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`, - :attr:`SUPERGROUP` or :attr:`CHANNEL`. - title (:obj:`str`, optional): Title, for supergroups, channels and group chats. - username (:obj:`str`, optional): Username, for private chats, supergroups and channels if - available. - first_name (:obj:`str`, optional): First name of the other party in a private chat. - last_name (:obj:`str`, optional): Last name of the other party in a private chat. - photo (:class:`telegram.ChatPhoto`, optional): Chat photo. - Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - bio (:obj:`str`, optional): Bio of the other party in a private chat. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_private_forwards (:obj:`bool`, optional): :obj:`True`, if privacy settings of the other - party in the private chat allows to use ``tg://user?id=`` links only in chats - with the user. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 13.9 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - description (:obj:`str`, optional): Description, for groups, supergroups and channel chats. - Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - invite_link (:obj:`str`, optional): Primary invite link, for groups, supergroups and - channel. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - pinned_message (:class:`telegram.Message`, optional): The most recent pinned message - (by sending date). Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - permissions (:class:`telegram.ChatPermissions`): Optional. Default chat member permissions, - for groups and supergroups. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - slow_mode_delay (:obj:`int`, optional): For supergroups, the minimum allowed delay between - consecutive messages sent by each unprivileged user. - Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - message_auto_delete_time (:obj:`int`, optional): The time after which all messages sent to - the chat will be automatically deleted; in seconds. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 13.4 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_protected_content (:obj:`bool`, optional): :obj:`True`, if messages from the chat can't - be forwarded to other chats. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 13.9 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_visible_history (:obj:`bool`, optional): :obj:`True`, if new chat members will have - access to old messages; available only to chat administrators. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - sticker_set_name (:obj:`str`, optional): For supergroups, name of group sticker set. - Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - can_set_sticker_set (:obj:`bool`, optional): :obj:`True`, if the bot can change group the - sticker set. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - linked_chat_id (:obj:`int`, optional): Unique identifier for the linked chat, i.e. the - discussion group identifier for a channel and vice versa; for supergroups and channel - chats. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - location (:class:`telegram.ChatLocation`, optional): For supergroups, the location to which - the supergroup is connected. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - join_to_send_messages (:obj:`bool`, optional): :obj:`True`, if users need to join the - supergroup before they can send messages. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - join_by_request (:obj:`bool`, optional): :obj:`True`, if all users directly joining the - supergroup without using an invite link need to be approved by supergroup - administrators. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_restricted_voice_and_video_messages (:obj:`bool`, optional): :obj:`True`, if the - privacy settings of the other party restrict sending voice and video note messages - in the private chat. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - is_forum (:obj:`bool`, optional): :obj:`True`, if the supergroup chat is a forum - (has topics_ enabled). - - .. versionadded:: 20.0 - active_usernames (Sequence[:obj:`str`], optional): If set, the list of all `active chat - usernames `_; for private chats, supergroups and channels. Returned - only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - business_intro (:class:`telegram.BusinessIntro`, optional): For private chats with - business accounts, the intro of the business. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - business_location (:class:`telegram.BusinessLocation`, optional): For private chats with - business accounts, the location of the business. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - business_opening_hours (:class:`telegram.BusinessOpeningHours`, optional): For private - chats with business accounts, the opening hours of the business. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available - reactions allowed in the chat. If omitted, then all of - :const:`telegram.constants.ReactionEmoji` are allowed. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - accent_color_id (:obj:`int`, optional): Identifier of the - :class:`accent color ` for the chat name and - backgrounds of the chat photo, reply header, and link preview. See `accent colors`_ - for more details. Returned only in :meth:`telegram.Bot.get_chat`. Always returned in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - background_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of emoji chosen - by the chat for the reply header and link preview background. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - profile_accent_color_id (:obj:`int`, optional): Identifier of the - :class:`accent color ` for the chat's profile - background. See profile `accent colors`_ for more details. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - profile_background_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of - the emoji chosen by the chat for its profile background. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - emoji_status_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of emoji - status of the chat or the other party in a private chat. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - emoji_status_expiration_date (:class:`datetime.datetime`, optional): Expiration date of - emoji status of the chat or the other party in a private chat, in seconds. Returned - only in :meth:`telegram.Bot.get_chat`. - |datetime_localization| - - .. versionadded:: 20.5 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - 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 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - 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 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - unrestrict_boost_count (:obj:`int`, optional): For supergroups, the minimum number of - boosts that a non-administrator user needs to add in order to ignore slow mode and chat - permissions. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - custom_emoji_sticker_set_name (:obj:`str`, optional): For supergroups, the name of the - group's custom emoji sticker set. Custom emoji from this set can be used by all users - and bots in the group. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - birthdate (:obj:`telegram.Birthdate`, optional): For private chats, - the date of birth of the user. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - personal_chat (:obj:`telegram.Chat`, optional): For private chats, the personal channel of - the user. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - - Attributes: - id (:obj:`int`): Unique identifier for this chat. This number may be greater than 32 bits - and some programming languages may have difficulty/silent defects in interpreting it. - But it is smaller than 52 bits, so a signed 64-bit integer or double-precision float - type are safe for storing this identifier. - type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`, - :attr:`SUPERGROUP` or :attr:`CHANNEL`. - title (:obj:`str`): Optional. Title, for supergroups, channels and group chats. - username (:obj:`str`): Optional. Username, for private chats, supergroups and channels if - available. - first_name (:obj:`str`): Optional. First name of the other party in a private chat. - last_name (:obj:`str`): Optional. Last name of the other party in a private chat. - photo (:class:`telegram.ChatPhoto`): Optional. Chat photo. - Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - bio (:obj:`str`): Optional. Bio of the other party in a private chat. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_private_forwards (:obj:`bool`): Optional. :obj:`True`, if privacy settings of the other - party in the private chat allows to use ``tg://user?id=`` links only in chats - with the user. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 13.9 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - description (:obj:`str`): Optional. Description, for groups, supergroups and channel chats. - Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - invite_link (:obj:`str`): Optional. Primary invite link, for groups, supergroups and - channel. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - pinned_message (:class:`telegram.Message`): Optional. The most recent pinned message - (by sending date). Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - permissions (:class:`telegram.ChatPermissions`): Optional. Default chat member permissions, - for groups and supergroups. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - slow_mode_delay (:obj:`int`): Optional. For supergroups, the minimum allowed delay between - consecutive messages sent by each unprivileged user. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - message_auto_delete_time (:obj:`int`): Optional. The time after which all messages sent to - the chat will be automatically deleted; in seconds. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 13.4 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_protected_content (:obj:`bool`): Optional. :obj:`True`, if messages from the chat can't - be forwarded to other chats. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 13.9 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_visible_history (:obj:`bool`): Optional. :obj:`True`, if new chat members will have - access to old messages; available only to chat administrators. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - sticker_set_name (:obj:`str`): Optional. For supergroups, name of Group sticker set. - Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - can_set_sticker_set (:obj:`bool`): Optional. :obj:`True`, if the bot can change group the - sticker set. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - linked_chat_id (:obj:`int`): Optional. Unique identifier for the linked chat, i.e. the - discussion group identifier for a channel and vice versa; for supergroups and channel - chats. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - location (:class:`telegram.ChatLocation`): Optional. For supergroups, the location to which - the supergroup is connected. Returned only in :meth:`telegram.Bot.get_chat`. - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - join_to_send_messages (:obj:`bool`): Optional. :obj:`True`, if users need to join - the supergroup before they can send messages. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - join_by_request (:obj:`bool`): Optional. :obj:`True`, if all users directly joining the - supergroup without using an invite link need to be approved by supergroup - administrators. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - has_restricted_voice_and_video_messages (:obj:`bool`): Optional. :obj:`True`, if the - privacy settings of the other party restrict sending voice and video note messages - in the private chat. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - is_forum (:obj:`bool`): Optional. :obj:`True`, if the supergroup chat is a forum - (has topics_ enabled). - - .. versionadded:: 20.0 - active_usernames (Tuple[:obj:`str`]): Optional. If set, the list of all `active chat - usernames `_; for private chats, supergroups and channels. Returned - only in :meth:`telegram.Bot.get_chat`. - This list is empty if the chat has no active usernames or this chat instance was not - obtained via :meth:`~telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - business_intro (:class:`telegram.BusinessIntro`): Optional. For private chats with - business accounts, the intro of the business. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - business_location (:class:`telegram.BusinessLocation`): Optional. For private chats with - business accounts, the location of the business. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - business_opening_hours (:class:`telegram.BusinessOpeningHours`): Optional. For private - chats with business accounts, the opening hours of the business. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available - reactions allowed in the chat. If omitted, then all of - :const:`telegram.constants.ReactionEmoji` are allowed. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - accent_color_id (:obj:`int`): Optional. Identifier of the - :class:`accent color ` for the chat name and - backgrounds of the chat photo, reply header, and link preview. See `accent colors`_ - for more details. Returned only in :meth:`telegram.Bot.get_chat`. Always returned in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - background_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of emoji chosen - by the chat for the reply header and link preview background. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - profile_accent_color_id (:obj:`int`): Optional. Identifier of the - :class:`accent color ` for the chat's profile - background. See profile `accent colors`_ for more details. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - profile_background_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of - the emoji chosen by the chat for its profile background. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.8 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - emoji_status_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of emoji - status of the chat or the other party in a private chat. Returned only in - :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 20.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - emoji_status_expiration_date (:class:`datetime.datetime`): Optional. Expiration date of - emoji status of the chat or the other party in a private chat, in seconds. Returned - only in :meth:`telegram.Bot.get_chat`. - |datetime_localization| - - .. versionadded:: 20.5 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - 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 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - 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 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - unrestrict_boost_count (:obj:`int`): Optional. For supergroups, the minimum number of - boosts that a non-administrator user needs to add in order to ignore slow mode and chat - permissions. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.0 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - custom_emoji_sticker_set_name (:obj:`str`): Optional. For supergroups, the name of the - group's custom emoji sticker set. Custom emoji from this set can be used by all users - and bots in the group. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.0 +class _ChatBase(TelegramObject): + """Base class for :class:`telegram.Chat` and :class:`telegram.ChatFullInfo`. - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - birthdate (:obj:`telegram.Birthdate`): Optional. For private chats, - the date of birth of the user. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - personal_chat (:obj:`telegram.Chat`): Optional. For private chats, the personal channel of - the user. Returned only in :meth:`telegram.Bot.get_chat`. - - .. versionadded:: 21.1 - - .. deprecated:: 21.2 - In accordance to Bot API 7.3, this attribute will be moved to - :class:`telegram.ChatFullInfo`. - - .. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups - .. _accent colors: https://core.telegram.org/bots/api#accent-colors + .. versionadded:: NEXT.VERSION """ - __slots__ = ( - "accent_color_id", - "active_usernames", - "available_reactions", - "background_custom_emoji_id", - "bio", - "birthdate", - "business_intro", - "business_location", - "business_opening_hours", - "can_set_sticker_set", - "custom_emoji_sticker_set_name", - "description", - "emoji_status_custom_emoji_id", - "emoji_status_expiration_date", - "first_name", - "has_aggressive_anti_spam_enabled", - "has_hidden_members", - "has_private_forwards", - "has_protected_content", - "has_restricted_voice_and_video_messages", - "has_visible_history", - "id", - "invite_link", - "is_forum", - "join_by_request", - "join_to_send_messages", - "last_name", - "linked_chat_id", - "location", - "message_auto_delete_time", - "permissions", - "personal_chat", - "photo", - "pinned_message", - "profile_accent_color_id", - "profile_background_custom_emoji_id", - "slow_mode_delay", - "sticker_set_name", - "title", - "type", - "unrestrict_boost_count", - "username", - ) - SENDER: Final[str] = constants.ChatType.SENDER - """:const:`telegram.constants.ChatType.SENDER` - - .. versionadded:: 13.5 - """ - PRIVATE: Final[str] = constants.ChatType.PRIVATE - """:const:`telegram.constants.ChatType.PRIVATE`""" - GROUP: Final[str] = constants.ChatType.GROUP - """:const:`telegram.constants.ChatType.GROUP`""" - SUPERGROUP: Final[str] = constants.ChatType.SUPERGROUP - """:const:`telegram.constants.ChatType.SUPERGROUP`""" - CHANNEL: Final[str] = constants.ChatType.CHANNEL - """:const:`telegram.constants.ChatType.CHANNEL`""" + __slots__ = ("first_name", "id", "is_forum", "last_name", "title", "type", "username") def __init__( self, @@ -815,42 +82,7 @@ def __init__( username: Optional[str] = None, first_name: Optional[str] = None, last_name: Optional[str] = None, - photo: Optional[ChatPhoto] = None, - description: Optional[str] = None, - invite_link: Optional[str] = None, - pinned_message: Optional["Message"] = None, - permissions: Optional[ChatPermissions] = None, - sticker_set_name: Optional[str] = None, - can_set_sticker_set: Optional[bool] = None, - slow_mode_delay: Optional[int] = None, - bio: Optional[str] = None, - linked_chat_id: Optional[int] = None, - location: Optional[ChatLocation] = None, - message_auto_delete_time: Optional[int] = None, - has_private_forwards: Optional[bool] = None, - has_protected_content: Optional[bool] = None, - join_to_send_messages: Optional[bool] = None, - join_by_request: Optional[bool] = None, - has_restricted_voice_and_video_messages: Optional[bool] = None, is_forum: Optional[bool] = None, - active_usernames: Optional[Sequence[str]] = None, - emoji_status_custom_emoji_id: Optional[str] = None, - emoji_status_expiration_date: Optional[datetime] = None, - has_aggressive_anti_spam_enabled: Optional[bool] = None, - has_hidden_members: Optional[bool] = None, - available_reactions: Optional[Sequence[ReactionType]] = None, - accent_color_id: Optional[int] = None, # required in API 7.3 - Optional for back compat - background_custom_emoji_id: Optional[str] = None, - profile_accent_color_id: Optional[int] = None, - profile_background_custom_emoji_id: Optional[str] = None, - has_visible_history: Optional[bool] = None, - unrestrict_boost_count: Optional[int] = None, - custom_emoji_sticker_set_name: Optional[str] = None, - birthdate: Optional[Birthdate] = None, - personal_chat: Optional["Chat"] = None, - business_intro: Optional["BusinessIntro"] = None, - business_location: Optional["BusinessLocation"] = None, - business_opening_hours: Optional["BusinessOpeningHours"] = None, *, api_kwargs: Optional[JSONDict] = None, ): @@ -863,82 +95,31 @@ def __init__( self.username: Optional[str] = username self.first_name: Optional[str] = first_name self.last_name: Optional[str] = last_name - self.photo: Optional[ChatPhoto] = photo - self.bio: Optional[str] = bio - self.has_private_forwards: Optional[bool] = has_private_forwards - self.description: Optional[str] = description - self.invite_link: Optional[str] = invite_link - self.pinned_message: Optional[Message] = pinned_message - self.permissions: Optional[ChatPermissions] = permissions - self.slow_mode_delay: Optional[int] = slow_mode_delay - self.message_auto_delete_time: Optional[int] = ( - int(message_auto_delete_time) if message_auto_delete_time is not None else None - ) - self.has_protected_content: Optional[bool] = has_protected_content - self.has_visible_history: Optional[bool] = has_visible_history - self.sticker_set_name: Optional[str] = sticker_set_name - self.can_set_sticker_set: Optional[bool] = can_set_sticker_set - self.linked_chat_id: Optional[int] = linked_chat_id - self.location: Optional[ChatLocation] = location - self.join_to_send_messages: Optional[bool] = join_to_send_messages - self.join_by_request: Optional[bool] = join_by_request - self.has_restricted_voice_and_video_messages: Optional[bool] = ( - has_restricted_voice_and_video_messages - ) self.is_forum: Optional[bool] = is_forum - self.active_usernames: Tuple[str, ...] = parse_sequence_arg(active_usernames) - self.emoji_status_custom_emoji_id: Optional[str] = emoji_status_custom_emoji_id - self.emoji_status_expiration_date: Optional[datetime] = emoji_status_expiration_date - self.has_aggressive_anti_spam_enabled: Optional[bool] = has_aggressive_anti_spam_enabled - self.has_hidden_members: Optional[bool] = has_hidden_members - self.available_reactions: Optional[Tuple[ReactionType, ...]] = parse_sequence_arg( - available_reactions - ) - self.accent_color_id: Optional[int] = accent_color_id - self.background_custom_emoji_id: Optional[str] = background_custom_emoji_id - self.profile_accent_color_id: Optional[int] = profile_accent_color_id - self.profile_background_custom_emoji_id: Optional[str] = profile_background_custom_emoji_id - self.unrestrict_boost_count: Optional[int] = unrestrict_boost_count - self.custom_emoji_sticker_set_name: Optional[str] = custom_emoji_sticker_set_name - self.birthdate: Optional[Birthdate] = birthdate - self.personal_chat: Optional["Chat"] = personal_chat - self.business_intro: Optional["BusinessIntro"] = business_intro - self.business_location: Optional["BusinessLocation"] = business_location - self.business_opening_hours: Optional["BusinessOpeningHours"] = business_opening_hours - - if self.__class__ is Chat: - for arg in _deprecated_attrs: - if (val := object.__getattribute__(self, arg)) is not None and val != (): - warn( - PTBDeprecationWarning( - "21.2", - f"The argument `{arg}` is deprecated and will only be available via " - "`ChatFullInfo` in the future.", - ), - stacklevel=2, - ) self._id_attrs = (self.id,) self._freeze() - def __getattribute__(self, name: str) -> Any: - if name in _deprecated_attrs and self.__class__ is Chat: - warn( - PTBDeprecationWarning( - "21.2", - f"The attribute `{name}` is deprecated and will only be accessible via " - "`ChatFullInfo` in the future.", - ), - stacklevel=2, - ) - return super().__getattribute__(name) + SENDER: Final[str] = constants.ChatType.SENDER + """:const:`telegram.constants.ChatType.SENDER` + + .. versionadded:: 13.5 + """ + PRIVATE: Final[str] = constants.ChatType.PRIVATE + """:const:`telegram.constants.ChatType.PRIVATE`""" + GROUP: Final[str] = constants.ChatType.GROUP + """:const:`telegram.constants.ChatType.GROUP`""" + SUPERGROUP: Final[str] = constants.ChatType.SUPERGROUP + """:const:`telegram.constants.ChatType.SUPERGROUP`""" + CHANNEL: Final[str] = constants.ChatType.CHANNEL + """:const:`telegram.constants.ChatType.CHANNEL`""" @property def effective_name(self) -> Optional[str]: """ - :obj:`str`: Convenience property. Gives :attr:`title` if not :obj:`None`, - else :attr:`full_name` if not :obj:`None`. + :obj:`str`: Convenience property. Gives :attr:`~Chat.title` if not :obj:`None`, + else :attr:`~Chat.full_name` if not :obj:`None`. .. versionadded:: 20.1 """ @@ -951,8 +132,8 @@ def effective_name(self) -> Optional[str]: @property def full_name(self) -> Optional[str]: """ - :obj:`str`: Convenience property. If :attr:`first_name` is not :obj:`None`, gives - :attr:`first_name` followed by (if available) :attr:`last_name`. + :obj:`str`: Convenience property. If :attr:`~Chat.first_name` is not :obj:`None`, gives + :attr:`~Chat.first_name` followed by (if available) :attr:`~Chat.last_name`. Note: :attr:`full_name` will always be :obj:`None`, if the chat is a (super)group or @@ -968,58 +149,13 @@ def full_name(self) -> Optional[str]: @property def link(self) -> Optional[str]: - """:obj:`str`: Convenience property. If the chat has a :attr:`username`, returns a t.me - link of the chat. + """:obj:`str`: Convenience property. If the chat has a :attr:`~Chat.username`, returns a + t.me link of the chat. """ if self.username: return f"https://t.me/{self.username}" return None - @classmethod - def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["Chat"]: - """See :meth:`telegram.TelegramObject.de_json`.""" - data = cls._parse_data(data) - - if not data: - return None - - # Get the local timezone from the bot if it has defaults - loc_tzinfo = extract_tzinfo_from_defaults(bot) - - data["emoji_status_expiration_date"] = from_timestamp( - data.get("emoji_status_expiration_date"), tzinfo=loc_tzinfo - ) - - data["photo"] = ChatPhoto.de_json(data.get("photo"), bot) - from telegram import ( # pylint: disable=import-outside-toplevel - BusinessIntro, - BusinessLocation, - BusinessOpeningHours, - Message, - ) - - data["pinned_message"] = Message.de_json(data.get("pinned_message"), bot) - data["permissions"] = ChatPermissions.de_json(data.get("permissions"), bot) - data["location"] = ChatLocation.de_json(data.get("location"), bot) - data["available_reactions"] = ReactionType.de_list(data.get("available_reactions"), bot) - data["birthdate"] = Birthdate.de_json(data.get("birthdate"), bot) - data["personal_chat"] = Chat.de_json(data.get("personal_chat"), bot) - data["business_intro"] = BusinessIntro.de_json(data.get("business_intro"), bot) - data["business_location"] = BusinessLocation.de_json(data.get("business_location"), bot) - data["business_opening_hours"] = BusinessOpeningHours.de_json( - data.get("business_opening_hours"), bot - ) - - api_kwargs = {} - # This is a deprecated field that TG still returns for backwards compatibility - # Let's filter it out to speed up the de-json process - if "all_members_are_administrators" in data: - api_kwargs["all_members_are_administrators"] = data.pop( - "all_members_are_administrators" - ) - - return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) - def mention_markdown(self, name: Optional[str] = None) -> str: """ Note: @@ -1030,17 +166,18 @@ def mention_markdown(self, name: Optional[str] = None) -> str: .. versionadded:: 20.0 Args: - name (:obj:`str`): The name used as a link for the chat. Defaults to :attr:`full_name`. + name (:obj:`str`): The name used as a link for the chat. Defaults to + :attr:`~Chat.full_name`. Returns: :obj:`str`: The inline mention for the chat as markdown (version 1). Raises: :exc:`TypeError`: If the chat is a private chat and neither the :paramref:`name` - nor the :attr:`first_name` is set, then throw an :exc:`TypeError`. - If the chat is a public chat and neither the :paramref:`name` nor the :attr:`title` - is set, then throw an :exc:`TypeError`. If chat is a private group chat, then - throw an :exc:`TypeError`. + nor the :attr:`~Chat.first_name` is set, then throw an :exc:`TypeError`. + If the chat is a public chat and neither the :paramref:`name` nor the + :attr:`~Chat.title` is set, then throw an :exc:`TypeError`. If chat is a + private group chat, then throw an :exc:`TypeError`. """ if self.type == self.PRIVATE: @@ -1062,17 +199,18 @@ def mention_markdown_v2(self, name: Optional[str] = None) -> str: .. versionadded:: 20.0 Args: - name (:obj:`str`): The name used as a link for the chat. Defaults to :attr:`full_name`. + name (:obj:`str`): The name used as a link for the chat. Defaults to + :attr:`~Chat.full_name`. Returns: :obj:`str`: The inline mention for the chat as markdown (version 2). Raises: :exc:`TypeError`: If the chat is a private chat and neither the :paramref:`name` - nor the :attr:`first_name` is set, then throw an :exc:`TypeError`. - If the chat is a public chat and neither the :paramref:`name` nor the :attr:`title` - is set, then throw an :exc:`TypeError`. If chat is a private group chat, then - throw an :exc:`TypeError`. + nor the :attr:`~Chat.first_name` is set, then throw an :exc:`TypeError`. + If the chat is a public chat and neither the :paramref:`name` nor the + :attr:`~Chat.title` is set, then throw an :exc:`TypeError`. If chat is a + private group chat, then throw an :exc:`TypeError`. """ if self.type == self.PRIVATE: @@ -1101,10 +239,10 @@ def mention_html(self, name: Optional[str] = None) -> str: Raises: :exc:`TypeError`: If the chat is a private chat and neither the :paramref:`name` - nor the :attr:`first_name` is set, then throw an :exc:`TypeError`. - If the chat is a public chat and neither the :paramref:`name` nor the :attr:`title` - is set, then throw an :exc:`TypeError`. If chat is a private group chat, then - throw an :exc:`TypeError`. + nor the :attr:`~Chat.first_name` is set, then throw an :exc:`TypeError`. + If the chat is a public chat and neither the :paramref:`name` nor the + :attr:`~Chat.title` is set, then throw an :exc:`TypeError`. + If chat is a private group chat, then throw an :exc:`TypeError`. """ if self.type == self.PRIVATE: @@ -4074,3 +3212,60 @@ async def set_message_reaction( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) + + +class Chat(_ChatBase): + """This object represents a chat. + + Objects of this class are comparable in terms of equality. Two objects of this class are + considered equal, if their :attr:`id` is equal. + + .. versionchanged:: 20.0 + + * Removed the deprecated methods ``kick_member`` and ``get_members_count``. + * The following are now keyword-only arguments in Bot methods: + ``location``, ``filename``, ``contact``, ``{read, write, connect, pool}_timeout``, + ``api_kwargs``. Use a named argument for those, + and notice that some positional arguments changed position as a result. + + .. versionchanged:: 20.0 + Removed the attribute ``all_members_are_administrators``. As long as Telegram provides + this field for backwards compatibility, it is available through + :attr:`~telegram.TelegramObject.api_kwargs`. + + .. versionchanged:: NEXT.VERSION + As per Bot API 7.3, most of the arguments and attributes of this class have now moved to + :class:`telegram.ChatFullInfo`. + + Args: + id (:obj:`int`): Unique identifier for this chat. + type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`, + :attr:`SUPERGROUP` or :attr:`CHANNEL`. + title (:obj:`str`, optional): Title, for supergroups, channels and group chats. + username (:obj:`str`, optional): Username, for private chats, supergroups and channels if + available. + first_name (:obj:`str`, optional): First name of the other party in a private chat. + last_name (:obj:`str`, optional): Last name of the other party in a private chat. + is_forum (:obj:`bool`, optional): :obj:`True`, if the supergroup chat is a forum + (has topics_ enabled). + + .. versionadded:: 20.0 + + Attributes: + id (:obj:`int`): Unique identifier for this chat. + type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`, + :attr:`SUPERGROUP` or :attr:`CHANNEL`. + title (:obj:`str`): Optional. Title, for supergroups, channels and group chats. + username (:obj:`str`): Optional. Username, for private chats, supergroups and channels if + available. + first_name (:obj:`str`): Optional. First name of the other party in a private chat. + last_name (:obj:`str`): Optional. Last name of the other party in a private chat. + is_forum (:obj:`bool`): Optional. :obj:`True`, if the supergroup chat is a forum + (has topics_ enabled). + + .. versionadded:: 20.0 + + .. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups + """ + + __slots__ = () diff --git a/telegram/_chatfullinfo.py b/telegram/_chatfullinfo.py index 9b100830bfc..64385186e2a 100644 --- a/telegram/_chatfullinfo.py +++ b/telegram/_chatfullinfo.py @@ -19,58 +19,375 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. """This module contains an object that represents a Telegram ChatFullInfo.""" from datetime import datetime -from typing import TYPE_CHECKING, Optional, Sequence +from typing import TYPE_CHECKING, Optional, Sequence, Tuple from telegram._birthdate import Birthdate -from telegram._chat import Chat +from telegram._chat import Chat, _ChatBase from telegram._chatlocation import ChatLocation from telegram._chatpermissions import ChatPermissions from telegram._files.chatphoto import ChatPhoto from telegram._reaction import ReactionType +from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict if TYPE_CHECKING: - from telegram import BusinessIntro, BusinessLocation, BusinessOpeningHours, Message + from telegram import Bot, BusinessIntro, BusinessLocation, BusinessOpeningHours, Message -class ChatFullInfo(Chat): +class ChatFullInfo(_ChatBase): """ This object contains full information about a chat. Objects of this class are comparable in terms of equality. Two objects of this class are considered equal, if their :attr:`~telegram.Chat.id` is equal. - Caution: - This class is a subclass of :class:`telegram.Chat` and inherits all attributes and methods - for backwards compatibility. In the future, this class will *NOT* inherit from - :class:`telegram.Chat`. - - .. seealso:: - All arguments and attributes can be found in :class:`telegram.Chat`. - .. versionadded:: 21.2 Args: + id (:obj:`int`): Unique identifier for this chat. + type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`, + :attr:`SUPERGROUP` or :attr:`CHANNEL`. + accent_color_id (:obj:`int`, optional): Identifier of the + :class:`accent color ` for the chat name and + backgrounds of the chat photo, reply header, and link preview. See `accent colors`_ + for more details. + + .. versionadded:: 20.8 max_reaction_count (:obj:`int`): The maximum number of reactions that can be set on a message in the chat. .. versionadded:: 21.2 + title (:obj:`str`, optional): Title, for supergroups, channels and group chats. + username (:obj:`str`, optional): Username, for private chats, supergroups and channels if + available. + first_name (:obj:`str`, optional): First name of the other party in a private chat. + last_name (:obj:`str`, optional): Last name of the other party in a private chat. + is_forum (:obj:`bool`, optional): :obj:`True`, if the supergroup chat is a forum + (has topics_ enabled). + + .. versionadded:: 20.0 + photo (:class:`telegram.ChatPhoto`, optional): Chat photo. + active_usernames (Sequence[:obj:`str`], optional): If set, the list of all `active chat + usernames `_; for private chats, supergroups and channels. + + .. versionadded:: 20.0 + birthdate (:obj:`telegram.Birthdate`, optional): For private chats, + the date of birth of the user. + + .. versionadded:: 21.1 + business_intro (:class:`telegram.BusinessIntro`, optional): For private chats with + business accounts, the intro of the business. + + .. versionadded:: 21.1 + business_location (:class:`telegram.BusinessLocation`, optional): For private chats with + business accounts, the location of the business. + + .. versionadded:: 21.1 + business_opening_hours (:class:`telegram.BusinessOpeningHours`, optional): For private + chats with business accounts, the opening hours of the business. + + .. versionadded:: 21.1 + personal_chat (:obj:`telegram.Chat`, optional): For private chats, the personal channel of + the user. + + .. versionadded:: 21.1 + available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available + reactions allowed in the chat. If omitted, then all of + :const:`telegram.constants.ReactionEmoji` are allowed. + + .. versionadded:: 20.8 + background_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of emoji chosen + by the chat for the reply header and link preview background. + + .. versionadded:: 20.8 + profile_accent_color_id (:obj:`int`, optional): Identifier of the + :class:`accent color ` for the chat's profile + background. See profile `accent colors`_ for more details. + + .. versionadded:: 20.8 + profile_background_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of + the emoji chosen by the chat for its profile background. + + .. versionadded:: 20.8 + emoji_status_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of emoji + status of the chat or the other party in a private chat. + + .. versionadded:: 20.0 + emoji_status_expiration_date (:class:`datetime.datetime`, optional): Expiration date of + emoji status of the chat or the other party in a private chat, in seconds. + + |datetime_localization| + + .. versionadded:: 20.5 + bio (:obj:`str`, optional): Bio of the other party in a private chat. + has_private_forwards (:obj:`bool`, optional): :obj:`True`, if privacy settings of the other + party in the private chat allows to use ``tg://user?id=`` links only in chats + with the user. + + .. versionadded:: 13.9 + has_restricted_voice_and_video_messages (:obj:`bool`, optional): :obj:`True`, if the + privacy settings of the other party restrict sending voice and video note messages + in the private chat. + + .. versionadded:: 20.0 + join_to_send_messages (:obj:`bool`, optional): :obj:`True`, if users need to join the + supergroup before they can send messages. + + .. versionadded:: 20.0 + join_by_request (:obj:`bool`, optional): :obj:`True`, if all users directly joining the + supergroup without using an invite link need to be approved by supergroup + administrators. + + .. versionadded:: 20.0 + description (:obj:`str`, optional): Description, for groups, supergroups and channel chats. + invite_link (:obj:`str`, optional): Primary invite link, for groups, supergroups and + channel. + pinned_message (:class:`telegram.Message`, optional): The most recent pinned message + (by sending date). + permissions (:class:`telegram.ChatPermissions`): Optional. Default chat member permissions, + for groups and supergroups. + slow_mode_delay (:obj:`int`, optional): For supergroups, the minimum allowed delay between + consecutive messages sent by each unprivileged user. + unrestrict_boost_count (:obj:`int`, optional): For supergroups, the minimum number of + boosts that a non-administrator user needs to add in order to ignore slow mode and chat + permissions. + + .. versionadded:: 21.0 + message_auto_delete_time (:obj:`int`, optional): The time after which all messages sent to + the chat will be automatically deleted; in seconds. + + .. versionadded:: 13.4 + 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. + + .. 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. + + .. versionadded:: 20.0 + has_protected_content (:obj:`bool`, optional): :obj:`True`, if messages from the chat can't + be forwarded to other chats. + + .. versionadded:: 13.9 + has_visible_history (:obj:`bool`, optional): :obj:`True`, if new chat members will have + access to old messages; available only to chat administrators. + + .. versionadded:: 20.8 + sticker_set_name (:obj:`str`, optional): For supergroups, name of group sticker set. + can_set_sticker_set (:obj:`bool`, optional): :obj:`True`, if the bot can change group the + sticker set. + custom_emoji_sticker_set_name (:obj:`str`, optional): For supergroups, the name of the + group's custom emoji sticker set. Custom emoji from this set can be used by all users + and bots in the group. + + .. versionadded:: 21.0 + linked_chat_id (:obj:`int`, optional): Unique identifier for the linked chat, i.e. the + discussion group identifier for a channel and vice versa; for supergroups and channel + chats. + location (:class:`telegram.ChatLocation`, optional): For supergroups, the location to which + the supergroup is connected. Attributes: + id (:obj:`int`): Unique identifier for this chat. + type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`, + :attr:`SUPERGROUP` or :attr:`CHANNEL`. + accent_color_id (:obj:`int`): Optional. Identifier of the + :class:`accent color ` for the chat name and + backgrounds of the chat photo, reply header, and link preview. See `accent colors`_ + for more details. + + .. versionadded:: 20.8 max_reaction_count (:obj:`int`): The maximum number of reactions that can be set on a message in the chat. .. versionadded:: 21.2 + title (:obj:`str`, optional): Title, for supergroups, channels and group chats. + username (:obj:`str`, optional): Username, for private chats, supergroups and channels if + available. + first_name (:obj:`str`, optional): First name of the other party in a private chat. + last_name (:obj:`str`, optional): Last name of the other party in a private chat. + is_forum (:obj:`bool`, optional): :obj:`True`, if the supergroup chat is a forum + (has topics_ enabled). + + .. versionadded:: 20.0 + photo (:class:`telegram.ChatPhoto`): Optional. Chat photo. + active_usernames (Tuple[:obj:`str`]): Optional. If set, the list of all `active chat + usernames `_; for private chats, supergroups and channels. + + This list is empty if the chat has no active usernames or this chat instance was not + obtained via :meth:`~telegram.Bot.get_chat`. + + .. versionadded:: 20.0 + birthdate (:obj:`telegram.Birthdate`): Optional. For private chats, + the date of birth of the user. + + .. versionadded:: 21.1 + business_intro (:class:`telegram.BusinessIntro`): Optional. For private chats with + business accounts, the intro of the business. + + .. versionadded:: 21.1 + business_location (:class:`telegram.BusinessLocation`): Optional. For private chats with + business accounts, the location of the business. + + .. versionadded:: 21.1 + business_opening_hours (:class:`telegram.BusinessOpeningHours`): Optional. For private + chats with business accounts, the opening hours of the business. + + .. versionadded:: 21.1 + personal_chat (:obj:`telegram.Chat`): Optional. For private chats, the personal channel of + the user. + + .. versionadded:: 21.1 + available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available + reactions allowed in the chat. If omitted, then all of + :const:`telegram.constants.ReactionEmoji` are allowed. + + .. versionadded:: 20.8 + background_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of emoji chosen + by the chat for the reply header and link preview background. + + .. versionadded:: 20.8 + profile_accent_color_id (:obj:`int`): Optional. Identifier of the + :class:`accent color ` for the chat's profile + background. See profile `accent colors`_ for more details. + + .. versionadded:: 20.8 + profile_background_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of + the emoji chosen by the chat for its profile background. + + .. versionadded:: 20.8 + emoji_status_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of emoji + status of the chat or the other party in a private chat. + + .. versionadded:: 20.0 + emoji_status_expiration_date (:class:`datetime.datetime`): Optional. Expiration date of + emoji status of the chat or the other party in a private chat, in seconds. + + |datetime_localization| + + .. versionadded:: 20.5 + bio (:obj:`str`): Optional. Bio of the other party in a private chat. + has_private_forwards (:obj:`bool`): Optional. :obj:`True`, if privacy settings of the other + party in the private chat allows to use ``tg://user?id=`` links only in chats + with the user. + + .. versionadded:: 13.9 + has_restricted_voice_and_video_messages (:obj:`bool`): Optional. :obj:`True`, if the + privacy settings of the other party restrict sending voice and video note messages + in the private chat. + + .. versionadded:: 20.0 + join_to_send_messages (:obj:`bool`): Optional. :obj:`True`, if users need to join + the supergroup before they can send messages. + + .. versionadded:: 20.0 + join_by_request (:obj:`bool`): Optional. :obj:`True`, if all users directly joining the + supergroup without using an invite link need to be approved by supergroup + administrators. + + .. versionadded:: 20.0 + description (:obj:`str`): Optional. Description, for groups, supergroups and channel chats. + invite_link (:obj:`str`): Optional. Primary invite link, for groups, supergroups and + channel. + pinned_message (:class:`telegram.Message`): Optional. The most recent pinned message + (by sending date). + permissions (:class:`telegram.ChatPermissions`): Optional. Default chat member permissions, + for groups and supergroups. + slow_mode_delay (:obj:`int`): Optional. For supergroups, the minimum allowed delay between + consecutive messages sent by each unprivileged user. + unrestrict_boost_count (:obj:`int`): Optional. For supergroups, the minimum number of + boosts that a non-administrator user needs to add in order to ignore slow mode and chat + permissions. + + .. versionadded:: 21.0 + message_auto_delete_time (:obj:`int`): Optional. The time after which all messages sent to + the chat will be automatically deleted; in seconds. + + .. versionadded:: 13.4 + 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. + + .. 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. + + .. versionadded:: 20.0 + has_protected_content (:obj:`bool`): Optional. :obj:`True`, if messages from the chat can't + be forwarded to other chats. + + .. versionadded:: 13.9 + has_visible_history (:obj:`bool`): Optional. :obj:`True`, if new chat members will have + access to old messages; available only to chat administrators. + + .. versionadded:: 20.8 + sticker_set_name (:obj:`str`): Optional. For supergroups, name of Group sticker set. + can_set_sticker_set (:obj:`bool`): Optional. :obj:`True`, if the bot can change group the + sticker set. + custom_emoji_sticker_set_name (:obj:`str`): Optional. For supergroups, the name of the + group's custom emoji sticker set. Custom emoji from this set can be used by all users + and bots in the group. + + .. versionadded:: 21.0 + linked_chat_id (:obj:`int`): Optional. Unique identifier for the linked chat, i.e. the + discussion group identifier for a channel and vice versa; for supergroups and channel + chats. + location (:class:`telegram.ChatLocation`): Optional. For supergroups, the location to which + the supergroup is connected. + + .. _accent colors: https://core.telegram.org/bots/api#accent-colors + .. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups """ - __slots__ = ("max_reaction_count",) + __slots__ = ( + "accent_color_id", + "active_usernames", + "available_reactions", + "background_custom_emoji_id", + "bio", + "birthdate", + "business_intro", + "business_location", + "business_opening_hours", + "can_set_sticker_set", + "custom_emoji_sticker_set_name", + "description", + "emoji_status_custom_emoji_id", + "emoji_status_expiration_date", + "has_aggressive_anti_spam_enabled", + "has_hidden_members", + "has_private_forwards", + "has_protected_content", + "has_restricted_voice_and_video_messages", + "has_visible_history", + "invite_link", + "join_by_request", + "join_to_send_messages", + "linked_chat_id", + "location", + "max_reaction_count", + "message_auto_delete_time", + "permissions", + "personal_chat", + "photo", + "pinned_message", + "profile_accent_color_id", + "profile_background_custom_emoji_id", + "slow_mode_delay", + "sticker_set_name", + "unrestrict_boost_count", + ) def __init__( self, id: int, type: str, - accent_color_id: int, # API 7.3 made this argument required - max_reaction_count: int, # NEW arg in api 7.3 and is required + accent_color_id: int, + max_reaction_count: int, title: Optional[str] = None, username: Optional[str] = None, first_name: Optional[str] = None, @@ -120,47 +437,99 @@ def __init__( username=username, first_name=first_name, last_name=last_name, - photo=photo, - description=description, - invite_link=invite_link, - pinned_message=pinned_message, - permissions=permissions, - sticker_set_name=sticker_set_name, - can_set_sticker_set=can_set_sticker_set, - slow_mode_delay=slow_mode_delay, - bio=bio, - linked_chat_id=linked_chat_id, - location=location, - message_auto_delete_time=message_auto_delete_time, - has_private_forwards=has_private_forwards, - has_protected_content=has_protected_content, - join_to_send_messages=join_to_send_messages, - join_by_request=join_by_request, - has_restricted_voice_and_video_messages=has_restricted_voice_and_video_messages, is_forum=is_forum, - active_usernames=active_usernames, - emoji_status_custom_emoji_id=emoji_status_custom_emoji_id, - emoji_status_expiration_date=emoji_status_expiration_date, - has_aggressive_anti_spam_enabled=has_aggressive_anti_spam_enabled, - has_hidden_members=has_hidden_members, - available_reactions=available_reactions, - accent_color_id=accent_color_id, - background_custom_emoji_id=background_custom_emoji_id, - profile_accent_color_id=profile_accent_color_id, - profile_background_custom_emoji_id=profile_background_custom_emoji_id, - has_visible_history=has_visible_history, - unrestrict_boost_count=unrestrict_boost_count, - custom_emoji_sticker_set_name=custom_emoji_sticker_set_name, - birthdate=birthdate, - personal_chat=personal_chat, - business_intro=business_intro, - business_location=business_location, - business_opening_hours=business_opening_hours, api_kwargs=api_kwargs, ) # Required and unique to this class- with self._unfrozen(): self.max_reaction_count: int = max_reaction_count + self.photo: Optional[ChatPhoto] = photo + self.bio: Optional[str] = bio + self.has_private_forwards: Optional[bool] = has_private_forwards + self.description: Optional[str] = description + self.invite_link: Optional[str] = invite_link + self.pinned_message: Optional[Message] = pinned_message + self.permissions: Optional[ChatPermissions] = permissions + self.slow_mode_delay: Optional[int] = slow_mode_delay + self.message_auto_delete_time: Optional[int] = ( + int(message_auto_delete_time) if message_auto_delete_time is not None else None + ) + self.has_protected_content: Optional[bool] = has_protected_content + self.has_visible_history: Optional[bool] = has_visible_history + self.sticker_set_name: Optional[str] = sticker_set_name + self.can_set_sticker_set: Optional[bool] = can_set_sticker_set + self.linked_chat_id: Optional[int] = linked_chat_id + self.location: Optional[ChatLocation] = location + self.join_to_send_messages: Optional[bool] = join_to_send_messages + self.join_by_request: Optional[bool] = join_by_request + self.has_restricted_voice_and_video_messages: Optional[bool] = ( + has_restricted_voice_and_video_messages + ) + self.active_usernames: Tuple[str, ...] = parse_sequence_arg(active_usernames) + self.emoji_status_custom_emoji_id: Optional[str] = emoji_status_custom_emoji_id + self.emoji_status_expiration_date: Optional[datetime] = emoji_status_expiration_date + self.has_aggressive_anti_spam_enabled: Optional[bool] = ( + has_aggressive_anti_spam_enabled + ) + self.has_hidden_members: Optional[bool] = has_hidden_members + self.available_reactions: Optional[Tuple[ReactionType, ...]] = parse_sequence_arg( + available_reactions + ) + self.accent_color_id: Optional[int] = accent_color_id + self.background_custom_emoji_id: Optional[str] = background_custom_emoji_id + self.profile_accent_color_id: Optional[int] = profile_accent_color_id + self.profile_background_custom_emoji_id: Optional[str] = ( + profile_background_custom_emoji_id + ) + self.unrestrict_boost_count: Optional[int] = unrestrict_boost_count + self.custom_emoji_sticker_set_name: Optional[str] = custom_emoji_sticker_set_name + self.birthdate: Optional[Birthdate] = birthdate + self.personal_chat: Optional["Chat"] = personal_chat + self.business_intro: Optional["BusinessIntro"] = business_intro + self.business_location: Optional["BusinessLocation"] = business_location + self.business_opening_hours: Optional["BusinessOpeningHours"] = business_opening_hours + + @classmethod + def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatFullInfo"]: + """See :meth:`telegram.TelegramObject.de_json`.""" + data = cls._parse_data(data) + + if not data: + return None + + # Get the local timezone from the bot if it has defaults + loc_tzinfo = extract_tzinfo_from_defaults(bot) + + data["emoji_status_expiration_date"] = from_timestamp( + data.get("emoji_status_expiration_date"), tzinfo=loc_tzinfo + ) + + data["photo"] = ChatPhoto.de_json(data.get("photo"), bot) + + from telegram import ( # pylint: disable=import-outside-toplevel + BusinessIntro, + BusinessLocation, + BusinessOpeningHours, + Message, + ) + + data["pinned_message"] = Message.de_json(data.get("pinned_message"), bot) + data["permissions"] = ChatPermissions.de_json(data.get("permissions"), bot) + data["location"] = ChatLocation.de_json(data.get("location"), bot) + data["available_reactions"] = ReactionType.de_list(data.get("available_reactions"), bot) + data["birthdate"] = Birthdate.de_json(data.get("birthdate"), bot) + data["personal_chat"] = Chat.de_json(data.get("personal_chat"), bot) + data["business_intro"] = BusinessIntro.de_json(data.get("business_intro"), bot) + data["business_location"] = BusinessLocation.de_json(data.get("business_location"), bot) + data["business_opening_hours"] = BusinessOpeningHours.de_json( + data.get("business_opening_hours"), bot + ) + + api_kwargs = {} + # This is a deprecated field that TG still returns for backwards compatibility + # Let's filter it out to speed up the de-json process + if (amaa := "all_members_are_administrators") in data: + api_kwargs[amaa] = data.pop(amaa) - self._freeze() + return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) diff --git a/telegram/_message.py b/telegram/_message.py index eaea1f3fb08..195724d36f7 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -3331,7 +3331,7 @@ async def forward( Note: Since the release of Bot API 5.5 it can be impossible to forward messages from some chats. Use the attributes :attr:`telegram.Message.has_protected_content` and - :attr:`telegram.Chat.has_protected_content` to check this. + :attr:`telegram.ChatFullInfo.has_protected_content` to check this. As a workaround, it is still possible to use :meth:`copy`. However, this behaviour is undocumented and might be changed by Telegram. diff --git a/telegram/constants.py b/telegram/constants.py index a2d91885cb4..06f5bff86f5 100644 --- a/telegram/constants.py +++ b/telegram/constants.py @@ -168,7 +168,8 @@ class _AccentColor(NamedTuple): class AccentColor(Enum): - """This enum contains the available accent colors for :class:`telegram.Chat.accent_color_id`. + """This enum contains the available accent colors for + :class:`telegram.ChatFullInfo.accent_color_id`. The members of this enum are named tuples with the following attributes: - ``identifier`` (:obj:`int`): The identifier of the accent color. @@ -1959,7 +1960,7 @@ class PollingLimit(IntEnum): class ProfileAccentColor(Enum): """This enum contains the available accent colors for - :class:`telegram.Chat.profile_accent_color_id`. + :class:`telegram.ChatFullInfo.profile_accent_color_id`. The members of this enum are named tuples with the following attributes: - ``identifier`` (:obj:`int`): The identifier of the accent color. diff --git a/tests/test_chat.py b/tests/test_chat.py index 7af7a677ce0..36c1e80a800 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -17,31 +17,12 @@ # 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 warnings import pytest -from telegram import ( - Birthdate, - Bot, - BusinessIntro, - BusinessLocation, - BusinessOpeningHours, - BusinessOpeningHoursInterval, - Chat, - ChatLocation, - ChatPermissions, - Location, - ReactionTypeCustomEmoji, - ReactionTypeEmoji, - User, -) -from telegram._chat import _deprecated_attrs -from telegram._utils.datetime import UTC, to_timestamp +from telegram import Bot, Chat, ChatPermissions, ReactionTypeEmoji, User from telegram.constants import ChatAction, ChatType, ReactionEmoji from telegram.helpers import escape_markdown -from telegram.warnings import PTBDeprecationWarning from tests.auxil.bot_method_checks import ( check_defaults_handling, check_shortcut_call, @@ -57,37 +38,7 @@ def chat(bot): title=TestChatBase.title, type=TestChatBase.type_, username=TestChatBase.username, - sticker_set_name=TestChatBase.sticker_set_name, - can_set_sticker_set=TestChatBase.can_set_sticker_set, - permissions=TestChatBase.permissions, - slow_mode_delay=TestChatBase.slow_mode_delay, - bio=TestChatBase.bio, - linked_chat_id=TestChatBase.linked_chat_id, - location=TestChatBase.location, - has_private_forwards=True, - has_protected_content=True, - has_visible_history=True, - join_to_send_messages=True, - join_by_request=True, - has_restricted_voice_and_video_messages=True, is_forum=True, - active_usernames=TestChatBase.active_usernames, - emoji_status_custom_emoji_id=TestChatBase.emoji_status_custom_emoji_id, - emoji_status_expiration_date=TestChatBase.emoji_status_expiration_date, - has_aggressive_anti_spam_enabled=TestChatBase.has_aggressive_anti_spam_enabled, - has_hidden_members=TestChatBase.has_hidden_members, - available_reactions=TestChatBase.available_reactions, - accent_color_id=TestChatBase.accent_color_id, - background_custom_emoji_id=TestChatBase.background_custom_emoji_id, - profile_accent_color_id=TestChatBase.profile_accent_color_id, - profile_background_custom_emoji_id=TestChatBase.profile_background_custom_emoji_id, - unrestrict_boost_count=TestChatBase.unrestrict_boost_count, - custom_emoji_sticker_set_name=TestChatBase.custom_emoji_sticker_set_name, - business_intro=TestChatBase.business_intro, - business_location=TestChatBase.business_location, - business_opening_hours=TestChatBase.business_opening_hours, - birthdate=Birthdate(1, 1), - personal_chat=TestChatBase.personal_chat, first_name=TestChatBase.first_name, last_name=TestChatBase.last_name, ) @@ -101,48 +52,7 @@ class TestChatBase: title = "ToledosPalaceBot - Group" type_ = "group" username = "username" - all_members_are_administrators = False - sticker_set_name = "stickers" - can_set_sticker_set = False - permissions = ChatPermissions( - can_send_messages=True, - can_change_info=False, - can_invite_users=True, - ) - slow_mode_delay = 30 - bio = "I'm a Barbie Girl in a Barbie World" - linked_chat_id = 11880 - location = ChatLocation(Location(123, 456), "Barbie World") - has_protected_content = True - has_visible_history = True - has_private_forwards = True - join_to_send_messages = True - join_by_request = True - has_restricted_voice_and_video_messages = True is_forum = True - active_usernames = ["These", "Are", "Usernames!"] - emoji_status_custom_emoji_id = "VeryUniqueCustomEmojiID" - emoji_status_expiration_date = datetime.datetime.now(tz=UTC).replace(microsecond=0) - has_aggressive_anti_spam_enabled = True - has_hidden_members = True - available_reactions = [ - ReactionTypeEmoji(ReactionEmoji.THUMBS_DOWN), - ReactionTypeCustomEmoji("custom_emoji_id"), - ] - business_intro = BusinessIntro("Title", "Description", None) - business_location = BusinessLocation("Address", Location(123, 456)) - business_opening_hours = BusinessOpeningHours( - "Country/City", - [BusinessOpeningHoursInterval(opening, opening + 60) for opening in (0, 24 * 60)], - ) - accent_color_id = 1 - background_custom_emoji_id = "background_custom_emoji_id" - profile_accent_color_id = 2 - profile_background_custom_emoji_id = "profile_background_custom_emoji_id" - unrestrict_boost_count = 100 - custom_emoji_sticker_set_name = "custom_emoji_sticker_set_name" - birthdate = Birthdate(1, 1) - personal_chat = Chat(3, "private", "private") first_name = "first" last_name = "last" @@ -159,40 +69,7 @@ def test_de_json(self, bot): "title": self.title, "type": self.type_, "username": self.username, - "all_members_are_administrators": self.all_members_are_administrators, - "sticker_set_name": self.sticker_set_name, - "can_set_sticker_set": self.can_set_sticker_set, - "permissions": self.permissions.to_dict(), - "slow_mode_delay": self.slow_mode_delay, - "bio": self.bio, - "business_intro": self.business_intro.to_dict(), - "business_location": self.business_location.to_dict(), - "business_opening_hours": self.business_opening_hours.to_dict(), - "has_protected_content": self.has_protected_content, - "has_visible_history": self.has_visible_history, - "has_private_forwards": self.has_private_forwards, - "linked_chat_id": self.linked_chat_id, - "location": self.location.to_dict(), - "join_to_send_messages": self.join_to_send_messages, - "join_by_request": self.join_by_request, - "has_restricted_voice_and_video_messages": ( - self.has_restricted_voice_and_video_messages - ), "is_forum": self.is_forum, - "active_usernames": self.active_usernames, - "emoji_status_custom_emoji_id": self.emoji_status_custom_emoji_id, - "emoji_status_expiration_date": to_timestamp(self.emoji_status_expiration_date), - "has_aggressive_anti_spam_enabled": self.has_aggressive_anti_spam_enabled, - "has_hidden_members": self.has_hidden_members, - "available_reactions": [reaction.to_dict() for reaction in self.available_reactions], - "accent_color_id": self.accent_color_id, - "background_custom_emoji_id": self.background_custom_emoji_id, - "profile_accent_color_id": self.profile_accent_color_id, - "profile_background_custom_emoji_id": self.profile_background_custom_emoji_id, - "unrestrict_boost_count": self.unrestrict_boost_count, - "custom_emoji_sticker_set_name": self.custom_emoji_sticker_set_name, - "birthdate": self.birthdate.to_dict(), - "personal_chat": self.personal_chat.to_dict(), "first_name": self.first_name, "last_name": self.last_name, } @@ -202,76 +79,10 @@ def test_de_json(self, bot): assert chat.title == self.title assert chat.type == self.type_ assert chat.username == self.username - assert chat.sticker_set_name == self.sticker_set_name - assert chat.can_set_sticker_set == self.can_set_sticker_set - assert chat.permissions == self.permissions - assert chat.slow_mode_delay == self.slow_mode_delay - assert chat.bio == self.bio - assert chat.business_intro == self.business_intro - assert chat.business_location == self.business_location - assert chat.business_opening_hours == self.business_opening_hours - assert chat.has_protected_content == self.has_protected_content - assert chat.has_visible_history == self.has_visible_history - assert chat.has_private_forwards == self.has_private_forwards - assert chat.linked_chat_id == self.linked_chat_id - assert chat.location.location == self.location.location - assert chat.location.address == self.location.address - assert chat.join_to_send_messages == self.join_to_send_messages - assert chat.join_by_request == self.join_by_request - assert ( - chat.has_restricted_voice_and_video_messages - == self.has_restricted_voice_and_video_messages - ) - assert chat.api_kwargs == { - "all_members_are_administrators": self.all_members_are_administrators - } 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.emoji_status_expiration_date == (self.emoji_status_expiration_date) - assert chat.has_aggressive_anti_spam_enabled == self.has_aggressive_anti_spam_enabled - assert chat.has_hidden_members == self.has_hidden_members - assert chat.available_reactions == tuple(self.available_reactions) - assert chat.accent_color_id == self.accent_color_id - assert chat.background_custom_emoji_id == self.background_custom_emoji_id - assert chat.profile_accent_color_id == self.profile_accent_color_id - assert chat.profile_background_custom_emoji_id == self.profile_background_custom_emoji_id - assert chat.unrestrict_boost_count == self.unrestrict_boost_count - assert chat.custom_emoji_sticker_set_name == self.custom_emoji_sticker_set_name - assert chat.birthdate == self.birthdate - assert chat.personal_chat == self.personal_chat assert chat.first_name == self.first_name assert chat.last_name == self.last_name - def test_de_json_localization(self, bot, raw_bot, tz_bot): - json_dict = { - "id": self.id_, - "type": self.type_, - "emoji_status_expiration_date": to_timestamp(self.emoji_status_expiration_date), - } - chat_bot = Chat.de_json(json_dict, bot) - chat_bot_raw = Chat.de_json(json_dict, raw_bot) - chat_bot_tz = Chat.de_json(json_dict, tz_bot) - - # comparing utcoffsets because comparing tzinfo objects is not reliable - emoji_expire_offset = chat_bot_tz.emoji_status_expiration_date.utcoffset() - emoji_expire_offset_tz = tz_bot.defaults.tzinfo.utcoffset( - chat_bot_tz.emoji_status_expiration_date.replace(tzinfo=None) - ) - - assert chat_bot.emoji_status_expiration_date.tzinfo == UTC - assert chat_bot_raw.emoji_status_expiration_date.tzinfo == UTC - assert emoji_expire_offset_tz == emoji_expire_offset - - def test_always_tuples_attributes(self): - chat = Chat( - id=123, - title="title", - type=Chat.PRIVATE, - ) - assert isinstance(chat.active_usernames, tuple) - assert chat.active_usernames == () - def test_to_dict(self, chat): chat_dict = chat.to_dict() @@ -280,67 +91,10 @@ def test_to_dict(self, chat): assert chat_dict["title"] == chat.title assert chat_dict["type"] == chat.type assert chat_dict["username"] == chat.username - assert chat_dict["permissions"] == chat.permissions.to_dict() - assert chat_dict["slow_mode_delay"] == chat.slow_mode_delay - assert chat_dict["bio"] == chat.bio - assert chat_dict["business_intro"] == chat.business_intro.to_dict() - assert chat_dict["business_location"] == chat.business_location.to_dict() - assert chat_dict["business_opening_hours"] == chat.business_opening_hours.to_dict() - assert chat_dict["has_private_forwards"] == chat.has_private_forwards - assert chat_dict["has_protected_content"] == chat.has_protected_content - assert chat_dict["has_visible_history"] == chat.has_visible_history - assert chat_dict["linked_chat_id"] == chat.linked_chat_id - assert chat_dict["location"] == chat.location.to_dict() - assert chat_dict["join_to_send_messages"] == chat.join_to_send_messages - assert chat_dict["join_by_request"] == chat.join_by_request - assert ( - chat_dict["has_restricted_voice_and_video_messages"] - == chat.has_restricted_voice_and_video_messages - ) 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["emoji_status_expiration_date"] == to_timestamp( - chat.emoji_status_expiration_date - ) - assert ( - chat_dict["has_aggressive_anti_spam_enabled"] == chat.has_aggressive_anti_spam_enabled - ) - assert chat_dict["has_hidden_members"] == chat.has_hidden_members - assert chat_dict["available_reactions"] == [ - reaction.to_dict() for reaction in chat.available_reactions - ] - assert chat_dict["accent_color_id"] == chat.accent_color_id - assert chat_dict["background_custom_emoji_id"] == chat.background_custom_emoji_id - assert chat_dict["profile_accent_color_id"] == chat.profile_accent_color_id - assert ( - chat_dict["profile_background_custom_emoji_id"] - == chat.profile_background_custom_emoji_id - ) - assert chat_dict["custom_emoji_sticker_set_name"] == chat.custom_emoji_sticker_set_name - assert chat_dict["unrestrict_boost_count"] == chat.unrestrict_boost_count - assert chat_dict["birthdate"] == chat.birthdate.to_dict() - assert chat_dict["personal_chat"] == chat.personal_chat.to_dict() assert chat_dict["first_name"] == chat.first_name assert chat_dict["last_name"] == chat.last_name - def test_deprecated_attributes(self, chat): - for depr_attr in _deprecated_attrs: - with pytest.warns(PTBDeprecationWarning, match="deprecated and will only be accessib"): - getattr(chat, depr_attr) - with warnings.catch_warnings(): # No warning should be raised - warnings.simplefilter("error") - chat.id - chat.first_name - - def test_deprecated_arguments(self): - for depr_attr in _deprecated_attrs: - with pytest.warns(PTBDeprecationWarning, match="deprecated and will only be availabl"): - Chat(1, "type", **{depr_attr: "1"}) - with warnings.catch_warnings(): # No warning should be raised - warnings.simplefilter("error") - Chat(1, "type", first_name="first_name") - def test_enum_init(self): chat = Chat(id=1, type="foo") assert chat.type == "foo" diff --git a/tests/test_chatfullinfo.py b/tests/test_chatfullinfo.py index f42642e4ed2..a2903e01104 100644 --- a/tests/test_chatfullinfo.py +++ b/tests/test_chatfullinfo.py @@ -17,7 +17,6 @@ # 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 warnings import pytest @@ -35,7 +34,6 @@ ReactionTypeCustomEmoji, ReactionTypeEmoji, ) -from telegram._chat import _deprecated_attrs from telegram._utils.datetime import UTC, to_timestamp from telegram.constants import ReactionEmoji from tests.auxil.slots import mro_slots @@ -44,19 +42,19 @@ @pytest.fixture(scope="module") def chat_full_info(bot): chat = ChatFullInfo( - TestChatInfoBase.id_, - type=TestChatInfoBase.type_, - accent_color_id=TestChatInfoBase.accent_color_id, - max_reaction_count=TestChatInfoBase.max_reaction_count, - title=TestChatInfoBase.title, - username=TestChatInfoBase.username, - sticker_set_name=TestChatInfoBase.sticker_set_name, - can_set_sticker_set=TestChatInfoBase.can_set_sticker_set, - permissions=TestChatInfoBase.permissions, - slow_mode_delay=TestChatInfoBase.slow_mode_delay, - bio=TestChatInfoBase.bio, - linked_chat_id=TestChatInfoBase.linked_chat_id, - location=TestChatInfoBase.location, + TestChatFullInfoBase.id_, + type=TestChatFullInfoBase.type_, + accent_color_id=TestChatFullInfoBase.accent_color_id, + max_reaction_count=TestChatFullInfoBase.max_reaction_count, + title=TestChatFullInfoBase.title, + username=TestChatFullInfoBase.username, + sticker_set_name=TestChatFullInfoBase.sticker_set_name, + can_set_sticker_set=TestChatFullInfoBase.can_set_sticker_set, + permissions=TestChatFullInfoBase.permissions, + slow_mode_delay=TestChatFullInfoBase.slow_mode_delay, + bio=TestChatFullInfoBase.bio, + linked_chat_id=TestChatFullInfoBase.linked_chat_id, + location=TestChatFullInfoBase.location, has_private_forwards=True, has_protected_content=True, has_visible_history=True, @@ -64,29 +62,31 @@ def chat_full_info(bot): join_by_request=True, has_restricted_voice_and_video_messages=True, is_forum=True, - active_usernames=TestChatInfoBase.active_usernames, - emoji_status_custom_emoji_id=TestChatInfoBase.emoji_status_custom_emoji_id, - emoji_status_expiration_date=TestChatInfoBase.emoji_status_expiration_date, - has_aggressive_anti_spam_enabled=TestChatInfoBase.has_aggressive_anti_spam_enabled, - has_hidden_members=TestChatInfoBase.has_hidden_members, - available_reactions=TestChatInfoBase.available_reactions, - background_custom_emoji_id=TestChatInfoBase.background_custom_emoji_id, - profile_accent_color_id=TestChatInfoBase.profile_accent_color_id, - profile_background_custom_emoji_id=TestChatInfoBase.profile_background_custom_emoji_id, - unrestrict_boost_count=TestChatInfoBase.unrestrict_boost_count, - custom_emoji_sticker_set_name=TestChatInfoBase.custom_emoji_sticker_set_name, - business_intro=TestChatInfoBase.business_intro, - business_location=TestChatInfoBase.business_location, - business_opening_hours=TestChatInfoBase.business_opening_hours, + active_usernames=TestChatFullInfoBase.active_usernames, + emoji_status_custom_emoji_id=TestChatFullInfoBase.emoji_status_custom_emoji_id, + emoji_status_expiration_date=TestChatFullInfoBase.emoji_status_expiration_date, + has_aggressive_anti_spam_enabled=TestChatFullInfoBase.has_aggressive_anti_spam_enabled, + has_hidden_members=TestChatFullInfoBase.has_hidden_members, + available_reactions=TestChatFullInfoBase.available_reactions, + background_custom_emoji_id=TestChatFullInfoBase.background_custom_emoji_id, + profile_accent_color_id=TestChatFullInfoBase.profile_accent_color_id, + profile_background_custom_emoji_id=TestChatFullInfoBase.profile_background_custom_emoji_id, + unrestrict_boost_count=TestChatFullInfoBase.unrestrict_boost_count, + custom_emoji_sticker_set_name=TestChatFullInfoBase.custom_emoji_sticker_set_name, + business_intro=TestChatFullInfoBase.business_intro, + business_location=TestChatFullInfoBase.business_location, + business_opening_hours=TestChatFullInfoBase.business_opening_hours, birthdate=Birthdate(1, 1), - personal_chat=TestChatInfoBase.personal_chat, + personal_chat=TestChatFullInfoBase.personal_chat, + first_name="first_name", + last_name="last_name", ) chat.set_bot(bot) chat._unfreeze() return chat -class TestChatInfoBase: +class TestChatFullInfoBase: id_ = -28767330 max_reaction_count = 2 title = "ToledosPalaceBot - Group" @@ -134,13 +134,16 @@ class TestChatInfoBase: custom_emoji_sticker_set_name = "custom_emoji_sticker_set_name" birthdate = Birthdate(1, 1) personal_chat = Chat(3, "private", "private") + first_name = "first_name" + last_name = "last_name" -class TestChatWithoutRequest(TestChatInfoBase): +class TestChatFullInfoWithoutRequest(TestChatFullInfoBase): def test_slot_behaviour(self, chat_full_info): cfi = chat_full_info for attr in cfi.__slots__: assert getattr(cfi, attr, "err") != "err", f"got extra slot '{attr}'" + assert len(mro_slots(cfi)) == len(set(mro_slots(cfi))), "duplicate slot" def test_de_json(self, bot): @@ -184,26 +187,137 @@ def test_de_json(self, bot): "custom_emoji_sticker_set_name": self.custom_emoji_sticker_set_name, "birthdate": self.birthdate.to_dict(), "personal_chat": self.personal_chat.to_dict(), + "first_name": self.first_name, + "last_name": self.last_name, } cfi = ChatFullInfo.de_json(json_dict, bot) + assert cfi.id == self.id_ + assert cfi.title == self.title + assert cfi.type == self.type_ + assert cfi.username == self.username + assert cfi.sticker_set_name == self.sticker_set_name + assert cfi.can_set_sticker_set == self.can_set_sticker_set + assert cfi.permissions == self.permissions + assert cfi.slow_mode_delay == self.slow_mode_delay + assert cfi.bio == self.bio + assert cfi.business_intro == self.business_intro + assert cfi.business_location == self.business_location + assert cfi.business_opening_hours == self.business_opening_hours + assert cfi.has_protected_content == self.has_protected_content + assert cfi.has_visible_history == self.has_visible_history + assert cfi.has_private_forwards == self.has_private_forwards + assert cfi.linked_chat_id == self.linked_chat_id + assert cfi.location.location == self.location.location + assert cfi.location.address == self.location.address + assert cfi.join_to_send_messages == self.join_to_send_messages + assert cfi.join_by_request == self.join_by_request + assert ( + cfi.has_restricted_voice_and_video_messages + == self.has_restricted_voice_and_video_messages + ) + assert cfi.api_kwargs == { + "all_members_are_administrators": self.all_members_are_administrators + } + assert cfi.is_forum == self.is_forum + assert cfi.active_usernames == tuple(self.active_usernames) + assert cfi.emoji_status_custom_emoji_id == self.emoji_status_custom_emoji_id + assert cfi.emoji_status_expiration_date == (self.emoji_status_expiration_date) + assert cfi.has_aggressive_anti_spam_enabled == self.has_aggressive_anti_spam_enabled + assert cfi.has_hidden_members == self.has_hidden_members + assert cfi.available_reactions == tuple(self.available_reactions) + assert cfi.accent_color_id == self.accent_color_id + assert cfi.background_custom_emoji_id == self.background_custom_emoji_id + assert cfi.profile_accent_color_id == self.profile_accent_color_id + assert cfi.profile_background_custom_emoji_id == self.profile_background_custom_emoji_id + assert cfi.unrestrict_boost_count == self.unrestrict_boost_count + assert cfi.custom_emoji_sticker_set_name == self.custom_emoji_sticker_set_name + assert cfi.birthdate == self.birthdate + assert cfi.personal_chat == self.personal_chat + assert cfi.first_name == self.first_name + assert cfi.last_name == self.last_name assert cfi.max_reaction_count == self.max_reaction_count + def test_de_json_localization(self, bot, raw_bot, tz_bot): + json_dict = { + "id": self.id_, + "type": self.type_, + "accent_color_id": self.accent_color_id, + "max_reaction_count": self.max_reaction_count, + "emoji_status_expiration_date": to_timestamp(self.emoji_status_expiration_date), + } + cfi_bot = ChatFullInfo.de_json(json_dict, bot) + cfi_bot_raw = ChatFullInfo.de_json(json_dict, raw_bot) + cfi_bot_tz = ChatFullInfo.de_json(json_dict, tz_bot) + + # comparing utcoffsets because comparing tzinfo objects is not reliable + emoji_expire_offset = cfi_bot_tz.emoji_status_expiration_date.utcoffset() + emoji_expire_offset_tz = tz_bot.defaults.tzinfo.utcoffset( + cfi_bot_tz.emoji_status_expiration_date.replace(tzinfo=None) + ) + + assert cfi_bot.emoji_status_expiration_date.tzinfo == UTC + assert cfi_bot_raw.emoji_status_expiration_date.tzinfo == UTC + assert emoji_expire_offset_tz == emoji_expire_offset + def test_to_dict(self, chat_full_info): cfi = chat_full_info cfi_dict = cfi.to_dict() assert isinstance(cfi_dict, dict) - assert cfi_dict["max_reaction_count"] == cfi.max_reaction_count + assert cfi_dict["id"] == cfi.id + assert cfi_dict["title"] == cfi.title + assert cfi_dict["type"] == cfi.type + assert cfi_dict["username"] == cfi.username + assert cfi_dict["permissions"] == cfi.permissions.to_dict() + assert cfi_dict["slow_mode_delay"] == cfi.slow_mode_delay + assert cfi_dict["bio"] == cfi.bio + assert cfi_dict["business_intro"] == cfi.business_intro.to_dict() + assert cfi_dict["business_location"] == cfi.business_location.to_dict() + assert cfi_dict["business_opening_hours"] == cfi.business_opening_hours.to_dict() + assert cfi_dict["has_private_forwards"] == cfi.has_private_forwards + assert cfi_dict["has_protected_content"] == cfi.has_protected_content + assert cfi_dict["has_visible_history"] == cfi.has_visible_history + assert cfi_dict["linked_chat_id"] == cfi.linked_chat_id + assert cfi_dict["location"] == cfi.location.to_dict() + assert cfi_dict["join_to_send_messages"] == cfi.join_to_send_messages + assert cfi_dict["join_by_request"] == cfi.join_by_request + assert ( + cfi_dict["has_restricted_voice_and_video_messages"] + == cfi.has_restricted_voice_and_video_messages + ) + assert cfi_dict["is_forum"] == cfi.is_forum + assert cfi_dict["active_usernames"] == list(cfi.active_usernames) + assert cfi_dict["emoji_status_custom_emoji_id"] == cfi.emoji_status_custom_emoji_id + assert cfi_dict["emoji_status_expiration_date"] == to_timestamp( + cfi.emoji_status_expiration_date + ) + assert cfi_dict["has_aggressive_anti_spam_enabled"] == cfi.has_aggressive_anti_spam_enabled + assert cfi_dict["has_hidden_members"] == cfi.has_hidden_members + assert cfi_dict["available_reactions"] == [ + reaction.to_dict() for reaction in cfi.available_reactions + ] + assert cfi_dict["accent_color_id"] == cfi.accent_color_id + assert cfi_dict["background_custom_emoji_id"] == cfi.background_custom_emoji_id + assert cfi_dict["profile_accent_color_id"] == cfi.profile_accent_color_id + assert ( + cfi_dict["profile_background_custom_emoji_id"] + == cfi.profile_background_custom_emoji_id + ) + assert cfi_dict["custom_emoji_sticker_set_name"] == cfi.custom_emoji_sticker_set_name + assert cfi_dict["unrestrict_boost_count"] == cfi.unrestrict_boost_count + assert cfi_dict["birthdate"] == cfi.birthdate.to_dict() + assert cfi_dict["personal_chat"] == cfi.personal_chat.to_dict() + assert cfi_dict["first_name"] == cfi.first_name + assert cfi_dict["last_name"] == cfi.last_name - def test_attr_access_no_warning(self, chat_full_info): - cfi = chat_full_info - for depr_attr in _deprecated_attrs: - with warnings.catch_warnings(): # No warning should be raised - warnings.simplefilter("error") - getattr(cfi, depr_attr) + assert cfi_dict["max_reaction_count"] == cfi.max_reaction_count - def test_cfi_creation_no_warning(self, chat_full_info): - cfi = chat_full_info - with warnings.catch_warnings(): - dict = cfi.to_dict() - ChatFullInfo(**dict) + def test_always_tuples_attributes(self): + cfi = ChatFullInfo( + id=123, + type=Chat.PRIVATE, + accent_color_id=1, + max_reaction_count=2, + ) + assert isinstance(cfi.active_usernames, tuple) + assert cfi.active_usernames == () diff --git a/tests/test_official/exceptions.py b/tests/test_official/exceptions.py index ac043de997d..4b44d286b32 100644 --- a/tests/test_official/exceptions.py +++ b/tests/test_official/exceptions.py @@ -20,7 +20,6 @@ from telegram import Animation, Audio, Document, PhotoSize, Sticker, Video, VideoNote, Voice -from telegram._chat import _deprecated_attrs from tests.test_official.helpers import _get_params_base IGNORED_OBJECTS = ("ResponseParameters",) @@ -173,9 +172,7 @@ def ignored_param_requirements(object_name: str) -> set[str]: # Arguments that are optional arguments for now for backwards compatibility -BACKWARDS_COMPAT_KWARGS: dict[str, set[str]] = { - "Chat": set(_deprecated_attrs), # removed by bot api 7.3 -} +BACKWARDS_COMPAT_KWARGS: dict[str, set[str]] = {} def backwards_compat_kwargs(object_name: str) -> set[str]: From ffa02a0fa8689af72e9e3cb9662a85572e87df70 Mon Sep 17 00:00:00 2001 From: Harshil <37377066+harshil21@users.noreply.github.com> Date: Tue, 21 May 2024 13:47:27 -0400 Subject: [PATCH 2/5] Fix tests --- tests/test_telegramobject.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_telegramobject.py b/tests/test_telegramobject.py index c97db1adaea..39f3aaff4aa 100644 --- a/tests/test_telegramobject.py +++ b/tests/test_telegramobject.py @@ -342,10 +342,14 @@ async def test_pickle_backwards_compatibility(self): chat = (await pp.get_chat_data())[1] assert chat.id == 1 assert chat.type == Chat.PRIVATE - assert chat.api_kwargs == { + api_kwargs_expected = { "all_members_are_administrators": True, "something": "Manually inserted", } + # There are older attrs in Chat's api_kwargs which are present but we don't care about them + for k, v in api_kwargs_expected.items(): + assert chat.api_kwargs[k] == v + with pytest.raises(AttributeError): # removed attribute should not be available as attribute, only though api_kwargs chat.all_members_are_administrators From 85edccfabe560e1a89d370362c572adb1f5e7ac9 Mon Sep 17 00:00:00 2001 From: Harshil <37377066+harshil21@users.noreply.github.com> Date: Wed, 22 May 2024 08:48:13 -0400 Subject: [PATCH 3/5] Goodbye, all_members_are_administrators This field is no longer returned for Chat/ChatFullInfo --- examples/echobot.py | 71 -------------------------------------- telegram/_chatfullinfo.py | 11 +++--- tests/test_chatfullinfo.py | 6 +--- 3 files changed, 5 insertions(+), 83 deletions(-) delete mode 100644 examples/echobot.py diff --git a/examples/echobot.py b/examples/echobot.py deleted file mode 100644 index b2ccdc139f2..00000000000 --- a/examples/echobot.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python -# pylint: disable=unused-argument -# This program is dedicated to the public domain under the CC0 license. - -""" -Simple Bot to reply to Telegram messages. - -First, a few handler functions are defined. Then, those functions are passed to -the Application and registered at their respective places. -Then, the bot is started and runs until we press Ctrl-C on the command line. - -Usage: -Basic Echobot example, repeats messages. -Press Ctrl-C on the command line or send a signal to the process to stop the -bot. -""" - -import logging - -from telegram import ForceReply, Update -from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters - -# Enable logging -logging.basicConfig( - format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO -) -# set higher logging level for httpx to avoid all GET and POST requests being logged -logging.getLogger("httpx").setLevel(logging.WARNING) - -logger = logging.getLogger(__name__) - - -# Define a few command handlers. These usually take the two arguments update and -# context. -async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: - """Send a message when the command /start is issued.""" - user = update.effective_user - await update.message.reply_html( - rf"Hi {user.mention_html()}!", - reply_markup=ForceReply(selective=True), - ) - - -async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: - """Send a message when the command /help is issued.""" - await update.message.reply_text("Help!") - - -async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: - """Echo the user message.""" - await update.message.reply_text(update.message.text) - - -def main() -> None: - """Start the bot.""" - # Create the Application and pass it your bot's token. - application = Application.builder().token("TOKEN").build() - - # on different commands - answer in Telegram - application.add_handler(CommandHandler("start", start)) - application.add_handler(CommandHandler("help", help_command)) - - # on non command i.e message - echo the message on Telegram - application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo)) - - # Run the bot until the user presses Ctrl-C - application.run_polling(allowed_updates=Update.ALL_TYPES) - - -if __name__ == "__main__": - main() diff --git a/telegram/_chatfullinfo.py b/telegram/_chatfullinfo.py index 64385186e2a..cf4b4155d3b 100644 --- a/telegram/_chatfullinfo.py +++ b/telegram/_chatfullinfo.py @@ -44,6 +44,9 @@ class ChatFullInfo(_ChatBase): .. versionadded:: 21.2 + .. versionchanged:: NEXT.VERSION + You can now also use the shortcut methods of :class:`telegram.Chat` on this object. + Args: id (:obj:`int`): Unique identifier for this chat. type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`, @@ -526,10 +529,4 @@ def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatFullInfo data.get("business_opening_hours"), bot ) - api_kwargs = {} - # This is a deprecated field that TG still returns for backwards compatibility - # Let's filter it out to speed up the de-json process - if (amaa := "all_members_are_administrators") in data: - api_kwargs[amaa] = data.pop(amaa) - - return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) + return super().de_json(data=data, bot=bot) diff --git a/tests/test_chatfullinfo.py b/tests/test_chatfullinfo.py index a2903e01104..b547e4de913 100644 --- a/tests/test_chatfullinfo.py +++ b/tests/test_chatfullinfo.py @@ -86,13 +86,13 @@ def chat_full_info(bot): return chat +# Shortcut methods are tested in test_chat.py. class TestChatFullInfoBase: id_ = -28767330 max_reaction_count = 2 title = "ToledosPalaceBot - Group" type_ = "group" username = "username" - all_members_are_administrators = False sticker_set_name = "stickers" can_set_sticker_set = False permissions = ChatPermissions( @@ -154,7 +154,6 @@ def test_de_json(self, bot): "accent_color_id": self.accent_color_id, "max_reaction_count": self.max_reaction_count, "username": self.username, - "all_members_are_administrators": self.all_members_are_administrators, "sticker_set_name": self.sticker_set_name, "can_set_sticker_set": self.can_set_sticker_set, "permissions": self.permissions.to_dict(), @@ -215,9 +214,6 @@ def test_de_json(self, bot): cfi.has_restricted_voice_and_video_messages == self.has_restricted_voice_and_video_messages ) - assert cfi.api_kwargs == { - "all_members_are_administrators": self.all_members_are_administrators - } assert cfi.is_forum == self.is_forum assert cfi.active_usernames == tuple(self.active_usernames) assert cfi.emoji_status_custom_emoji_id == self.emoji_status_custom_emoji_id From 8c4923133c718e03bcfb056573bbcc901a14f3e1 Mon Sep 17 00:00:00 2001 From: Harshil <37377066+harshil21@users.noreply.github.com> Date: Wed, 22 May 2024 08:49:53 -0400 Subject: [PATCH 4/5] oops: bring back echobot.py --- examples/echobot.py | 71 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 examples/echobot.py diff --git a/examples/echobot.py b/examples/echobot.py new file mode 100644 index 00000000000..b2ccdc139f2 --- /dev/null +++ b/examples/echobot.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# pylint: disable=unused-argument +# This program is dedicated to the public domain under the CC0 license. + +""" +Simple Bot to reply to Telegram messages. + +First, a few handler functions are defined. Then, those functions are passed to +the Application and registered at their respective places. +Then, the bot is started and runs until we press Ctrl-C on the command line. + +Usage: +Basic Echobot example, repeats messages. +Press Ctrl-C on the command line or send a signal to the process to stop the +bot. +""" + +import logging + +from telegram import ForceReply, Update +from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters + +# Enable logging +logging.basicConfig( + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO +) +# set higher logging level for httpx to avoid all GET and POST requests being logged +logging.getLogger("httpx").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) + + +# Define a few command handlers. These usually take the two arguments update and +# context. +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: + """Send a message when the command /start is issued.""" + user = update.effective_user + await update.message.reply_html( + rf"Hi {user.mention_html()}!", + reply_markup=ForceReply(selective=True), + ) + + +async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: + """Send a message when the command /help is issued.""" + await update.message.reply_text("Help!") + + +async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: + """Echo the user message.""" + await update.message.reply_text(update.message.text) + + +def main() -> None: + """Start the bot.""" + # Create the Application and pass it your bot's token. + application = Application.builder().token("TOKEN").build() + + # on different commands - answer in Telegram + application.add_handler(CommandHandler("start", start)) + application.add_handler(CommandHandler("help", help_command)) + + # on non command i.e message - echo the message on Telegram + application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo)) + + # Run the bot until the user presses Ctrl-C + application.run_polling(allowed_updates=Update.ALL_TYPES) + + +if __name__ == "__main__": + main() From 875b8b92cd05ef96a347d3c5ddb98409038bc233 Mon Sep 17 00:00:00 2001 From: Harshil <37377066+harshil21@users.noreply.github.com> Date: Sat, 25 May 2024 20:14:35 -0400 Subject: [PATCH 5/5] Review: conf.py version revert and versionchanged doc change --- docs/source/conf.py | 2 +- telegram/_chatfullinfo.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 947479ba4d9..a50e3dbdb05 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,7 @@ release = "21.2" # telegram.__version__ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "7.3.7" +needs_sphinx = "6.1.3" # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom diff --git a/telegram/_chatfullinfo.py b/telegram/_chatfullinfo.py index cf4b4155d3b..221b8f623cc 100644 --- a/telegram/_chatfullinfo.py +++ b/telegram/_chatfullinfo.py @@ -45,7 +45,9 @@ class ChatFullInfo(_ChatBase): .. versionadded:: 21.2 .. versionchanged:: NEXT.VERSION - You can now also use the shortcut methods of :class:`telegram.Chat` on this object. + Explicit support for all shortcut methods known from :class:`telegram.Chat` on this + object. Previously those were only available because this class inherited from + :class:`telegram.Chat`. Args: id (:obj:`int`): Unique identifier for this chat. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy