Skip to content

Api 8.3 Cover & Start Timestamp #4682

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions telegram/_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,7 @@ async def forward_message(
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,
Expand All @@ -1242,6 +1243,10 @@ async def forward_message(
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|

Expand All @@ -1260,6 +1265,7 @@ async def forward_message(
"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(
Expand Down Expand Up @@ -1955,6 +1961,8 @@ async def send_video(
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,
Expand Down Expand Up @@ -2002,6 +2010,13 @@ async def send_video(
|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.
Expand Down Expand Up @@ -2088,6 +2103,8 @@ async def send_video(
"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,
Expand Down Expand Up @@ -7974,6 +7991,7 @@ async def copy_message(
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,
Expand All @@ -7993,6 +8011,10 @@ async def copy_message(
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.
Expand Down Expand Up @@ -8083,6 +8105,7 @@ async def copy_message(
"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(
Expand Down
2 changes: 2 additions & 0 deletions telegram/_callbackquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ async def copy_message(
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,
Expand Down Expand Up @@ -864,6 +865,7 @@ async def copy_message(
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,
Expand Down
12 changes: 12 additions & 0 deletions telegram/_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1940,6 +1940,8 @@ async def send_video(
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,
Expand Down Expand Up @@ -1978,6 +1980,8 @@ async def send_video(
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,
Expand Down Expand Up @@ -2199,6 +2203,7 @@ async def send_copy(
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,
Expand All @@ -2225,6 +2230,7 @@ async def send_copy(
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,
Expand Down Expand Up @@ -2257,6 +2263,7 @@ async def copy_message(
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,
Expand All @@ -2283,6 +2290,7 @@ async def copy_message(
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,
Expand Down Expand Up @@ -2398,6 +2406,7 @@ async def forward_from(
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,
Expand All @@ -2423,6 +2432,7 @@ async def forward_from(
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,
Expand All @@ -2440,6 +2450,7 @@ async def forward_to(
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,
Expand All @@ -2466,6 +2477,7 @@ async def forward_to(
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,
Expand Down
52 changes: 51 additions & 1 deletion telegram/_files/inputmedia.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -225,14 +232,29 @@ 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.
supports_streaming (:obj:`bool`): Optional. :obj:`True`, if the uploaded video is
suitable for streaming.
"""

__slots__ = ("duration", "height", "supports_streaming", "thumbnail", "width")
__slots__ = (
"cover",
"duration",
"height",
"start_timestamp",
"supports_streaming",
"thumbnail",
"width",
)

def __init__(
self,
Expand All @@ -242,6 +264,8 @@ def __init__(
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,
):
Expand All @@ -264,6 +288,10 @@ def __init__(
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):
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand All @@ -594,6 +638,8 @@ def __init__(
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,
):
Expand Down Expand Up @@ -625,6 +671,10 @@ def __init__(
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):
Expand Down
44 changes: 42 additions & 2 deletions telegram/_files/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -79,6 +106,8 @@ def __init__(
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,
):
Expand All @@ -97,3 +126,14 @@ def __init__(
# 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)
Loading
Loading