diff --git a/README.md b/README.md index 8a6c7fd96..3d3c4ad82 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

diff --git a/telebot/__init__.py b/telebot/__init__.py index 3e1973eb5..9a8904a18 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1512,6 +1512,29 @@ def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, apihelper.get_user_profile_photos(self.token, user_id, offset=offset, limit=limit) ) + def get_user_profile_audios(self, user_id: int, offset: Optional[int]=None, + limit: Optional[int]=None) -> types.UserProfileAudios: + """ + Use this method to get a list of profile audios for a user. Returns a :class:`telebot.types.UserProfileAudios` object. + + Telegram documentation: https://core.telegram.org/bots/api#getuserprofileaudios + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param offset: Sequential number of the first audio to be returned. By default, all audios are returned. + :type offset: :obj:`int` + + :param limit: Limits the number of audios to be retrieved. Values between 1-100 are accepted. Defaults to 100. + :type limit: :obj:`int` + + :return: If the request is successful, a UserProfileAudios object is returned. + :rtype: :class:`telebot.types.UserProfileAudios` + """ + return types.UserProfileAudios.de_json( + apihelper.get_user_profile_audios(self.token, user_id, offset=offset, limit=limit) + ) + def set_user_emoji_status(self, user_id: int, emoji_status_custom_emoji_id: Optional[str]=None, emoji_status_expiration_date: Optional[int]=None) -> bool: """ Changes the emoji status for a given user that previously allowed the bot to manage their emoji status via the Mini App method requestEmojiStatusAccess. Returns True on success. @@ -5048,6 +5071,31 @@ def get_my_short_description(self, language_code: Optional[str]=None): return types.BotShortDescription.de_json( apihelper.get_my_short_description(self.token, language_code=language_code)) + def set_my_profile_photo(self, photo: types.InputProfilePhoto) -> bool: + """ + Use this method to change the profile photo of the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setmyprofilephoto + + :param photo: The new profile photo to set + :type photo: :class:`telebot.types.InputProfilePhoto` + + :return: True on success. + :rtype: :obj:`bool` + """ + return apihelper.set_my_profile_photo(self.token, photo) + + def remove_my_profile_photo(self) -> bool: + """ + Use this method to remove the profile photo of the bot. Requires no parameters. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removemyprofilephoto + + :return: True on success. + :rtype: :obj:`bool` + """ + return apihelper.remove_my_profile_photo(self.token) + def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ @@ -7758,7 +7806,7 @@ def delete_sticker_from_set(self, sticker: str) -> bool: :param sticker: File identifier of the sticker :return: On success, True is returned. - :rtype: :obj:`bool` + :rtype: :obj:`bool` """ return apihelper.delete_sticker_from_set(self.token, sticker) @@ -7767,8 +7815,8 @@ def create_forum_topic(self, chat_id: int, name: str, icon_color: Optional[int]=None, icon_custom_emoji_id: Optional[str]=None) -> types.ForumTopic: """ - Use this method to create a topic in a forum supergroup chat. The bot must be an administrator - in the chat for this to work and must have the can_manage_topics administrator rights. + Use this method to create a topic in a forum supergroup chat or a private chat with a user. In the case of a supergroup chat the bot + must be an administrator in the chat for this to work and must have the can_manage_topics administrator right. Returns information about the created topic as a ForumTopic object. Telegram documentation: https://core.telegram.org/bots/api#createforumtopic diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 649b85f77..ea189b26b 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -349,6 +349,16 @@ def get_user_profile_photos(token, user_id, offset=None, limit=None): return _make_request(token, method_url, params=payload) +def get_user_profile_audios(token, user_id, offset=None, limit=None): + method_url = r'getUserProfileAudios' + payload = {'user_id': user_id} + if offset: + payload['offset'] = offset + if limit: + payload['limit'] = limit + return _make_request(token, method_url, params=payload) + + def set_user_emoji_status(token, user_id, emoji_status_custom_emoji_id=None, emoji_status_expiration_date=None): method_url = r'setUserEmojiStatus' payload = {'user_id': user_id} @@ -1526,6 +1536,17 @@ def get_my_name(token, language_code=None): payload['language_code'] = language_code return _make_request(token, method_url, params=payload) +def set_my_profile_photo(token, photo): + method_url = r'setMyProfilePhoto' + payload = {} + photo_json, files = photo.convert_input_profile_photo() + payload['photo'] = photo_json + return _make_request(token, method_url, params=payload, files=files, method='post') + +def delete_my_profile_photo(token): + method_url = r'deleteMyProfilePhoto' + return _make_request(token, method_url, method='post') + def set_chat_menu_button(token, chat_id=None, menu_button=None): method_url = r'setChatMenuButton' payload = {} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index e1a2685c1..1bdece11b 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2989,6 +2989,26 @@ async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None result = await asyncio_helper.get_user_profile_photos(self.token, user_id, offset, limit) return types.UserProfilePhotos.de_json(result) + async def get_user_profile_audios(self, user_id: int, offset: Optional[int]=None, limit: Optional[int]=None) -> types.UserProfileAudios: + """ + Use this method to get a list of profile audios for a user. Returns a UserProfileAudios object. + + Telegram documentation: https://core.telegram.org/bots/api#getuserprofileaudios + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param offset: Sequential number of the first audio to be returned. By default, all audios are returned. + :type offset: :obj:`int` + + :param limit: Limits the number of audios to be retrieved. Values between 1-100 are accepted. Defaults to 100. + :type limit: :obj:`int` + + :return: If successful, returns a UserProfileAudios object. + :rtype: :class:`telebot.types.UserProfileAudios` + """ + return types.UserProfileAudios.de_json(await asyncio_helper.get_user_profile_audios(self.token, user_id, offset=offset, limit=limit)) + async def set_user_emoji_status(self, user_id: int, emoji_status_custom_emoji_id: Optional[str]=None, emoji_status_expiration_date: Optional[int]=None) -> bool: """ Use this method to change the emoji status for a given user that previously allowed the bot to manage their emoji status via the Mini App method requestEmojiStatusAccess. @@ -6533,6 +6553,31 @@ async def get_my_name(self, language_code: Optional[str]=None): result = await asyncio_helper.get_my_name(self.token, language_code) return types.BotName.de_json(result) + async def set_my_profile_photo(self, photo: types.InputProfilePhoto) -> bool: + """ + Use this method to change the profile photo of the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setmyprofilephoto + + :param photo: InputProfilePhoto: The new profile photo to set + :type photo: :class:`telebot.types.InputProfilePhoto` + + :return: True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.set_my_profile_photo(self.token, photo) + + async def remove_my_profile_photo(self) -> bool: + """ + Use this method to remove the profile photo of the bot. Requires no parameters. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removemyprofilephoto + + :return: True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.remove_my_profile_photo(self.token) + async def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ @@ -9193,8 +9238,8 @@ async def create_forum_topic(self, chat_id: int, name: str, icon_color: Optional[int]=None, icon_custom_emoji_id: Optional[str]=None) -> types.ForumTopic: """ - Use this method to create a topic in a forum supergroup chat. The bot must be an administrator - in the chat for this to work and must have the can_manage_topics administrator rights. + Use this method to create a topic in a forum supergroup chat or a private chat with a user. In the case of a supergroup chat the bot + must be an administrator in the chat for this to work and must have the can_manage_topics administrator right. Returns information about the created topic as a ForumTopic object. Telegram documentation: https://core.telegram.org/bots/api#createforumtopic diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index e5e815c09..20e9127d2 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -330,6 +330,16 @@ async def get_user_profile_photos(token, user_id, offset=None, limit=None): return await _process_request(token, method_url, params=payload) +async def get_user_profile_audios(token, user_id, offset=None, limit=None): + method_url = r'getUserProfileAudios' + payload = {'user_id': user_id} + if offset: + payload['offset'] = offset + if limit: + payload['limit'] = limit + return await _process_request(token, method_url, params=payload) + + async def set_user_emoji_status(token, user_id, emoji_status_custom_emoji_id=None, emoji_status_expiration_date=None): method_url = r'setUserEmojiStatus' payload = {'user_id': user_id} @@ -1517,6 +1527,18 @@ async def get_my_name(token, language_code=None): payload['language_code'] = language_code return await _process_request(token, method_url, params=payload) +async def set_my_profile_photo(token, photo): + method_url = r'setMyProfilePhoto' + payload = {} + photo_json, files = photo.convert_input_profile_photo() + payload['photo'] = photo_json + + return await _process_request(token, method_url, params=payload, files=files, method='post') + +async def remove_my_profile_photo(token): + method_url = r'removeMyProfilePhoto' + return await _process_request(token, method_url, method='post') + async def set_chat_menu_button(token, chat_id=None, menu_button=None): method_url = r'setChatMenuButton' payload = {} diff --git a/telebot/types.py b/telebot/types.py index 73dba2015..13811ffe7 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -515,6 +515,9 @@ class User(JsonDeserializable, Dictionaryable, JsonSerializable): :param has_topics_enabled: Optional. True, if the bot has forum topic mode enabled in private chats. Returned only in getMe. :type has_topics_enabled: :obj:`bool` + :param allows_users_to_create_topics: Optional. True, if the bot allows users to create and delete topics in private chats. Returned only in getMe. + :type allows_users_to_create_topics: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.User` """ @@ -528,7 +531,7 @@ def de_json(cls, json_string): def __init__(self, id, is_bot, first_name, last_name=None, username=None, language_code=None, can_join_groups=None, can_read_all_group_messages=None, supports_inline_queries=None, is_premium=None, added_to_attachment_menu=None, can_connect_to_business=None, - has_main_web_app=None, has_topics_enabled=None, **kwargs): + has_main_web_app=None, has_topics_enabled=None, allows_users_to_create_topics=None, **kwargs): self.id: int = id self.is_bot: bool = is_bot self.first_name: str = first_name @@ -543,6 +546,7 @@ def __init__(self, id, is_bot, first_name, last_name=None, username=None, langua self.can_connect_to_business: Optional[bool] = can_connect_to_business self.has_main_web_app: Optional[bool] = has_main_web_app self.has_topics_enabled: Optional[bool] = has_topics_enabled + self.allows_users_to_create_topics: Optional[bool] = allows_users_to_create_topics @property def full_name(self) -> str: @@ -570,7 +574,10 @@ def to_dict(self): 'is_premium': self.is_premium, 'added_to_attachment_menu': self.added_to_attachment_menu, 'can_connect_to_business': self.can_connect_to_business, - 'has_main_web_app': self.has_main_web_app} + 'has_main_web_app': self.has_main_web_app, + 'has_topics_enabled': self.has_topics_enabled, + 'allows_users_to_create_topics': self.allows_users_to_create_topics + } # noinspection PyShadowingBuiltins @@ -753,6 +760,9 @@ class ChatFullInfo(JsonDeserializable): :param paid_message_star_count: Optional. The number of Telegram Stars a general user have to pay to send a message to the chat :type paid_message_star_count: :obj:`int` + + :param first_profile_audio: Optional. For private chats, the first audio added to the profile of the user + :type first_profile_audio: :class:`telebot.types.Audio` :param unique_gift_colors: Optional. The color scheme based on a unique gift that must be used for the chat's name, message replies and link previews :type unique_gift_colors: :class:`telebot.types.UniqueGiftColors` @@ -792,6 +802,8 @@ def de_json(cls, json_string): obj['rating'] = UserRating.de_json(obj['rating']) if 'unique_gift_colors' in obj: obj['unique_gift_colors'] = UniqueGiftColors.de_json(obj['unique_gift_colors']) + if 'first_profile_audio' in obj: + obj['first_profile_audio'] = Audio.de_json(obj['first_profile_audio']) return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, @@ -809,7 +821,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, business_opening_hours=None, personal_chat=None, birthdate=None, can_send_paid_media=None, accepted_gift_types=None, is_direct_messages=None, parent_chat=None, rating=None, paid_message_star_count=None, - unique_gift_colors=None, **kwargs): + unique_gift_colors=None, first_profile_audio=None, **kwargs): self.id: int = id self.type: str = type self.title: Optional[str] = title @@ -860,6 +872,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.rating: Optional[UserRating] = rating self.paid_message_star_count: Optional[int] = paid_message_star_count self.unique_gift_colors: Optional[UniqueGiftColors] = unique_gift_colors + self.first_profile_audio: Optional[Audio] = first_profile_audio @property @@ -1126,6 +1139,12 @@ class Message(JsonDeserializable): the bot itself) :type left_chat_member: :class:`telebot.types.User` + :param chat_owner_left: Optional. Service message: chat owner has left + :type chat_owner_left: :class:`telebot.types.ChatOwnerLeft` + + :param chat_owner_changed: Optional. Service message: chat owner has changed + :type chat_owner_changed: :class:`telebot.types.ChatOwnerChanged` + :param new_chat_title: Optional. A chat title was changed to this value :type new_chat_title: :obj:`str` @@ -1577,6 +1596,12 @@ def de_json(cls, json_string): if 'suggested_post_refunded' in obj: opts['suggested_post_refunded'] = SuggestedPostRefunded.de_json(obj['suggested_post_refunded']) content_type = 'suggested_post_refunded' + if 'chat_owner_changed' in obj: + opts['chat_owner_changed'] = ChatOwnerChanged.de_json(obj['chat_owner_changed']) + content_type = 'chat_owner_changed' + if 'chat_owner_left' in obj: + opts['chat_owner_left'] = ChatOwnerLeft.de_json(obj['chat_owner_left']) + content_type = 'chat_owner_left' return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1713,6 +1738,8 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.suggested_post_declined: Optional[SuggestedPostDeclined] = None self.suggested_post_paid: Optional[SuggestedPostPaid] = None self.suggested_post_refunded: Optional[SuggestedPostRefunded] = None + self.chat_owner_left: Optional[ChatOwnerLeft] = None + self.chat_owner_changed: Optional[ChatOwnerChanged] = None for key in options: setattr(self, key, options[key]) @@ -2164,6 +2191,9 @@ class Video(JsonDeserializable): :param start_timestamp: Optional. Timestamp in seconds from which the video will play in the message :type start_timestamp: :obj:`int` + :param qualities: Optional. List of available qualities of the video + :type qualities: List[:class:`telebot.types.VideoQuality`] + :param file_name: Optional. Original filename as defined by sender :type file_name: :obj:`str` @@ -2186,10 +2216,12 @@ def de_json(cls, json_string): obj['thumbnail'] = PhotoSize.de_json(obj['thumbnail']) if 'cover' in obj: obj['cover'] = [PhotoSize.de_json(c) for c in obj['cover']] + if 'qualities' in obj: + obj['qualities'] = [VideoQuality.de_json(q) for q in obj['qualities']] return cls(**obj) def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=None, file_name=None, mime_type=None, file_size=None, - cover=None, start_timestamp=None, **kwargs): + cover=None, start_timestamp=None, qualities=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.width: int = width @@ -2201,6 +2233,7 @@ def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=N self.file_size: Optional[int] = file_size self.cover: Optional[List[PhotoSize]] = cover self.start_timestamp: Optional[int] = start_timestamp + self.qualities: Optional[List[VideoQuality]] = qualities @property def thumb(self) -> Optional[PhotoSize]: @@ -2898,10 +2931,18 @@ class KeyboardButton(Dictionaryable, JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#keyboardbutton - :param text: Text of the button. If none of the optional fields are used, it will be sent as a message when the button is - pressed + :param text: Text of the button. If none of the fields other than text, icon_custom_emoji_id, and style are used, + it will be sent as a message when the button is pressed :type text: :obj:`str` + :param icon_custom_emoji_id: Optional. Unique identifier of the custom emoji shown before the text of the button. + Can only be used by bots that purchased additional usernames on Fragment or in the messages directly sent by the bot to private, group and supergroup chats + if the owner of the bot has a Telegram Premium subscription. + :type icon_custom_emoji_id: :obj:`str` + + :param style: Optional. Style of the button. Must be one of “danger” (red), “success” (green) or “primary” (blue). If omitted, then an app-specific style is used. + :type style: :obj:`str` + :param request_contact: Optional. If True, the user's phone number will be sent as a contact when the button is pressed. Available in private chats only. :type request_contact: :obj:`bool` @@ -2935,7 +2976,8 @@ class KeyboardButton(Dictionaryable, JsonSerializable): def __init__(self, text: str, request_contact: Optional[bool]=None, request_location: Optional[bool]=None, request_poll: Optional[KeyboardButtonPollType]=None, web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUser]=None, - request_chat: Optional[KeyboardButtonRequestChat]=None, request_users: Optional[KeyboardButtonRequestUsers]=None): + request_chat: Optional[KeyboardButtonRequestChat]=None, request_users: Optional[KeyboardButtonRequestUsers]=None, + icon_custom_emoji_id: Optional[str]=None, style: Optional[str]=None, **kwargs): self.text: str = text self.request_contact: Optional[bool] = request_contact self.request_location: Optional[bool] = request_location @@ -2943,6 +2985,8 @@ def __init__(self, text: str, request_contact: Optional[bool]=None, self.web_app: Optional[WebAppInfo] = web_app self.request_chat: Optional[KeyboardButtonRequestChat] = request_chat self.request_users: Optional[KeyboardButtonRequestUsers] = request_users + self.icon_custom_emoji_id: Optional[str] = icon_custom_emoji_id + self.style: Optional[str] = style if request_user is not None: log_deprecation_warning('The parameter "request_user" is deprecated, use "request_users" instead') if self.request_users is None: @@ -2967,6 +3011,10 @@ def to_dict(self): json_dict['request_users'] = self.request_users.to_dict() if self.request_chat is not None: json_dict['request_chat'] = self.request_chat.to_dict() + if self.icon_custom_emoji_id is not None: + json_dict['icon_custom_emoji_id'] = self.icon_custom_emoji_id + if self.style is not None: + json_dict['style'] = self.style return json_dict @@ -3090,6 +3138,15 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable) :param text: Label text on the button :type text: :obj:`str` + :param icon_custom_emoji_id: Optional. Unique identifier of the custom emoji shown before the text of the button. + Can only be used by bots that purchased additional usernames on Fragment or in the messages directly sent by the bot to private, + group and supergroup chats if the owner of the bot has a Telegram Premium subscription. + :type icon_custom_emoji_id: :obj:`str` + + :param style: Optional. Style of the button. Must be one of “danger” (red), “success” (green) or “primary” (blue). If omitted, + then an app-specific style is used. + :type style: :obj:`str` + :param url: Optional. HTTP or tg:// URL to be opened when the button is pressed. Links tg://user?id= can be used to mention a user by their ID without using a username, if this is allowed by their privacy settings. :type url: :obj:`str` @@ -3155,7 +3212,7 @@ def de_json(cls, json_string): def __init__(self, text: str, url: Optional[str]=None, callback_data: Optional[str]=None, web_app: Optional[WebAppInfo]=None, switch_inline_query: Optional[str]=None, switch_inline_query_current_chat: Optional[str]=None, switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat]=None, callback_game=None, pay: Optional[bool]=None, - login_url: Optional[LoginUrl]=None, copy_text: Optional[CopyTextButton]=None, **kwargs): + login_url: Optional[LoginUrl]=None, copy_text: Optional[CopyTextButton]=None, icon_custom_emoji_id: Optional[str]=None, style: Optional[str]=None, **kwargs): self.text: str = text self.url: Optional[str] = url self.callback_data: Optional[str] = callback_data @@ -3167,6 +3224,8 @@ def __init__(self, text: str, url: Optional[str]=None, callback_data: Optional[s self.pay: Optional[bool] = pay self.login_url: Optional[LoginUrl] = login_url self.copy_text: Optional[CopyTextButton] = copy_text + self.icon_custom_emoji_id: Optional[str] = icon_custom_emoji_id + self.style: Optional[str] = style def to_json(self): return json.dumps(self.to_dict()) @@ -3193,6 +3252,10 @@ def to_dict(self): json_dict['switch_inline_query_chosen_chat'] = self.switch_inline_query_chosen_chat.to_dict() if self.copy_text is not None: json_dict['copy_text'] = self.copy_text.to_dict() + if self.icon_custom_emoji_id is not None: + json_dict['icon_custom_emoji_id'] = self.icon_custom_emoji_id + if self.style is not None: + json_dict['style'] = self.style return json_dict @@ -11969,6 +12032,9 @@ class UniqueGift(JsonDeserializable): :param is_premium: Optional. True, if the gift can only be purchased by Telegram Premium subscribers :type is_premium: :obj:`bool` + :param is_burned: Optional. True, if the gift was used to craft another gift and isn't available anymore + :type is_burned: :obj:`bool` + :param colors: Optional. The color scheme that can be used by the gift's owner for the chat's name, replies to messages and link previews; for business account gifts and gifts that are currently on sale only :type colors: :class:`UniqueGiftColors` :param publisher_chat: Optional. Information about the chat that published the gift @@ -11977,7 +12043,8 @@ class UniqueGift(JsonDeserializable): :return: Instance of the class :rtype: :class:`UniqueGift` """ - def __init__(self, base_name, name, number, model, symbol, backdrop, gift_id, publisher_chat=None, is_from_blockchain=None, is_premium=None, colors=None, **kwargs): + def __init__(self, base_name, name, number, model, symbol, backdrop, gift_id, publisher_chat=None, is_from_blockchain=None, is_premium=None, colors=None, + is_burned=None, **kwargs): self.base_name: str = base_name self.name: str = name self.number: int = number @@ -11989,6 +12056,7 @@ def __init__(self, base_name, name, number, model, symbol, backdrop, gift_id, pu self.is_premium: Optional[bool] = is_premium self.colors: Optional[UniqueGiftColors] = colors self.publisher_chat: Optional[Chat] = publisher_chat + self.is_burned: Optional[bool] = is_burned @classmethod def de_json(cls, json_string): @@ -12019,14 +12087,18 @@ class UniqueGiftModel(JsonDeserializable): :param rarity_per_mille: The number of unique gifts that receive this model for every 1000 gifts upgraded :type rarity_per_mille: :obj:`int` + :param rarity: Optional. Rarity of the model if it is a crafted model. Currently, can be “uncommon”, “rare”, “epic”, or “legendary”. + :type rarity: :obj:`str` + :return: Instance of the class :rtype: :class:`UniqueGiftModel` """ - def __init__(self, name, sticker, rarity_per_mille, **kwargs): + def __init__(self, name, sticker, rarity_per_mille, rarity=None, **kwargs): self.name: str = name self.sticker: Sticker = sticker self.rarity_per_mille: int = rarity_per_mille + self.rarity: Optional[str] = rarity @classmethod def de_json(cls, json_string): @@ -13468,4 +13540,118 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - \ No newline at end of file + +class ChatOwnerLeft(JsonDeserializable): + """ + Describes a service message about the chat owner leaving the chat. + + Telegram documentation: https://core.telegram.org/bots/api#chatownerleft + + :param new_owner: Optional. The user which will be the new owner of the chat if the previous owner does not return to the chat + :type new_owner: :class:`User` + + :return: Instance of the class + :rtype: :class:`ChatOwnerLeft` + """ + def __init__(self, new_owner: Optional[User] = None, **kwargs): + self.new_owner: Optional[User] = new_owner + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'new_owner' in obj: + obj['new_owner'] = User.de_json(obj['new_owner']) + return cls(**obj) + +class ChatOwnerChanged(JsonDeserializable): + """ + Describes a service message about an ownership change in the chat. + + Telegram documentation: https://core.telegram.org/bots/api#chatownerchanged + + :param new_owner: The new owner of the chat + :type new_owner: :class:`User` + + :return: Instance of the class + :rtype: :class:`ChatOwnerChanged` + """ + def __init__(self, new_owner: User, **kwargs): + self.new_owner: User = new_owner + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['new_owner'] = User.de_json(obj['new_owner']) + return cls(**obj) + +class VideoQuality(JsonDeserializable): + """ + This object represents a video file of a specific quality. + + Telegram documentation: https://core.telegram.org/bots/api#videoquality + + :param file_id: Identifier for this file, which can be used to download or reuse the file + :type file_id: :obj:`str` + + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. + :type file_unique_id: :obj:`str` + + :param width: Video width + :type width: :obj:`int` + + :param height: Video height + :type height: :obj:`int` + + :param codec: Codec that was used to encode the video, for example, “h264”, “h265”, or “av01” + :type codec: :obj:`str` + + :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have difficulty/silent defects in interpreting it. + But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this value. + :type file_size: :obj:`int` + + :return: Instance of the class + :rtype: :class:`VideoQuality` + """ + def __init__(self, file_id: str, file_unique_id: str, width: int, height: int, codec: str, file_size: Optional[int] = None, **kwargs): + self.file_id: str = file_id + self.file_unique_id: str = file_unique_id + self.width: int = width + self.height: int = height + self.codec: str = codec + self.file_size: Optional[int] = file_size + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + +class UserProfileAudios(JsonDeserializable): + """ + This object represents the audios displayed on a user's profile. + + Telegram documentation: https://core.telegram.org/bots/api#userprofileaudios + + :param total_count: Total number of profile audios for the target user + :type total_count: :obj:`int` + + :param audios: Requested profile audios + :type audios: :obj:`list` of :class:`Audio` + + :return: Instance of the class + :rtype: :class:`UserProfileAudios` + """ + def __init__(self, total_count: int, audios: List[Audio], **kwargs): + self.total_count: int = total_count + self.audios: List[Audio] = audios + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['audios'] = [Audio.de_json(audio) for audio in obj['audios']] + return cls(**obj) + diff --git a/telebot/util.py b/telebot/util.py index 9d16a0dca..71117c679 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -43,7 +43,7 @@ 'giveaway_created', 'giveaway_winners', 'giveaway_completed', 'boost_added', 'paid_message_price_changed', 'checklist_tasks_done', 'checklist_tasks_added', 'direct_message_price_changed', 'suggested_post_refunded', 'suggested_post_info', 'suggested_post_approved', 'suggested_post_approval_failed', 'suggested_post_declined', - 'suggested_post_paid', 'gift_upgrade_sent' + 'suggested_post_paid', 'gift_upgrade_sent', 'chat_owner_left', 'chat_owner_changed' ] #: All update types, should be used for allowed_updates parameter in polling.