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
Esempio n. 2
0
    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
Esempio n. 4
0
    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))
Esempio n. 5
0
    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
            )
        )
Esempio n. 7
0
    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
Esempio n. 9
0
    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}
                )
Esempio n. 10
0
    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))
Esempio n. 11
0
    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})
Esempio n. 12
0
    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})
Esempio n. 13
0
    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