def send_video( self, chat_id: Union[int, str], video: str, file_ref: str = None, caption: str = "", parse_mode: Union[str, None] = object, duration: int = 0, width: int = 0, height: int = 0, thumb: str = None, supports_streaming: bool = True, disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, reply_markup: Union["pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply"] = None, progress: callable = None, progress_args: tuple = () ) -> Union["pyrogram.Message", None]: """Send video files. Parameters: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). video (``str``): Video to send. Pass a file_id as string to send a video that exists on the Telegram servers, pass an HTTP URL as a string for Telegram to get a video from the Internet, or pass a file path as string to upload a new video that exists on your local machine. file_ref (``str``, *optional*): A valid file reference obtained by a recently fetched media message. To be used in combination with a file id in case a file reference is needed. caption (``str``, *optional*): Video caption, 0-1024 characters. parse_mode (``str``, *optional*): By default, texts are parsed using both Markdown and HTML styles. You can combine both syntaxes together. Pass "markdown" or "md" to enable Markdown-style parsing only. Pass "html" to enable HTML-style parsing only. Pass None to completely disable style parsing. duration (``int``, *optional*): Duration of sent video in seconds. width (``int``, *optional*): Video width. height (``int``, *optional*): Video height. thumb (``str``, *optional*): Thumbnail of the video sent. The thumbnail should be in JPEG format and less than 200 KB in size. A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. supports_streaming (``bool``, *optional*): Pass True, if the uploaded video is suitable for streaming. Defaults to True. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. progress (``callable``, *optional*): Pass a callback function to view the file transmission progress. The function must take *(current, total)* as positional arguments (look at Other Parameters below for a detailed description) and will be called back each time a new file chunk has been successfully transmitted. progress_args (``tuple``, *optional*): Extra custom arguments for the progress callback function. You can pass anything you need to be available in the progress callback scope; for example, a Message object or a Client instance in order to edit the message with the updated progress status. Other Parameters: current (``int``): The amount of bytes transmitted so far. total (``int``): The total size of the file. *args (``tuple``, *optional*): Extra custom arguments as defined in the *progress_args* parameter. You can either keep *\*args* or add every single extra argument in your function signature. Returns: :obj:`Message` | ``None``: On success, the sent video message is returned, otherwise, in case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Example: .. code-block:: python # Send video by uploading from local file app.send_video("me", "video.mp4") # Add caption to the video app.send_video("me", "video.mp4", caption="recording") # Keep track of the progress while uploading def progress(current, total): print("{:.1f}%".format(current * 100 / total)) app.send_video("me", "video.mp4", progress=progress) """ file = None try: if os.path.exists(video): thumb = None if thumb is None else self.save_file(thumb) file = self.save_file(video, progress=progress, progress_args=progress_args) media = types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(video) or "video/mp4", file=file, thumb=thumb, attributes=[ types.DocumentAttributeVideo( supports_streaming=supports_streaming or None, duration=duration, w=width, h=height), types.DocumentAttributeFilename( file_name=os.path.basename(video)) ]) elif video.startswith("http"): media = types.InputMediaDocumentExternal(url=video) else: media = utils.get_input_media_from_file_id(video, file_ref, 4) while True: try: r = self.send( functions.messages.SendMedia( peer=self.resolve_peer(chat_id), media=media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **self.parser.parse(caption, parse_mode))) except FilePartMissing as e: self.save_file(video, file_id=file.id, file_part=e.x) else: for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats}, is_scheduled=isinstance( i, types.UpdateNewScheduledMessage)) except BaseClient.StopTransmission: return None
def send_video_note(self, chat_id: int or str, video_note: str, duration: int = 0, length: int = 1, disable_notification: bool = None, reply_to_message_id: int = None, reply_markup=None, progress: callable = None, progress_args: tuple = ()): """Use this method to send video messages. Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). For a private channel/supergroup you can use its *t.me/joinchat/* link. video_note (``str``): Video note to send. Pass a file_id as string to send a video note that exists on the Telegram servers, or pass a file path as string to upload a new video note that exists on your local machine. Sending video notes by a URL is currently unsupported. duration (``int``, *optional*): Duration of sent video in seconds. length (``int``, *optional*): Video width and height. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. progress (``callable``, *optional*): Pass a callback function to view the upload progress. The function must take *(client, current, total, \*args)* as positional arguments (look at the section below for a detailed description). progress_args (``tuple``, *optional*): Extra custom arguments for the progress callback function. Useful, for example, if you want to pass a chat_id and a message_id in order to edit a message with the updated progress. Other Parameters: client (:obj:`Client <pyrogram.Client>`): The Client itself, useful when you want to call other API methods inside the callback function. current (``int``): The amount of bytes uploaded so far. total (``int``): The size of the file. *args (``tuple``, *optional*): Extra custom arguments as defined in the *progress_args* parameter. You can either keep *\*args* or add every single extra argument in your function signature. Returns: On success, the sent :obj:`Message <pyrogram.Message>` is returned. Raises: :class:`Error <pyrogram.Error>` """ file = None if os.path.exists(video_note): file = self.save_file(video_note, progress=progress, progress_args=progress_args) media = types.InputMediaUploadedDocument( mime_type=mimetypes.types_map[".mp4"], file=file, attributes=[ types.DocumentAttributeVideo(round_message=True, duration=duration, w=length, h=length) ]) else: try: decoded = utils.decode(video_note) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 13: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format(media_type)) else: raise FileIdInvalid("Unknown media type: {}".format( unpacked[0])) media = types.InputMediaDocument(id=types.InputDocument( id=unpacked[2], access_hash=unpacked[3])) while True: try: r = self.send( functions.messages.SendMedia( peer=self.resolve_peer(chat_id), media=media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), reply_markup=reply_markup.write() if reply_markup else None, message="")) except FilePartMissing as e: self.save_file(video_note, file_id=file.id, file_part=e.x) else: for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): return utils.parse_messages(self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats})
async def send_video_note( self, chat_id: Union[int, str], video_note: str, file_ref: str = None, duration: int = 0, length: int = 1, thumb: str = None, disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, reply_markup: Union["pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply"] = None, progress: callable = None, progress_args: tuple = () ) -> Union["pyrogram.Message", None]: """Send video messages. Parameters: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). video_note (``str``): Video note to send. Pass a file_id as string to send a video note that exists on the Telegram servers, or pass a file path as string to upload a new video note that exists on your local machine. Sending video notes by a URL is currently unsupported. file_ref (``str``, *optional*): A valid file reference obtained by a recently fetched media message. To be used in combination with a file id in case a file reference is needed. duration (``int``, *optional*): Duration of sent video in seconds. length (``int``, *optional*): Video width and height. thumb (``str``, *optional*): Thumbnail of the video sent. The thumbnail should be in JPEG format and less than 200 KB in size. A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. progress (``callable``, *optional*): Pass a callback function to view the file transmission progress. The function must take *(current, total)* as positional arguments (look at Other Parameters below for a detailed description) and will be called back each time a new file chunk has been successfully transmitted. progress_args (``tuple``, *optional*): Extra custom arguments for the progress callback function. You can pass anything you need to be available in the progress callback scope; for example, a Message object or a Client instance in order to edit the message with the updated progress status. Other Parameters: current (``int``): The amount of bytes transmitted so far. total (``int``): The total size of the file. *args (``tuple``, *optional*): Extra custom arguments as defined in the *progress_args* parameter. You can either keep *\*args* or add every single extra argument in your function signature. Returns: :obj:`Message` | ``None``: On success, the sent video note message is returned, otherwise, in case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Example: .. code-block:: python # Send video note by uploading from local file app.send_video_note("me", "video_note.mp4") # Set video note length app.send_video_note("me", "video_note.mp4", length=25) """ file = None try: if os.path.exists(video_note): thumb = None if thumb is None else await self.save_file(thumb) file = await self.save_file(video_note, progress=progress, progress_args=progress_args) media = types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(video_note) or "video/mp4", file=file, thumb=thumb, attributes=[ types.DocumentAttributeVideo(round_message=True, duration=duration, w=length, h=length) ]) else: media = utils.get_input_media_from_file_id( video_note, file_ref, 13) while True: try: r = await self.send( functions.messages.SendMedia( peer=await self.resolve_peer(chat_id), media=media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, message="")) except FilePartMissing as e: await self.save_file(video_note, file_id=file.id, file_part=e.x) else: for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats}, is_scheduled=isinstance( i, types.UpdateNewScheduledMessage)) except BaseClient.StopTransmission: return None
def send_media_group( self, chat_id: Union[int, str], media: List[Union["pyrogram.InputMediaPhoto", "pyrogram.InputMediaVideo"]], disable_notification: bool = None, reply_to_message_id: int = None) -> List["pyrogram.Message"]: """Send a group of photos or videos as an album. Parameters: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). media (List of :obj:`InputMediaPhoto` and :obj:`InputMediaVideo`): A list describing photos and videos to be sent, must include 2–10 items. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. Returns: List of :obj:`Message`: On success, a list of the sent messages is returned. Example: .. code-block:: python from pyrogram import InputMediaPhoto, InputMediaVideo app.send_media_group( "me", [ InputMediaPhoto("photo1.jpg"), InputMediaPhoto("photo2.jpg", caption="photo caption"), InputMediaVideo("video.mp4", caption="a video") ] ) """ multi_media = [] for i in media: if isinstance(i, pyrogram.InputMediaPhoto): if os.path.exists(i.media): while True: try: media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedPhoto( file=self.save_file(i.media)))) except FloodWait as e: log.warning("Sleeping for {}s".format(e.x)) time.sleep(e.x) else: break media = types.InputMediaPhoto(id=types.InputPhoto( id=media.photo.id, access_hash=media.photo.access_hash, file_reference=media.photo.file_reference)) elif i.media.startswith("http"): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaPhotoExternal(url=i.media))) media = types.InputMediaPhoto(id=types.InputPhoto( id=media.photo.id, access_hash=media.photo.access_hash, file_reference=media.photo.file_reference)) else: media = utils.get_input_media_from_file_id( i.media, i.file_ref, 2) elif isinstance(i, pyrogram.InputMediaVideo): if os.path.exists(i.media): while True: try: media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( file=self.save_file(i.media), thumb=None if i.thumb is None else self.save_file(i.thumb), mime_type=self.guess_mime_type(i.media) or "video/mp4", attributes=[ types.DocumentAttributeVideo( supports_streaming=i. supports_streaming or None, duration=i.duration, w=i.width, h=i.height), types.DocumentAttributeFilename( file_name=os.path.basename( i.media)) ]))) except FloodWait as e: log.warning("Sleeping for {}s".format(e.x)) time.sleep(e.x) else: break media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference)) elif i.media.startswith("http"): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaDocumentExternal( url=i.media))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference)) else: media = utils.get_input_media_from_file_id( i.media, i.file_ref, 4) multi_media.append( types.InputSingleMedia(media=media, random_id=self.rnd_id(), **self.parser.parse( i.caption, i.parse_mode))) while True: try: r = self.send( functions.messages.SendMultiMedia( peer=self.resolve_peer(chat_id), multi_media=multi_media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id)) except FloodWait as e: log.warning("Sleeping for {}s".format(e.x)) time.sleep(e.x) else: break return utils.parse_messages( self, types.messages.Messages(messages=[ m.message for m in filter( lambda u: isinstance(u, (types.UpdateNewMessage, types. UpdateNewChannelMessage)), r.updates) ], users=r.users, chats=r.chats))
def send_video(self, chat_id: int or str, video: str, caption: str = "", parse_mode: str = "", duration: int = 0, width: int = 0, height: int = 0, thumb: str = None, supports_streaming: bool = True, disable_notification: bool = None, reply_to_message_id: int = None, reply_markup=None, progress: callable = None, progress_args: tuple = ()): """Use this method to send video files. Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). For a private channel/supergroup you can use its *t.me/joinchat/* link. video (``str``): Video to send. Pass a file_id as string to send a video that exists on the Telegram servers, pass an HTTP URL as a string for Telegram to get a video from the Internet, or pass a file path as string to upload a new video that exists on your local machine. caption (``str``, *optional*): Video caption, 0-200 characters. parse_mode (``str``, *optional*): Use :obj:`MARKDOWN <pyrogram.ParseMode.MARKDOWN>` or :obj:`HTML <pyrogram.ParseMode.HTML>` if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your caption. Defaults to Markdown. duration (``int``, *optional*): Duration of sent video in seconds. width (``int``, *optional*): Video width. height (``int``, *optional*): Video height. thumb (``str``, *optional*): Video thumbnail. Pass a file path as string to send an image that exists on your local machine. Thumbnail should have 90 or less pixels of width and 90 or less pixels of height. supports_streaming (``bool``, *optional*): Pass True, if the uploaded video is suitable for streaming. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. progress (``callable``, *optional*): Pass a callback function to view the upload progress. The function must take *(client, current, total, \*args)* as positional arguments (look at the section below for a detailed description). progress_args (``tuple``, *optional*): Extra custom arguments for the progress callback function. Useful, for example, if you want to pass a chat_id and a message_id in order to edit a message with the updated progress. Other Parameters: client (:obj:`Client <pyrogram.Client>`): The Client itself, useful when you want to call other API methods inside the callback function. current (``int``): The amount of bytes uploaded so far. total (``int``): The size of the file. *args (``tuple``, *optional*): Extra custom arguments as defined in the *progress_args* parameter. You can either keep *\*args* or add every single extra argument in your function signature. Returns: On success, the sent :obj:`Message <pyrogram.Message>` is returned. Raises: :class:`Error <pyrogram.Error>` """ file = None style = self.html if parse_mode.lower() == "html" else self.markdown if os.path.exists(video): thumb = None if thumb is None else self.save_file(thumb) file = self.save_file(video, progress=progress, progress_args=progress_args) media = types.InputMediaUploadedDocument( mime_type=mimetypes.types_map[".mp4"], file=file, thumb=thumb, attributes=[ types.DocumentAttributeVideo( supports_streaming=supports_streaming or None, duration=duration, w=width, h=height), types.DocumentAttributeFilename(os.path.basename(video)) ]) elif video.startswith("http"): media = types.InputMediaDocumentExternal(url=video) else: try: decoded = utils.decode(video) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 4: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format(media_type)) else: raise FileIdInvalid("Unknown media type: {}".format( unpacked[0])) media = types.InputMediaDocument(id=types.InputDocument( id=unpacked[2], access_hash=unpacked[3])) while True: try: r = self.send( functions.messages.SendMedia( peer=self.resolve_peer(chat_id), media=media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), reply_markup=reply_markup.write() if reply_markup else None, **style.parse(caption))) except FilePartMissing as e: self.save_file(video, file_id=file.id, file_part=e.x) else: for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): return utils.parse_messages(self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats})
def send_media_group(self, chat_id: int or str, media: list, disable_notification: bool = None, reply_to_message_id: int = None): """Use this method to send a group of photos or videos as an album. On success, an Update containing the sent Messages is returned. Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). For a private channel/supergroup you can use its *t.me/joinchat/* link. media (``list``): A list containing either :obj:`InputMediaPhoto <pyrogram.InputMediaPhoto>` or :obj:`InputMediaVideo <pyrogram.InputMediaVideo>` objects describing photos and videos to be sent, must include 2–10 items. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. """ multi_media = [] for i in media: style = self.html if i.parse_mode.lower() == "html" else self.markdown if isinstance(i, pyrogram_types.InputMediaPhoto): if os.path.exists(i.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedPhoto( file=self.save_file(i.media) ) ) ) media = types.InputMediaPhoto( id=types.InputPhoto( id=media.photo.id, access_hash=media.photo.access_hash ) ) else: try: decoded = utils.decode(i.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 2: media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None) if media_type: raise FileIdInvalid("The file_id belongs to a {}".format(media_type)) else: raise FileIdInvalid("Unknown media type: {}".format(unpacked[0])) media = types.InputMediaPhoto( id=types.InputPhoto( id=unpacked[2], access_hash=unpacked[3] ) ) elif isinstance(i, pyrogram_types.InputMediaVideo): if os.path.exists(i.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( file=self.save_file(i.media), mime_type=mimetypes.types_map[".mp4"], attributes=[ types.DocumentAttributeVideo( supports_streaming=i.supports_streaming or None, duration=i.duration, w=i.width, h=i.height ), types.DocumentAttributeFilename(os.path.basename(i.media)) ] ) ) ) media = types.InputMediaDocument( id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash ) ) else: try: decoded = utils.decode(i.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 4: media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None) if media_type: raise FileIdInvalid("The file_id belongs to a {}".format(media_type)) else: raise FileIdInvalid("Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument( id=types.InputDocument( id=unpacked[2], access_hash=unpacked[3] ) ) multi_media.append( types.InputSingleMedia( media=media, random_id=self.rnd_id(), **style.parse(i.caption) ) ) return self.send( functions.messages.SendMultiMedia( peer=self.resolve_peer(chat_id), multi_media=multi_media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id ) )
def edit_message_media( self, chat_id: Union[int, str], message_id: int, media: InputMedia, reply_markup: "pyrogram.InlineKeyboardMarkup" = None ) -> "pyrogram.Message": """Edit audio, document, photo, or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise, message type can be changed arbitrarily. When inline message is edited, new file can't be uploaded. Use previously uploaded file via its file_id or specify a URL. On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. Parameters: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). message_id (``int``): Message identifier in the chat specified in chat_id. media (:obj:`InputMedia`) One of the InputMedia objects describing an animation, audio, document, photo or video. reply_markup (:obj:`InlineKeyboardMarkup`, *optional*): An InlineKeyboardMarkup object. Returns: :obj:`Message`: On success, the edited message is returned. Raises: RPCError: In case of a Telegram RPC error. """ style = self.html if media.parse_mode.lower( ) == "html" else self.markdown caption = media.caption if isinstance(media, InputMediaPhoto): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedPhoto( file=self.save_file(media.media)))) media = types.InputMediaPhoto( id=types.InputPhoto(id=media.photo.id, access_hash=media.photo.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaPhotoExternal(url=media.media) else: media = utils.get_input_media_from_file_id(media.media, 2) if isinstance(media, InputMediaVideo): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "video/mp4", thumb=None if media.thumb is None else self.save_file(media.thumb), file=self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=media.supports_streaming or None, duration=media.duration, w=media.width, h=media.height), types.DocumentAttributeFilename( file_name=os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: media = utils.get_input_media_from_file_id(media.media, 4) if isinstance(media, InputMediaAudio): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "audio/mpeg", thumb=None if media.thumb is None else self.save_file(media.thumb), file=self.save_file(media.media), attributes=[ types.DocumentAttributeAudio( duration=media.duration, performer=media.performer, title=media.title), types.DocumentAttributeFilename( file_name=os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: media = utils.get_input_media_from_file_id(media.media, 9) if isinstance(media, InputMediaAnimation): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "video/mp4", thumb=None if media.thumb is None else self.save_file(media.thumb), file=self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=True, duration=media.duration, w=media.width, h=media.height), types.DocumentAttributeFilename( file_name=os.path.basename(media.media)), types.DocumentAttributeAnimated() ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: media = utils.get_input_media_from_file_id(media.media, 10) if isinstance(media, InputMediaDocument): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "application/zip", thumb=None if media.thumb is None else self.save_file(media.thumb), file=self.save_file(media.media), attributes=[ types.DocumentAttributeFilename( file_name=os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: media = utils.get_input_media_from_file_id(media.media, 5) r = self.send( functions.messages.EditMessage( peer=self.resolve_peer(chat_id), id=message_id, reply_markup=reply_markup.write() if reply_markup else None, media=media, **style.parse(caption))) for i in r.updates: if isinstance( i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)): return pyrogram.Message._parse(self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats})
async def send_animation( self, chat_id: Union[int, str], animation: str, caption: str = "", unsave: bool = False, parse_mode: Union[str, None] = "", duration: int = 0, width: int = 0, height: int = 0, thumb: str = None, disable_notification: bool = None, reply_to_message_id: int = None, reply_markup: Union["pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply"] = None, progress: callable = None, progress_args: tuple = () ) -> Union["pyrogram.Message", None]: """Send animation files (animation or H.264/MPEG-4 AVC video without sound). Parameters: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). animation (``str``): Animation to send. Pass a file_id as string to send an animation that exists on the Telegram servers, pass an HTTP URL as a string for Telegram to get an animation from the Internet, or pass a file path as string to upload a new animation that exists on your local machine. caption (``str``, *optional*): Animation caption, 0-1024 characters. unsave (``bool``, *optional*): By default, the server will save into your own collection any new animation GIF you send. Pass True to automatically unsave the sent animation. Defaults to False. parse_mode (``str``, *optional*): By default, texts are parsed using both Markdown and HTML styles. You can combine both syntaxes together. Pass "markdown" to enable Markdown-style parsing only. Pass "html" to enable HTML-style parsing only. Pass None to completely disable style parsing. duration (``int``, *optional*): Duration of sent animation in seconds. width (``int``, *optional*): Animation width. height (``int``, *optional*): Animation height. thumb (``str``, *optional*): Thumbnail of the animation file sent. The thumbnail should be in JPEG format and less than 200 KB in size. A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. progress (``callable``, *optional*): Pass a callback function to view the upload progress. The function must take *(client, current, total, \*args)* as positional arguments (look at the section below for a detailed description). progress_args (``tuple``, *optional*): Extra custom arguments for the progress callback function. Useful, for example, if you want to pass a chat_id and a message_id in order to edit a message with the updated progress. Other Parameters: client (:obj:`Client`): The Client itself, useful when you want to call other API methods inside the callback function. current (``int``): The amount of bytes uploaded so far. total (``int``): The size of the file. *args (``tuple``, *optional*): Extra custom arguments as defined in the *progress_args* parameter. You can either keep *\*args* or add every single extra argument in your function signature. Returns: :obj:`Message` | ``None``: On success, the sent animation message is returned, otherwise, in case the upload is deliberately stopped with :meth:`~Client.stop_transmission`, None is returned. Raises: RPCError: In case of a Telegram RPC error. """ file = None try: if os.path.exists(animation): thumb = None if thumb is None else await self.save_file(thumb) file = await self.save_file(animation, progress=progress, progress_args=progress_args) media = types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(animation) or "video/mp4", file=file, thumb=thumb, attributes=[ types.DocumentAttributeVideo(supports_streaming=True, duration=duration, w=width, h=height), types.DocumentAttributeFilename( file_name=os.path.basename(animation)), types.DocumentAttributeAnimated() ]) elif animation.startswith("http"): media = types.InputMediaDocumentExternal(url=animation) else: media = utils.get_input_media_from_file_id(animation, 10) while True: try: r = await self.send( functions.messages.SendMedia( peer=await self.resolve_peer(chat_id), media=media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode))) except FilePartMissing as e: await self.save_file(animation, file_id=file.id, file_part=e.x) else: for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): message = await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats}) if unsave: document = message.animation or message.document document_id = utils.get_input_media_from_file_id( document.file_id).id await self.send( functions.messages.SaveGif(id=document_id, unsave=True)) return message except BaseClient.StopTransmission: return None
async def edit_message_media( self, chat_id: Union[int, str], message_id: int, media: InputMedia, reply_markup: "pyrogram.InlineKeyboardMarkup" = None ) -> "pyrogram.Message": """Edit animation, audio, document, photo or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise, the message type can be changed arbitrarily. Parameters: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). message_id (``int``): Message identifier in the chat specified in chat_id. media (:obj:`InputMedia`): One of the InputMedia objects describing an animation, audio, document, photo or video. reply_markup (:obj:`InlineKeyboardMarkup`, *optional*): An InlineKeyboardMarkup object. Returns: :obj:`Message`: On success, the edited message is returned. Example: .. code-block:: python from pyrogram import InputMediaPhoto, InputMediaVideo, InputMediaAudio # Replace the current media with a local photo app.edit_message_media(chat_id, message_id, InputMediaPhoto("new_photo.jpg")) # Replace the current media with a local video app.edit_message_media(chat_id, message_id, InputMediaVideo("new_video.mp4")) # Replace the current media with a local audio app.edit_message_media(chat_id, message_id, InputMediaAudio("new_audio.mp3")) """ caption = media.caption parse_mode = media.parse_mode if isinstance(media, InputMediaPhoto): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedPhoto( file=await self.save_file(media.media) ) ) ) media = types.InputMediaPhoto( id=types.InputPhoto( id=media.photo.id, access_hash=media.photo.access_hash, file_reference=media.photo.file_reference ) ) elif media.media.startswith("http"): media = types.InputMediaPhotoExternal( url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2) elif isinstance(media, InputMediaVideo): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "video/mp4", thumb=None if media.thumb is None else await self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=media.supports_streaming or None, duration=media.duration, w=media.width, h=media.height ), types.DocumentAttributeFilename( file_name=os.path.basename(media.media) ) ] ) ) ) media = types.InputMediaDocument( id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference ) ) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal( url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4) elif isinstance(media, InputMediaAudio): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "audio/mpeg", thumb=None if media.thumb is None else await self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeAudio( duration=media.duration, performer=media.performer, title=media.title ), types.DocumentAttributeFilename( file_name=os.path.basename(media.media) ) ] ) ) ) media = types.InputMediaDocument( id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference ) ) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal( url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9) elif isinstance(media, InputMediaAnimation): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "video/mp4", thumb=None if media.thumb is None else self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=True, duration=media.duration, w=media.width, h=media.height ), types.DocumentAttributeFilename( file_name=os.path.basename(media.media) ), types.DocumentAttributeAnimated() ] ) ) ) media = types.InputMediaDocument( id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference ) ) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal( url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10) elif isinstance(media, InputMediaDocument): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=self.guess_mime_type(media.media) or "application/zip", thumb=None if media.thumb is None else await self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeFilename( file_name=os.path.basename(media.media) ) ] ) ) ) media = types.InputMediaDocument( id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=media.document.file_reference ) ) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal( url=media.media ) else: media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5) r = await self.send( functions.messages.EditMessage( peer=await self.resolve_peer(chat_id), id=message_id, media=media, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) ) for i in r.updates: if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats} )
def send_media_group(self, chat_id: Union[int, str], media: List[Union["pyrogram.InputMediaPhoto", "pyrogram.InputMediaVideo"]], disable_notification: bool = None, reply_to_message_id: int = None): """Use this method to send a group of photos or videos as an album. Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). media (List of :obj:`InputMediaPhoto` and :obj:`InputMediaVideo`): A list describing photos and videos to be sent, must include 2–10 items. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. Returns: On success, a :obj:`Messages <pyrogram.Messages>` object is returned containing all the single messages sent. Raises: :class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. """ multi_media = [] for i in media: style = self.html if i.parse_mode.lower( ) == "html" else self.markdown if isinstance(i, pyrogram.InputMediaPhoto): if os.path.exists(i.media): while True: try: media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedPhoto( file=self.save_file(i.media)))) except FloodWait as e: log.warning("Sleeping for {}s".format(e.x)) time.sleep(e.x) else: break media = types.InputMediaPhoto(id=types.InputPhoto( id=media.photo.id, access_hash=media.photo.access_hash, file_reference=b"")) else: try: decoded = utils.decode(i.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 2: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format( unpacked[0])) media = types.InputMediaPhoto( id=types.InputPhoto(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) elif isinstance(i, pyrogram.InputMediaVideo): if os.path.exists(i.media): while True: try: media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( file=self.save_file(i.media), thumb=None if i.thumb is None else self.save_file(i.thumb), mime_type="video/mp4", attributes=[ types.DocumentAttributeVideo( supports_streaming=i. supports_streaming or None, duration=i.duration, w=i.width, h=i.height), types.DocumentAttributeFilename( file_name=os.path.basename( i.media)) ]))) except FloodWait as e: log.warning("Sleeping for {}s".format(e.x)) time.sleep(e.x) else: break media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) else: try: decoded = utils.decode(i.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 4: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format( unpacked[0])) media = types.InputMediaDocument( id=types.InputDocument(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) multi_media.append( types.InputSingleMedia(media=media, random_id=self.rnd_id(), **style.parse(i.caption))) while True: try: r = self.send( functions.messages.SendMultiMedia( peer=self.resolve_peer(chat_id), multi_media=multi_media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id)) except FloodWait as e: log.warning("Sleeping for {}s".format(e.x)) time.sleep(e.x) else: break return pyrogram.Messages._parse( self, types.messages.Messages(messages=[ m.message for m in filter( lambda u: isinstance(u, (types.UpdateNewMessage, types. UpdateNewChannelMessage)), r.updates) ], users=r.users, chats=r.chats))
async def edit_message_media( self, chat_id: Union[int, str], message_id: int, media: InputMedia, reply_markup: "pyrogram.InlineKeyboardMarkup" = None ) -> "pyrogram.Message": """Use this method to edit audio, document, photo, or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise, message type can be changed arbitrarily. When inline message is edited, new file can't be uploaded. Use previously uploaded file via its file_id or specify a URL. On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). message_id (``int``): Message identifier in the chat specified in chat_id. media (:obj:`InputMedia`) One of the InputMedia objects describing an animation, audio, document, photo or video. reply_markup (:obj:`InlineKeyboardMarkup`, *optional*): An InlineKeyboardMarkup object. Returns: On success, the edited :obj:`Message <pyrogram.Message>` is returned. Raises: :class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. """ style = self.html if media.parse_mode.lower( ) == "html" else self.markdown caption = media.caption if isinstance(media, InputMediaPhoto): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedPhoto( file=await self.save_file(media.media)))) media = types.InputMediaPhoto( id=types.InputPhoto(id=media.photo.id, access_hash=media.photo.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaPhotoExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 2: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaPhoto( id=types.InputPhoto(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) if isinstance(media, InputMediaVideo): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type="video/mp4", thumb=None if media.thumb is None else self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=media.supports_streaming or None, duration=media.duration, w=media.width, h=media.height), types.DocumentAttributeFilename( file_name=os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 4: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument( id=types.InputDocument(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) if isinstance(media, InputMediaAudio): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type="audio/mpeg", thumb=None if media.thumb is None else self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeAudio( duration=media.duration, performer=media.performer, title=media.title), types.DocumentAttributeFilename( file_name=os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 9: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument( id=types.InputDocument(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) if isinstance(media, InputMediaAnimation): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type="video/mp4", thumb=None if media.thumb is None else self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=True, duration=media.duration, w=media.width, h=media.height), types.DocumentAttributeFilename( file_name=os.path.basename(media.media)), types.DocumentAttributeAnimated() ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 10: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument( id=types.InputDocument(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) if isinstance(media, InputMediaDocument): if os.path.exists(media.media): media = await self.send( functions.messages.UploadMedia( peer=await self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type="application/zip", thumb=None if media.thumb is None else self.save_file(media.thumb), file=await self.save_file(media.media), attributes=[ types.DocumentAttributeFilename( file_name=os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash, file_reference=b"")) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] not in (5, 10): media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument( id=types.InputDocument(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) r = await self.send( functions.messages.EditMessage( peer=await self.resolve_peer(chat_id), id=message_id, reply_markup=reply_markup.write() if reply_markup else None, media=media, **await style.parse(caption))) for i in r.updates: if isinstance( i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats})
def edit_message_media(self, chat_id: int or str, message_id: int, media, reply_markup=None): style = self.html if media.parse_mode.lower( ) == "html" else self.markdown caption = media.caption if isinstance(media, InputMediaPhoto): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedPhoto( file=self.save_file(media.media)))) media = types.InputMediaPhoto(id=types.InputPhoto( id=media.photo.id, access_hash=media.photo.access_hash)) elif media.media.startswith("http"): media = types.InputMediaPhotoExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 2: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaPhoto(id=types.InputPhoto( id=unpacked[2], access_hash=unpacked[3])) if isinstance(media, InputMediaVideo): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=mimetypes.types_map[".mp4"], file=self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=media.supports_streaming or None, duration=media.duration, w=media.width, h=media.height), types.DocumentAttributeFilename( os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash)) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 4: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument(id=types.InputDocument( id=unpacked[2], access_hash=unpacked[3])) if isinstance(media, InputMediaAudio): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=mimetypes.types_map.get( "." + media.media.split(".")[-1], "audio/mpeg"), file=self.save_file(media.media), attributes=[ types.DocumentAttributeAudio( duration=media.duration, performer=media.performer, title=media.title), types.DocumentAttributeFilename( os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash)) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 9: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument(id=types.InputDocument( id=unpacked[2], access_hash=unpacked[3])) if isinstance(media, InputMediaAnimation): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=mimetypes.types_map[".mp4"], file=self.save_file(media.media), attributes=[ types.DocumentAttributeVideo( supports_streaming=True, duration=media.duration, w=media.width, h=media.height), types.DocumentAttributeFilename( os.path.basename(media.media)), types.DocumentAttributeAnimated() ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash)) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 10: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument(id=types.InputDocument( id=unpacked[2], access_hash=unpacked[3])) if isinstance(media, InputMediaDocument): if os.path.exists(media.media): media = self.send( functions.messages.UploadMedia( peer=self.resolve_peer(chat_id), media=types.InputMediaUploadedDocument( mime_type=mimetypes.types_map.get( "." + media.media.split(".")[-1], "text/plain"), file=self.save_file(media.media), attributes=[ types.DocumentAttributeFilename( os.path.basename(media.media)) ]))) media = types.InputMediaDocument(id=types.InputDocument( id=media.document.id, access_hash=media.document.access_hash)) elif media.media.startswith("http"): media = types.InputMediaDocumentExternal(url=media.media) else: try: decoded = utils.decode(media.media) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] not in (5, 10): media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument(id=types.InputDocument( id=unpacked[2], access_hash=unpacked[3])) r = self.send( functions.messages.EditMessage( peer=self.resolve_peer(chat_id), id=message_id, reply_markup=reply_markup.write() if reply_markup else None, media=media, **style.parse(caption))) for i in r.updates: if isinstance( i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)): return utils.parse_messages(self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats})
async def send_animation( self, chat_id: Union[int, str], animation: str, caption: str = "", parse_mode: str = "", duration: int = 0, width: int = 0, height: int = 0, thumb: str = None, disable_notification: bool = None, reply_to_message_id: int = None, reply_markup: Union["pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply"] = None, progress: callable = None, progress_args: tuple = () ) -> Union["pyrogram.Message", None]: """Use this method to send animation files (animation or H.264/MPEG-4 AVC video without sound). Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). animation (``str``): Animation to send. Pass a file_id as string to send an animation that exists on the Telegram servers, pass an HTTP URL as a string for Telegram to get an animation from the Internet, or pass a file path as string to upload a new animation that exists on your local machine. caption (``str``, *optional*): Animation caption, 0-1024 characters. parse_mode (``str``, *optional*): Use :obj:`MARKDOWN <pyrogram.ParseMode.MARKDOWN>` or :obj:`HTML <pyrogram.ParseMode.HTML>` if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your caption. Defaults to Markdown. duration (``int``, *optional*): Duration of sent animation in seconds. width (``int``, *optional*): Animation width. height (``int``, *optional*): Animation height. thumb (``str``, *optional*): Thumbnail of the animation file sent. The thumbnail should be in JPEG format and less than 200 KB in size. A thumbnail's width and height should not exceed 90 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. progress (``callable``, *optional*): Pass a callback function to view the upload progress. The function must take *(client, current, total, \*args)* as positional arguments (look at the section below for a detailed description). progress_args (``tuple``, *optional*): Extra custom arguments for the progress callback function. Useful, for example, if you want to pass a chat_id and a message_id in order to edit a message with the updated progress. Other Parameters: client (:obj:`Client <pyrogram.Client>`): The Client itself, useful when you want to call other API methods inside the callback function. current (``int``): The amount of bytes uploaded so far. total (``int``): The size of the file. *args (``tuple``, *optional*): Extra custom arguments as defined in the *progress_args* parameter. You can either keep *\*args* or add every single extra argument in your function signature. Returns: On success, the sent :obj:`Message <pyrogram.Message>` is returned. In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. """ file = None style = self.html if parse_mode.lower() == "html" else self.markdown try: if os.path.exists(animation): thumb = None if thumb is None else await self.save_file(thumb) file = await self.save_file(animation, progress=progress, progress_args=progress_args) media = types.InputMediaUploadedDocument( mime_type="video/mp4", file=file, thumb=thumb, attributes=[ types.DocumentAttributeVideo(supports_streaming=True, duration=duration, w=width, h=height), types.DocumentAttributeFilename( file_name=os.path.basename(animation)), types.DocumentAttributeAnimated() ]) elif animation.startswith("http"): media = types.InputMediaDocumentExternal(url=animation) else: try: decoded = utils.decode(animation) fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq" unpacked = struct.unpack(fmt, decoded) except (AssertionError, binascii.Error, struct.error): raise FileIdInvalid from None else: if unpacked[0] != 10: media_type = BaseClient.MEDIA_TYPE_ID.get( unpacked[0], None) if media_type: raise FileIdInvalid( "The file_id belongs to a {}".format( media_type)) else: raise FileIdInvalid( "Unknown media type: {}".format(unpacked[0])) media = types.InputMediaDocument( id=types.InputDocument(id=unpacked[2], access_hash=unpacked[3], file_reference=b"")) while True: try: r = await self.send( functions.messages.SendMedia( peer=await self.resolve_peer(chat_id), media=media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), reply_markup=reply_markup.write() if reply_markup else None, **await style.parse(caption))) except FilePartMissing as e: await self.save_file(animation, file_id=file.id, file_part=e.x) else: for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats}) except BaseClient.StopTransmission: return None