From 89572c378ccd656604c9bc0c548d28f809fbda2f Mon Sep 17 00:00:00 2001 From: Poolitzer Date: Tue, 31 Dec 2024 14:59:46 +0100 Subject: [PATCH 1/9] Implementation without tests --- telegram/_bot.py | 170 +++++++++++++++++++ telegram/_gifts.py | 19 ++- telegram/_inline/inlinequeryresultarticle.py | 19 +++ telegram/constants.py | 17 ++ telegram/ext/_extbot.py | 90 ++++++++++ 5 files changed, 314 insertions(+), 1 deletion(-) diff --git a/telegram/_bot.py b/telegram/_bot.py index feea41b922b..e53dc9f8880 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -9721,6 +9721,7 @@ async def send_gift( text: Optional[str] = None, text_parse_mode: ODVInput[str] = DEFAULT_NONE, text_entities: Optional[Sequence["MessageEntity"]] = None, + pay_for_upgrade: Optional[bool] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, write_timeout: ODVInput[float] = DEFAULT_NONE, @@ -9752,6 +9753,10 @@ async def send_gift( :attr:`~MessageEntity.ITALIC`, :attr:`~MessageEntity.UNDERLINE`, :attr:`~MessageEntity.STRIKETHROUGH`, :attr:`~MessageEntity.SPOILER`, and :attr:`~MessageEntity.CUSTOM_EMOJI` are ignored. + pay_for_upgrade (:obj:`bool`, optional): Pass :obj:`True` to pay for the gift upgrade + from the bot's balance, thereby making the upgrade free for the receiver. + + .. versionadded:: NEXT.VERSION Returns: :obj:`bool`: On success, :obj:`True` is returned. @@ -9765,6 +9770,7 @@ async def send_gift( "text": text, "text_parse_mode": text_parse_mode, "text_entities": text_entities, + "pay_for_upgrade": pay_for_upgrade, } return await self._post( "sendGift", @@ -9776,6 +9782,162 @@ async def send_gift( api_kwargs=api_kwargs, ) + async def verify_chat( + self, + chat_id: Union[int, str], + custom_description: Optional[str] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Verifies a chat on behalf of the organization which is represented by the bot. + + .. versionadded:: NEXT.VERSION + + Args: + chat_id (:obj:`int` | :obj:`str`): |chat_id_channel| + custom_description (:obj:`str`, optional): Custom description for the verification; + 0- :tg-const:`telegram.constants.VerifyLimit.MAX_TEXT_LENGTH` characters. Must be + empty if the organization isn't allowed to provide a custom verification + description. + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + + Raises: + :class:`telegram.error.TelegramError` + """ + data: JSONDict = { + "chat_id": chat_id, + "custom_description": custom_description, + } + return await self._post( + "verifyChat", + data, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + + async def verify_user( + self, + user_id: int, + custom_description: Optional[str] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Verifies a user on behalf of the organization which is represented by the bot. + + .. versionadded:: NEXT.VERSION + + Args: + user_id (:obj:`int`): Unique identifier of the target user. + custom_description (:obj:`str`, optional): Custom description for the verification; + 0- :tg-const:`telegram.constants.VerifyLimit.MAX_TEXT_LENGTH` characters. Must be + empty if the organization isn't allowed to provide a custom verification + description. + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + + Raises: + :class:`telegram.error.TelegramError` + """ + data: JSONDict = { + "user_id": user_id, + "custom_description": custom_description, + } + return await self._post( + "verifyUser", + data, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + + async def remove_chat_verification( + self, + chat_id: Union[int, str], + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Verifies a user on behalf of the organization which is represented by the bot. + + .. versionadded:: NEXT.VERSION + + Args: + chat_id (:obj:`int` | :obj:`str`): |chat_id_channel| + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + + Raises: + :class:`telegram.error.TelegramError` + """ + data: JSONDict = { + "chat_id": chat_id, + } + return await self._post( + "removeChatVerification", + data, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + + async def remove_user_verification( + self, + user_id: int, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Verifies a user on behalf of the organization which is represented by the bot. + + .. versionadded:: NEXT.VERSION + + Args: + user_id (:obj:`int`): Unique identifier of the target user. + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + + Raises: + :class:`telegram.error.TelegramError` + """ + data: JSONDict = { + "user_id": user_id, + } + return await self._post( + "removeUserVerification", + data, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002 """See :meth:`telegram.TelegramObject.to_dict`.""" data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name} @@ -10046,3 +10208,11 @@ def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002 """Alias for :meth:`get_available_gifts`""" sendGift = send_gift """Alias for :meth:`send_gift`""" + verifyChat = verify_chat + """Alias for :meth:`verify_chat`""" + verifyUser = verify_user + """Alias for :meth:`verify_user`""" + removeChatVerification = remove_chat_verification + """Alias for :meth:`remove_chat_verification`""" + removeUserVerification = remove_user_verification + """Alias for :meth:`remove_user_verification`""" diff --git a/telegram/_gifts.py b/telegram/_gifts.py index 4aa5f5f604c..47c8f53a666 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -46,6 +46,10 @@ class Gift(TelegramObject): sent; for limited gifts only remaining_count (:obj:`int`, optional): The number of remaining gifts of this type that can be sent; for limited gifts only + upgrade_star_count (:obj:`int`, optional): The number of Telegram Stars that must be paid + to upgrade the gift to a unique one + + .. versionadded:: NEXT.VERSION Attributes: id (:obj:`str`): Unique identifier of the gift @@ -55,10 +59,21 @@ class Gift(TelegramObject): sent; for limited gifts only remaining_count (:obj:`int`): Optional. The number of remaining gifts of this type that can be sent; for limited gifts only + upgrade_star_count (:obj:`int`): Optional. The number of Telegram Stars that must be paid + to upgrade the gift to a unique one + + .. versionadded:: NEXT.VERSION """ - __slots__ = ("id", "remaining_count", "star_count", "sticker", "total_count") + __slots__ = ( + "id", + "remaining_count", + "star_count", + "sticker", + "total_count", + "upgrade_star_count", + ) def __init__( self, @@ -67,6 +82,7 @@ def __init__( star_count: int, total_count: Optional[int] = None, remaining_count: Optional[int] = None, + upgrade_star_count: Optional[int] = None, *, api_kwargs: Optional[JSONDict] = None, ): @@ -76,6 +92,7 @@ def __init__( 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 self._id_attrs = (self.id,) diff --git a/telegram/_inline/inlinequeryresultarticle.py b/telegram/_inline/inlinequeryresultarticle.py index 92c358e77ef..652f917512e 100644 --- a/telegram/_inline/inlinequeryresultarticle.py +++ b/telegram/_inline/inlinequeryresultarticle.py @@ -23,7 +23,9 @@ from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup from telegram._inline.inlinequeryresult import InlineQueryResult from telegram._utils.types import JSONDict +from telegram._utils.warnings import warn from telegram.constants import InlineQueryResultType +from telegram.warnings import PTBDeprecationWarning if TYPE_CHECKING: from telegram import InputMessageContent @@ -50,6 +52,10 @@ class InlineQueryResultArticle(InlineQueryResult): url (:obj:`str`, optional): URL of the result. hide_url (:obj:`bool`, optional): Pass :obj:`True`, if you don't want the URL to be shown in the message. + + .. deprecated:: NEXT.VERSION + This attribute will be removed in future major PTB/Bot API versions. Pass an + empty string as URL instead. description (:obj:`str`, optional): Short description of the result. thumbnail_url (:obj:`str`, optional): Url of the thumbnail for the result. @@ -74,6 +80,10 @@ class InlineQueryResultArticle(InlineQueryResult): url (:obj:`str`): Optional. URL of the result. hide_url (:obj:`bool`): Optional. Pass :obj:`True`, if you don't want the URL to be shown in the message. + + .. deprecated:: NEXT.VERSION + This attribute will be removed in future major PTB/Bot API versions. Pass an + empty string as URL instead. description (:obj:`str`): Optional. Short description of the result. thumbnail_url (:obj:`str`): Optional. Url of the thumbnail for the result. @@ -123,6 +133,15 @@ def __init__( # Optional self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup self.url: Optional[str] = url + if hide_url is not None: + warn( + PTBDeprecationWarning( + "NEXT.VERSION", + "The argument `hide_url` will be removed in future major PTB/Bot API" + "versions. Pass an empty string as URL instead.", + ), + stacklevel=2, + ) self.hide_url: Optional[bool] = hide_url self.description: Optional[str] = description self.thumbnail_url: Optional[str] = thumbnail_url diff --git a/telegram/constants.py b/telegram/constants.py index 6453cf55d4e..099a239510b 100644 --- a/telegram/constants.py +++ b/telegram/constants.py @@ -3229,3 +3229,20 @@ class ReactionEmoji(StringEnum): """:obj:`str`: Woman Shrugging""" POUTING_FACE = "😡" """:obj:`str`: Pouting face""" + + +class VerifyLimit(IntEnum): + """This enum contains limitations for :meth:`~telegram.Bot.verify_chat` and + :meth:`~telegram.Bot.verify_user`. + The enum members of this enumeration are instances of :class:`int` and can be treated as such. + + .. versionadded:: NEXT.VERSION + """ + + __slots__ = () + + MAX_TEXT_LENGTH = 70 + """:obj:`int`: Maximum number of characters in a :obj:`str` passed as the + :paramref:`~telegram.Bot.verify_chat.custom_description` or + :paramref:`~telegram.Bot.verify_user.custom_description` parameter. + """ diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py index 910cff98157..04e1617a0f0 100644 --- a/telegram/ext/_extbot.py +++ b/telegram/ext/_extbot.py @@ -4465,6 +4465,7 @@ async def send_gift( text: Optional[str] = None, text_parse_mode: ODVInput[str] = DEFAULT_NONE, text_entities: Optional[Sequence["MessageEntity"]] = None, + pay_for_upgrade: Optional[bool] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, write_timeout: ODVInput[float] = DEFAULT_NONE, @@ -4479,6 +4480,91 @@ async def send_gift( text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, + pay_for_upgrade=pay_for_upgrade, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), + ) + + async def verify_chat( + self, + chat_id: Union[int, str], + custom_description: Optional[str] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + rate_limit_args: Optional[RLARGS] = None, + ) -> bool: + return await super().verify_chat( + chat_id=chat_id, + custom_description=custom_description, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), + ) + + async def verify_user( + self, + user_id: int, + custom_description: Optional[str] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + rate_limit_args: Optional[RLARGS] = None, + ) -> bool: + return await super().verify_user( + user_id=user_id, + custom_description=custom_description, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), + ) + + async def remove_chat_verification( + self, + chat_id: Union[int, str], + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + rate_limit_args: Optional[RLARGS] = None, + ) -> bool: + return await super().remove_chat_verification( + chat_id=chat_id, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), + ) + + async def remove_user_verification( + self, + user_id: int, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + rate_limit_args: Optional[RLARGS] = None, + ) -> bool: + return await super().remove_user_verification( + user_id=user_id, read_timeout=read_timeout, write_timeout=write_timeout, connect_timeout=connect_timeout, @@ -4617,3 +4703,7 @@ async def send_gift( sendPaidMedia = send_paid_media getAvailableGifts = get_available_gifts sendGift = send_gift + verifyChat = verify_chat + verifyUser = verify_user + removeChatVerification = remove_chat_verification + removeUserVerification = remove_user_verification From 8262da2b12790faa6664882f6caba0f48d6e8a76 Mon Sep 17 00:00:00 2001 From: Poolitzer Date: Tue, 31 Dec 2024 15:54:15 +0100 Subject: [PATCH 2/9] Add tests + fix stuff --- telegram/_chat.py | 64 +++++++++++++++++++ telegram/_user.py | 64 +++++++++++++++++++ telegram/constants.py | 1 + .../_inline/test_inlinequeryresultarticle.py | 29 +++++++++ tests/test_chat.py | 31 +++++++++ tests/test_gifts.py | 37 +++++++++-- tests/test_user.py | 31 +++++++++ 7 files changed, 253 insertions(+), 4 deletions(-) diff --git a/telegram/_chat.py b/telegram/_chat.py index 1ae884bb6b9..edbe8aab951 100644 --- a/telegram/_chat.py +++ b/telegram/_chat.py @@ -3443,6 +3443,7 @@ async def send_gift( text: Optional[str] = None, text_parse_mode: ODVInput[str] = DEFAULT_NONE, text_entities: Optional[Sequence["MessageEntity"]] = None, + pay_for_upgrade: Optional[bool] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, write_timeout: ODVInput[float] = DEFAULT_NONE, @@ -3470,6 +3471,69 @@ async def send_gift( text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, + pay_for_upgrade=pay_for_upgrade, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + + async def verify_chat( + self, + custom_description: Optional[str] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Shortcut for:: + + await bot.verify_chat(chat_id=update.effective_chat.id, *args, **kwargs) + + For the documentation of the arguments, please see + :meth:`telegram.Bot.verify_chat`. + + .. versionadded:: NEXT.VERSION + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + """ + return await self.get_bot().verify_chat( + chat_id=self.id, + custom_description=custom_description, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + + async def remove_chat_verification( + self, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Shortcut for:: + + await bot.remove_chat_verification(chat_id=update.effective_chat.id, *args, **kwargs) + + For the documentation of the arguments, please see + :meth:`telegram.Bot.remove_chat_verification`. + + .. versionadded:: NEXT.VERSION + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + """ + return await self.get_bot().remove_chat_verification( + chat_id=self.id, read_timeout=read_timeout, write_timeout=write_timeout, connect_timeout=connect_timeout, diff --git a/telegram/_user.py b/telegram/_user.py index f70decde82c..560858473f9 100644 --- a/telegram/_user.py +++ b/telegram/_user.py @@ -1653,6 +1653,7 @@ async def send_gift( text: Optional[str] = None, text_parse_mode: ODVInput[str] = DEFAULT_NONE, text_entities: Optional[Sequence["MessageEntity"]] = None, + pay_for_upgrade: Optional[bool] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, write_timeout: ODVInput[float] = DEFAULT_NONE, @@ -1677,6 +1678,7 @@ async def send_gift( text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, + pay_for_upgrade=pay_for_upgrade, read_timeout=read_timeout, write_timeout=write_timeout, connect_timeout=connect_timeout, @@ -2270,3 +2272,65 @@ async def refund_star_payment( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) + + async def verify_user( + self, + custom_description: Optional[str] = None, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Shortcut for:: + + await bot.verify_user(user_id=update.effective_user.id, *args, **kwargs) + + For the documentation of the arguments, please see + :meth:`telegram.Bot.verify_user`. + + .. versionadded:: NEXT.VERSION + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + """ + return await self.get_bot().verify_user( + user_id=self.id, + custom_description=custom_description, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) + + async def remove_user_verification( + self, + *, + read_timeout: ODVInput[float] = DEFAULT_NONE, + write_timeout: ODVInput[float] = DEFAULT_NONE, + connect_timeout: ODVInput[float] = DEFAULT_NONE, + pool_timeout: ODVInput[float] = DEFAULT_NONE, + api_kwargs: Optional[JSONDict] = None, + ) -> bool: + """Shortcut for:: + + await bot.remove_user_verification(user_id=update.effective_user.id, *args, **kwargs) + + For the documentation of the arguments, please see + :meth:`telegram.Bot.remove_user_verification`. + + .. versionadded:: NEXT.VERSION + + Returns: + :obj:`bool`: On success, :obj:`True` is returned. + """ + return await self.get_bot().remove_user_verification( + user_id=self.id, + read_timeout=read_timeout, + write_timeout=write_timeout, + connect_timeout=connect_timeout, + pool_timeout=pool_timeout, + api_kwargs=api_kwargs, + ) diff --git a/telegram/constants.py b/telegram/constants.py index 099a239510b..0694f47bc56 100644 --- a/telegram/constants.py +++ b/telegram/constants.py @@ -104,6 +104,7 @@ "TransactionPartnerType", "UpdateType", "UserProfilePhotosLimit", + "VerifyLimit", "WebhookLimit", ] diff --git a/tests/_inline/test_inlinequeryresultarticle.py b/tests/_inline/test_inlinequeryresultarticle.py index 0692c425d0a..33858e41b51 100644 --- a/tests/_inline/test_inlinequeryresultarticle.py +++ b/tests/_inline/test_inlinequeryresultarticle.py @@ -28,6 +28,7 @@ InputTextMessageContent, ) from telegram.constants import InlineQueryResultType +from telegram.warnings import PTBDeprecationWarning from tests.auxil.slots import mro_slots @@ -157,3 +158,31 @@ def test_equality(self): assert a != e assert hash(a) != hash(e) + + def test_deprecation_warning_for_hide_url(self): + with pytest.warns(PTBDeprecationWarning, match="The argument `hide_url`") as record: + InlineQueryResultArticle( + self.id_, self.title, self.input_message_content, hide_url=True + ) + + assert record[0].filename == __file__, "wrong stacklevel!" + + with pytest.warns(PTBDeprecationWarning, match="The argument `hide_url`") as record: + InlineQueryResultArticle( + self.id_, self.title, self.input_message_content, hide_url=False + ) + + assert record[0].filename == __file__, "wrong stacklevel!" + + assert ( + InlineQueryResultArticle( + self.id_, self.title, self.input_message_content, hide_url=True + ).hide_url + is True + ) + assert ( + InlineQueryResultArticle( + self.id_, self.title, self.input_message_content, hide_url=False + ).hide_url + is False + ) diff --git a/tests/test_chat.py b/tests/test_chat.py index b2db4e36f76..38a80ae6bd7 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -1333,6 +1333,37 @@ async def make_assertion(*_, **kwargs): text_entities="text_entities", ) + async def test_instance_method_verify_chat(self, monkeypatch, chat): + async def make_assertion(*_, **kwargs): + return ( + kwargs["chat_id"] == chat.id + and kwargs["custom_description"] == "This is a custom description" + ) + + assert check_shortcut_signature(Chat.verify_chat, Bot.verify_chat, ["chat_id"], []) + assert await check_shortcut_call(chat.verify_chat, chat.get_bot(), "verify_chat") + assert await check_defaults_handling(chat.verify_chat, chat.get_bot()) + + monkeypatch.setattr(chat.get_bot(), "verify_chat", make_assertion) + assert await chat.verify_chat( + custom_description="This is a custom description", + ) + + async def test_instance_method_remove_chat_verification(self, monkeypatch, chat): + async def make_assertion(*_, **kwargs): + return kwargs["chat_id"] == chat.id + + assert check_shortcut_signature( + Chat.remove_chat_verification, Bot.remove_chat_verification, ["chat_id"], [] + ) + assert await check_shortcut_call( + chat.remove_chat_verification, chat.get_bot(), "remove_chat_verification" + ) + assert await check_defaults_handling(chat.remove_chat_verification, chat.get_bot()) + + monkeypatch.setattr(chat.get_bot(), "remove_chat_verification", make_assertion) + assert await chat.remove_chat_verification() + def test_mention_html(self): chat = Chat(id=1, type="foo") with pytest.raises(TypeError, match="Can not create a mention to a private group chat"): diff --git a/tests/test_gifts.py b/tests/test_gifts.py index e7e13c75cef..208a6a6e9f4 100644 --- a/tests/test_gifts.py +++ b/tests/test_gifts.py @@ -34,6 +34,7 @@ def gift(request): star_count=GiftTestBase.star_count, total_count=GiftTestBase.total_count, remaining_count=GiftTestBase.remaining_count, + upgrade_star_count=GiftTestBase.upgrade_star_count, ) @@ -51,6 +52,7 @@ class GiftTestBase: star_count = 5 total_count = 10 remaining_count = 5 + upgrade_star_count = 10 class TestGiftWithoutRequest(GiftTestBase): @@ -66,6 +68,7 @@ def test_de_json(self, offline_bot, gift): "star_count": self.star_count, "total_count": self.total_count, "remaining_count": self.remaining_count, + "upgrade_star_count": self.upgrade_star_count, } gift = Gift.de_json(json_dict, offline_bot) assert gift.api_kwargs == {} @@ -75,6 +78,7 @@ def test_de_json(self, offline_bot, gift): assert gift.star_count == self.star_count assert gift.total_count == self.total_count assert gift.remaining_count == self.remaining_count + assert gift.upgrade_star_count == self.upgrade_star_count assert Gift.de_json(None, offline_bot) is None @@ -87,12 +91,25 @@ def test_to_dict(self, gift): assert gift_dict["star_count"] == self.star_count assert gift_dict["total_count"] == self.total_count assert gift_dict["remaining_count"] == self.remaining_count + assert gift_dict["upgrade_star_count"] == self.upgrade_star_count def test_equality(self, gift): a = gift - b = Gift(self.id, self.sticker, self.star_count, self.total_count, self.remaining_count) + b = Gift( + self.id, + self.sticker, + self.star_count, + self.total_count, + self.remaining_count, + self.upgrade_star_count, + ) c = Gift( - "other_uid", self.sticker, self.star_count, self.total_count, self.remaining_count + "other_uid", + self.sticker, + self.star_count, + self.total_count, + self.remaining_count, + self.upgrade_star_count, ) d = BotCommand("start", "description") @@ -115,6 +132,7 @@ def test_equality(self, gift): 5, 10, 5, + 10, ), ], ids=["string", "Gift"], @@ -134,11 +152,18 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): tes = request_data.parameters["text_entities"] == [ me.to_dict() for me in text_entities ] - return user_id and gift_id and text and text_parse_mode and tes + pay_for_upgrade = request_data.parameters["pay_for_upgrade"] is True + + return user_id and gift_id and text and text_parse_mode and tes and pay_for_upgrade monkeypatch.setattr(offline_bot.request, "post", make_assertion) assert await offline_bot.send_gift( - "user_id", gift, "text", text_parse_mode="text_parse_mode", text_entities=text_entities + "user_id", + gift, + "text", + text_parse_mode="text_parse_mode", + text_entities=text_entities, + pay_for_upgrade=True, ) @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True) @@ -184,6 +209,7 @@ class GiftsTestBase: star_count=5, total_count=5, remaining_count=5, + upgrade_star_count=5, ), Gift( id="id2", @@ -199,6 +225,7 @@ class GiftsTestBase: star_count=6, total_count=6, remaining_count=6, + upgrade_star_count=6, ), Gift( id="id3", @@ -214,6 +241,7 @@ class GiftsTestBase: star_count=7, total_count=7, remaining_count=7, + upgrade_star_count=7, ), ] @@ -236,6 +264,7 @@ def test_de_json(self, offline_bot, gifts): assert de_json_gift.star_count == original_gift.star_count assert de_json_gift.total_count == original_gift.total_count assert de_json_gift.remaining_count == original_gift.remaining_count + assert de_json_gift.upgrade_star_count == original_gift.upgrade_star_count assert Gifts.de_json(None, offline_bot) is None diff --git a/tests/test_user.py b/tests/test_user.py index ede518f6f8f..0801bbddca0 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -742,3 +742,34 @@ async def make_assertion(*_, **kwargs): text_parse_mode="text_parse_mode", text_entities="text_entities", ) + + async def test_instance_method_verify_user(self, monkeypatch, user): + async def make_assertion(*_, **kwargs): + return ( + kwargs["user_id"] == user.id + and kwargs["custom_description"] == "This is a custom description" + ) + + assert check_shortcut_signature(user.verify_user, Bot.verify_user, ["user_id"], []) + assert await check_shortcut_call(user.verify_user, user.get_bot(), "verify_user") + assert await check_defaults_handling(user.verify_user, user.get_bot()) + + monkeypatch.setattr(user.get_bot(), "verify_user", make_assertion) + assert await user.verify_user( + custom_description="This is a custom description", + ) + + async def test_instance_method_remove_user_verification(self, monkeypatch, user): + async def make_assertion(*_, **kwargs): + return kwargs["user_id"] == user.id + + assert check_shortcut_signature( + user.remove_user_verification, Bot.remove_user_verification, ["user_id"], [] + ) + assert await check_shortcut_call( + user.remove_user_verification, user.get_bot(), "remove_user_verification" + ) + assert await check_defaults_handling(user.remove_user_verification, user.get_bot()) + + monkeypatch.setattr(user.get_bot(), "remove_user_verification", make_assertion) + assert await user.remove_user_verification() From bc00f8d7d423aa0903800eeddcb911c1b0ac7e4f Mon Sep 17 00:00:00 2001 From: Poolitzer Date: Tue, 31 Dec 2024 16:15:43 +0100 Subject: [PATCH 3/9] went through the checklist... --- README.rst | 4 ++-- docs/source/inclusions/bot_methods.rst | 23 +++++++++++++++++++++++ telegram/constants.py | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 3721a834fd0..e05b6bbf9b2 100644 --- a/README.rst +++ b/README.rst @@ -11,7 +11,7 @@ :target: https://pypi.org/project/python-telegram-bot/ :alt: Supported Python versions -.. image:: https://img.shields.io/badge/Bot%20API-8.1-blue?logo=telegram +.. image:: https://img.shields.io/badge/Bot%20API-8.2-blue?logo=telegram :target: https://core.telegram.org/bots/api-changelog :alt: Supported Bot API version @@ -81,7 +81,7 @@ After installing_ the library, be sure to check out the section on `working with Telegram API support ~~~~~~~~~~~~~~~~~~~~ -All types and methods of the Telegram Bot API **8.1** are natively supported by this library. +All types and methods of the Telegram Bot API **8.2** are natively supported by this library. In addition, Bot API functionality not yet natively included can still be used as described `in our wiki `_. Notable Features diff --git a/docs/source/inclusions/bot_methods.rst b/docs/source/inclusions/bot_methods.rst index b8501d8b2c7..240c258f68f 100644 --- a/docs/source/inclusions/bot_methods.rst +++ b/docs/source/inclusions/bot_methods.rst @@ -183,6 +183,29 @@
+.. raw:: html + +
+ Verification on behalf of an organization + +.. list-table:: + :align: left + :widths: 1 4 + + * - :meth:`~telegram.Bot.verify_chat` + - Used for verifying a chat + * - :meth:`~telegram.Bot.verify_user` + - Used for verifying a user + * - :meth:`~telegram.Bot.remove_chat_verification` + - Used for removing the verification from a chat + * - :meth:`~telegram.Bot.remove_user_verification` + - Used for removing the verification from a user + +.. raw:: html + +
+
+ .. raw:: html
diff --git a/telegram/constants.py b/telegram/constants.py index 0694f47bc56..37f1d43ba4f 100644 --- a/telegram/constants.py +++ b/telegram/constants.py @@ -155,7 +155,7 @@ class _AccentColor(NamedTuple): #: :data:`telegram.__bot_api_version_info__`. #: #: .. versionadded:: 20.0 -BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=8, minor=1) +BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=8, minor=2) #: :obj:`str`: Telegram Bot API #: version supported by this version of `python-telegram-bot`. Also available as #: :data:`telegram.__bot_api_version__`. From a79c91d8960dd5bd667281317baa4db311065372 Mon Sep 17 00:00:00 2001 From: Poolitzer Date: Wed, 1 Jan 2025 23:41:21 +0100 Subject: [PATCH 4/9] adding offline tests for the new methods --- tests/test_bot.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/test_bot.py b/tests/test_bot.py index 7977efec36c..2804b839ddc 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -2386,6 +2386,48 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): 4242, "emoji_status_custom_emoji_id", dtm.datetime(2024, 1, 1) ) + async def test_verify_user(self, offline_bot, monkeypatch): + "No way to test this without getting verified" + + async def make_assertion(url, request_data: RequestData, *args, **kwargs): + assert request_data.parameters.get("user_id") == 1234 + assert request_data.parameters.get("custom_description") == "this is so custom" + + monkeypatch.setattr(offline_bot.request, "post", make_assertion) + + await offline_bot.verify_user(1234, "this is so custom") + + async def test_verify_chat(self, offline_bot, monkeypatch): + "No way to test this without getting verified" + + async def make_assertion(url, request_data: RequestData, *args, **kwargs): + assert request_data.parameters.get("chat_id") == 1234 + assert request_data.parameters.get("custom_description") == "this is so custom" + + monkeypatch.setattr(offline_bot.request, "post", make_assertion) + + await offline_bot.verify_chat(1234, "this is so custom") + + async def test_unverify_user(self, offline_bot, monkeypatch): + "No way to test this without getting verified" + + async def make_assertion(url, request_data: RequestData, *args, **kwargs): + assert request_data.parameters.get("user_id") == 1234 + + monkeypatch.setattr(offline_bot.request, "post", make_assertion) + + await offline_bot.remove_user_verification(1234) + + async def test_unverify_chat(self, offline_bot, monkeypatch): + "No way to test this without getting verified" + + async def make_assertion(url, request_data: RequestData, *args, **kwargs): + assert request_data.parameters.get("chat_id") == 1234 + + monkeypatch.setattr(offline_bot.request, "post", make_assertion) + + await offline_bot.remove_chat_verification(1234) + class TestBotWithRequest: """ From 45339cc81a0a2a4ea6943a5cc7febe99e407512b Mon Sep 17 00:00:00 2001 From: Poolitzer Date: Wed, 1 Jan 2025 23:54:19 +0100 Subject: [PATCH 5/9] Tried to add the backwards arg, not sure who let harshil make it like this without docs grrr... --- tests/test_official/exceptions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_official/exceptions.py b/tests/test_official/exceptions.py index 00e109cc8fa..e86056a8733 100644 --- a/tests/test_official/exceptions.py +++ b/tests/test_official/exceptions.py @@ -200,7 +200,8 @@ 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]] = { - "send_invoice|create_invoice_link|InputInvoiceMessageContent": {"provider_token"} + "send_invoice|create_invoice_link|InputInvoiceMessageContent": {"provider_token"}, + "InlineQueryResultArticle": {"hide_url"}, } From d248d3b9f05285904c0852cbf94201101399e384 Mon Sep 17 00:00:00 2001 From: Poolitzer Date: Thu, 2 Jan 2025 16:32:05 +0100 Subject: [PATCH 6/9] Apply suggestions from code review Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com> Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> --- telegram/_bot.py | 10 ++++++++-- telegram/_chat.py | 4 ++-- telegram/_inline/inlinequeryresultarticle.py | 2 +- telegram/_user.py | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/telegram/_bot.py b/telegram/_bot.py index 9d7855b6445..222a234b381 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -9876,7 +9876,10 @@ async def remove_chat_verification( pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, ) -> bool: - """Verifies a user on behalf of the organization which is represented by the bot. + """Removes verification from a chat that is currently verified on behalf of the + organization represented by the bot. + + .. versionadded:: NEXT.VERSION @@ -9912,7 +9915,10 @@ async def remove_user_verification( pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, ) -> bool: - """Verifies a user on behalf of the organization which is represented by the bot. + """Removes verification from a user who is currently verified on behalf of the + organization represented by the bot. + + .. versionadded:: NEXT.VERSION diff --git a/telegram/_chat.py b/telegram/_chat.py index 40b861f61c9..7f33b049823 100644 --- a/telegram/_chat.py +++ b/telegram/_chat.py @@ -3479,7 +3479,7 @@ async def send_gift( api_kwargs=api_kwargs, ) - async def verify_chat( + async def verify( self, custom_description: Optional[str] = None, *, @@ -3511,7 +3511,7 @@ async def verify_chat( api_kwargs=api_kwargs, ) - async def remove_chat_verification( + async def remove_verification( self, *, read_timeout: ODVInput[float] = DEFAULT_NONE, diff --git a/telegram/_inline/inlinequeryresultarticle.py b/telegram/_inline/inlinequeryresultarticle.py index 52bff8ce6bb..2d07bca2628 100644 --- a/telegram/_inline/inlinequeryresultarticle.py +++ b/telegram/_inline/inlinequeryresultarticle.py @@ -137,7 +137,7 @@ def __init__( warn( PTBDeprecationWarning( "NEXT.VERSION", - "The argument `hide_url` will be removed in future major PTB/Bot API" + "The argument `hide_url` will be removed in future PTB" "versions. Pass an empty string as URL instead.", ), stacklevel=2, diff --git a/telegram/_user.py b/telegram/_user.py index d4ccc5cf340..e5f3c3d6f37 100644 --- a/telegram/_user.py +++ b/telegram/_user.py @@ -2273,7 +2273,7 @@ async def refund_star_payment( api_kwargs=api_kwargs, ) - async def verify_user( + async def verify( self, custom_description: Optional[str] = None, *, @@ -2305,7 +2305,7 @@ async def verify_user( api_kwargs=api_kwargs, ) - async def remove_user_verification( + async def remove_verification( self, *, read_timeout: ODVInput[float] = DEFAULT_NONE, From 7af7839ce4b4d5b77abff690989df67d59786b60 Mon Sep 17 00:00:00 2001 From: Poolitzer Date: Thu, 2 Jan 2025 16:47:55 +0100 Subject: [PATCH 7/9] more review changes --- telegram/_inline/inlinequeryresultarticle.py | 8 ++++---- tests/test_chat.py | 16 ++++++++-------- tests/test_user.py | 16 ++++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/telegram/_inline/inlinequeryresultarticle.py b/telegram/_inline/inlinequeryresultarticle.py index 2d07bca2628..a54fcbd0012 100644 --- a/telegram/_inline/inlinequeryresultarticle.py +++ b/telegram/_inline/inlinequeryresultarticle.py @@ -54,8 +54,8 @@ class InlineQueryResultArticle(InlineQueryResult): in the message. .. deprecated:: NEXT.VERSION - This attribute will be removed in future major PTB/Bot API versions. Pass an - empty string as URL instead. + This attribute will be removed in future PTP versions. Pass an empty string as URL + instead. description (:obj:`str`, optional): Short description of the result. thumbnail_url (:obj:`str`, optional): Url of the thumbnail for the result. @@ -82,8 +82,8 @@ class InlineQueryResultArticle(InlineQueryResult): in the message. .. deprecated:: NEXT.VERSION - This attribute will be removed in future major PTB/Bot API versions. Pass an - empty string as URL instead. + This attribute will be removed in future PTP versions. Pass an empty string as URL + instead. description (:obj:`str`): Optional. Short description of the result. thumbnail_url (:obj:`str`): Optional. Url of the thumbnail for the result. diff --git a/tests/test_chat.py b/tests/test_chat.py index ff1f9cc0e42..e39281ee010 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -1340,12 +1340,12 @@ async def make_assertion(*_, **kwargs): and kwargs["custom_description"] == "This is a custom description" ) - assert check_shortcut_signature(Chat.verify_chat, Bot.verify_chat, ["chat_id"], []) - assert await check_shortcut_call(chat.verify_chat, chat.get_bot(), "verify_chat") - assert await check_defaults_handling(chat.verify_chat, chat.get_bot()) + assert check_shortcut_signature(Chat.verify, Bot.verify_chat, ["chat_id"], []) + assert await check_shortcut_call(chat.verify, chat.get_bot(), "verify_chat") + assert await check_defaults_handling(chat.verify, chat.get_bot()) monkeypatch.setattr(chat.get_bot(), "verify_chat", make_assertion) - assert await chat.verify_chat( + assert await chat.verify( custom_description="This is a custom description", ) @@ -1354,15 +1354,15 @@ async def make_assertion(*_, **kwargs): return kwargs["chat_id"] == chat.id assert check_shortcut_signature( - Chat.remove_chat_verification, Bot.remove_chat_verification, ["chat_id"], [] + Chat.remove_verification, Bot.remove_chat_verification, ["chat_id"], [] ) assert await check_shortcut_call( - chat.remove_chat_verification, chat.get_bot(), "remove_chat_verification" + chat.remove_verification, chat.get_bot(), "remove_chat_verification" ) - assert await check_defaults_handling(chat.remove_chat_verification, chat.get_bot()) + assert await check_defaults_handling(chat.remove_verification, chat.get_bot()) monkeypatch.setattr(chat.get_bot(), "remove_chat_verification", make_assertion) - assert await chat.remove_chat_verification() + assert await chat.remove_verification() def test_mention_html(self): chat = Chat(id=1, type="foo") diff --git a/tests/test_user.py b/tests/test_user.py index d941742311d..54657c59047 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -750,12 +750,12 @@ async def make_assertion(*_, **kwargs): and kwargs["custom_description"] == "This is a custom description" ) - assert check_shortcut_signature(user.verify_user, Bot.verify_user, ["user_id"], []) - assert await check_shortcut_call(user.verify_user, user.get_bot(), "verify_user") - assert await check_defaults_handling(user.verify_user, user.get_bot()) + assert check_shortcut_signature(user.verify, Bot.verify_user, ["user_id"], []) + assert await check_shortcut_call(user.verify, user.get_bot(), "verify_user") + assert await check_defaults_handling(user.verify, user.get_bot()) monkeypatch.setattr(user.get_bot(), "verify_user", make_assertion) - assert await user.verify_user( + assert await user.verify( custom_description="This is a custom description", ) @@ -764,12 +764,12 @@ async def make_assertion(*_, **kwargs): return kwargs["user_id"] == user.id assert check_shortcut_signature( - user.remove_user_verification, Bot.remove_user_verification, ["user_id"], [] + user.remove_verification, Bot.remove_user_verification, ["user_id"], [] ) assert await check_shortcut_call( - user.remove_user_verification, user.get_bot(), "remove_user_verification" + user.remove_verification, user.get_bot(), "remove_user_verification" ) - assert await check_defaults_handling(user.remove_user_verification, user.get_bot()) + assert await check_defaults_handling(user.remove_verification, user.get_bot()) monkeypatch.setattr(user.get_bot(), "remove_user_verification", make_assertion) - assert await user.remove_user_verification() + assert await user.remove_verification() From 60826d7d7200f22ef33837df88912cbedea85eed Mon Sep 17 00:00:00 2001 From: Harshil <37377066+harshil21@users.noreply.github.com> Date: Fri, 3 Jan 2025 10:40:47 +0400 Subject: [PATCH 8/9] Apply suggestions from code review --- telegram/_inline/inlinequeryresultarticle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telegram/_inline/inlinequeryresultarticle.py b/telegram/_inline/inlinequeryresultarticle.py index a54fcbd0012..667ab5cb3dc 100644 --- a/telegram/_inline/inlinequeryresultarticle.py +++ b/telegram/_inline/inlinequeryresultarticle.py @@ -54,7 +54,7 @@ class InlineQueryResultArticle(InlineQueryResult): in the message. .. deprecated:: NEXT.VERSION - This attribute will be removed in future PTP versions. Pass an empty string as URL + This attribute will be removed in future PTB versions. Pass an empty string as URL instead. description (:obj:`str`, optional): Short description of the result. thumbnail_url (:obj:`str`, optional): Url of the thumbnail for the result. @@ -82,7 +82,7 @@ class InlineQueryResultArticle(InlineQueryResult): in the message. .. deprecated:: NEXT.VERSION - This attribute will be removed in future PTP versions. Pass an empty string as URL + This attribute will be removed in future PTB versions. Pass an empty string as URL instead. description (:obj:`str`): Optional. Short description of the result. thumbnail_url (:obj:`str`): Optional. Url of the thumbnail for the result. From ea6b60b9ad468818d270e42985902ecc567bb102 Mon Sep 17 00:00:00 2001 From: poolitzer Date: Fri, 3 Jan 2025 10:51:38 +0100 Subject: [PATCH 9/9] make ruff/black happy --- telegram/_bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telegram/_bot.py b/telegram/_bot.py index 222a234b381..f455d63b4b7 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -9876,7 +9876,7 @@ async def remove_chat_verification( pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, ) -> bool: - """Removes verification from a chat that is currently verified on behalf of the + """Removes verification from a chat that is currently verified on behalf of the organization represented by the bot. @@ -9915,7 +9915,7 @@ async def remove_user_verification( pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, ) -> bool: - """Removes verification from a user who is currently verified on behalf of the + """Removes verification from a user who is currently verified on behalf of the organization represented by the bot.