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:
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.