mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-19 07:35:19 +00:00
Full Support for Bot API 8.3 (#4676)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> Co-authored-by: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com>
This commit is contained in:
+2
-2
@@ -11,7 +11,7 @@
|
||||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-8.2-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-8.3-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API version
|
||||
|
||||
@@ -81,7 +81,7 @@ After installing_ the library, be sure to check out the section on `working with
|
||||
Telegram API support
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All types and methods of the Telegram Bot API **8.2** are natively supported by this library.
|
||||
All types and methods of the Telegram Bot API **8.3** are natively supported by this library.
|
||||
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
|
||||
|
||||
Notable Features
|
||||
|
||||
@@ -27,6 +27,7 @@ Your bot can accept payments from Telegram users. Please see the `introduction t
|
||||
telegram.successfulpayment
|
||||
telegram.transactionpartner
|
||||
telegram.transactionpartneraffiliateprogram
|
||||
telegram.transactionpartnerchat
|
||||
telegram.transactionpartnerfragment
|
||||
telegram.transactionpartnerother
|
||||
telegram.transactionpartnertelegramads
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
TransactionPartnerChat
|
||||
======================
|
||||
|
||||
.. autoclass:: telegram.TransactionPartnerChat
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:inherited-members: TransactionPartner
|
||||
@@ -238,6 +238,7 @@ __all__ = (
|
||||
"TextQuote",
|
||||
"TransactionPartner",
|
||||
"TransactionPartnerAffiliateProgram",
|
||||
"TransactionPartnerChat",
|
||||
"TransactionPartnerFragment",
|
||||
"TransactionPartnerOther",
|
||||
"TransactionPartnerTelegramAds",
|
||||
@@ -275,6 +276,7 @@ from telegram._payment.stars.startransactions import StarTransaction, StarTransa
|
||||
from telegram._payment.stars.transactionpartner import (
|
||||
TransactionPartner,
|
||||
TransactionPartnerAffiliateProgram,
|
||||
TransactionPartnerChat,
|
||||
TransactionPartnerFragment,
|
||||
TransactionPartnerOther,
|
||||
TransactionPartnerTelegramAds,
|
||||
|
||||
+46
-7
@@ -1218,6 +1218,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: Optional[int] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -1242,6 +1243,10 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
original message was sent (or channel username in the format ``@channelusername``).
|
||||
message_id (:obj:`int`): Message identifier in the chat specified in
|
||||
:paramref:`from_chat_id`.
|
||||
video_start_timestamp (:obj:`int`, optional): New start timestamp for the
|
||||
forwarded video in the message
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
disable_notification (:obj:`bool`, optional): |disable_notification|
|
||||
protect_content (:obj:`bool`, optional): |protect_content|
|
||||
|
||||
@@ -1260,6 +1265,7 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
"chat_id": chat_id,
|
||||
"from_chat_id": from_chat_id,
|
||||
"message_id": message_id,
|
||||
"video_start_timestamp": video_start_timestamp,
|
||||
}
|
||||
|
||||
return await self._send_message(
|
||||
@@ -1955,6 +1961,8 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
message_effect_id: Optional[str] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
cover: Optional[FileInput] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
@@ -2002,6 +2010,13 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
|time-period-input|
|
||||
width (:obj:`int`, optional): Video width.
|
||||
height (:obj:`int`, optional): Video height.
|
||||
cover (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): Cover for the video in the message. |fileinputnopath|
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
start_timestamp (:obj:`int`, optional): Start timestamp for the video in the message.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
caption (:obj:`str`, optional): Video caption (may also be used when resending videos
|
||||
by file_id), 0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH`
|
||||
characters after entities parsing.
|
||||
@@ -2088,6 +2103,8 @@ class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
|
||||
"width": width,
|
||||
"height": height,
|
||||
"supports_streaming": supports_streaming,
|
||||
"cover": self._parse_file_input(cover, attach=True) if cover else None,
|
||||
"start_timestamp": start_timestamp,
|
||||
"thumbnail": self._parse_file_input(thumbnail, attach=True) if thumbnail else None,
|
||||
"has_spoiler": has_spoiler,
|
||||
"show_caption_above_media": show_caption_above_media,
|
||||
@@ -7977,6 +7994,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
@@ -7996,6 +8014,10 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
from_chat_id (:obj:`int` | :obj:`str`): Unique identifier for the chat where the
|
||||
original message was sent (or channel username in the format ``@channelusername``).
|
||||
message_id (:obj:`int`): Message identifier in the chat specified in from_chat_id.
|
||||
video_start_timestamp (:obj:`int`, optional): New start timestamp for the
|
||||
copied video in the message
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
caption (:obj:`str`, optional): New caption for media,
|
||||
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
|
||||
entities parsing. If not specified, the original caption is kept.
|
||||
@@ -8086,6 +8108,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
"reply_parameters": reply_parameters,
|
||||
"show_caption_above_media": show_caption_above_media,
|
||||
"allow_paid_broadcast": allow_paid_broadcast,
|
||||
"video_start_timestamp": video_start_timestamp,
|
||||
}
|
||||
|
||||
result = await self._post(
|
||||
@@ -9277,7 +9300,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
Use this method to change the chosen reactions on a message. Service messages can't be
|
||||
Use this method to change the chosen reactions on a message. Service messages of some types
|
||||
can't be
|
||||
reacted to. Automatically forwarded messages from a channel to its discussion group have
|
||||
the same available reactions as messages in the channel. Bots can't use paid reactions.
|
||||
|
||||
@@ -9807,7 +9831,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Gifts:
|
||||
"""Returns the list of gifts that can be sent by the bot to users.
|
||||
"""Returns the list of gifts that can be sent by the bot to users and channel chats.
|
||||
Requires no parameters.
|
||||
|
||||
.. versionadded:: 21.8
|
||||
@@ -9831,12 +9855,13 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
|
||||
async def send_gift(
|
||||
self,
|
||||
user_id: int,
|
||||
gift_id: Union[str, Gift],
|
||||
user_id: Optional[int] = None,
|
||||
gift_id: Union[str, Gift] = None, # type: ignore
|
||||
text: Optional[str] = None,
|
||||
text_parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
text_entities: Optional[Sequence["MessageEntity"]] = None,
|
||||
pay_for_upgrade: Optional[bool] = None,
|
||||
chat_id: Optional[Union[str, int]] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -9844,15 +9869,23 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""Sends a gift to the given user.
|
||||
The gift can't be converted to Telegram Stars by the user
|
||||
"""Sends a gift to the given user or channel chat.
|
||||
The gift can't be converted to Telegram Stars by the receiver.
|
||||
|
||||
.. versionadded:: 21.8
|
||||
|
||||
Args:
|
||||
user_id (:obj:`int`): Unique identifier of the target user that will receive the gift
|
||||
user_id (:obj:`int`, optional): Required if :paramref:`chat_id` is not specified.
|
||||
Unique identifier of the target user that will receive the gift.
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
Now optional.
|
||||
gift_id (:obj:`str` | :class:`~telegram.Gift`): Identifier of the gift or a
|
||||
:class:`~telegram.Gift` object
|
||||
chat_id (:obj:`int` | :obj:`str`, optional): Required if :paramref:`user_id`
|
||||
is not specified. |chat_id_channel| It will receive the gift.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
text (:obj:`str`, optional): Text that will be shown along with the gift;
|
||||
0- :tg-const:`telegram.constants.GiftLimit.MAX_TEXT_LENGTH` characters
|
||||
text_parse_mode (:obj:`str`, optional): Mode for parsing entities.
|
||||
@@ -9879,6 +9912,11 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
Raises:
|
||||
:class:`telegram.error.TelegramError`
|
||||
"""
|
||||
# TODO: Remove when stability policy allows, tags: deprecated NEXT.VERSION
|
||||
# also we should raise a deprecation warnung if anything is passed by
|
||||
# position since it will be moved, not sure how
|
||||
if gift_id is None:
|
||||
raise TypeError("Missing required argument `gift_id`.")
|
||||
data: JSONDict = {
|
||||
"user_id": user_id,
|
||||
"gift_id": gift_id.id if isinstance(gift_id, Gift) else gift_id,
|
||||
@@ -9886,6 +9924,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
"text_parse_mode": text_parse_mode,
|
||||
"text_entities": text_entities,
|
||||
"pay_for_upgrade": pay_for_upgrade,
|
||||
"chat_id": chat_id,
|
||||
}
|
||||
return await self._post(
|
||||
"sendGift",
|
||||
|
||||
@@ -831,6 +831,7 @@ class CallbackQuery(TelegramObject):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
@@ -864,6 +865,7 @@ class CallbackQuery(TelegramObject):
|
||||
chat_id=chat_id,
|
||||
caption=caption,
|
||||
parse_mode=parse_mode,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
|
||||
+22
-2
@@ -1940,6 +1940,8 @@ class _ChatBase(TelegramObject):
|
||||
message_effect_id: Optional[str] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
cover: Optional[FileInput] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -1978,6 +1980,8 @@ class _ChatBase(TelegramObject):
|
||||
parse_mode=parse_mode,
|
||||
supports_streaming=supports_streaming,
|
||||
thumbnail=thumbnail,
|
||||
cover=cover,
|
||||
start_timestamp=start_timestamp,
|
||||
api_kwargs=api_kwargs,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
caption_entities=caption_entities,
|
||||
@@ -2199,6 +2203,7 @@ class _ChatBase(TelegramObject):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -2225,6 +2230,7 @@ class _ChatBase(TelegramObject):
|
||||
from_chat_id=from_chat_id,
|
||||
message_id=message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
@@ -2257,6 +2263,7 @@ class _ChatBase(TelegramObject):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -2283,6 +2290,7 @@ class _ChatBase(TelegramObject):
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
@@ -2398,6 +2406,7 @@ class _ChatBase(TelegramObject):
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: Optional[int] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2423,6 +2432,7 @@ class _ChatBase(TelegramObject):
|
||||
chat_id=self.id,
|
||||
from_chat_id=from_chat_id,
|
||||
message_id=message_id,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
disable_notification=disable_notification,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
@@ -2440,6 +2450,7 @@ class _ChatBase(TelegramObject):
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: Optional[int] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -2466,6 +2477,7 @@ class _ChatBase(TelegramObject):
|
||||
from_chat_id=self.id,
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
disable_notification=disable_notification,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
@@ -3462,18 +3474,25 @@ class _ChatBase(TelegramObject):
|
||||
|
||||
await bot.send_gift(user_id=update.effective_chat.id, *args, **kwargs )
|
||||
|
||||
or::
|
||||
|
||||
await bot.send_gift(chat_id=update.effective_chat.id, *args, **kwargs )
|
||||
|
||||
For the documentation of the arguments, please see :meth:`telegram.Bot.send_gift`.
|
||||
|
||||
Caution:
|
||||
Can only work, if the chat is a private chat, see :attr:`type`.
|
||||
Will only work if the chat is a private or channel chat, see :attr:`type`.
|
||||
|
||||
.. versionadded:: 21.8
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
|
||||
Added support for channel chats.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().send_gift(
|
||||
user_id=self.id,
|
||||
gift_id=gift_id,
|
||||
text=text,
|
||||
text_parse_mode=text_parse_mode,
|
||||
@@ -3484,6 +3503,7 @@ class _ChatBase(TelegramObject):
|
||||
connect_timeout=connect_timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
api_kwargs=api_kwargs,
|
||||
**{"chat_id" if self.type == Chat.CHANNEL else "user_id": self.id},
|
||||
)
|
||||
|
||||
async def verify(
|
||||
|
||||
@@ -200,6 +200,9 @@ class ChatFullInfo(_ChatBase):
|
||||
sent or forwarded to the channel chat. The field is available only for channel chats.
|
||||
|
||||
.. versionadded:: 21.4
|
||||
can_send_gift (:obj:`bool`, optional): :obj:`True`, if gifts can be sent to the chat.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
id (:obj:`int`): Unique identifier for this chat.
|
||||
@@ -354,6 +357,9 @@ class ChatFullInfo(_ChatBase):
|
||||
sent or forwarded to the channel chat. The field is available only for channel chats.
|
||||
|
||||
.. versionadded:: 21.4
|
||||
can_send_gift (:obj:`bool`): Optional. :obj:`True`, if gifts can be sent to the chat.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
.. _accent colors: https://core.telegram.org/bots/api#accent-colors
|
||||
.. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups
|
||||
@@ -369,6 +375,7 @@ class ChatFullInfo(_ChatBase):
|
||||
"business_intro",
|
||||
"business_location",
|
||||
"business_opening_hours",
|
||||
"can_send_gift",
|
||||
"can_send_paid_media",
|
||||
"can_set_sticker_set",
|
||||
"custom_emoji_sticker_set_name",
|
||||
@@ -445,6 +452,7 @@ class ChatFullInfo(_ChatBase):
|
||||
linked_chat_id: Optional[int] = None,
|
||||
location: Optional[ChatLocation] = None,
|
||||
can_send_paid_media: Optional[bool] = None,
|
||||
can_send_gift: Optional[bool] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
@@ -510,6 +518,7 @@ class ChatFullInfo(_ChatBase):
|
||||
self.business_location: Optional[BusinessLocation] = business_location
|
||||
self.business_opening_hours: Optional[BusinessOpeningHours] = business_opening_hours
|
||||
self.can_send_paid_media: Optional[bool] = can_send_paid_media
|
||||
self.can_send_gift: Optional[bool] = can_send_gift
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatFullInfo":
|
||||
|
||||
@@ -214,6 +214,13 @@ class InputPaidMediaVideo(InputPaidMedia):
|
||||
Lastly you can pass an existing :class:`telegram.Video` object to send.
|
||||
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): |thumbdocstringnopath|
|
||||
cover (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): Cover for the video in the message. |fileinputnopath|
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
start_timestamp (:obj:`int`, optional): Start timestamp for the video in the message
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
width (:obj:`int`, optional): Video width.
|
||||
height (:obj:`int`, optional): Video height.
|
||||
duration (:obj:`int`, optional): Video duration in seconds.
|
||||
@@ -225,6 +232,13 @@ class InputPaidMediaVideo(InputPaidMedia):
|
||||
:tg-const:`telegram.constants.InputPaidMediaType.VIDEO`.
|
||||
media (:obj:`str` | :class:`telegram.InputFile`): Video to send.
|
||||
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
|
||||
cover (:class:`telegram.InputFile`): Optional. Cover for the video in the message.
|
||||
|fileinputnopath|
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
start_timestamp (:obj:`int`): Optional. Start timestamp for the video in the message
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
width (:obj:`int`): Optional. Video width.
|
||||
height (:obj:`int`): Optional. Video height.
|
||||
duration (:obj:`int`): Optional. Video duration in seconds.
|
||||
@@ -232,7 +246,15 @@ class InputPaidMediaVideo(InputPaidMedia):
|
||||
suitable for streaming.
|
||||
"""
|
||||
|
||||
__slots__ = ("duration", "height", "supports_streaming", "thumbnail", "width")
|
||||
__slots__ = (
|
||||
"cover",
|
||||
"duration",
|
||||
"height",
|
||||
"start_timestamp",
|
||||
"supports_streaming",
|
||||
"thumbnail",
|
||||
"width",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -242,6 +264,8 @@ class InputPaidMediaVideo(InputPaidMedia):
|
||||
height: Optional[int] = None,
|
||||
duration: Optional[int] = None,
|
||||
supports_streaming: Optional[bool] = None,
|
||||
cover: Optional[FileInput] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
@@ -264,6 +288,10 @@ class InputPaidMediaVideo(InputPaidMedia):
|
||||
self.height: Optional[int] = height
|
||||
self.duration: Optional[int] = duration
|
||||
self.supports_streaming: Optional[bool] = supports_streaming
|
||||
self.cover: Optional[Union[InputFile, str]] = (
|
||||
parse_file_input(cover, attach=True, local_mode=True) if cover else None
|
||||
)
|
||||
self.start_timestamp: Optional[int] = start_timestamp
|
||||
|
||||
|
||||
class InputMediaAnimation(InputMedia):
|
||||
@@ -536,6 +564,13 @@ class InputMediaVideo(InputMedia):
|
||||
optional): |thumbdocstringnopath|
|
||||
|
||||
.. versionadded:: 20.2
|
||||
cover (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): Cover for the video in the message. |fileinputnopath|
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
start_timestamp (:obj:`int`, optional): Start timestamp for the video in the message
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
|
||||
|
||||
.. versionadded:: 21.3
|
||||
@@ -568,13 +603,22 @@ class InputMediaVideo(InputMedia):
|
||||
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
|
||||
|
||||
.. versionadded:: 21.3
|
||||
cover (:class:`telegram.InputFile`): Optional. Cover for the video in the message.
|
||||
|fileinputnopath|
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
start_timestamp (:obj:`int`): Optional. Start timestamp for the video in the message
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"cover",
|
||||
"duration",
|
||||
"has_spoiler",
|
||||
"height",
|
||||
"show_caption_above_media",
|
||||
"start_timestamp",
|
||||
"supports_streaming",
|
||||
"thumbnail",
|
||||
"width",
|
||||
@@ -594,6 +638,8 @@ class InputMediaVideo(InputMedia):
|
||||
has_spoiler: Optional[bool] = None,
|
||||
thumbnail: Optional[FileInput] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
cover: Optional[FileInput] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
@@ -625,6 +671,10 @@ class InputMediaVideo(InputMedia):
|
||||
self.supports_streaming: Optional[bool] = supports_streaming
|
||||
self.has_spoiler: Optional[bool] = has_spoiler
|
||||
self.show_caption_above_media: Optional[bool] = show_caption_above_media
|
||||
self.cover: Optional[Union[InputFile, str]] = (
|
||||
parse_file_input(cover, attach=True, local_mode=True) if cover else None
|
||||
)
|
||||
self.start_timestamp: Optional[int] = start_timestamp
|
||||
|
||||
|
||||
class InputMediaAudio(InputMedia):
|
||||
|
||||
@@ -17,12 +17,17 @@
|
||||
# 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 Video."""
|
||||
from typing import Optional
|
||||
from collections.abc import Sequence
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from telegram._files._basethumbedmedium import _BaseThumbedMedium
|
||||
from telegram._files.photosize import PhotoSize
|
||||
from telegram._utils.argumentparsing import de_list_optional, parse_sequence_arg
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot
|
||||
|
||||
|
||||
class Video(_BaseThumbedMedium):
|
||||
"""This object represents a video file.
|
||||
@@ -48,6 +53,13 @@ class Video(_BaseThumbedMedium):
|
||||
thumbnail (:class:`telegram.PhotoSize`, optional): Video thumbnail.
|
||||
|
||||
.. versionadded:: 20.2
|
||||
cover (Sequence[:class:`telegram.PhotoSize`], optional): Available sizes of the cover of
|
||||
the video in the message.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
start_timestamp (:obj:`int`, optional): Timestamp in seconds from which the video
|
||||
will play in the message
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
@@ -64,9 +76,24 @@ class Video(_BaseThumbedMedium):
|
||||
thumbnail (:class:`telegram.PhotoSize`): Optional. Video thumbnail.
|
||||
|
||||
.. versionadded:: 20.2
|
||||
cover (tuple[:class:`telegram.PhotoSize`]): Optional, Available sizes of the cover of
|
||||
the video in the message.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
start_timestamp (:obj:`int`): Optional, Timestamp in seconds from which the video
|
||||
will play in the message
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
|
||||
__slots__ = ("duration", "file_name", "height", "mime_type", "width")
|
||||
__slots__ = (
|
||||
"cover",
|
||||
"duration",
|
||||
"file_name",
|
||||
"height",
|
||||
"mime_type",
|
||||
"start_timestamp",
|
||||
"width",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -79,6 +106,8 @@ class Video(_BaseThumbedMedium):
|
||||
file_size: Optional[int] = None,
|
||||
file_name: Optional[str] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
cover: Optional[Sequence[PhotoSize]] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
@@ -97,3 +126,14 @@ class Video(_BaseThumbedMedium):
|
||||
# Optional
|
||||
self.mime_type: Optional[str] = mime_type
|
||||
self.file_name: Optional[str] = file_name
|
||||
self.cover: Optional[Sequence[PhotoSize]] = parse_sequence_arg(cover)
|
||||
self.start_timestamp: Optional[int] = start_timestamp
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Video":
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
data["cover"] = de_list_optional(data.get("cover"), PhotoSize, bot)
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
@@ -2592,6 +2592,8 @@ class Message(MaybeInaccessibleMessage):
|
||||
message_effect_id: Optional[str] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
cover: Optional[FileInput] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -2661,6 +2663,8 @@ class Message(MaybeInaccessibleMessage):
|
||||
message_thread_id=message_thread_id,
|
||||
has_spoiler=has_spoiler,
|
||||
thumbnail=thumbnail,
|
||||
cover=cover,
|
||||
start_timestamp=start_timestamp,
|
||||
business_connection_id=self.business_connection_id,
|
||||
message_effect_id=message_effect_id,
|
||||
allow_paid_broadcast=allow_paid_broadcast,
|
||||
@@ -3506,6 +3510,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: Optional[int] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -3540,6 +3545,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
chat_id=chat_id,
|
||||
from_chat_id=self.chat_id,
|
||||
message_id=self.message_id,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
disable_notification=disable_notification,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
@@ -3563,6 +3569,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -3593,6 +3600,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
from_chat_id=self.chat_id,
|
||||
message_id=self.message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
@@ -3625,6 +3633,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -3675,6 +3684,7 @@ class Message(MaybeInaccessibleMessage):
|
||||
from_chat_id=from_chat_id,
|
||||
message_id=message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
|
||||
@@ -23,6 +23,7 @@ from collections.abc import Sequence
|
||||
from typing import TYPE_CHECKING, Final, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._chat import Chat
|
||||
from telegram._gifts import Gift
|
||||
from telegram._paidmedia import PaidMedia
|
||||
from telegram._telegramobject import TelegramObject
|
||||
@@ -43,6 +44,7 @@ class TransactionPartner(TelegramObject):
|
||||
transactions. Currently, it can be one of:
|
||||
|
||||
* :class:`TransactionPartnerUser`
|
||||
* :class:`TransactionPartnerChat`
|
||||
* :class:`TransactionPartnerAffiliateProgram`
|
||||
* :class:`TransactionPartnerFragment`
|
||||
* :class:`TransactionPartnerTelegramAds`
|
||||
@@ -54,6 +56,9 @@ class TransactionPartner(TelegramObject):
|
||||
|
||||
.. versionadded:: 21.4
|
||||
|
||||
..versionchanged:: NEXT.VERSION
|
||||
Added :class:`TransactionPartnerChat`
|
||||
|
||||
Args:
|
||||
type (:obj:`str`): The type of the transaction partner.
|
||||
|
||||
@@ -68,6 +73,11 @@ class TransactionPartner(TelegramObject):
|
||||
|
||||
.. versionadded:: 21.9
|
||||
"""
|
||||
CHAT: Final[str] = constants.TransactionPartnerType.CHAT
|
||||
""":const:`telegram.constants.TransactionPartnerType.CHAT`
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
FRAGMENT: Final[str] = constants.TransactionPartnerType.FRAGMENT
|
||||
""":const:`telegram.constants.TransactionPartnerType.FRAGMENT`"""
|
||||
OTHER: Final[str] = constants.TransactionPartnerType.OTHER
|
||||
@@ -103,6 +113,7 @@ class TransactionPartner(TelegramObject):
|
||||
|
||||
_class_mapping: dict[str, type[TransactionPartner]] = {
|
||||
cls.AFFILIATE_PROGRAM: TransactionPartnerAffiliateProgram,
|
||||
cls.CHAT: TransactionPartnerChat,
|
||||
cls.FRAGMENT: TransactionPartnerFragment,
|
||||
cls.USER: TransactionPartnerUser,
|
||||
cls.TELEGRAM_ADS: TransactionPartnerTelegramAds,
|
||||
@@ -171,6 +182,60 @@ class TransactionPartnerAffiliateProgram(TransactionPartner):
|
||||
return super().de_json(data=data, bot=bot) # type: ignore[return-value]
|
||||
|
||||
|
||||
class TransactionPartnerChat(TransactionPartner):
|
||||
"""Describes a transaction with a chat.
|
||||
|
||||
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||
considered equal, if their :attr:`chat` are equal.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Args:
|
||||
chat (:class:`telegram.Chat`): Information about the chat.
|
||||
gift (:class:`telegram.Gift`, optional): The gift sent to the chat by the bot.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): The type of the transaction partner,
|
||||
always :tg-const:`telegram.TransactionPartner.CHAT`.
|
||||
chat (:class:`telegram.Chat`): Information about the chat.
|
||||
gift (:class:`telegram.Gift`): Optional. The gift sent to the user by the bot.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = (
|
||||
"chat",
|
||||
"gift",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
chat: Chat,
|
||||
gift: Optional[Gift] = None,
|
||||
*,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> None:
|
||||
super().__init__(type=TransactionPartner.CHAT, api_kwargs=api_kwargs)
|
||||
|
||||
with self._unfrozen():
|
||||
self.chat: Chat = chat
|
||||
self.gift: Optional[Gift] = gift
|
||||
|
||||
self._id_attrs = (
|
||||
self.type,
|
||||
self.chat,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPartnerChat":
|
||||
"""See :meth:`telegram.TransactionPartner.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
data["chat"] = de_json_optional(data.get("chat"), Chat, bot)
|
||||
data["gift"] = de_json_optional(data.get("gift"), Gift, bot)
|
||||
|
||||
return super().de_json(data=data, bot=bot) # type: ignore[return-value]
|
||||
|
||||
|
||||
class TransactionPartnerFragment(TransactionPartner):
|
||||
"""Describes a withdrawal transaction with Fragment.
|
||||
|
||||
|
||||
+14
-1
@@ -1328,6 +1328,8 @@ class User(TelegramObject):
|
||||
message_effect_id: Optional[str] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
cover: Optional[FileInput] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -1369,6 +1371,8 @@ class User(TelegramObject):
|
||||
parse_mode=parse_mode,
|
||||
supports_streaming=supports_streaming,
|
||||
thumbnail=thumbnail,
|
||||
cover=cover,
|
||||
start_timestamp=start_timestamp,
|
||||
api_kwargs=api_kwargs,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
caption_entities=caption_entities,
|
||||
@@ -1670,7 +1674,7 @@ class User(TelegramObject):
|
||||
) -> bool:
|
||||
"""Shortcut for::
|
||||
|
||||
await bot.send_gift( user_id=update.effective_user.id, *args, **kwargs )
|
||||
await bot.send_gift(user_id=update.effective_user.id, *args, **kwargs )
|
||||
|
||||
For the documentation of the arguments, please see :meth:`telegram.Bot.send_gift`.
|
||||
|
||||
@@ -1680,6 +1684,7 @@ class User(TelegramObject):
|
||||
:obj:`bool`: On success, :obj:`True` is returned.
|
||||
"""
|
||||
return await self.get_bot().send_gift(
|
||||
chat_id=None,
|
||||
user_id=self.id,
|
||||
gift_id=gift_id,
|
||||
text=text,
|
||||
@@ -1707,6 +1712,7 @@ class User(TelegramObject):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -1734,6 +1740,7 @@ class User(TelegramObject):
|
||||
from_chat_id=from_chat_id,
|
||||
message_id=message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
@@ -1766,6 +1773,7 @@ class User(TelegramObject):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -1793,6 +1801,7 @@ class User(TelegramObject):
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
@@ -1908,6 +1917,7 @@ class User(TelegramObject):
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: Optional[int] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -1933,6 +1943,7 @@ class User(TelegramObject):
|
||||
chat_id=self.id,
|
||||
from_chat_id=from_chat_id,
|
||||
message_id=message_id,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
disable_notification=disable_notification,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
@@ -1950,6 +1961,7 @@ class User(TelegramObject):
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: Optional[int] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -1976,6 +1988,7 @@ class User(TelegramObject):
|
||||
from_chat_id=self.id,
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
disable_notification=disable_notification,
|
||||
read_timeout=read_timeout,
|
||||
write_timeout=write_timeout,
|
||||
|
||||
+10
-2
@@ -155,7 +155,7 @@ class _AccentColor(NamedTuple):
|
||||
#: :data:`telegram.__bot_api_version_info__`.
|
||||
#:
|
||||
#: .. versionadded:: 20.0
|
||||
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=8, minor=2)
|
||||
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=8, minor=3)
|
||||
#: :obj:`str`: Telegram Bot API
|
||||
#: version supported by this version of `python-telegram-bot`. Also available as
|
||||
#: :data:`telegram.__bot_api_version__`.
|
||||
@@ -1236,9 +1236,12 @@ class GiftLimit(IntEnum):
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
MAX_TEXT_LENGTH = 255
|
||||
MAX_TEXT_LENGTH = 128
|
||||
""":obj:`int`: Maximum number of characters in a :obj:`str` passed as the
|
||||
:paramref:`~telegram.Bot.send_gift.text` parameter of :meth:`~telegram.Bot.send_gift`.
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
Updated Value to 128 based on Bot API 8.3
|
||||
"""
|
||||
|
||||
|
||||
@@ -2659,6 +2662,11 @@ class TransactionPartnerType(StringEnum):
|
||||
|
||||
.. versionadded:: 21.9
|
||||
"""
|
||||
CHAT = "chat"
|
||||
""":obj:`str`: Transaction with a chat.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
FRAGMENT = "fragment"
|
||||
""":obj:`str`: Withdrawal transaction with Fragment."""
|
||||
OTHER = "other"
|
||||
|
||||
+12
-2
@@ -815,6 +815,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
reply_parameters: Optional["ReplyParameters"] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -831,6 +832,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
from_chat_id=from_chat_id,
|
||||
message_id=message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
@@ -1752,6 +1754,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: Optional[int] = None,
|
||||
video_start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -1764,6 +1767,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
chat_id=chat_id,
|
||||
from_chat_id=from_chat_id,
|
||||
message_id=message_id,
|
||||
video_start_timestamp=video_start_timestamp,
|
||||
disable_notification=disable_notification,
|
||||
protect_content=protect_content,
|
||||
message_thread_id=message_thread_id,
|
||||
@@ -3240,6 +3244,8 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
message_effect_id: Optional[str] = None,
|
||||
allow_paid_broadcast: Optional[bool] = None,
|
||||
show_caption_above_media: Optional[bool] = None,
|
||||
cover: Optional[FileInput] = None,
|
||||
start_timestamp: Optional[int] = None,
|
||||
*,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
|
||||
@@ -3270,6 +3276,8 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
business_connection_id=business_connection_id,
|
||||
has_spoiler=has_spoiler,
|
||||
thumbnail=thumbnail,
|
||||
cover=cover,
|
||||
start_timestamp=start_timestamp,
|
||||
filename=filename,
|
||||
reply_parameters=reply_parameters,
|
||||
read_timeout=read_timeout,
|
||||
@@ -4468,12 +4476,13 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
|
||||
async def send_gift(
|
||||
self,
|
||||
user_id: int,
|
||||
gift_id: Union[str, Gift],
|
||||
user_id: Optional[int] = None,
|
||||
gift_id: Union[str, Gift] = None, # type: ignore
|
||||
text: Optional[str] = None,
|
||||
text_parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
text_entities: Optional[Sequence["MessageEntity"]] = None,
|
||||
pay_for_upgrade: Optional[bool] = None,
|
||||
chat_id: Optional[Union[str, int]] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -4484,6 +4493,7 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
) -> bool:
|
||||
return await super().send_gift(
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
gift_id=gift_id,
|
||||
text=text,
|
||||
text_parse_mode=text_parse_mode,
|
||||
|
||||
@@ -58,6 +58,8 @@ def input_media_video(class_thumb_file):
|
||||
parse_mode=InputMediaVideoTestBase.parse_mode,
|
||||
caption_entities=InputMediaVideoTestBase.caption_entities,
|
||||
thumbnail=class_thumb_file,
|
||||
cover=class_thumb_file,
|
||||
start_timestamp=InputMediaVideoTestBase.start_timestamp,
|
||||
supports_streaming=InputMediaVideoTestBase.supports_streaming,
|
||||
has_spoiler=InputMediaVideoTestBase.has_spoiler,
|
||||
show_caption_above_media=InputMediaVideoTestBase.show_caption_above_media,
|
||||
@@ -130,6 +132,8 @@ def input_paid_media_video(class_thumb_file):
|
||||
return InputPaidMediaVideo(
|
||||
media=InputMediaVideoTestBase.media,
|
||||
thumbnail=class_thumb_file,
|
||||
cover=class_thumb_file,
|
||||
start_timestamp=InputMediaVideoTestBase.start_timestamp,
|
||||
width=InputMediaVideoTestBase.width,
|
||||
height=InputMediaVideoTestBase.height,
|
||||
duration=InputMediaVideoTestBase.duration,
|
||||
@@ -144,6 +148,7 @@ class InputMediaVideoTestBase:
|
||||
width = 3
|
||||
height = 4
|
||||
duration = 5
|
||||
start_timestamp = 3
|
||||
parse_mode = "HTML"
|
||||
supports_streaming = True
|
||||
caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
|
||||
@@ -169,6 +174,8 @@ class TestInputMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||
assert input_media_video.caption_entities == tuple(self.caption_entities)
|
||||
assert input_media_video.supports_streaming == self.supports_streaming
|
||||
assert isinstance(input_media_video.thumbnail, InputFile)
|
||||
assert isinstance(input_media_video.cover, InputFile)
|
||||
assert input_media_video.start_timestamp == self.start_timestamp
|
||||
assert input_media_video.has_spoiler == self.has_spoiler
|
||||
assert input_media_video.show_caption_above_media == self.show_caption_above_media
|
||||
|
||||
@@ -194,6 +201,8 @@ class TestInputMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||
input_media_video_dict["show_caption_above_media"]
|
||||
== input_media_video.show_caption_above_media
|
||||
)
|
||||
assert input_media_video_dict["cover"] == input_media_video.cover
|
||||
assert input_media_video_dict["start_timestamp"] == input_media_video.start_timestamp
|
||||
|
||||
def test_with_video(self, video):
|
||||
# fixture found in test_video
|
||||
@@ -214,10 +223,13 @@ class TestInputMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||
|
||||
def test_with_local_files(self):
|
||||
input_media_video = InputMediaVideo(
|
||||
data_file("telegram.mp4"), thumbnail=data_file("telegram.jpg")
|
||||
data_file("telegram.mp4"),
|
||||
thumbnail=data_file("telegram.jpg"),
|
||||
cover=data_file("telegram.jpg"),
|
||||
)
|
||||
assert input_media_video.media == data_file("telegram.mp4").as_uri()
|
||||
assert input_media_video.thumbnail == data_file("telegram.jpg").as_uri()
|
||||
assert input_media_video.cover == data_file("telegram.jpg").as_uri()
|
||||
|
||||
def test_type_enum_conversion(self):
|
||||
# Since we have a lot of different test classes for all the input media types, we test this
|
||||
@@ -565,6 +577,8 @@ class TestInputPaidMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||
assert input_paid_media_video.duration == self.duration
|
||||
assert input_paid_media_video.supports_streaming == self.supports_streaming
|
||||
assert isinstance(input_paid_media_video.thumbnail, InputFile)
|
||||
assert isinstance(input_paid_media_video.cover, InputFile)
|
||||
assert input_paid_media_video.start_timestamp == self.start_timestamp
|
||||
|
||||
def test_to_dict(self, input_paid_media_video):
|
||||
input_paid_media_video_dict = input_paid_media_video.to_dict()
|
||||
@@ -578,6 +592,11 @@ class TestInputPaidMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||
== input_paid_media_video.supports_streaming
|
||||
)
|
||||
assert input_paid_media_video_dict["thumbnail"] == input_paid_media_video.thumbnail
|
||||
assert input_paid_media_video_dict["cover"] == input_paid_media_video.cover
|
||||
assert (
|
||||
input_paid_media_video_dict["start_timestamp"]
|
||||
== input_paid_media_video.start_timestamp
|
||||
)
|
||||
|
||||
def test_with_video(self, video):
|
||||
# fixture found in test_video
|
||||
@@ -596,10 +615,13 @@ class TestInputPaidMediaVideoWithoutRequest(InputMediaVideoTestBase):
|
||||
|
||||
def test_with_local_files(self):
|
||||
input_paid_media_video = InputPaidMediaVideo(
|
||||
data_file("telegram.mp4"), thumbnail=data_file("telegram.jpg")
|
||||
data_file("telegram.mp4"),
|
||||
thumbnail=data_file("telegram.jpg"),
|
||||
cover=data_file("telegram.jpg"),
|
||||
)
|
||||
assert input_paid_media_video.media == data_file("telegram.mp4").as_uri()
|
||||
assert input_paid_media_video.thumbnail == data_file("telegram.jpg").as_uri()
|
||||
assert input_paid_media_video.cover == data_file("telegram.jpg").as_uri()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -46,6 +46,8 @@ class VideoTestBase:
|
||||
mime_type = "video/mp4"
|
||||
supports_streaming = True
|
||||
file_name = "telegram.mp4"
|
||||
start_timestamp = 3
|
||||
cover = (PhotoSize("file_id", "unique_id", 640, 360, file_size=0),)
|
||||
thumb_width = 180
|
||||
thumb_height = 320
|
||||
thumb_file_size = 1767
|
||||
@@ -92,6 +94,8 @@ class TestVideoWithoutRequest(VideoTestBase):
|
||||
"mime_type": self.mime_type,
|
||||
"file_size": self.file_size,
|
||||
"file_name": self.file_name,
|
||||
"start_timestamp": self.start_timestamp,
|
||||
"cover": [photo_size.to_dict() for photo_size in self.cover],
|
||||
}
|
||||
json_video = Video.de_json(json_dict, offline_bot)
|
||||
assert json_video.api_kwargs == {}
|
||||
@@ -104,6 +108,8 @@ class TestVideoWithoutRequest(VideoTestBase):
|
||||
assert json_video.mime_type == self.mime_type
|
||||
assert json_video.file_size == self.file_size
|
||||
assert json_video.file_name == self.file_name
|
||||
assert json_video.start_timestamp == self.start_timestamp
|
||||
assert json_video.cover == self.cover
|
||||
|
||||
def test_to_dict(self, video):
|
||||
video_dict = video.to_dict()
|
||||
@@ -223,7 +229,9 @@ class TestVideoWithoutRequest(VideoTestBase):
|
||||
|
||||
class TestVideoWithRequest(VideoTestBase):
|
||||
@pytest.mark.parametrize("duration", [dtm.timedelta(seconds=5), 5])
|
||||
async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file, duration):
|
||||
async def test_send_all_args(
|
||||
self, bot, chat_id, video_file, video, thumb_file, photo_file, duration
|
||||
):
|
||||
message = await bot.send_video(
|
||||
chat_id,
|
||||
video_file,
|
||||
@@ -236,6 +244,8 @@ class TestVideoWithRequest(VideoTestBase):
|
||||
height=video.height,
|
||||
parse_mode="Markdown",
|
||||
thumbnail=thumb_file,
|
||||
cover=photo_file,
|
||||
start_timestamp=self.start_timestamp,
|
||||
has_spoiler=True,
|
||||
show_caption_above_media=True,
|
||||
)
|
||||
@@ -256,6 +266,11 @@ class TestVideoWithRequest(VideoTestBase):
|
||||
assert message.video.thumbnail.width == self.thumb_width
|
||||
assert message.video.thumbnail.height == self.thumb_height
|
||||
|
||||
assert message.video.start_timestamp == self.start_timestamp
|
||||
|
||||
assert isinstance(message.video.cover, tuple)
|
||||
assert isinstance(message.video.cover[0], PhotoSize)
|
||||
|
||||
assert message.video.file_name == self.file_name
|
||||
assert message.has_protected_content
|
||||
assert message.has_media_spoiler
|
||||
|
||||
@@ -22,12 +22,14 @@ import pytest
|
||||
|
||||
from telegram import (
|
||||
AffiliateInfo,
|
||||
Chat,
|
||||
Gift,
|
||||
PaidMediaVideo,
|
||||
RevenueWithdrawalStatePending,
|
||||
Sticker,
|
||||
TransactionPartner,
|
||||
TransactionPartnerAffiliateProgram,
|
||||
TransactionPartnerChat,
|
||||
TransactionPartnerFragment,
|
||||
TransactionPartnerOther,
|
||||
TransactionPartnerTelegramAds,
|
||||
@@ -95,6 +97,10 @@ class TransactionPartnerTestBase:
|
||||
amount=42,
|
||||
)
|
||||
request_count = 42
|
||||
chat = Chat(
|
||||
id=3,
|
||||
type=Chat.CHANNEL,
|
||||
)
|
||||
|
||||
|
||||
class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase):
|
||||
@@ -123,6 +129,7 @@ class TestTransactionPartnerWithoutRequest(TransactionPartnerTestBase):
|
||||
("telegram_ads", TransactionPartnerTelegramAds),
|
||||
("telegram_api", TransactionPartnerTelegramApi),
|
||||
("other", TransactionPartnerOther),
|
||||
("chat", TransactionPartnerChat),
|
||||
],
|
||||
)
|
||||
def test_subclass(self, offline_bot, tp_type, subclass):
|
||||
@@ -450,3 +457,58 @@ class TestTransactionPartnerTelegramApiWithoutRequest(TransactionPartnerTestBase
|
||||
|
||||
assert a != d
|
||||
assert hash(a) != hash(d)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def transaction_partner_chat():
|
||||
return TransactionPartnerChat(
|
||||
chat=TransactionPartnerTestBase.chat,
|
||||
gift=TransactionPartnerTestBase.gift,
|
||||
)
|
||||
|
||||
|
||||
class TestTransactionPartnerChatWithoutRequest(TransactionPartnerTestBase):
|
||||
type = TransactionPartnerType.CHAT
|
||||
|
||||
def test_slot_behaviour(self, transaction_partner_chat):
|
||||
inst = transaction_partner_chat
|
||||
for attr in inst.__slots__:
|
||||
assert getattr(inst, attr, "err") != "err", f"got extra slot '{attr}'"
|
||||
assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
|
||||
|
||||
def test_de_json(self, offline_bot):
|
||||
json_dict = {
|
||||
"chat": self.chat.to_dict(),
|
||||
"gift": self.gift.to_dict(),
|
||||
}
|
||||
tp = TransactionPartnerChat.de_json(json_dict, offline_bot)
|
||||
assert tp.api_kwargs == {}
|
||||
assert tp.type == "chat"
|
||||
assert tp.chat == self.chat
|
||||
assert tp.gift == self.gift
|
||||
|
||||
def test_to_dict(self, transaction_partner_chat):
|
||||
json_dict = transaction_partner_chat.to_dict()
|
||||
assert json_dict["type"] == self.type
|
||||
assert json_dict["chat"] == self.chat.to_dict()
|
||||
assert json_dict["gift"] == self.gift.to_dict()
|
||||
|
||||
def test_equality(self, transaction_partner_chat):
|
||||
a = transaction_partner_chat
|
||||
b = TransactionPartnerChat(
|
||||
chat=self.chat,
|
||||
gift=self.gift,
|
||||
)
|
||||
c = TransactionPartnerChat(
|
||||
chat=Chat(id=1, type=Chat.CHANNEL),
|
||||
)
|
||||
d = Chat(id=1, type=Chat.CHANNEL)
|
||||
|
||||
assert a == b
|
||||
assert hash(a) == hash(b)
|
||||
|
||||
assert a != c
|
||||
assert hash(a) != hash(c)
|
||||
|
||||
assert a != d
|
||||
assert hash(a) != hash(d)
|
||||
|
||||
@@ -351,6 +351,9 @@ def build_kwargs(
|
||||
allow_sending_without_reply=manually_passed_value,
|
||||
quote_parse_mode=manually_passed_value,
|
||||
)
|
||||
# TODO remove when gift_id isnt marked as optional anymore, tags: deprecated NEXT.VERSION
|
||||
elif name == "gift_id":
|
||||
kws[name] = "GIFT-ID"
|
||||
|
||||
return kws
|
||||
|
||||
|
||||
@@ -1617,6 +1617,7 @@ class TestBotWithoutRequest:
|
||||
== [MessageEntity(MessageEntity.BOLD, 0, 4).to_dict()],
|
||||
data["protect_content"] is True,
|
||||
data["message_thread_id"] == 1,
|
||||
data["video_start_timestamp"] == 999,
|
||||
]
|
||||
):
|
||||
pytest.fail("I got wrong parameters in post")
|
||||
@@ -1628,6 +1629,7 @@ class TestBotWithoutRequest:
|
||||
from_chat_id=chat_id,
|
||||
message_id=media_message.message_id,
|
||||
caption=caption,
|
||||
video_start_timestamp=999,
|
||||
caption_entities=[MessageEntity(MessageEntity.BOLD, 0, 4)],
|
||||
parse_mode=ParseMode.HTML,
|
||||
reply_to_message_id=media_message.message_id,
|
||||
|
||||
+32
-4
@@ -1312,7 +1312,7 @@ class TestChatWithoutRequest(ChatTestBase):
|
||||
)
|
||||
|
||||
async def test_instance_method_send_gift(self, monkeypatch, chat):
|
||||
async def make_assertion(*_, **kwargs):
|
||||
async def make_assertion_private(*_, **kwargs):
|
||||
return (
|
||||
kwargs["user_id"] == chat.id
|
||||
and kwargs["gift_id"] == "gift_id"
|
||||
@@ -1321,11 +1321,39 @@ class TestChatWithoutRequest(ChatTestBase):
|
||||
and kwargs["text_entities"] == "text_entities"
|
||||
)
|
||||
|
||||
assert check_shortcut_signature(Chat.send_gift, Bot.send_gift, ["user_id"], [])
|
||||
assert await check_shortcut_call(chat.send_gift, chat.get_bot(), "send_gift")
|
||||
async def make_assertion_channel(*_, **kwargs):
|
||||
return (
|
||||
kwargs["chat_id"] == chat.id
|
||||
and kwargs["gift_id"] == "gift_id"
|
||||
and kwargs["text"] == "text"
|
||||
and kwargs["text_parse_mode"] == "text_parse_mode"
|
||||
and kwargs["text_entities"] == "text_entities"
|
||||
)
|
||||
|
||||
# TODO discuss if better way exists
|
||||
# tags: deprecated NEXT.VERSION
|
||||
with pytest.raises(
|
||||
Exception,
|
||||
match="Default for argument gift_id does not match the default of the Bot method.",
|
||||
):
|
||||
assert check_shortcut_signature(
|
||||
Chat.send_gift, Bot.send_gift, ["user_id", "chat_id"], []
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
chat.send_gift, chat.get_bot(), "send_gift", ["user_id", "chat_id"]
|
||||
)
|
||||
assert await check_defaults_handling(chat.send_gift, chat.get_bot())
|
||||
|
||||
monkeypatch.setattr(chat.get_bot(), "send_gift", make_assertion)
|
||||
monkeypatch.setattr(chat.get_bot(), "send_gift", make_assertion_private)
|
||||
chat.type = chat.PRIVATE
|
||||
assert await chat.send_gift(
|
||||
gift_id="gift_id",
|
||||
text="text",
|
||||
text_parse_mode="text_parse_mode",
|
||||
text_entities="text_entities",
|
||||
)
|
||||
monkeypatch.setattr(chat.get_bot(), "send_gift", make_assertion_channel)
|
||||
chat.type = chat.CHANNEL
|
||||
assert await chat.send_gift(
|
||||
gift_id="gift_id",
|
||||
text="text",
|
||||
|
||||
@@ -164,6 +164,43 @@ class TestGiftWithoutRequest(GiftTestBase):
|
||||
pay_for_upgrade=True,
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("id_name", ["user_id", "chat_id"])
|
||||
async def test_send_gift_user_chat_id(self, offline_bot, gift, monkeypatch, id_name):
|
||||
# Only here because we have to temporarily mark gift_id as optional.
|
||||
# tags: deprecated NEXT.VERSION
|
||||
|
||||
# We can't send actual gifts, so we just check that the correct parameters are passed
|
||||
text_entities = [
|
||||
MessageEntity(MessageEntity.TEXT_LINK, 0, 4, "url"),
|
||||
MessageEntity(MessageEntity.BOLD, 5, 9),
|
||||
]
|
||||
|
||||
async def make_assertion(url, request_data: RequestData, *args, **kwargs):
|
||||
received_id = request_data.parameters[id_name] == id_name
|
||||
gift_id = request_data.parameters["gift_id"] == "some_id"
|
||||
text = request_data.parameters["text"] == "text"
|
||||
text_parse_mode = request_data.parameters["text_parse_mode"] == "text_parse_mode"
|
||||
tes = request_data.parameters["text_entities"] == [
|
||||
me.to_dict() for me in text_entities
|
||||
]
|
||||
pay_for_upgrade = request_data.parameters["pay_for_upgrade"] is True
|
||||
|
||||
return received_id and gift_id and text and text_parse_mode and tes and pay_for_upgrade
|
||||
|
||||
monkeypatch.setattr(offline_bot.request, "post", make_assertion)
|
||||
assert await offline_bot.send_gift(
|
||||
gift_id=gift,
|
||||
text="text",
|
||||
text_parse_mode="text_parse_mode",
|
||||
text_entities=text_entities,
|
||||
pay_for_upgrade=True,
|
||||
**{id_name: id_name},
|
||||
)
|
||||
|
||||
async def test_send_gift_without_gift_id(self, offline_bot):
|
||||
with pytest.raises(TypeError, match="Missing required argument `gift_id`."):
|
||||
await offline_bot.send_gift()
|
||||
|
||||
@pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("passed_value", "expected_value"),
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"""This module contains exceptions to our API compared to the official API."""
|
||||
import datetime as dtm
|
||||
|
||||
from telegram import Animation, Audio, Document, Gift, PhotoSize, Sticker, Video, VideoNote, Voice
|
||||
from telegram import Animation, Audio, Document, PhotoSize, Sticker, Video, VideoNote, Voice
|
||||
from tests.test_official.helpers import _get_params_base
|
||||
|
||||
IGNORED_OBJECTS = ("ResponseParameters",)
|
||||
@@ -47,7 +47,8 @@ class ParamTypeCheckingExceptions:
|
||||
"animation": Animation,
|
||||
"voice": Voice,
|
||||
"sticker": Sticker,
|
||||
"gift_id": Gift,
|
||||
# TODO: Deprecated and will be corrected (and readded) in next major bot API release:
|
||||
# "gift_id": Gift,
|
||||
},
|
||||
"(delete|set)_sticker.*": {
|
||||
"sticker$": Sticker,
|
||||
@@ -72,36 +73,40 @@ class ParamTypeCheckingExceptions:
|
||||
("keyboard", True): "KeyboardButton", # + sequence[sequence[str]]
|
||||
("reaction", False): "ReactionType", # + str
|
||||
("options", False): "InputPollOption", # + str
|
||||
# TODO: Deprecated and will be corrected (and removed) in next major PTB version:
|
||||
# TODO: Deprecated and will be corrected (and removed) in next bot api release
|
||||
("file_hashes", True): "list[str]",
|
||||
}
|
||||
|
||||
# Special cases for other parameters that accept more types than the official API, and are
|
||||
# too complex to compare/predict with official API
|
||||
# structure: class/method_name: {param_name: reduced form of annotation}
|
||||
COMPLEX_TYPES = (
|
||||
{ # (param_name, is_class (i.e appears in a class?)): reduced form of annotation
|
||||
"send_poll": {"correct_option_id": int}, # actual: Literal
|
||||
"get_file": {
|
||||
"file_id": str, # actual: Union[str, objs_with_file_id_attr]
|
||||
},
|
||||
r"\w+invite_link": {
|
||||
"invite_link": str, # actual: Union[str, ChatInviteLink]
|
||||
},
|
||||
"send_invoice|create_invoice_link": {
|
||||
"provider_data": str, # actual: Union[str, obj]
|
||||
},
|
||||
"InlineKeyboardButton": {
|
||||
"callback_data": str, # actual: Union[str, obj]
|
||||
},
|
||||
"Input(Paid)?Media.*": {
|
||||
"media": str, # actual: Union[str, InputMedia*, FileInput]
|
||||
},
|
||||
"EncryptedPassportElement": {
|
||||
"data": str, # actual: Union[IdDocumentData, PersonalDetails, ResidentialAddress]
|
||||
},
|
||||
}
|
||||
)
|
||||
COMPLEX_TYPES = {
|
||||
"send_poll": {"correct_option_id": int}, # actual: Literal
|
||||
"get_file": {
|
||||
"file_id": str, # actual: Union[str, objs_with_file_id_attr]
|
||||
},
|
||||
r"\w+invite_link": {
|
||||
"invite_link": str, # actual: Union[str, ChatInviteLink]
|
||||
},
|
||||
"send_invoice|create_invoice_link": {
|
||||
"provider_data": str, # actual: Union[str, obj]
|
||||
},
|
||||
"InlineKeyboardButton": {
|
||||
"callback_data": str, # actual: Union[str, obj]
|
||||
},
|
||||
"Input(Paid)?Media.*": {
|
||||
"media": str, # actual: Union[str, InputMedia*, FileInput]
|
||||
# see also https://github.com/tdlib/telegram-bot-api/issues/707
|
||||
"thumbnail": str, # actual: Union[str, FileInput]
|
||||
"cover": str, # actual: Union[str, FileInput]
|
||||
},
|
||||
"EncryptedPassportElement": {
|
||||
"data": str, # actual: Union[IdDocumentData, PersonalDetails, ResidentialAddress]
|
||||
},
|
||||
# TODO: Deprecated and will be corrected (and removed) in next major PTB
|
||||
# version:
|
||||
"send_gift": {"gift_id": str}, # actual: Non optional
|
||||
}
|
||||
|
||||
# param names ignored in the param type checking in classes for the `tg.Defaults` case.
|
||||
IGNORED_DEFAULTS_PARAM_NAMES = {
|
||||
@@ -198,6 +203,8 @@ IGNORED_PARAM_REQUIREMENTS = {
|
||||
"send_venue": {"latitude", "longitude", "title", "address"},
|
||||
"send_contact": {"phone_number", "first_name"},
|
||||
# ---->
|
||||
# here for backwards compatibility. Todo: remove on next bot api release
|
||||
"send_gift": {"gift_id"},
|
||||
}
|
||||
|
||||
|
||||
|
||||
+12
-2
@@ -731,8 +731,18 @@ class TestUserWithoutRequest(UserTestBase):
|
||||
and kwargs["text_entities"] == "text_entities"
|
||||
)
|
||||
|
||||
assert check_shortcut_signature(user.send_gift, Bot.send_gift, ["user_id"], [])
|
||||
assert await check_shortcut_call(user.send_gift, user.get_bot(), "send_gift")
|
||||
# TODO discuss if better way exists
|
||||
# tags: deprecated NEXT.VERSION
|
||||
with pytest.raises(
|
||||
Exception,
|
||||
match="Default for argument gift_id does not match the default of the Bot method.",
|
||||
):
|
||||
assert check_shortcut_signature(
|
||||
user.send_gift, Bot.send_gift, ["user_id", "chat_id"], []
|
||||
)
|
||||
assert await check_shortcut_call(
|
||||
user.send_gift, user.get_bot(), "send_gift", ["chat_id", "user_id"]
|
||||
)
|
||||
assert await check_defaults_handling(user.send_gift, user.get_bot())
|
||||
|
||||
monkeypatch.setattr(user.get_bot(), "send_gift", make_assertion)
|
||||
|
||||
Reference in New Issue
Block a user