Pyrofork: Fix video cover

Signed-off-by: Yasir Aris <git@yasir.id>
This commit is contained in:
Yasir Aris M 2025-02-25 11:18:02 +07:00 committed by wulan17
parent 8528eea303
commit c31d41e3d3
No known key found for this signature in database
GPG key ID: 318CD6CD3A6AC0A5
3 changed files with 83 additions and 22 deletions

View file

@ -23,10 +23,7 @@ from datetime import datetime
from typing import Union, BinaryIO, List, Optional, Callable
import pyrogram
from pyrogram import StopTransmission, enums
from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram import StopTransmission, enums, raw, types, utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
@ -55,7 +52,7 @@ class SendVideo:
reply_to_chat_id: Union[int, str] = None,
quote_text: str = None,
quote_entities: List["types.MessageEntity"] = None,
cover: Optional[Union[str, "io.BytesIO"]] = None,
cover: Union[str, BinaryIO] = None,
start_timestamp: int = None,
schedule_date: datetime = None,
protect_content: bool = None,
@ -161,8 +158,12 @@ class SendVideo:
List of special entities that appear in quote_text, which can be specified instead of *parse_mode*.
for reply_to_message only.
cover (``str`` | :obj:`io.BytesIO`, *optional*):
Cover of the video; pass None to skip cover uploading.
cover (``str`` | ``BinaryIO``, *optional*):
Video cover.
Pass a file_id as string to attach a photo that exists on the Telegram servers,
pass a HTTP URL as a string for Telegram to get a video from the Internet,
pass a file path as string to upload a new photo civer that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
start_timestamp (``int``, *optional*):
Timestamp from which the video playing must start, in seconds.
@ -224,6 +225,9 @@ class SendVideo:
# Send self-destructing video
await app.send_video("me", "video.mp4", ttl_seconds=10)
# Add video_cover to the video
await app.send_video(channel_id, "video.mp4", video_cover="coverku.jpg")
# Keep track of the progress while uploading
async def progress(current, total):
print(f"{current * 100 / total:.1f}%")
@ -231,6 +235,9 @@ class SendVideo:
await app.send_video("me", "video.mp4", progress=progress)
"""
file = None
vidcover_file = None
vidcover_media = None
peer = await self.resolve_peer(chat_id)
reply_to = await utils.get_reply_to(
client=self,
@ -245,6 +252,45 @@ class SendVideo:
)
try:
if cover is not None:
if isinstance(cover, str):
if os.path.isfile(cover):
vidcover_media = await self.invoke(
raw.functions.messages.UploadMedia(
peer=peer,
media=raw.types.InputMediaUploadedPhoto(
file=await self.save_file(cover)
)
)
)
elif re.match("^https?://", cover):
vidcover_media = await self.invoke(
raw.functions.messages.UploadMedia(
peer=peer,
media=raw.types.InputMediaPhotoExternal(
url=cover
)
)
)
else:
vidcover_file = utils.get_input_media_from_file_id(cover, FileType.PHOTO).id
else:
vidcover_media = await self.invoke(
raw.functions.messages.UploadMedia(
peer=peer,
media=raw.types.InputMediaUploadedPhoto(
file=await self.save_file(cover)
)
)
)
if vidcover_media:
vidcover_file = raw.types.InputPhoto(
id=vidcover_media.photo.id,
access_hash=vidcover_media.photo.access_hash,
file_reference=vidcover_media.photo.file_reference
)
if isinstance(video, str):
if os.path.isfile(video):
thumb = await self.save_file(thumb)
@ -264,7 +310,7 @@ class SendVideo:
),
raw.types.DocumentAttributeFilename(file_name=file_name or os.path.basename(video))
],
video_cover=await self.save_file(cover) if cover else None,
video_cover=vidcover_file,
video_timestamp=start_timestamp
)
elif re.match("^https?://", video):
@ -272,7 +318,7 @@ class SendVideo:
url=video,
ttl_seconds=ttl_seconds,
spoiler=has_spoiler,
video_cover=await self.save_file(cover) if cover else None,
video_cover=vidcover_file,
video_timestamp=start_timestamp
)
else:
@ -296,14 +342,14 @@ class SendVideo:
),
raw.types.DocumentAttributeFilename(file_name=file_name or video.name)
],
video_cover=await self.save_file(cover) if cover else None,
video_cover=vidcover_file,
video_timestamp=start_timestamp
)
while True:
try:
rpc = raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
peer=peer,
media=media,
silent=disable_notification or None,
reply_to=reply_to,

View file

@ -23,9 +23,7 @@ from functools import partial
from typing import List, Match, Union, BinaryIO, Optional, Callable
import pyrogram
from pyrogram import raw, enums
from pyrogram import types
from pyrogram import utils
from pyrogram import enums, raw, types, utils
from pyrogram.errors import ChannelPrivate, MessageIdsEmpty, PeerIdInvalid
from pyrogram.parser import utils as parser_utils, Parser
from ..object import Object
@ -1115,7 +1113,7 @@ class Message(Object, Update):
video_note = types.VideoNote._parse(client, doc, video_attributes)
media_type = enums.MessageMediaType.VIDEO_NOTE
else:
video = types.Video._parse(client, doc, video_attributes, file_name, media.ttl_seconds)
video = types.Video._parse(client, doc, video_attributes, file_name, media.ttl_seconds, media.video_cover, media.video_timestamp)
media_type = enums.MessageMediaType.VIDEO
has_media_spoiler = media.spoiler
@ -3600,7 +3598,7 @@ class Message(Object, Update):
quote_entities: List["types.MessageEntity"] = None,
allow_paid_broadcast: bool = None,
message_effect_id: int = None,
cover: Optional[Union[str, "io.BytesIO"]] = None,
cover: Union[str, BinaryIO] = None,
start_timestamp: int = None,
schedule_date: datetime = None,
invert_media: bool = None,
@ -3707,8 +3705,12 @@ class Message(Object, Update):
allow_paid_broadcast (``bool``, *optional*):
Pass True to allow the message to ignore regular broadcast limits for a small fee; for bots.
cover (``str`` | :obj:`io.BytesIO`, *optional*):
Cover of the video; pass None to skip cover uploading.
cover (``str`` | ``BinaryIO``, *optional*):
Video cover.
Pass a file_id as string to attach a photo that exists on the Telegram servers,
pass a HTTP URL as a string for Telegram to get a video from the Internet,
pass a file path as string to upload a new photo civer that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
start_timestamp (``int``, *optional*):
Timestamp from which the video playing must start, in seconds.

View file

@ -21,8 +21,7 @@ from datetime import datetime
from typing import List
import pyrogram
from pyrogram import raw, utils
from pyrogram import types
from pyrogram import raw, types, utils
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType, ThumbnailSource
from ..object import Object
@ -67,6 +66,12 @@ class Video(Object):
thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Video thumbnails.
cover (:obj:`~pyrogram.types.Photo`, *optional*):
Video cover.
start_timestamp (``int``, *optional*):
Video startpoint, in seconds.
"""
def __init__(
@ -84,7 +89,9 @@ class Video(Object):
supports_streaming: bool = None,
ttl_seconds: int = None,
date: datetime = None,
thumbs: List["types.Thumbnail"] = None
thumbs: List["types.Thumbnail"] = None,
cover: "types.Photo" = None,
start_timestamp: int = None,
):
super().__init__(client)
@ -100,6 +107,8 @@ class Video(Object):
self.ttl_seconds = ttl_seconds
self.date = date
self.thumbs = thumbs
self.cover = cover
self.start_timestamp = start_timestamp
@staticmethod
def _parse(
@ -107,7 +116,9 @@ class Video(Object):
video: "raw.types.Document",
video_attributes: "raw.types.DocumentAttributeVideo",
file_name: str,
ttl_seconds: int = None
ttl_seconds: int = None,
cover = None,
start_timestamp: int = None
) -> "Video":
return Video(
file_id=FileId(
@ -131,5 +142,7 @@ class Video(Object):
date=utils.timestamp_to_datetime(video.date),
ttl_seconds=ttl_seconds,
thumbs=types.Thumbnail._parse(client, video),
cover=types.Photo._parse(client, cover),
start_timestamp=start_timestamp,
client=client
)