diff --git a/README.md b/README.md index bbc6f1698..ff1b5159f 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 51eb63d4a..ae210f130 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6250,7 +6250,8 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) - def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. @@ -6262,6 +6263,9 @@ def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_p :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver + :type pay_for_upgrade: :obj:`bool` + :param text: Text that will be shown along with the gift; 0-255 characters :type text: :obj:`str` @@ -6274,7 +6278,71 @@ def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_p :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.send_gift(self.token, user_id, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities) + return apihelper.send_gift(self.token, user_id, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, + pay_for_upgrade=pay_for_upgrade) + + def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: + """ + Verifies a user on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifyuser + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.verify_user(self.token, user_id, custom_description=custom_description) + + def verify_chat(self, chat_id: Union[int, str], custom_description: Optional[str]=None) -> bool: + """ + Verifies a chat on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifychat + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.verify_chat(self.token, chat_id, custom_description=custom_description) + + def remove_user_verification(self, user_id: int) -> bool: + """ + Removes verification from a user who is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removeuserverification + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + + return apihelper.remove_user_verification(self.token, user_id) + + def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: + """ + Removes verification from a chat that is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removechatverification + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.remove_chat_verification(self.token, chat_id) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 3044b226d..887f163db 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1929,7 +1929,7 @@ def get_available_gifts(token): return _make_request(token, method_url) -def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None): +def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1938,6 +1938,36 @@ def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_ent payload['text_parse_mode'] = text_parse_mode if text_entities: payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + if pay_for_upgrade is not None: + payload['pay_for_upgrade'] = pay_for_upgrade + return _make_request(token, method_url, params=payload, method='post') + + +def verify_user(token, user_id, custom_description=None): + method_url = 'verifyUser' + payload = {'user_id': user_id} + if custom_description: + payload['custom_description'] = custom_description + return _make_request(token, method_url, params=payload, method='post') + + +def verify_chat(token, chat_id, custom_description=None): + method_url = 'verifyChat' + payload = {'chat_id': chat_id} + if custom_description: + payload['custom_description'] = custom_description + return _make_request(token, method_url, params=payload, method='post') + + +def remove_user_verification(token, user_id): + method_url = 'removeUserVerification' + payload = {'user_id': user_id} + return _make_request(token, method_url, params=payload, method='post') + + +def remove_chat_verification(token, chat_id): + method_url = 'removeChatVerification' + payload = {'chat_id': chat_id} return _make_request(token, method_url, params=payload, method='post') def set_sticker_emoji_list(token, sticker, emoji_list): @@ -2271,12 +2301,6 @@ def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media - if 'thumbnail' in media_dict: - thumbnail = media_dict['thumbnail'] - if isinstance(thumbnail, types.InputFile): - thumbnail_key = 'thumbnail_' + key - files[thumbnail_key] = thumbnail - media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 0e298ace7..288b5f26e 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7707,7 +7707,8 @@ async def delete_sticker_set(self, name:str) -> bool: return await asyncio_helper.delete_sticker_set(self.token, name) - async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. @@ -7719,6 +7720,9 @@ async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver + :type pay_for_upgrade: :obj:`bool` + :param text: Text that will be shown along with the gift; 0-255 characters :type text: :obj:`str` @@ -7731,7 +7735,71 @@ async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.send_gift(self.token, user_id, gift_id, text, text_parse_mode, text_entities) + return await asyncio_helper.send_gift(self.token, user_id, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade) + + async def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: + """ + Verifies a user on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifyuser + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.verify_user(self.token, user_id, custom_description) + + async def verify_chat(self, chat_id: Union[int, str], custom_description: Optional[str]=None) -> bool: + """ + Verifies a chat on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifychat + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + + return await asyncio_helper.verify_chat(self.token, chat_id, custom_description) + + async def remove_user_verification(self, user_id: int) -> bool: + """ + Removes verification from a user who is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removeuserverification + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + + """ + return await asyncio_helper.remove_user_verification(self.token, user_id) + + async def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: + """ + Removes verification from a chat that is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removechatverification + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.remove_chat_verification(self.token, chat_id) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index d11245d56..8c5b9ace6 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1916,7 +1916,7 @@ async def delete_sticker_set(token, name): payload = {'name': name} return await _process_request(token, method_url, params=payload, method='post') -async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None): +async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1925,6 +1925,32 @@ async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, te payload['text_parse_mode'] = text_parse_mode if text_entities: payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + if pay_for_upgrade is not None: + payload['pay_for_upgrade'] = pay_for_upgrade + return await _process_request(token, method_url, params=payload, method='post') + +async def verify_user(token, user_id, custom_description=None): + method_url = 'verifyUser' + payload = {'user_id': user_id} + if custom_description: + payload['custom_description'] = custom_description + return await _process_request(token, method_url, params=payload, method='post') + +async def verify_chat(token, chat_id, custom_description=None): + method_url = 'verifyChat' + payload = {'chat_id': chat_id} + if custom_description: + payload['custom_description'] = custom_description + return await _process_request(token, method_url, params=payload, method='post') + +async def remove_user_verification(token, user_id): + method_url = 'removeUserVerification' + payload = {'user_id': user_id} + return await _process_request(token, method_url, params=payload, method='post') + +async def remove_chat_verification(token, chat_id): + method_url = 'removeChatVerification' + payload = {'chat_id': chat_id} return await _process_request(token, method_url, params=payload, method='post') async def get_available_gifts(token): @@ -2243,12 +2269,6 @@ async def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media - if 'thumbnail' in media_dict: - thumbnail = media_dict['thumbnail'] - if isinstance(thumbnail, types.InputFile): - thumbnail_key = 'thumbnail_' + key - files[thumbnail_key] = thumbnail - media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files diff --git a/telebot/types.py b/telebot/types.py index e4dafaa7d..301ae61a1 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -4449,6 +4449,10 @@ def __init__(self, id: str, title: str, input_message_content: InputMessageConte self.thumbnail_width: Optional[int] = thumbnail_width self.thumbnail_height: Optional[int] = thumbnail_height + if hide_url: + log_deprecation_warning('The parameter "hide_url" is deprecated. Pass an empty string as url instead.') + self.url = '' + @property def thumb_url(self) -> str: @@ -11059,6 +11063,9 @@ class Gift(JsonDeserializable): :param star_count: The number of Telegram Stars that must be paid to send the sticker :type star_count: :obj:`int` + :param upgrade_star_count: Optional. The number of Telegram Stars that must be paid to upgrade the gift to a unique one + :type upgrade_star_count: :obj:`int` + :param total_count: Optional. The total number of the gifts of this type that can be sent; for limited gifts only :type total_count: :obj:`int` @@ -11069,12 +11076,13 @@ class Gift(JsonDeserializable): :rtype: :class:`Gift` """ - def __init__(self, id, sticker, star_count, total_count=None, remaining_count=None, **kwargs): + def __init__(self, id, sticker, star_count, total_count=None, remaining_count=None, upgrade_star_count=None, **kwargs): self.id: str = id self.sticker: Sticker = sticker self.star_count: int = star_count self.total_count: Optional[int] = total_count self.remaining_count: Optional[int] = remaining_count + self.upgrade_star_count: Optional[int] = upgrade_star_count @classmethod def de_json(cls, json_string): diff --git a/telebot/version.py b/telebot/version.py index 9317bd5d7..bde2003e4 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.25.0' +__version__ = '4.24.0'