diff --git a/README.md b/README.md index ff1b5159f..7431dc001 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

diff --git a/telebot/__init__.py b/telebot/__init__.py index ae210f130..2ac86cf06 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1810,7 +1810,8 @@ def forward_message( message_id: int, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + video_start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -1825,6 +1826,9 @@ def forward_message( :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) :type from_chat_id: :obj:`int` or :obj:`str` + :param video_start_timestamp: New start timestamp for the forwarded video in the message + :type video_start_timestamp: :obj:`int` + :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` @@ -1846,7 +1850,8 @@ def forward_message( return types.Message.de_json( apihelper.forward_message( self.token, chat_id, from_chat_id, message_id, disable_notification=disable_notification, - timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id)) + timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, + video_start_timestamp=video_start_timestamp)) def copy_message( @@ -1865,7 +1870,8 @@ def copy_message( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.MessageID: + allow_paid_broadcast: Optional[bool]=None, + video_start_timestamp: Optional[int]=None) -> types.MessageID: """ Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. @@ -1883,6 +1889,9 @@ def copy_message( :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` + :param video_start_timestamp: New start timestamp for the copied video in the message + :type video_start_timestamp: :obj:`int` + :param caption: New caption for media, 0-1024 characters after entities parsing. If not specified, the original caption is kept :type caption: :obj:`str` @@ -1956,7 +1965,8 @@ def copy_message( parse_mode=parse_mode, caption_entities=caption_entities, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + video_start_timestamp=video_start_timestamp)) def delete_message(self, chat_id: Union[int, str], message_id: int, @@ -2824,7 +2834,9 @@ def send_video( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + cover: Optional[Union[Any, str]]=None, + start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -2845,8 +2857,18 @@ def send_video( :param height: Video height :type height: :obj:`int` - :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . + :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, + so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` + + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -2949,7 +2971,8 @@ def send_video( thumbnail=thumbnail, height=height, width=width, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + cover=cover, start_timestamp=start_timestamp) ) @@ -6250,19 +6273,24 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) - def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, - text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: + def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None, + chat_id: Optional[Union[str, int]] = None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#sendgift - :param user_id: Unique identifier of the target user that will receive the gift - :type user_id: :obj:`int` - :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param user_id: Required if chat_id is not specified. Unique identifier of the target user who will receive the gift. + :type user_id::obj:`int` | :obj:`str` + + :param chat_id: Required if user_id is not specified. Unique identifier for the chat or username of the channel + (in the format @channelusername) that will receive the gift. + :type chat_id: :obj:`int` | :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver :type pay_for_upgrade: :obj:`bool` @@ -6278,8 +6306,14 @@ def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_p :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.send_gift(self.token, user_id, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, - pay_for_upgrade=pay_for_upgrade) + if user_id is None and chat_id is None: + raise ValueError("Either user_id or chat_id must be specified.") + + if gift_id is None: + raise ValueError("gift_id must be specified.") + + return apihelper.send_gift(self.token, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, + pay_for_upgrade=pay_for_upgrade, chat_id=chat_id, user_id=user_id) def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 69f3f8e4f..879dfdec5 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -424,7 +424,8 @@ def get_chat_member(token, chat_id, user_id): def forward_message( token, chat_id, from_chat_id, message_id, - disable_notification=None, timeout=None, protect_content=None, message_thread_id=None): + disable_notification=None, timeout=None, protect_content=None, message_thread_id=None, + video_start_timestamp=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -435,12 +436,15 @@ def forward_message( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return _make_request(token, method_url, params=payload) def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, - reply_parameters=None, show_caption_above_media=None, allow_paid_broadcast=None): + reply_parameters=None, show_caption_above_media=None, allow_paid_broadcast=None, + video_start_timestamp=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -465,6 +469,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return _make_request(token, method_url, params=payload) @@ -783,7 +789,8 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, + cover=None, start_timestamp=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -835,6 +842,16 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if cover: + if not util.is_string(cover): + if files: + files['cover'] = cover + else: + files = {'cover': cover} + else: + payload['cover'] = cover + if start_timestamp: + payload['start_timestamp'] = start_timestamp return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1929,7 +1946,8 @@ def get_available_gifts(token): return _make_request(token, method_url) -def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): +def send_gift(token, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None, + chat_id=None, user_id=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1940,6 +1958,10 @@ def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_ent payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) if pay_for_upgrade is not None: payload['pay_for_upgrade'] = pay_for_upgrade + if chat_id: + payload['chat_id'] = chat_id + if user_id: + payload['user_id'] = user_id return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index a3f717dff..bc251220a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3337,7 +3337,8 @@ async def forward_message( message_id: int, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + video_start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -3355,6 +3356,9 @@ async def forward_message( :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` + :param video_start_timestamp: New start timestamp for the forwarded video in the message + :type video_start_timestamp: :obj:`int` + :param protect_content: Protects the contents of the forwarded message from forwarding and saving :type protect_content: :obj:`bool` @@ -3371,8 +3375,9 @@ async def forward_message( protect_content = self.protect_content if (protect_content is None) else protect_content return types.Message.de_json( - await asyncio_helper.forward_message(self.token, chat_id, from_chat_id, message_id, disable_notification, timeout, protect_content, - message_thread_id)) + await asyncio_helper.forward_message(self.token, chat_id=chat_id, from_chat_id=from_chat_id, message_id=message_id, + disable_notification=disable_notification, protect_content=protect_content, + timeout=timeout, message_thread_id=message_thread_id, video_start_timestamp=video_start_timestamp)) async def copy_message( self, chat_id: Union[int, str], @@ -3390,7 +3395,8 @@ async def copy_message( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.MessageID: + allow_paid_broadcast: Optional[bool]=None, + video_start_timestamp: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, @@ -3405,9 +3411,13 @@ async def copy_message( :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) :type from_chat_id: :obj:`int` or :obj:`str` + :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` + :param video_start_timestamp: New start timestamp for the forwarded video in the message + :type video_start_timestamp: :obj:`int` + :param caption: New caption for media, 0-1024 characters after entities parsing. If not specified, the original caption is kept :type caption: :obj:`str` @@ -3478,10 +3488,12 @@ async def copy_message( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.MessageID.de_json( - await asyncio_helper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, - disable_notification, reply_markup, - timeout, protect_content, message_thread_id, reply_parameters, show_caption_above_media=show_caption_above_media, - allow_paid_broadcast=allow_paid_broadcast)) + await asyncio_helper.copy_message(self.token, chat_id=chat_id, from_chat_id=from_chat_id, message_id=message_id, + caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, + disable_notification=disable_notification, protect_content=protect_content, + reply_parameters=reply_parameters, reply_markup=reply_markup, timeout=timeout, + message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, video_start_timestamp=video_start_timestamp)) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -4341,7 +4353,9 @@ async def send_video( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + cover: Optional[Union[Any, str]]=None, + start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4364,6 +4378,14 @@ async def send_video( :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` + + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -4467,7 +4489,7 @@ async def send_video( self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, cover=cover, start_timestamp=start_timestamp)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -7707,19 +7729,24 @@ async def delete_sticker_set(self, name:str) -> bool: return await asyncio_helper.delete_sticker_set(self.token, name) - async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, - text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: + async def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, + text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None, + pay_for_upgrade: Optional[bool]=None, chat_id: Optional[Union[str, int]] = None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#sendgift - :param user_id: Unique identifier of the target user that will receive the gift - :type user_id: :obj:`int` - :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param user_id: Required if chat_id is not specified. Unique identifier of the target user who will receive the gift. + :type user_id::obj:`int` | :obj:`str` + + :param chat_id: Required if user_id is not specified. Unique identifier for the chat or username of the channel + (in the format @channelusername) that will receive the gift. + :type chat_id: :obj:`int` | :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver :type pay_for_upgrade: :obj:`bool` @@ -7735,7 +7762,14 @@ async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.send_gift(self.token, user_id, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade) + if user_id is None and chat_id is None: + raise ValueError("Either user_id or chat_id must be specified.") + + if gift_id is None: + raise ValueError("gift_id must be specified.") + + return await asyncio_helper.send_gift(self.token, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade, + chat_id=chat_id, user_id=user_id) async def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index e076b8e26..99937ff63 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -429,7 +429,7 @@ async def get_chat_member(token, chat_id, user_id): async def forward_message( token, chat_id, from_chat_id, message_id, disable_notification=None, timeout=None, protect_content=None, - message_thread_id=None): + message_thread_id=None, video_start_timestamp=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -440,13 +440,15 @@ async def forward_message( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return await _process_request(token, method_url, params=payload) async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, video_start_timestamp=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -471,6 +473,8 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return await _process_request(token, method_url, params=payload) @@ -789,7 +793,7 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, cover=None, start_timestamp=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -841,6 +845,16 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if cover: + if not util.is_string(cover): + if files: + files['cover'] = cover + else: + files = {'cover': cover} + else: + payload['cover'] = cover + if start_timestamp: + payload['start_timestamp'] = start_timestamp return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1916,7 +1930,8 @@ async def delete_sticker_set(token, name): payload = {'name': name} return await _process_request(token, method_url, params=payload, method='post') -async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): +async def send_gift(token, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None, + user_id=None, chat_id=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1927,6 +1942,10 @@ async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, te payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) if pay_for_upgrade is not None: payload['pay_for_upgrade'] = pay_for_upgrade + if chat_id: + payload['chat_id'] = chat_id + if user_id: + payload['user_id'] = user_id return await _process_request(token, method_url, params=payload, method='post') async def verify_user(token, user_id, custom_description=None): diff --git a/telebot/types.py b/telebot/types.py index 301ae61a1..af0d4cf74 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -688,6 +688,13 @@ class ChatFullInfo(JsonDeserializable): :param permissions: Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat. :type permissions: :class:`telebot.types.ChatPermissions` + :param can_send_gift: Optional. True, if gifts can be sent to the chat + :type can_send_gift: :obj:`bool` + + :param can_send_paid_media: Optional. True, if paid media messages can be sent or forwarded to the channel chat. + The field is available only for channel chats. + :type can_send_paid_media: :obj:`bool` + :param slow_mode_delay: Optional. For supergroups, the minimum allowed delay between consecutive messages sent by each unpriviledged user; in seconds. Returned only in getChat. :type slow_mode_delay: :obj:`int` @@ -728,10 +735,6 @@ class ChatFullInfo(JsonDeserializable): :param location: Optional. For supergroups, the location to which the supergroup is connected. Returned only in getChat. :type location: :class:`telebot.types.ChatLocation` - :param can_send_paid_media: Optional. True, if paid media messages can be sent or forwarded to the channel chat. - The field is available only for channel chats. - :type can_send_paid_media: :obj:`bool` - :return: Instance of the class :rtype: :class:`telebot.types.ChatFullInfo` """ @@ -774,7 +777,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, profile_background_custom_emoji_id=None, has_visible_history=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, business_opening_hours=None, personal_chat=None, birthdate=None, - can_send_paid_media=None, **kwargs): + can_send_paid_media=None, can_send_gift=None, **kwargs): self.id: int = id self.type: str = type self.title: Optional[str] = title @@ -819,6 +822,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.personal_chat: Optional[Chat] = personal_chat self.birthdate: Optional[Birthdate] = birthdate self.can_send_paid_media: Optional[bool] = can_send_paid_media + self.can_send_gift: Optional[bool] = can_send_gift class Chat(ChatFullInfo): @@ -1981,6 +1985,12 @@ class Video(JsonDeserializable): :param thumbnail: Optional. Video thumbnail :type thumbnail: :class:`telebot.types.PhotoSize` + :param cover: Optional. Available sizes of the cover of the video in the message + :type cover: List[:class:`telebot.types.PhotoSize`] + + :param start_timestamp: Optional. Timestamp in seconds from which the video will play in the message + :type start_timestamp: :obj:`int` + :param file_name: Optional. Original filename as defined by sender :type file_name: :obj:`str` @@ -2001,9 +2011,12 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) if 'thumbnail' in obj and 'file_id' in obj['thumbnail']: obj['thumbnail'] = PhotoSize.de_json(obj['thumbnail']) + if 'cover' in obj: + obj['cover'] = [PhotoSize.de_json(c) for c in obj['cover']] return cls(**obj) - def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=None, file_name=None, mime_type=None, file_size=None, **kwargs): + def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=None, file_name=None, mime_type=None, file_size=None, + cover=None, start_timestamp=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.width: int = width @@ -2013,6 +2026,8 @@ def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=N self.file_name: Optional[str] = file_name self.mime_type: Optional[str] = mime_type self.file_size: Optional[int] = file_size + self.cover: Optional[List[PhotoSize]] = cover + self.start_timestamp: Optional[int] = start_timestamp @property def thumb(self) -> Optional[PhotoSize]: @@ -6787,6 +6802,14 @@ class InputMediaVideo(InputMedia): multipart/form-data under . More information on Sending Files » :type thumbnail: InputFile or :obj:`str` + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` + :param caption: Optional. Caption of the video to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -6824,7 +6847,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, caption_entities: Optional[List[MessageEntity]] = None, width: Optional[int] = None, height: Optional[int] = None, duration: Optional[int] = None, supports_streaming: Optional[bool] = None, has_spoiler: Optional[bool] = None, - show_caption_above_media: Optional[bool] = None): + show_caption_above_media: Optional[bool] = None, cover: Optional[Union[str, InputFile]] = None, + start_timestamp: Optional[int] = None): super(InputMediaVideo, self).__init__( type="video", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) self.thumbnail: Optional[Union[str, InputFile]] = thumbnail @@ -6834,6 +6858,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, 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[str] = cover + self.start_timestamp: Optional[int] = start_timestamp @property def thumb(self) -> Optional[Union[str, Any]]: @@ -6856,6 +6882,10 @@ def to_dict(self): ret['has_spoiler'] = self.has_spoiler if self.show_caption_above_media is not None: ret['show_caption_above_media'] = self.show_caption_above_media + if self.cover: + ret['cover'] = self.cover + if self.start_timestamp: + ret['start_timestamp'] = self.start_timestamp return ret @@ -10419,6 +10449,8 @@ def de_json(cls, json_string): return TransactionPartnerAffiliateProgram.de_json(obj) elif obj["type"] == "other": return TransactionPartnerOther.de_json(obj) + elif obj["type"] == "chat": + return TransactionPartnerChat.de_json(obj) # noinspection PyShadowingBuiltins @@ -10882,6 +10914,14 @@ class InputPaidMediaVideo(InputPaidMedia): More information on Sending Files » :type thumbnail: :class:`InputFile` + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` + :param width: Optional. Video width :type width: :obj:`int` @@ -10900,13 +10940,16 @@ class InputPaidMediaVideo(InputPaidMedia): """ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[InputFile] = None, width: Optional[int] = None, height: Optional[int] = None, duration: Optional[int] = None, supports_streaming: Optional[bool] = None, - **kwargs): + cover: Optional[Union[str,InputFile]] = None, start_timestamp: Optional[int] = None, **kwargs): super().__init__(type='video', media=media) self.thumbnail: Optional[Union[str,InputFile]] = thumbnail self.width: Optional[int] = width self.height: Optional[int] = height self.duration: Optional[int] = duration self.supports_streaming: Optional[bool] = supports_streaming + self.cover: Optional[Union[str,InputFile]] = cover + self.start_timestamp: Optional[int] = start_timestamp + def to_dict(self): @@ -10921,6 +10964,10 @@ def to_dict(self): data['duration'] = self.duration if self.supports_streaming is not None: data['supports_streaming'] = self.supports_streaming + if self.cover: + data['cover'] = self.cover + if self.start_timestamp: + data['start_timestamp'] = self.start_timestamp return data class RefundedPayment(JsonDeserializable): @@ -11192,3 +11239,36 @@ def de_json(cls, json_string): return cls(**obj) +class TransactionPartnerChat(TransactionPartner): + """ + Describes a transaction with a chat. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartnerchat + + :param type: Type of the transaction partner, always “chat” + :type type: :obj:`str` + + :param chat: Information about the chat + :type chat: :class:`Chat` + + :param gift: Optional. The gift sent to the chat by the bot + :type gift: :class:`Gift` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerChat` + """ + + def __init__(self, type, chat, gift=None, **kwargs): + self.type: str = type + self.chat: Chat = chat + self.gift: Optional[Gift] = gift + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj['chat']) + if 'gift' in obj: + obj['gift'] = Gift.de_json(obj['gift']) + return cls(**obj) +