From 62f89758d7174c138f525a447dcdaafe08e7dc1c Mon Sep 17 00:00:00 2001 From: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:11:10 +0100 Subject: [PATCH] Bot API 7.11 (#4546) --- README.rst | 4 +- docs/source/telegram.at-tree.rst | 1 + docs/source/telegram.copytextbutton.rst | 6 + docs/source/telegram.payments-tree.rst | 1 + .../telegram.transactionpartnerfragment.rst | 2 +- .../telegram.transactionpartnerother.rst | 2 +- ...telegram.transactionpartnertelegramads.rst | 2 +- ...telegram.transactionpartnertelegramapi.rst | 7 + .../telegram.transactionpartneruser.rst | 2 +- docs/substitutions/global.rst | 2 + telegram/__init__.py | 4 + telegram/_bot.py | 142 ++++++++++++++---- telegram/_callbackquery.py | 2 + telegram/_chat.py | 40 +++++ telegram/_copytextbutton.py | 55 +++++++ telegram/_inline/inlinekeyboardbutton.py | 13 ++ telegram/_message.py | 54 ++++++- telegram/_messageentity.py | 18 ++- telegram/_messageid.py | 10 +- telegram/_payment/stars.py | 38 ++++- telegram/_user.py | 38 +++++ telegram/constants.py | 32 +++- telegram/ext/_extbot.py | 40 +++++ tests/_inline/test_inlinekeyboardbutton.py | 9 ++ tests/test_bot.py | 10 ++ tests/test_copytextbutton.py | 70 +++++++++ tests/test_stars.py | 46 ++++-- 27 files changed, 583 insertions(+), 67 deletions(-) create mode 100644 docs/source/telegram.copytextbutton.rst create mode 100644 docs/source/telegram.transactionpartnertelegramapi.rst create mode 100644 telegram/_copytextbutton.py create mode 100644 tests/test_copytextbutton.py diff --git a/README.rst b/README.rst index aba1c2c09..dd19bbbbd 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-7.10-blue?logo=telegram +.. image:: https://img.shields.io/badge/Bot%20API-7.11-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 **7.10** are natively supported by this library. +All types and methods of the Telegram Bot API **7.11** 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/telegram.at-tree.rst b/docs/source/telegram.at-tree.rst index f40223391..bdeb70159 100644 --- a/docs/source/telegram.at-tree.rst +++ b/docs/source/telegram.at-tree.rst @@ -29,6 +29,7 @@ Available Types telegram.chat telegram.chatadministratorrights telegram.chatbackground + telegram.copytextbutton telegram.backgroundtype telegram.backgroundtypefill telegram.backgroundtypewallpaper diff --git a/docs/source/telegram.copytextbutton.rst b/docs/source/telegram.copytextbutton.rst new file mode 100644 index 000000000..7110fbf8b --- /dev/null +++ b/docs/source/telegram.copytextbutton.rst @@ -0,0 +1,6 @@ +CopyTextButton +============== + +.. autoclass:: telegram.CopyTextButton + :members: + :show-inheritance: \ No newline at end of file diff --git a/docs/source/telegram.payments-tree.rst b/docs/source/telegram.payments-tree.rst index ba4c838ca..590a96fda 100644 --- a/docs/source/telegram.payments-tree.rst +++ b/docs/source/telegram.payments-tree.rst @@ -28,4 +28,5 @@ Your bot can accept payments from Telegram users. Please see the `introduction t telegram.transactionpartnerfragment telegram.transactionpartnerother telegram.transactionpartnertelegramads + telegram.transactionpartnertelegramapi telegram.transactionpartneruser diff --git a/docs/source/telegram.transactionpartnerfragment.rst b/docs/source/telegram.transactionpartnerfragment.rst index 0845b4a80..c65f9262f 100644 --- a/docs/source/telegram.transactionpartnerfragment.rst +++ b/docs/source/telegram.transactionpartnerfragment.rst @@ -4,4 +4,4 @@ TransactionPartnerFragment .. autoclass:: telegram.TransactionPartnerFragment :members: :show-inheritance: - :inherited-members: TelegramObject + :inherited-members: TransactionPartner diff --git a/docs/source/telegram.transactionpartnerother.rst b/docs/source/telegram.transactionpartnerother.rst index c3ffddc7d..b0c14f071 100644 --- a/docs/source/telegram.transactionpartnerother.rst +++ b/docs/source/telegram.transactionpartnerother.rst @@ -4,4 +4,4 @@ TransactionPartnerOther .. autoclass:: telegram.TransactionPartnerOther :members: :show-inheritance: - :inherited-members: TelegramObject + :inherited-members: TransactionPartner diff --git a/docs/source/telegram.transactionpartnertelegramads.rst b/docs/source/telegram.transactionpartnertelegramads.rst index 926b25bdc..ce9a52a11 100644 --- a/docs/source/telegram.transactionpartnertelegramads.rst +++ b/docs/source/telegram.transactionpartnertelegramads.rst @@ -4,4 +4,4 @@ TransactionPartnerTelegramAds .. autoclass:: telegram.TransactionPartnerTelegramAds :members: :show-inheritance: - :inherited-members: TelegramObject + :inherited-members: TransactionPartner diff --git a/docs/source/telegram.transactionpartnertelegramapi.rst b/docs/source/telegram.transactionpartnertelegramapi.rst new file mode 100644 index 000000000..9aeba6b94 --- /dev/null +++ b/docs/source/telegram.transactionpartnertelegramapi.rst @@ -0,0 +1,7 @@ +TransactionPartnerTelegramApi +============================= + +.. autoclass:: telegram.TransactionPartnerTelegramApi + :members: + :show-inheritance: + :inherited-members: TransactionPartner diff --git a/docs/source/telegram.transactionpartneruser.rst b/docs/source/telegram.transactionpartneruser.rst index d2e145e18..def374953 100644 --- a/docs/source/telegram.transactionpartneruser.rst +++ b/docs/source/telegram.transactionpartneruser.rst @@ -4,4 +4,4 @@ TransactionPartnerUser .. autoclass:: telegram.TransactionPartnerUser :members: :show-inheritance: - :inherited-members: TelegramObject + :inherited-members: TransactionPartner diff --git a/docs/substitutions/global.rst b/docs/substitutions/global.rst index 88a604cd1..ab9c69249 100644 --- a/docs/substitutions/global.rst +++ b/docs/substitutions/global.rst @@ -93,3 +93,5 @@ .. |show_cap_above_med| replace:: :obj:`True`, if the caption must be shown above the message media. .. |tg_stars| replace:: `Telegram Stars `__ + +.. |allow_paid_broadcast| replace:: Pass True to allow up to :tg-const:`telegram.constants.FloodLimit.PAID_MESSAGES_PER_SECOND` messages per second, ignoring `broadcasting limits `__ for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance. diff --git a/telegram/__init__.py b/telegram/__init__.py index 0ff15a7a9..a4902d4d8 100644 --- a/telegram/__init__.py +++ b/telegram/__init__.py @@ -81,6 +81,7 @@ __all__ = ( "ChatShared", "ChosenInlineResult", "Contact", + "CopyTextButton", "Credentials", "DataCredentials", "Dice", @@ -235,6 +236,7 @@ __all__ = ( "TransactionPartnerFragment", "TransactionPartnerOther", "TransactionPartnerTelegramAds", + "TransactionPartnerTelegramApi", "TransactionPartnerUser", "Update", "User", @@ -330,6 +332,7 @@ from ._chatmember import ( from ._chatmemberupdated import ChatMemberUpdated from ._chatpermissions import ChatPermissions from ._choseninlineresult import ChosenInlineResult +from ._copytextbutton import CopyTextButton from ._dice import Dice from ._files.animation import Animation from ._files.audio import Audio @@ -471,6 +474,7 @@ from ._payment.stars import ( TransactionPartnerFragment, TransactionPartnerOther, TransactionPartnerTelegramAds, + TransactionPartnerTelegramApi, TransactionPartnerUser, ) from ._payment.successfulpayment import SuccessfulPayment diff --git a/telegram/_bot.py b/telegram/_bot.py index 345dac4ed..448668702 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -672,6 +672,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -708,33 +709,22 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): allow_sending_without_reply=allow_sending_without_reply, ) - data["disable_notification"] = disable_notification - data["protect_content"] = protect_content - data["parse_mode"] = parse_mode - - if reply_parameters is not None: - data["reply_parameters"] = reply_parameters - - if link_preview_options is not None: - data["link_preview_options"] = link_preview_options - - if reply_markup is not None: - data["reply_markup"] = reply_markup - - if message_thread_id is not None: - data["message_thread_id"] = message_thread_id - - if caption is not None: - data["caption"] = caption - - if caption_entities is not None: - data["caption_entities"] = caption_entities - - if business_connection_id is not None: - data["business_connection_id"] = business_connection_id - - if message_effect_id is not None: - data["message_effect_id"] = message_effect_id + data.update( + { + "allow_paid_broadcast": allow_paid_broadcast, + "business_connection_id": business_connection_id, + "caption": caption, + "caption_entities": caption_entities, + "disable_notification": disable_notification, + "link_preview_options": link_preview_options, + "message_thread_id": message_thread_id, + "message_effect_id": message_effect_id, + "parse_mode": parse_mode, + "protect_content": protect_content, + "reply_markup": reply_markup, + "reply_parameters": reply_parameters, + } + ) result = await self._post( endpoint, @@ -925,6 +915,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -976,6 +967,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -1034,6 +1028,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): link_preview_options=link_preview_options, reply_parameters=reply_parameters, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, read_timeout=read_timeout, write_timeout=write_timeout, connect_timeout=connect_timeout, @@ -1283,6 +1278,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1350,6 +1346,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med| .. versionadded:: 21.3 @@ -1413,6 +1412,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_audio( @@ -1433,6 +1433,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -1508,6 +1509,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -1570,6 +1574,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_document( @@ -1588,6 +1593,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -1662,6 +1668,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -1720,6 +1729,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_sticker( @@ -1734,6 +1744,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -1788,6 +1799,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -1838,6 +1852,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_video( @@ -1860,6 +1875,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1944,6 +1960,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med| .. versionadded:: 21.3 @@ -2012,6 +2031,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_video_note( @@ -2028,6 +2048,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -2097,6 +2118,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -2155,6 +2179,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_animation( @@ -2176,6 +2201,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2254,6 +2280,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med| .. versionadded:: 21.3 @@ -2321,6 +2350,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_voice( @@ -2338,6 +2368,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -2409,6 +2440,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -2468,6 +2502,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_media_group( @@ -2482,6 +2517,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -2535,6 +2571,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -2629,6 +2668,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): "reply_parameters": reply_parameters, "business_connection_id": business_connection_id, "message_effect_id": message_effect_id, + "allow_paid_broadcast": allow_paid_broadcast, } result = await self._post( @@ -2659,6 +2699,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -2718,6 +2759,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -2788,6 +2832,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def edit_message_live_location( @@ -2970,6 +3015,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -3025,6 +3071,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -3106,6 +3155,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_contact( @@ -3122,6 +3172,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -3167,6 +3218,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -3239,6 +3293,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_game( @@ -3252,6 +3307,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -3287,6 +3343,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -3334,6 +3393,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_chat_action( @@ -4148,7 +4208,8 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): api_kwargs: Optional[JSONDict] = None, ) -> Union[Message, bool]: """ - Use this method to edit animation, audio, document, photo, or video messages. If a message + Use this method to edit animation, audio, document, photo, or video messages, or to add + media to text messages. If a message is part of a message album, then it can be edited only to an audio for audio albums, only to a document for document albums and to a photo or a video otherwise. When an inline message is edited, a new file can't be uploaded; use a previously uploaded file via its @@ -4973,6 +5034,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -5090,6 +5152,9 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -5159,6 +5224,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]): pool_timeout=pool_timeout, api_kwargs=api_kwargs, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def answer_shipping_query( @@ -6999,6 +7065,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. question_parse_mode: ODVInput[str] = DEFAULT_NONE, question_entities: Optional[Sequence["MessageEntity"]] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -7096,6 +7163,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -7162,6 +7232,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def stop_poll( @@ -7225,6 +7296,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -7274,6 +7346,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. message_effect_id (:obj:`str`, optional): |message_effect_id| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -7322,6 +7397,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def get_my_default_administrator_rights( @@ -7652,6 +7728,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -7699,6 +7776,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med| .. versionadded:: 21.3 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -7757,6 +7837,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. "message_thread_id": message_thread_id, "reply_parameters": reply_parameters, "show_caption_above_media": show_caption_above_media, + "allow_paid_broadcast": allow_paid_broadcast, } result = await self._post( @@ -9188,6 +9269,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. reply_markup: Optional[ReplyMarkup] = None, business_connection_id: Optional[str] = None, payload: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -9231,6 +9313,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. business_connection_id (:obj:`str`, optional): |business_id_str| .. versionadded:: 21.5 + allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast| + + .. versionadded:: NEXT.VERSION Keyword Args: allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| @@ -9274,6 +9359,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. pool_timeout=pool_timeout, api_kwargs=api_kwargs, business_connection_id=business_connection_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def create_chat_subscription_invite_link( diff --git a/telegram/_callbackquery.py b/telegram/_callbackquery.py index af44a3243..9264feaaa 100644 --- a/telegram/_callbackquery.py +++ b/telegram/_callbackquery.py @@ -834,6 +834,7 @@ class CallbackQuery(TelegramObject): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -881,6 +882,7 @@ class CallbackQuery(TelegramObject): message_thread_id=message_thread_id, reply_parameters=reply_parameters, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) MAX_ANSWER_TEXT_LENGTH: Final[int] = ( diff --git a/telegram/_chat.py b/telegram/_chat.py index 7e5dc0ad8..bb0e24b1d 100644 --- a/telegram/_chat.py +++ b/telegram/_chat.py @@ -1012,6 +1012,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1053,6 +1054,7 @@ class _ChatBase(TelegramObject): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def delete_message( @@ -1130,6 +1132,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1172,6 +1175,7 @@ class _ChatBase(TelegramObject): reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_chat_action( @@ -1225,6 +1229,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -1268,6 +1273,7 @@ class _ChatBase(TelegramObject): has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -1284,6 +1290,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1325,6 +1332,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_audio( @@ -1344,6 +1352,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1389,6 +1398,7 @@ class _ChatBase(TelegramObject): thumbnail=thumbnail, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_document( @@ -1406,6 +1416,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1449,6 +1460,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_dice( @@ -1461,6 +1473,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1497,6 +1510,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_game( @@ -1509,6 +1523,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1545,6 +1560,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_invoice( @@ -1576,6 +1592,7 @@ class _ChatBase(TelegramObject): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1641,6 +1658,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, reply_parameters=reply_parameters, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_location( @@ -1658,6 +1676,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1701,6 +1720,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_animation( @@ -1721,6 +1741,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -1768,6 +1789,7 @@ class _ChatBase(TelegramObject): thumbnail=thumbnail, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -1782,6 +1804,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1819,6 +1842,7 @@ class _ChatBase(TelegramObject): emoji=emoji, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_venue( @@ -1838,6 +1862,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1883,6 +1908,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_video( @@ -1904,6 +1930,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -1952,6 +1979,7 @@ class _ChatBase(TelegramObject): has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -1968,6 +1996,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2009,6 +2038,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_voice( @@ -2025,6 +2055,7 @@ class _ChatBase(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2067,6 +2098,7 @@ class _ChatBase(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_poll( @@ -2092,6 +2124,7 @@ class _ChatBase(TelegramObject): question_parse_mode: ODVInput[str] = DEFAULT_NONE, question_entities: Optional[Sequence["MessageEntity"]] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2129,6 +2162,7 @@ class _ChatBase(TelegramObject): connect_timeout=connect_timeout, pool_timeout=pool_timeout, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, explanation=explanation, explanation_parse_mode=explanation_parse_mode, open_period=open_period, @@ -2156,6 +2190,7 @@ class _ChatBase(TelegramObject): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2197,6 +2232,7 @@ class _ChatBase(TelegramObject): protect_content=protect_content, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) async def copy_message( @@ -2212,6 +2248,7 @@ class _ChatBase(TelegramObject): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2253,6 +2290,7 @@ class _ChatBase(TelegramObject): protect_content=protect_content, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_copies( @@ -3352,6 +3390,7 @@ class _ChatBase(TelegramObject): reply_markup: Optional[ReplyMarkup] = None, business_connection_id: Optional[str] = None, payload: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -3394,6 +3433,7 @@ class _ChatBase(TelegramObject): api_kwargs=api_kwargs, business_connection_id=business_connection_id, payload=payload, + allow_paid_broadcast=allow_paid_broadcast, ) diff --git a/telegram/_copytextbutton.py b/telegram/_copytextbutton.py new file mode 100644 index 000000000..e3dee813b --- /dev/null +++ b/telegram/_copytextbutton.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# A library that provides a Python interface to the Telegram Bot API +# Copyright (C) 2015-2024 +# Leandro Toledo de Souza +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser Public License for more details. +# +# You should have received a copy of the GNU Lesser Public License +# along with this program. If not, see [http://www.gnu.org/licenses/]. +"""This module contains an object that represents a Telegram CopyTextButton.""" +from typing import Optional + +from telegram._telegramobject import TelegramObject +from telegram._utils.types import JSONDict + + +class CopyTextButton(TelegramObject): + """ + This object represents an inline keyboard button that copies specified text to the clipboard. + + Objects of this class are comparable in terms of equality. Two objects of this class are + considered equal, if their :attr:`text` is equal. + + .. versionadded:: NEXT.VERSION + + Args: + text (:obj:`str`): The text to be copied to the clipboard; + :tg-const:`telegram.constants.InlineKeyboardButtonLimit.MIN_COPY_TEXT`- + :tg-const:`telegram.constants.InlineKeyboardButtonLimit.MAX_COPY_TEXT` characters + + Attributes: + text (:obj:`str`): The text to be copied to the clipboard; + :tg-const:`telegram.constants.InlineKeyboardButtonLimit.MIN_COPY_TEXT`- + :tg-const:`telegram.constants.InlineKeyboardButtonLimit.MAX_COPY_TEXT` characters + + """ + + __slots__ = ("text",) + + def __init__(self, text: str, *, api_kwargs: Optional[JSONDict] = None): + super().__init__(api_kwargs=api_kwargs) + self.text: str = text + + self._id_attrs = (self.text,) + + self._freeze() diff --git a/telegram/_inline/inlinekeyboardbutton.py b/telegram/_inline/inlinekeyboardbutton.py index cff4df66a..62031af8c 100644 --- a/telegram/_inline/inlinekeyboardbutton.py +++ b/telegram/_inline/inlinekeyboardbutton.py @@ -21,6 +21,7 @@ from typing import TYPE_CHECKING, Final, Optional, Union from telegram import constants +from telegram._copytextbutton import CopyTextButton from telegram._games.callbackgame import CallbackGame from telegram._loginurl import LoginUrl from telegram._switchinlinequerychosenchat import SwitchInlineQueryChosenChat @@ -123,6 +124,10 @@ class InlineKeyboardButton(TelegramObject): This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. Not supported in channels and for messages sent on behalf of a Telegram Business account. + copy_text (:class:`telegram.CopyTextButton`, optional): Description of the button that + copies the specified text to the clipboard. + + .. versionadded:: NEXT.VERSION callback_game (:class:`telegram.CallbackGame`, optional): Description of the game that will be launched when the user presses the button @@ -192,6 +197,10 @@ class InlineKeyboardButton(TelegramObject): This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. Not supported in channels and for messages sent on behalf of a Telegram Business account. + copy_text (:class:`telegram.CopyTextButton`): Optional. Description of the button that + copies the specified text to the clipboard. + + .. versionadded:: NEXT.VERSION callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will be launched when the user presses the button. @@ -224,6 +233,7 @@ class InlineKeyboardButton(TelegramObject): __slots__ = ( "callback_data", "callback_game", + "copy_text", "login_url", "pay", "switch_inline_query", @@ -246,6 +256,7 @@ class InlineKeyboardButton(TelegramObject): login_url: Optional[LoginUrl] = None, web_app: Optional[WebAppInfo] = None, switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat] = None, + copy_text: Optional[CopyTextButton] = None, *, api_kwargs: Optional[JSONDict] = None, ): @@ -265,6 +276,7 @@ class InlineKeyboardButton(TelegramObject): self.switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat] = ( switch_inline_query_chosen_chat ) + self.copy_text: Optional[CopyTextButton] = copy_text self._id_attrs = () self._set_id_attrs() @@ -299,6 +311,7 @@ class InlineKeyboardButton(TelegramObject): data["switch_inline_query_chosen_chat"] = SwitchInlineQueryChosenChat.de_json( data.get("switch_inline_query_chosen_chat"), bot ) + data["copy_text"] = CopyTextButton.de_json(data.get("copy_text"), bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_message.py b/telegram/_message.py index 44490482b..6390c8b05 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -280,7 +280,10 @@ class Message(MaybeInaccessibleMessage): and notice that some positional arguments changed position as a result. Args: - message_id (:obj:`int`): Unique message identifier inside this chat. + message_id (:obj:`int`): Unique message identifier inside this chat. In specific instances + (e.g., message containing a video sent to a big chat), the server might automatically + schedule a message instead of sending it immediately. In such cases, this field will be + ``0`` and the relevant message will be unusable until it is actually sent. from_user (:class:`telegram.User`, optional): Sender of the message; may be empty for messages sent to channels. For backward compatibility, if the message was sent on behalf of a chat, the field contains a fake sender user in non-channel chats. @@ -590,7 +593,10 @@ class Message(MaybeInaccessibleMessage): .. versionadded:: 21.4 Attributes: - message_id (:obj:`int`): Unique message identifier inside this chat. + message_id (:obj:`int`): Unique message identifier inside this chat. In specific instances + (e.g., message containing a video sent to a big chat), the server might automatically + schedule a message instead of sending it immediately. In such cases, this field will be + ``0`` and the relevant message will be unusable until it is actually sent. from_user (:class:`telegram.User`): Optional. Sender of the message; may be empty for messages sent to channels. For backward compatibility, if the message was sent on behalf of a chat, the field contains a fake sender user in non-channel chats. @@ -1715,6 +1721,7 @@ class Message(MaybeInaccessibleMessage): link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1780,6 +1787,7 @@ class Message(MaybeInaccessibleMessage): api_kwargs=api_kwargs, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_markdown( @@ -1793,6 +1801,7 @@ class Message(MaybeInaccessibleMessage): link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1864,6 +1873,7 @@ class Message(MaybeInaccessibleMessage): api_kwargs=api_kwargs, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_markdown_v2( @@ -1877,6 +1887,7 @@ class Message(MaybeInaccessibleMessage): link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1944,6 +1955,7 @@ class Message(MaybeInaccessibleMessage): api_kwargs=api_kwargs, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_html( @@ -1957,6 +1969,7 @@ class Message(MaybeInaccessibleMessage): link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2024,6 +2037,7 @@ class Message(MaybeInaccessibleMessage): api_kwargs=api_kwargs, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_media_group( @@ -2036,6 +2050,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2103,6 +2118,7 @@ class Message(MaybeInaccessibleMessage): caption_entities=caption_entities, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_photo( @@ -2118,6 +2134,7 @@ class Message(MaybeInaccessibleMessage): has_spoiler: Optional[bool] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -2185,6 +2202,7 @@ class Message(MaybeInaccessibleMessage): has_spoiler=has_spoiler, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -2204,6 +2222,7 @@ class Message(MaybeInaccessibleMessage): thumbnail: Optional[FileInput] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2273,6 +2292,7 @@ class Message(MaybeInaccessibleMessage): thumbnail=thumbnail, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_document( @@ -2289,6 +2309,7 @@ class Message(MaybeInaccessibleMessage): thumbnail: Optional[FileInput] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2356,6 +2377,7 @@ class Message(MaybeInaccessibleMessage): thumbnail=thumbnail, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_animation( @@ -2375,6 +2397,7 @@ class Message(MaybeInaccessibleMessage): thumbnail: Optional[FileInput] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -2446,6 +2469,7 @@ class Message(MaybeInaccessibleMessage): thumbnail=thumbnail, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -2459,6 +2483,7 @@ class Message(MaybeInaccessibleMessage): emoji: Optional[str] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2520,6 +2545,7 @@ class Message(MaybeInaccessibleMessage): emoji=emoji, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_video( @@ -2540,6 +2566,7 @@ class Message(MaybeInaccessibleMessage): thumbnail: Optional[FileInput] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -2612,6 +2639,7 @@ class Message(MaybeInaccessibleMessage): thumbnail=thumbnail, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -2627,6 +2655,7 @@ class Message(MaybeInaccessibleMessage): thumbnail: Optional[FileInput] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2692,6 +2721,7 @@ class Message(MaybeInaccessibleMessage): thumbnail=thumbnail, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_voice( @@ -2707,6 +2737,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2773,6 +2804,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id=message_thread_id, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_location( @@ -2789,6 +2821,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2856,6 +2889,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id=message_thread_id, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_venue( @@ -2874,6 +2908,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2943,6 +2978,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id=message_thread_id, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_contact( @@ -2957,6 +2993,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3022,6 +3059,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id=message_thread_id, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_poll( @@ -3046,6 +3084,7 @@ class Message(MaybeInaccessibleMessage): question_parse_mode: ODVInput[str] = DEFAULT_NONE, question_entities: Optional[Sequence["MessageEntity"]] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3119,6 +3158,7 @@ class Message(MaybeInaccessibleMessage): question_parse_mode=question_parse_mode, question_entities=question_entities, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_dice( @@ -3130,6 +3170,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3190,6 +3231,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id=message_thread_id, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_chat_action( @@ -3245,6 +3287,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3307,6 +3350,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id=message_thread_id, business_connection_id=self.business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_invoice( @@ -3338,6 +3382,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3428,6 +3473,7 @@ class Message(MaybeInaccessibleMessage): protect_content=protect_content, message_thread_id=message_thread_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def forward( @@ -3492,6 +3538,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3537,6 +3584,7 @@ class Message(MaybeInaccessibleMessage): protect_content=protect_content, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) async def reply_copy( @@ -3552,6 +3600,7 @@ class Message(MaybeInaccessibleMessage): message_thread_id: ODVInput[int] = DEFAULT_NONE, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3616,6 +3665,7 @@ class Message(MaybeInaccessibleMessage): protect_content=protect_content, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) async def edit_text( diff --git a/telegram/_messageentity.py b/telegram/_messageentity.py index 4b076d5e5..2fa5953d5 100644 --- a/telegram/_messageentity.py +++ b/telegram/_messageentity.py @@ -45,10 +45,11 @@ class MessageEntity(TelegramObject): considered equal, if their :attr:`type`, :attr:`offset` and :attr:`length` are equal. Args: - type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (@username), - :attr:`HASHTAG` (#hashtag), :attr:`CASHTAG` ($USD), :attr:`BOT_COMMAND` - (/start@jobs_bot), :attr:`URL` (https://telegram.org), - :attr:`EMAIL` (do-not-reply@telegram.org), :attr:`PHONE_NUMBER` (+1-212-555-0123), + type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (``@username``), + :attr:`HASHTAG` (``#hashtag`` or ``#hashtag@chatusername``), :attr:`CASHTAG` (``$USD`` + or ``USD@chatusername``), :attr:`BOT_COMMAND` (``/start@jobs_bot``), :attr:`URL` + (``https://telegram.org``), :attr:`EMAIL` (``do-not-reply@telegram.org``), + :attr:`PHONE_NUMBER` (``+1-212-555-0123``), :attr:`BOLD` (**bold text**), :attr:`ITALIC` (*italic text*), :attr:`UNDERLINE` (underlined text), :attr:`STRIKETHROUGH`, :attr:`SPOILER` (spoiler message), :attr:`BLOCKQUOTE` (block quotation), :attr:`CODE` (monowidth string), :attr:`PRE` @@ -74,10 +75,11 @@ class MessageEntity(TelegramObject): .. versionadded:: 20.0 Attributes: - type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (@username), - :attr:`HASHTAG` (#hashtag), :attr:`CASHTAG` ($USD), :attr:`BOT_COMMAND` - (/start@jobs_bot), :attr:`URL` (https://telegram.org), - :attr:`EMAIL` (do-not-reply@telegram.org), :attr:`PHONE_NUMBER` (+1-212-555-0123), + type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (``@username``), + :attr:`HASHTAG` (``#hashtag`` or ``#hashtag@chatusername``), :attr:`CASHTAG` (``$USD`` + or ``USD@chatusername``), :attr:`BOT_COMMAND` (``/start@jobs_bot``), :attr:`URL` + (``https://telegram.org``), :attr:`EMAIL` (``do-not-reply@telegram.org``), + :attr:`PHONE_NUMBER` (``+1-212-555-0123``), :attr:`BOLD` (**bold text**), :attr:`ITALIC` (*italic text*), :attr:`UNDERLINE` (underlined text), :attr:`STRIKETHROUGH`, :attr:`SPOILER` (spoiler message), :attr:`BLOCKQUOTE` (block quotation), :attr:`CODE` (monowidth string), :attr:`PRE` diff --git a/telegram/_messageid.py b/telegram/_messageid.py index bbfedf470..b63fbe97d 100644 --- a/telegram/_messageid.py +++ b/telegram/_messageid.py @@ -31,10 +31,16 @@ class MessageId(TelegramObject): considered equal, if their :attr:`message_id` is equal. Args: - message_id (:obj:`int`): Unique message identifier. + message_id (:obj:`int`): Unique message identifier. In specific instances + (e.g., message containing a video sent to a big chat), the server might automatically + schedule a message instead of sending it immediately. In such cases, this field will be + ``0`` and the relevant message will be unusable until it is actually sent. Attributes: - message_id (:obj:`int`): Unique message identifier. + message_id (:obj:`int`): Unique message identifier. In specific instances + (e.g., message containing a video sent to a big chat), the server might automatically + schedule a message instead of sending it immediately. In such cases, this field will be + ``0`` and the relevant message will be unusable until it is actually sent. """ __slots__ = ("message_id",) diff --git a/telegram/_payment/stars.py b/telegram/_payment/stars.py index 32678915a..b420805f5 100644 --- a/telegram/_payment/stars.py +++ b/telegram/_payment/stars.py @@ -218,12 +218,14 @@ class TransactionPartner(TelegramObject): FRAGMENT: Final[str] = constants.TransactionPartnerType.FRAGMENT """:const:`telegram.constants.TransactionPartnerType.FRAGMENT`""" - USER: Final[str] = constants.TransactionPartnerType.USER - """:const:`telegram.constants.TransactionPartnerType.USER`""" OTHER: Final[str] = constants.TransactionPartnerType.OTHER """:const:`telegram.constants.TransactionPartnerType.OTHER`""" TELEGRAM_ADS: Final[str] = constants.TransactionPartnerType.TELEGRAM_ADS """:const:`telegram.constants.TransactionPartnerType.TELEGRAM_ADS`""" + TELEGRAM_API: Final[str] = constants.TransactionPartnerType.TELEGRAM_API + """:const:`telegram.constants.TransactionPartnerType.TELEGRAM_API`""" + USER: Final[str] = constants.TransactionPartnerType.USER + """:const:`telegram.constants.TransactionPartnerType.USER`""" def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None) -> None: super().__init__(api_kwargs=api_kwargs) @@ -258,8 +260,9 @@ class TransactionPartner(TelegramObject): _class_mapping: dict[str, type[TransactionPartner]] = { cls.FRAGMENT: TransactionPartnerFragment, cls.USER: TransactionPartnerUser, - cls.OTHER: TransactionPartnerOther, cls.TELEGRAM_ADS: TransactionPartnerTelegramAds, + cls.TELEGRAM_API: TransactionPartnerTelegramApi, + cls.OTHER: TransactionPartnerOther, } if cls is TransactionPartner and data.get("type") in _class_mapping: @@ -421,6 +424,35 @@ class TransactionPartnerTelegramAds(TransactionPartner): self._freeze() +class TransactionPartnerTelegramApi(TransactionPartner): + """Describes a transaction with payment for + `paid broadcasting `_. + + Objects of this class are comparable in terms of equality. Two objects of this class are + considered equal, if their :attr:`request_count` is equal. + + .. versionadded:: NEXT.VERSION + + Args: + request_count (:obj:`int`): The number of successful requests that exceeded regular limits + and were therefore billed. + + Attributes: + type (:obj:`str`): The type of the transaction partner, + always :tg-const:`telegram.TransactionPartner.TELEGRAM_API`. + request_count (:obj:`int`): The number of successful requests that exceeded regular limits + and were therefore billed. + """ + + __slots__ = ("request_count",) + + def __init__(self, request_count: int, *, api_kwargs: Optional[JSONDict] = None) -> None: + super().__init__(type=TransactionPartner.TELEGRAM_API, api_kwargs=api_kwargs) + with self._unfrozen(): + self.request_count: int = request_count + self._id_attrs = (self.request_count,) + + class StarTransaction(TelegramObject): """Describes a Telegram Star transaction. diff --git a/telegram/_user.py b/telegram/_user.py index 9e8e1f0ea..980ce7e49 100644 --- a/telegram/_user.py +++ b/telegram/_user.py @@ -427,6 +427,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, disable_web_page_preview: Optional[bool] = None, @@ -471,6 +472,7 @@ class User(TelegramObject): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def delete_message( @@ -551,6 +553,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -597,6 +600,7 @@ class User(TelegramObject): has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -611,6 +615,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -656,6 +661,7 @@ class User(TelegramObject): caption_entities=caption_entities, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_audio( @@ -675,6 +681,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -723,6 +730,7 @@ class User(TelegramObject): thumbnail=thumbnail, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_chat_action( @@ -778,6 +786,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -822,6 +831,7 @@ class User(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_dice( @@ -834,6 +844,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -873,6 +884,7 @@ class User(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_document( @@ -890,6 +902,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -936,6 +949,7 @@ class User(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_game( @@ -948,6 +962,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -987,6 +1002,7 @@ class User(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_invoice( @@ -1018,6 +1034,7 @@ class User(TelegramObject): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1086,6 +1103,7 @@ class User(TelegramObject): protect_content=protect_content, message_thread_id=message_thread_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_location( @@ -1103,6 +1121,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1149,6 +1168,7 @@ class User(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_animation( @@ -1169,6 +1189,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -1219,6 +1240,7 @@ class User(TelegramObject): thumbnail=thumbnail, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -1233,6 +1255,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1273,6 +1296,7 @@ class User(TelegramObject): emoji=emoji, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_video( @@ -1294,6 +1318,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -1345,6 +1370,7 @@ class User(TelegramObject): has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -1365,6 +1391,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1413,6 +1440,7 @@ class User(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_video_note( @@ -1428,6 +1456,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1472,6 +1501,7 @@ class User(TelegramObject): thumbnail=thumbnail, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_voice( @@ -1488,6 +1518,7 @@ class User(TelegramObject): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1533,6 +1564,7 @@ class User(TelegramObject): message_thread_id=message_thread_id, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_poll( @@ -1558,6 +1590,7 @@ class User(TelegramObject): question_parse_mode: ODVInput[str] = DEFAULT_NONE, question_entities: Optional[Sequence["MessageEntity"]] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1610,6 +1643,7 @@ class User(TelegramObject): question_parse_mode=question_parse_mode, question_entities=question_entities, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_copy( @@ -1625,6 +1659,7 @@ class User(TelegramObject): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1667,6 +1702,7 @@ class User(TelegramObject): protect_content=protect_content, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) async def copy_message( @@ -1682,6 +1718,7 @@ class User(TelegramObject): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -1724,6 +1761,7 @@ class User(TelegramObject): protect_content=protect_content, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_copies( diff --git a/telegram/constants.py b/telegram/constants.py index cffe79880..5ff4b8147 100644 --- a/telegram/constants.py +++ b/telegram/constants.py @@ -152,7 +152,7 @@ class _AccentColor(NamedTuple): #: :data:`telegram.__bot_api_version_info__`. #: #: .. versionadded:: 20.0 -BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=10) +BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=11) #: :obj:`str`: Telegram Bot API #: version supported by this version of `python-telegram-bot`. Also available as #: :data:`telegram.__bot_api_version__`. @@ -1154,6 +1154,14 @@ class FloodLimit(IntEnum): """:obj:`int`: The number of messages that can roughly be sent to a particular group within one minute. """ + PAID_MESSAGES_PER_SECOND = 1000 + """:obj:`int`: The number of messages that can be sent per second when paying with the bot's + Telegram Star balance. See e.g. parameter + :paramref:`~telegram.Bot.send_message.allow_paid_broadcast` of + :meth:`~telegram.Bot.send_message`. + + .. versionadded:: NEXT.VERSION + """ class ForumIconColor(IntEnum): @@ -1261,15 +1269,23 @@ class InlineKeyboardButtonLimit(IntEnum): __slots__ = () MIN_CALLBACK_DATA = 1 - """:obj:`int`: Minimum value allowed for + """:obj:`int`: Minimum length allowed for :paramref:`~telegram.InlineKeyboardButton.callback_data` parameter of :class:`telegram.InlineKeyboardButton` """ MAX_CALLBACK_DATA = 64 - """:obj:`int`: Maximum value allowed for + """:obj:`int`: Maximum length allowed for :paramref:`~telegram.InlineKeyboardButton.callback_data` parameter of :class:`telegram.InlineKeyboardButton` """ + MIN_COPY_TEXT = 1 + """:obj:`int`: Minimum length allowed for + :paramref:`~telegram.CopyTextButton.text` parameter of :class:`telegram.CopyTextButton` + """ + MAX_COPY_TEXT = 256 + """:obj:`int`: Maximum length allowed for + :paramref:`~telegram.CopyTextButton.text` parameter of :class:`telegram.CopyTextButton` + """ class InlineKeyboardMarkupLimit(IntEnum): @@ -2592,12 +2608,18 @@ class TransactionPartnerType(StringEnum): FRAGMENT = "fragment" """:obj:`str`: Withdrawal transaction with Fragment.""" - USER = "user" - """:obj:`str`: Transaction with a user.""" OTHER = "other" """:obj:`str`: Transaction with unknown source or recipient.""" TELEGRAM_ADS = "telegram_ads" """:obj:`str`: Transaction with Telegram Ads.""" + TELEGRAM_API = "telegram_api" + """:obj:`str`: Transaction with with payment for + `paid broadcasting `_. + + ..versionadded:: NEXT.VERSION + """ + USER = "user" + """:obj:`str`: Transaction with a user.""" class ParseMode(StringEnum): diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py index 2a4cdb2e4..66921e415 100644 --- a/telegram/ext/_extbot.py +++ b/telegram/ext/_extbot.py @@ -592,6 +592,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -624,6 +625,7 @@ class ExtBot(Bot, Generic[RLARGS]): api_kwargs=api_kwargs, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) if isinstance(result, Message): self._insert_callback_data(result) @@ -801,6 +803,7 @@ class ExtBot(Bot, Generic[RLARGS]): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, show_caption_above_media: Optional[bool] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -832,6 +835,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, ) async def copy_messages( @@ -2398,6 +2402,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -2436,6 +2441,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -2457,6 +2463,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2493,6 +2500,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_chat_action( @@ -2535,6 +2543,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2567,6 +2576,7 @@ class ExtBot(Bot, Generic[RLARGS]): business_connection_id=business_connection_id, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_dice( @@ -2580,6 +2590,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2607,6 +2618,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_document( @@ -2625,6 +2637,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2659,6 +2672,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_game( @@ -2672,6 +2686,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2699,6 +2714,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_invoice( @@ -2731,6 +2747,7 @@ class ExtBot(Bot, Generic[RLARGS]): message_thread_id: Optional[int] = None, reply_parameters: Optional["ReplyParameters"] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2777,6 +2794,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_location( @@ -2795,6 +2813,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2829,6 +2848,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_media_group( @@ -2843,6 +2863,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -2875,6 +2896,7 @@ class ExtBot(Bot, Generic[RLARGS]): parse_mode=parse_mode, caption_entities=caption_entities, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_message( @@ -2891,6 +2913,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, disable_web_page_preview: Optional[bool] = None, reply_to_message_id: Optional[int] = None, @@ -2923,6 +2946,7 @@ class ExtBot(Bot, Generic[RLARGS]): api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), link_preview_options=link_preview_options, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_photo( @@ -2940,6 +2964,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -2974,6 +2999,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -3001,6 +3027,7 @@ class ExtBot(Bot, Generic[RLARGS]): question_parse_mode: ODVInput[str] = DEFAULT_NONE, question_entities: Optional[Sequence["MessageEntity"]] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3041,6 +3068,7 @@ class ExtBot(Bot, Generic[RLARGS]): question_parse_mode=question_parse_mode, question_entities=question_entities, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_sticker( @@ -3055,6 +3083,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3083,6 +3112,7 @@ class ExtBot(Bot, Generic[RLARGS]): emoji=emoji, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_venue( @@ -3103,6 +3133,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3139,6 +3170,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_video( @@ -3161,6 +3193,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, show_caption_above_media: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, @@ -3200,6 +3233,7 @@ class ExtBot(Bot, Generic[RLARGS]): pool_timeout=pool_timeout, api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, show_caption_above_media=show_caption_above_media, ) @@ -3217,6 +3251,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3249,6 +3284,7 @@ class ExtBot(Bot, Generic[RLARGS]): api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def send_voice( @@ -3266,6 +3302,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_parameters: Optional["ReplyParameters"] = None, business_connection_id: Optional[str] = None, message_effect_id: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, reply_to_message_id: Optional[int] = None, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, @@ -3299,6 +3336,7 @@ class ExtBot(Bot, Generic[RLARGS]): api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), business_connection_id=business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast, ) async def set_chat_administrator_custom_title( @@ -4232,6 +4270,7 @@ class ExtBot(Bot, Generic[RLARGS]): reply_markup: Optional[ReplyMarkup] = None, business_connection_id: Optional[str] = None, payload: Optional[str] = None, + allow_paid_broadcast: Optional[bool] = None, *, allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE, reply_to_message_id: Optional[int] = None, @@ -4263,6 +4302,7 @@ class ExtBot(Bot, Generic[RLARGS]): api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args), business_connection_id=business_connection_id, payload=payload, + allow_paid_broadcast=allow_paid_broadcast, ) async def create_chat_subscription_invite_link( diff --git a/tests/_inline/test_inlinekeyboardbutton.py b/tests/_inline/test_inlinekeyboardbutton.py index 6e406f3ec..a71e77489 100644 --- a/tests/_inline/test_inlinekeyboardbutton.py +++ b/tests/_inline/test_inlinekeyboardbutton.py @@ -21,6 +21,7 @@ import pytest from telegram import ( CallbackGame, + CopyTextButton, InlineKeyboardButton, LoginUrl, SwitchInlineQueryChosenChat, @@ -46,6 +47,7 @@ def inline_keyboard_button(): switch_inline_query_chosen_chat=( InlineKeyboardButtonTestBase.switch_inline_query_chosen_chat ), + copy_text=InlineKeyboardButtonTestBase.copy_text, ) @@ -60,6 +62,7 @@ class InlineKeyboardButtonTestBase: login_url = LoginUrl("http://google.com") web_app = WebAppInfo(url="https://example.com") switch_inline_query_chosen_chat = SwitchInlineQueryChosenChat("a_bot", True, False, True, True) + copy_text = CopyTextButton("python-telegram-bot") class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase): @@ -86,6 +89,7 @@ class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase): inline_keyboard_button.switch_inline_query_chosen_chat == self.switch_inline_query_chosen_chat ) + assert inline_keyboard_button.copy_text == self.copy_text def test_to_dict(self, inline_keyboard_button): inline_keyboard_button_dict = inline_keyboard_button.to_dict() @@ -115,6 +119,9 @@ class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase): inline_keyboard_button_dict["switch_inline_query_chosen_chat"] == inline_keyboard_button.switch_inline_query_chosen_chat.to_dict() ) + assert ( + inline_keyboard_button_dict["copy_text"] == inline_keyboard_button.copy_text.to_dict() + ) def test_de_json(self, offline_bot): json_dict = { @@ -128,6 +135,7 @@ class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase): "login_url": self.login_url.to_dict(), "pay": self.pay, "switch_inline_query_chosen_chat": self.switch_inline_query_chosen_chat.to_dict(), + "copy_text": self.copy_text.to_dict(), } inline_keyboard_button = InlineKeyboardButton.de_json(json_dict, None) @@ -149,6 +157,7 @@ class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase): inline_keyboard_button.switch_inline_query_chosen_chat == self.switch_inline_query_chosen_chat ) + assert inline_keyboard_button.copy_text == self.copy_text none = InlineKeyboardButton.de_json({}, offline_bot) assert none is None diff --git a/tests/test_bot.py b/tests/test_bot.py index 7f060fb09..8ff0dec8d 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -2253,6 +2253,16 @@ class TestBotWithoutRequest: monkeypatch.setattr(offline_bot.request, "post", make_assertion) assert await offline_bot.send_message(2, "text", message_effect_id=42) + async def test_allow_paid_broadcast_argument(self, offline_bot, monkeypatch): + """We can't test every single method easily, so we just test one. Our linting will catch + any unused args with the others.""" + + async def make_assertion(url, request_data: RequestData, *args, **kwargs): + return request_data.parameters.get("allow_paid_broadcast") == 42 + + monkeypatch.setattr(offline_bot.request, "post", make_assertion) + assert await offline_bot.send_message(2, "text", allow_paid_broadcast=42) + async def test_get_business_connection(self, offline_bot, monkeypatch): bci = "42" user = User(1, "first", False) diff --git a/tests/test_copytextbutton.py b/tests/test_copytextbutton.py new file mode 100644 index 000000000..7092456d4 --- /dev/null +++ b/tests/test_copytextbutton.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# +# A library that provides a Python interface to the Telegram Bot API +# Copyright (C) 2015-2024 +# Leandro Toledo de Souza +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser Public License for more details. +# +# You should have received a copy of the GNU Lesser Public License +# along with this program. If not, see [http://www.gnu.org/licenses/]. + +import pytest + +from telegram import BotCommand, CopyTextButton +from tests.auxil.slots import mro_slots + + +@pytest.fixture(scope="module") +def copy_text_button(): + return CopyTextButton(text=CopyTextButtonTestBase.text) + + +class CopyTextButtonTestBase: + text = "This is some text" + + +class TestCopyTextButtonWithoutRequest(CopyTextButtonTestBase): + def test_slot_behaviour(self, copy_text_button): + for attr in copy_text_button.__slots__: + assert getattr(copy_text_button, attr, "err") != "err", f"got extra slot '{attr}'" + assert len(mro_slots(copy_text_button)) == len( + set(mro_slots(copy_text_button)) + ), "duplicate slot" + + def test_de_json(self, offline_bot): + json_dict = {"text": self.text} + copy_text_button = CopyTextButton.de_json(json_dict, offline_bot) + assert copy_text_button.api_kwargs == {} + + assert copy_text_button.text == self.text + assert CopyTextButton.de_json(None, offline_bot) is None + + def test_to_dict(self, copy_text_button): + copy_text_button_dict = copy_text_button.to_dict() + + assert isinstance(copy_text_button_dict, dict) + assert copy_text_button_dict["text"] == copy_text_button.text + + def test_equality(self): + a = CopyTextButton(self.text) + b = CopyTextButton(self.text) + c = CopyTextButton("text") + d = BotCommand("start", "description") + + assert a == b + assert hash(a) == hash(b) + + assert a != c + assert hash(a) != hash(c) + + assert a != d + assert hash(a) != hash(d) diff --git a/tests/test_stars.py b/tests/test_stars.py index d812c7cbb..12329b62e 100644 --- a/tests/test_stars.py +++ b/tests/test_stars.py @@ -36,6 +36,7 @@ from telegram import ( TransactionPartnerFragment, TransactionPartnerOther, TransactionPartnerTelegramAds, + TransactionPartnerTelegramApi, TransactionPartnerUser, User, ) @@ -78,11 +79,6 @@ def transaction_partner_user(): ) -@pytest.fixture -def transaction_partner_other(): - return TransactionPartnerOther() - - def transaction_partner_fragment(): return TransactionPartnerFragment( withdrawal_state=withdrawal_state_succeeded(), @@ -114,8 +110,9 @@ def star_transactions(): params=[ TransactionPartner.FRAGMENT, TransactionPartner.OTHER, - TransactionPartner.USER, TransactionPartner.TELEGRAM_ADS, + TransactionPartner.TELEGRAM_API, + TransactionPartner.USER, ], ) def tp_scope_type(request): @@ -127,14 +124,16 @@ def tp_scope_type(request): params=[ TransactionPartnerFragment, TransactionPartnerOther, - TransactionPartnerUser, TransactionPartnerTelegramAds, + TransactionPartnerTelegramApi, + TransactionPartnerUser, ], ids=[ TransactionPartner.FRAGMENT, TransactionPartner.OTHER, - TransactionPartner.USER, TransactionPartner.TELEGRAM_ADS, + TransactionPartner.TELEGRAM_API, + TransactionPartner.USER, ], ) def tp_scope_class(request): @@ -146,14 +145,16 @@ def tp_scope_class(request): params=[ (TransactionPartnerFragment, TransactionPartner.FRAGMENT), (TransactionPartnerOther, TransactionPartner.OTHER), - (TransactionPartnerUser, TransactionPartner.USER), (TransactionPartnerTelegramAds, TransactionPartner.TELEGRAM_ADS), + (TransactionPartnerTelegramApi, TransactionPartner.TELEGRAM_API), + (TransactionPartnerUser, TransactionPartner.USER), ], ids=[ TransactionPartner.FRAGMENT, TransactionPartner.OTHER, - TransactionPartner.USER, TransactionPartner.TELEGRAM_ADS, + TransactionPartner.TELEGRAM_API, + TransactionPartner.USER, ], ) def tp_scope_class_and_type(request): @@ -169,6 +170,7 @@ def transaction_partner(tp_scope_class_and_type): "invoice_payload": TransactionPartnerTestBase.invoice_payload, "withdrawal_state": TransactionPartnerTestBase.withdrawal_state.to_dict(), "user": TransactionPartnerTestBase.user.to_dict(), + "request_count": TransactionPartnerTestBase.request_count, }, bot=None, ) @@ -382,6 +384,7 @@ class TransactionPartnerTestBase: withdrawal_state = withdrawal_state_succeeded() user = transaction_partner_user().user invoice_payload = "payload" + request_count = 42 class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase): @@ -400,11 +403,15 @@ class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase): "invoice_payload": self.invoice_payload, "withdrawal_state": self.withdrawal_state.to_dict(), "user": self.user.to_dict(), + "request_count": self.request_count, } tp = TransactionPartner.de_json(json_dict, offline_bot) - assert set(tp.api_kwargs.keys()) == {"user", "withdrawal_state", "invoice_payload"} - set( - cls.__slots__ - ) + assert set(tp.api_kwargs.keys()) == { + "user", + "withdrawal_state", + "invoice_payload", + "request_count", + } - set(cls.__slots__) assert isinstance(tp, TransactionPartner) assert type(tp) is cls @@ -414,6 +421,8 @@ class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase): if "user" in cls.__slots__: assert tp.user == self.user assert tp.invoice_payload == self.invoice_payload + if "request_count" in cls.__slots__: + assert tp.request_count == self.request_count assert cls.de_json(None, offline_bot) is None assert TransactionPartner.de_json({}, offline_bot) is None @@ -424,12 +433,14 @@ class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase): "invoice_payload": self.invoice_payload, "withdrawal_state": self.withdrawal_state.to_dict(), "user": self.user.to_dict(), + "request_count": self.request_count, } tp = TransactionPartner.de_json(json_dict, offline_bot) assert tp.api_kwargs == { "withdrawal_state": self.withdrawal_state.to_dict(), "user": self.user.to_dict(), "invoice_payload": self.invoice_payload, + "request_count": self.request_count, } assert type(tp) is TransactionPartner @@ -443,6 +454,7 @@ class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase): "invoice_payload": self.invoice_payload, "withdrawal_state": self.withdrawal_state.to_dict(), "user": self.user.to_dict(), + "request_count": self.request_count, } assert type(tp_scope_class.de_json(json_dict, offline_bot)) is tp_scope_class @@ -494,6 +506,14 @@ class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase): assert c != f assert hash(c) != hash(f) + if hasattr(c, "request_count"): + json_dict = c.to_dict() + json_dict["request_count"] = 1 + f = c.__class__.de_json(json_dict, offline_bot) + + assert c != f + assert hash(c) != hash(f) + class RevenueWithdrawalStateTestBase: date = datetime.datetime(2024, 1, 1, 0, 0, 0, 0, tzinfo=UTC)