async def delete_profile_photos(
        self: "pyrogram.Client",
        photo_ids: Union[str, List[str]]
    ) -> bool:
        """Delete your own profile photos.

        Parameters:
            photo_ids (``str`` | List of ``str``):
                A single :obj:`~pyrogram.types.Photo` id as string or multiple ids as list of strings for deleting
                more than one photos at once.

        Returns:
            ``bool``: True on success.

        Example:
            .. code-block:: python

                # Get the photos to be deleted
                photos = await app.get_profile_photos("me")

                # Delete one photo
                await app.delete_profile_photos(photos[0].file_id)

                # Delete the rest of the photos
                await app.delete_profile_photos([p.file_id for p in photos[1:]])
        """
        photo_ids = photo_ids if isinstance(photo_ids, list) else [photo_ids]
        input_photos = [utils.get_input_media_from_file_id(i, FileType.PHOTO).id for i in photo_ids]

        return bool(await self.invoke(
            raw.functions.photos.DeletePhotos(
                id=input_photos
            )
        ))
    async def write(self):
        document = get_input_media_from_file_id(self.file_id)

        return raw.types.InputBotInlineResultDocument(
            id=self.id,
            type=self.type,
            title=self.title,
            description=self.description,
            document=document.id,
            send_message=(
                await self.input_message_content.write(self.reply_markup)
                if self.input_message_content
                else raw.types.InputBotInlineMessageMediaAuto(
                    reply_markup=self.reply_markup.write() if self.reply_markup else None,
                    **await(Parser(None)).parse(self.caption, self.parse_mode)
                )
            )
        )
Esempio n. 3
0
    async def write(self, client: "pyrogram.Client"):
        audio = utils.get_input_media_from_file_id(self.file_id,
                                                   FileType.AUDIO)

        message, entities = (await utils.parse_text_entities(
            client, self.caption, self.parse_mode,
            self.caption_entities)).values()
        print(audio)
        return raw.types.InputBotInlineResultDocument(
            id=self.id,
            type=self.type,
            document=audio,
            send_message=(await self.input_message_content.write(
                client, self.reply_markup) if self.input_message_content else
                          raw.types.InputBotInlineMessageMediaAuto(
                              reply_markup=await self.reply_markup.write(
                                  client) if self.reply_markup else None,
                              message=message,
                              entities=entities)))
    async def send_media_group(
        self,
        chat_id: Union[int, str],
        media: List[Union["types.InputMediaPhoto", "types.InputMediaVideo"]],
        disable_notification: bool = None,
        reply_to_message_id: int = None
    ) -> List["types.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:`~pyrogram.types.InputMediaPhoto` and :obj:`~pyrogram.types.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:`~pyrogram.types.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, types.InputMediaPhoto):
                if os.path.isfile(i.media):
                    media = await self.send(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaUploadedPhoto(
                                file=await self.save_file(i.media)
                            )
                        )
                    )

                    media = raw.types.InputMediaPhoto(
                        id=raw.types.InputPhoto(
                            id=media.photo.id,
                            access_hash=media.photo.access_hash,
                            file_reference=media.photo.file_reference
                        )
                    )
                elif re.match("^https?://", i.media):
                    media = await self.send(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaPhotoExternal(
                                url=i.media
                            )
                        )
                    )

                    media = raw.types.InputMediaPhoto(
                        id=raw.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, types.InputMediaVideo):
                if os.path.isfile(i.media):
                    media = await self.send(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaUploadedDocument(
                                file=await self.save_file(i.media),
                                thumb=await self.save_file(i.thumb),
                                mime_type=self.guess_mime_type(i.media) or "video/mp4",
                                attributes=[
                                    raw.types.DocumentAttributeVideo(
                                        supports_streaming=i.supports_streaming or None,
                                        duration=i.duration,
                                        w=i.width,
                                        h=i.height
                                    ),
                                    raw.types.DocumentAttributeFilename(file_name=os.path.basename(i.media))
                                ]
                            )
                        )
                    )

                    media = raw.types.InputMediaDocument(
                        id=raw.types.InputDocument(
                            id=media.document.id,
                            access_hash=media.document.access_hash,
                            file_reference=media.document.file_reference
                        )
                    )
                elif re.match("^https?://", i.media):
                    media = await self.send(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaDocumentExternal(
                                url=i.media
                            )
                        )
                    )

                    media = raw.types.InputMediaDocument(
                        id=raw.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(
                raw.types.InputSingleMedia(
                    media=media,
                    random_id=self.rnd_id(),
                    **await self.parser.parse(i.caption, i.parse_mode)
                )
            )

        r = await self.send(
            raw.functions.messages.SendMultiMedia(
                peer=await self.resolve_peer(chat_id),
                multi_media=multi_media,
                silent=disable_notification or None,
                reply_to_msg_id=reply_to_message_id
            ),
            sleep_threshold=60
        )

        return await utils.parse_messages(
            self,
            raw.types.messages.Messages(
                messages=[m.message for m in filter(
                    lambda u: isinstance(u, (raw.types.UpdateNewMessage, raw.types.UpdateNewChannelMessage)),
                    r.updates
                )],
                users=r.users,
                chats=r.chats
            )
        )
Esempio n. 5
0
    async def send_cached_media(
        self,
        chat_id: Union[int, str],
        file_id: str,
        caption: str = "",
        parse_mode: Union[str, None] = object,
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: int = None,
        reply_markup: Union["types.InlineKeyboardMarkup",
                            "types.ReplyKeyboardMarkup",
                            "types.ReplyKeyboardRemove",
                            "types.ForceReply"] = None
    ) -> Union["types.Message", None]:
        """Send any media stored on the Telegram servers using a file_id.

        This convenience method works with any valid file_id only.
        It does the same as calling the relevant method for sending media using a file_id, thus saving you from the
        hassle of using the correct method for the media the file_id is pointing to.

        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).

            file_id (``str``):
                Media to send.
                Pass a file_id as string to send a media that exists on the Telegram servers.

            caption (``str``, *optional*):
                Media 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.

            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:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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.

        Returns:
            :obj:`~pyrogram.types.Message`: On success, the sent media message is returned.

        Example:
            .. code-block:: python

                app.send_cached_media("me", "CAADBAADzg4AAvLQYAEz_x2EOgdRwBYE")
        """

        r = await self.send(
            raw.functions.messages.SendMedia(
                peer=await self.resolve_peer(chat_id),
                media=utils.get_input_media_from_file_id(file_id),
                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,
                **await self.parser.parse(caption, parse_mode)))

        for i in r.updates:
            if isinstance(
                    i,
                (raw.types.UpdateNewMessage, raw.types.UpdateNewChannelMessage,
                 raw.types.UpdateNewScheduledMessage)):
                return await types.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, raw.types.UpdateNewScheduledMessage))
    async def send_voice(
        self,
        chat_id: Union[int, str],
        voice: Union[str, BinaryIO],
        caption: str = "",
        parse_mode: Optional[str] = object,
        caption_entities: List["types.MessageEntity"] = None,
        duration: int = 0,
        disable_notification: bool = None,
        send_in_background: bool = True,
        reply_to_message_id: int = None,
        schedule_date: int = None,
        reply_markup: Union["types.InlineKeyboardMarkup",
                            "types.ReplyKeyboardMarkup",
                            "types.ReplyKeyboardRemove",
                            "types.ForceReply"] = None,
        progress: callable = None,
        progress_args: tuple = ()
    ) -> Optional["types.Message"]:
        """Send audio 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).

            voice (``str`` | ``BinaryIO``):
                Audio file to send.
                Pass a file_id as string to send an audio that exists on the Telegram servers,
                pass an HTTP URL as a string for Telegram to get an audio from the Internet,
                pass a file path as string to upload a new audio that exists on your local machine, or
                pass a binary file-like object with its attribute ".name" set for in-memory uploads.

            caption (``str``, *optional*):
                Voice message 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.

            caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
                List of special entities that appear in the caption, which can be specified instead of *parse_mode*.

            duration (``int``, *optional*):
                Duration of the voice message in seconds.

            disable_notification (``bool``, *optional*):
                Sends the message silently.
                Users will receive a notification with no sound.
            
            send_in_background (``bool``, *optional*):
                Sends the message in background.
                Defaults to True.

            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:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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:`~pyrogram.types.Message` | ``None``: On success, the sent voice message is returned, otherwise, in
            case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.

        Example:
            .. code-block:: python

                # Send voice note by uploading from local file
                app.send_voice("me", "voice.ogg")

                # Add caption to the voice note
                app.send_voice("me", "voice.ogg", caption="voice note")

                # Set voice note duration
                app.send_voice("me", "voice.ogg", duration=20)
        """
        file = None

        try:
            if isinstance(voice, str):
                if os.path.isfile(voice):
                    file = await self.save_file(voice,
                                                progress=progress,
                                                progress_args=progress_args)
                    media = raw.types.InputMediaUploadedDocument(
                        mime_type=self.guess_mime_type(voice) or "audio/mpeg",
                        file=file,
                        attributes=[
                            raw.types.DocumentAttributeAudio(voice=True,
                                                             duration=duration)
                        ])
                elif re.match("^https?://", voice):
                    media = raw.types.InputMediaDocumentExternal(url=voice)
                else:
                    media = utils.get_input_media_from_file_id(
                        voice, FileType.VOICE)
            else:
                file = await self.save_file(voice,
                                            progress=progress,
                                            progress_args=progress_args)
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(voice.name) or "audio/mpeg",
                    file=file,
                    attributes=[
                        raw.types.DocumentAttributeAudio(voice=True,
                                                         duration=duration)
                    ])

            while True:
                try:
                    r = await self.send(
                        raw.functions.messages.SendMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=media,
                            silent=disable_notification or None,
                            background=send_in_background,
                            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,
                            **await
                            utils.parse_text_entities(self, caption,
                                                      parse_mode,
                                                      caption_entities)))
                except FilePartMissing as e:
                    await self.save_file(voice, file_id=file.id, file_part=e.x)
                else:
                    for i in r.updates:
                        if isinstance(i,
                                      (raw.types.UpdateNewMessage,
                                       raw.types.UpdateNewChannelMessage,
                                       raw.types.UpdateNewScheduledMessage)):
                            return await types.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, raw.types.UpdateNewScheduledMessage))
        except StopTransmission:
            return None
Esempio n. 7
0
    async def send_animation(
        self,
        chat_id: Union[int, str],
        animation: Union[str, BinaryIO],
        file_ref: str = None,
        caption: str = "",
        unsave: bool = False,
        parse_mode: Union[str, None] = object,
        duration: int = 0,
        width: int = 0,
        height: int = 0,
        thumb: Union[str, BinaryIO] = None,
        file_name: str = None,
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: int = None,
        reply_markup: Union["types.InlineKeyboardMarkup",
                            "types.ReplyKeyboardMarkup",
                            "types.ReplyKeyboardRemove",
                            "types.ForceReply"] = None,
        progress: callable = None,
        progress_args: tuple = ()
    ) -> Union["types.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`` | ``BinaryIO``):
                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,
                pass a file path as string to upload a new animation that exists on your local machine, or
                pass a binary file-like object with its attribute ".name" set for in-memory uploads.

            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*):
                Animation caption, 0-1024 characters.

            unsave (``bool``, *optional*):
                By default, the server will save into your own collection any new animation 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" 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 animation in seconds.

            width (``int``, *optional*):
                Animation width.

            height (``int``, *optional*):
                Animation height.

            thumb (``str`` | ``BinaryIO``, *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.

            file_name (``str``, *optional*):
                File name of the animation sent.
                Defaults to file's path basename.

            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:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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:`~pyrogram.types.Message` | ``None``: On success, the sent animation message is returned, otherwise,
            in case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is
            returned.

        Example:
            .. code-block:: python

                # Send animation by uploading from local file
                app.send_animation("me", "animation.gif")

                # Add caption to the animation
                app.send_animation("me", "animation.gif", caption="cat")

                # Unsave the animation once is sent
                app.send_animation("me", "animation.gif", unsave=True)

                # Keep track of the progress while uploading
                def progress(current, total):
                    print(f"{current * 100 / total:.1f}%")

                app.send_animation("me", "animation.gif", progress=progress)
        """
        file = None

        try:
            if isinstance(animation, str):
                if os.path.isfile(animation):
                    thumb = await self.save_file(thumb)
                    file = await self.save_file(animation,
                                                progress=progress,
                                                progress_args=progress_args)
                    media = raw.types.InputMediaUploadedDocument(
                        mime_type=self.guess_mime_type(animation)
                        or "video/mp4",
                        file=file,
                        thumb=thumb,
                        attributes=[
                            raw.types.DocumentAttributeVideo(
                                supports_streaming=True,
                                duration=duration,
                                w=width,
                                h=height),
                            raw.types.DocumentAttributeFilename(
                                file_name=file_name
                                or os.path.basename(animation)),
                            raw.types.DocumentAttributeAnimated()
                        ])
                elif re.match("^https?://", animation):
                    media = raw.types.InputMediaDocumentExternal(url=animation)
                else:
                    media = utils.get_input_media_from_file_id(
                        animation, file_ref, 10)
            else:
                thumb = await self.save_file(thumb)
                file = await self.save_file(animation,
                                            progress=progress,
                                            progress_args=progress_args)
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(animation.name)
                    or "video/mp4",
                    file=file,
                    thumb=thumb,
                    attributes=[
                        raw.types.DocumentAttributeVideo(
                            supports_streaming=True,
                            duration=duration,
                            w=width,
                            h=height),
                        raw.types.DocumentAttributeFilename(
                            file_name=animation.name),
                        raw.types.DocumentAttributeAnimated()
                    ])

            while True:
                try:
                    r = await self.send(
                        raw.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,
                            **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,
                                      (raw.types.UpdateNewMessage,
                                       raw.types.UpdateNewChannelMessage,
                                       raw.types.UpdateNewScheduledMessage)):
                            message = await types.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, raw.types.UpdateNewScheduledMessage))

                            if unsave:
                                document = message.animation or message.document
                                document_id = utils.get_input_media_from_file_id(
                                    document.file_id, document.file_ref).id

                                await self.send(
                                    raw.functions.messages.SaveGif(
                                        id=document_id, unsave=True))

                            return message

        except StopTransmission:
            return None
Esempio n. 8
0
    async def set_chat_photo(
        self: "pyrogram.Client",
        chat_id: Union[int, str],
        *,
        photo: Union[str, BinaryIO] = None,
        video: Union[str, BinaryIO] = None,
        video_start_ts: float = None,
    ) -> bool:
        """Set a new chat photo or video (H.264/MPEG-4 AVC video, max 5 seconds).

        The ``photo`` and ``video`` arguments are mutually exclusive.
        Pass either one as named argument (see examples below).

        You must be an administrator in the chat for this to work and must have the appropriate admin rights.

        Parameters:
            chat_id (``int`` | ``str``):
                Unique identifier (int) or username (str) of the target chat.

            photo (``str`` | ``BinaryIO``, *optional*):
                New chat photo. You can pass a :obj:`~pyrogram.types.Photo` file_id, a file path to upload a new photo
                from your local machine or a binary file-like object with its attribute
                ".name" set for in-memory uploads.

            video (``str`` | ``BinaryIO``, *optional*):
                New chat video. You can pass a :obj:`~pyrogram.types.Video` file_id, a file path to upload a new video
                from your local machine or a binary file-like object with its attribute
                ".name" set for in-memory uploads.

            video_start_ts (``float``, *optional*):
                The timestamp in seconds of the video frame to use as photo profile preview.

        Returns:
            ``bool``: True on success.

        Raises:
            ValueError: if a chat_id belongs to user.

        Example:
            .. code-block:: python

                # Set chat photo using a local file
                await app.set_chat_photo(chat_id, photo="photo.jpg")

                # Set chat photo using an exiting Photo file_id
                await app.set_chat_photo(chat_id, photo=photo.file_id)


                # Set chat video using a local file
                await app.set_chat_photo(chat_id, video="video.mp4")

                # Set chat photo using an exiting Video file_id
                await app.set_chat_photo(chat_id, video=video.file_id)
        """
        peer = await self.resolve_peer(chat_id)

        if isinstance(photo, str):
            if os.path.isfile(photo):
                photo = raw.types.InputChatUploadedPhoto(
                    file=await self.save_file(photo),
                    video=await self.save_file(video),
                    video_start_ts=video_start_ts,
                )
            else:
                photo = utils.get_input_media_from_file_id(
                    photo, FileType.PHOTO)
                photo = raw.types.InputChatPhoto(id=photo.id)
        else:
            photo = raw.types.InputChatUploadedPhoto(
                file=await self.save_file(photo),
                video=await self.save_file(video),
                video_start_ts=video_start_ts,
            )

        if isinstance(peer, raw.types.InputPeerChat):
            await self.invoke(
                raw.functions.messages.EditChatPhoto(
                    chat_id=peer.chat_id,
                    photo=photo,
                ))
        elif isinstance(peer, raw.types.InputPeerChannel):
            await self.invoke(
                raw.functions.channels.EditPhoto(channel=peer, photo=photo))
        else:
            raise ValueError(f'The chat_id "{chat_id}" belongs to a user')

        return True
Esempio n. 9
0
    async def send_document(
        self,
        chat_id: Union[int, str],
        document: Union[str, BinaryIO],
        thumb: Union[str, BinaryIO] = None,
        caption: str = "",
        parse_mode: Optional[str] = object,
        caption_entities: List["types.MessageEntity"] = None,
        file_name: str = None,
        force_document: bool = None,
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: int = None,
        protect_content: bool = None,
        reply_markup: Union["types.InlineKeyboardMarkup",
                            "types.ReplyKeyboardMarkup",
                            "types.ReplyKeyboardRemove",
                            "types.ForceReply"] = None,
        progress: callable = None,
        progress_args: tuple = ()
    ) -> Optional["types.Message"]:
        """Send generic 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).

            document (``str`` | ``BinaryIO``):
                File to send.
                Pass a file_id as string to send a file that exists on the Telegram servers,
                pass an HTTP URL as a string for Telegram to get a file from the Internet,
                pass a file path as string to upload a new file that exists on your local machine, or
                pass a binary file-like object with its attribute ".name" set for in-memory uploads.

            thumb (``str`` | ``BinaryIO``, *optional*):
                Thumbnail of the 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.

            caption (``str``, *optional*):
                Document 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.

            caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
                List of special entities that appear in the caption, which can be specified instead of *parse_mode*.

            file_name (``str``, *optional*):
                File name of the document sent.
                Defaults to file's path basename.

            force_document (``bool``, *optional*):
                Pass True to force sending files as document. Useful for video files that need to be sent as
                document messages instead of video messages.
                Defaults to False.

            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.

            protect_content (``bool``, *optional*):
                Protects the contents of the sent message from forwarding and saving.

            reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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:`~pyrogram.types.Message` | ``None``: On success, the sent document message is returned, otherwise, in
            case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.

        Example:
            .. code-block:: python

                # Send document by uploading from local file
                app.send_document("me", "document.zip")

                # Add caption to the document file
                app.send_document("me", "document.zip", caption="document caption")

                # Keep track of the progress while uploading
                def progress(current, total):
                    print(f"{current * 100 / total:.1f}%")

                app.send_document("me", "document.zip", progress=progress)
        """
        file = None

        try:
            if isinstance(document, str):
                if os.path.isfile(document):
                    thumb = await self.save_file(thumb)
                    file = await self.save_file(document,
                                                progress=progress,
                                                progress_args=progress_args)
                    media = raw.types.InputMediaUploadedDocument(
                        mime_type=self.guess_mime_type(document)
                        or "application/zip",
                        file=file,
                        force_file=force_document or None,
                        thumb=thumb,
                        attributes=[
                            raw.types.DocumentAttributeFilename(
                                file_name=file_name
                                or os.path.basename(document))
                        ])
                elif re.match("^https?://", document):
                    media = raw.types.InputMediaDocumentExternal(url=document)
                else:
                    media = utils.get_input_media_from_file_id(
                        document, FileType.DOCUMENT)
            else:
                thumb = await self.save_file(thumb)
                file = await self.save_file(document,
                                            progress=progress,
                                            progress_args=progress_args)
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(file_name or document.name)
                    or "application/zip",
                    file=file,
                    thumb=thumb,
                    attributes=[
                        raw.types.DocumentAttributeFilename(
                            file_name=file_name or document.name)
                    ])

            while True:
                try:
                    r = await self.send(
                        raw.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,
                            noforwards=protect_content,
                            reply_markup=await reply_markup.write(self)
                            if reply_markup else None,
                            **await
                            utils.parse_text_entities(self, caption,
                                                      parse_mode,
                                                      caption_entities)))
                except FilePartMissing as e:
                    await self.save_file(document,
                                         file_id=file.id,
                                         file_part=e.x)
                else:
                    for i in r.updates:
                        if isinstance(i,
                                      (raw.types.UpdateNewMessage,
                                       raw.types.UpdateNewChannelMessage,
                                       raw.types.UpdateNewScheduledMessage)):
                            return await types.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, raw.types.UpdateNewScheduledMessage))
        except StopTransmission:
            return None
Esempio n. 10
0
    async def edit_inline_media(
        self,
        inline_message_id: str,
        media: "types.InputMedia",
        reply_markup: "types.InlineKeyboardMarkup" = None
    ) -> bool:
        """Edit inline animation, audio, document, photo or video messages.

        When the inline message is edited, a new file can't be uploaded. Use a previously uploaded file via its file_id
        or specify a URL.

        Parameters:
            inline_message_id (``str``):
                Required if *chat_id* and *message_id* are not specified.
                Identifier of the inline message.

            media (:obj:`~pyrogram.types.InputMedia`):
                One of the InputMedia objects describing an animation, audio, document, photo or video.

            reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
                An InlineKeyboardMarkup object.

        Returns:
            ``bool``: On success, True is returned.

        Example:
            .. code-block:: python

                from pyrogram import InputMediaPhoto, InputMediaVideo, InputMediaAudio

                # Bots only

                # Replace the current media with a local photo
                app.edit_inline_media(inline_message_id, InputMediaPhoto("new_photo.jpg"))

                # Replace the current media with a local video
                app.edit_inline_media(inline_message_id, InputMediaVideo("new_video.mp4"))

                # Replace the current media with a local audio
                app.edit_inline_media(inline_message_id, InputMediaAudio("new_audio.mp3"))
        """
        caption = media.caption
        parse_mode = media.parse_mode

        if isinstance(media, types.InputMediaPhoto):
            if re.match("^https?://", media.media):
                media = raw.types.InputMediaPhotoExternal(
                    url=media.media
                )
            else:
                media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2)
        elif isinstance(media, types.InputMediaVideo):
            if re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(
                    url=media.media
                )
            else:
                media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4)
        elif isinstance(media, types.InputMediaAudio):
            if re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(
                    url=media.media
                )
            else:
                media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9)
        elif isinstance(media, types.InputMediaAnimation):
            if re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(
                    url=media.media
                )
            else:
                media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10)
        elif isinstance(media, types.InputMediaDocument):
            if re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(
                    url=media.media
                )
            else:
                media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5)

        unpacked = utils.unpack_inline_message_id(inline_message_id)
        dc_id = unpacked.dc_id

        session = await get_session(self, dc_id)

        return await session.send(
            raw.functions.messages.EditInlineBotMessage(
                id=unpacked,
                media=media,
                reply_markup=reply_markup.write() if reply_markup else None,
                **await self.parser.parse(caption, parse_mode)
            )
        )
Esempio n. 11
0
    async def copy_media_group(
        self,
        chat_id: Union[int, str],
        from_chat_id: Union[int, str],
        message_id: int,
        captions: Union[List[str], str] = None,
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: int = None,
    ) -> List["types.Message"]:
        """Copy a media group by providing one of the message ids.

        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).

            from_chat_id (``int`` | ``str``):
                Unique identifier (int) or username (str) of the source chat where the original media group was sent.
                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 *from_chat_id*.

            captions (``str`` | List of ``str`` , *optional*):
                New caption for media, 0-1024 characters after entities parsing for each media.
                If not specified, the original caption is kept.
                Pass "" (empty string) to remove the caption.

                If a ``string`` is passed, it becomes a caption only for the first media.
                If a list of ``string`` passed, each element becomes caption for each media element.
                You can pass ``None`` in list to keep the original caption (see examples below).

            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.

        Returns:
            List of :obj:`~pyrogram.types.Message`: On success, a list of copied messages is returned.

        Example:
            .. code-block:: python

                # Copy a media group
                app.copy_media_group("me", source_chat, message_id)
                app.copy_media_group("me", source_chat, message_id, captions="single caption")
                app.copy_media_group("me", source_chat, message_id, captions=["caption 1", None, ""])
        """

        media_group = await self.get_media_group(from_chat_id, message_id)
        multi_media = []

        for i, message in enumerate(media_group):
            if message.photo:
                file_id = message.photo.file_id
            elif message.audio:
                file_id = message.audio.file_id
            elif message.document:
                file_id = message.document.file_id
            elif message.video:
                file_id = message.video.file_id
            else:
                raise ValueError("Message with this type can't be copied.")

            media = utils.get_input_media_from_file_id(file_id=file_id)
            multi_media.append(
                raw.types.InputSingleMedia(
                    media=media,
                    random_id=self.rnd_id(),
                    **await self.parser.parse(
                        captions[i] if isinstance(captions, list) and i < len(captions) and captions[i] else
                        captions if isinstance(captions, str) and i == 0 else
                        message.caption if message.caption and message.caption != "None" and not type(captions) is str else "")
                )
            )

        r = await self.send(
            raw.functions.messages.SendMultiMedia(
                peer=await self.resolve_peer(chat_id),
                multi_media=multi_media,
                silent=disable_notification or None,
                reply_to_msg_id=reply_to_message_id,
                schedule_date=schedule_date
            ),
            sleep_threshold=60
        )

        return await utils.parse_messages(
            self,
            raw.types.messages.Messages(
                messages=[m.message for m in filter(
                    lambda u: isinstance(u, (raw.types.UpdateNewMessage,
                                             raw.types.UpdateNewChannelMessage,
                                             raw.types.UpdateNewScheduledMessage)),
                    r.updates
                )],
                users=r.users,
                chats=r.chats
            )
        )
Esempio n. 12
0
    async def send_video_note(
        self,
        chat_id: Union[int, str],
        video_note: Union[str, BinaryIO],
        duration: int = 0,
        length: int = 1,
        thumb: Union[str, BinaryIO] = None,
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: int = None,
        reply_markup: Union["types.InlineKeyboardMarkup",
                            "types.ReplyKeyboardMarkup",
                            "types.ReplyKeyboardRemove",
                            "types.ForceReply"] = None,
        progress: callable = None,
        progress_args: tuple = ()
    ) -> Optional["types.Message"]:
        """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`` | ``BinaryIO``):
                Video note to send.
                Pass a file_id as string to send a video note that exists on the Telegram servers,
                pass a file path as string to upload a new video note that exists on your local machine, or
                pass a binary file-like object with its attribute ".name" set for in-memory uploads.
                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.

            thumb (``str`` | ``BinaryIO``, *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:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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:`~pyrogram.types.Message` | ``None``: On success, the sent video note message is returned, otherwise,
            in case the upload is deliberately stopped with :meth:`~pyrogram.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 isinstance(video_note, str):
                if os.path.isfile(video_note):
                    thumb = await self.save_file(thumb)
                    file = await self.save_file(video_note,
                                                progress=progress,
                                                progress_args=progress_args)
                    media = raw.types.InputMediaUploadedDocument(
                        mime_type=self.guess_mime_type(video_note)
                        or "video/mp4",
                        file=file,
                        thumb=thumb,
                        attributes=[
                            raw.types.DocumentAttributeVideo(
                                round_message=True,
                                duration=duration,
                                w=length,
                                h=length)
                        ])
                else:
                    media = utils.get_input_media_from_file_id(
                        video_note, FileType.VIDEO_NOTE)
            else:
                thumb = await self.save_file(thumb)
                file = await self.save_file(video_note,
                                            progress=progress,
                                            progress_args=progress_args)
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(video_note.name)
                    or "video/mp4",
                    file=file,
                    thumb=thumb,
                    attributes=[
                        raw.types.DocumentAttributeVideo(round_message=True,
                                                         duration=duration,
                                                         w=length,
                                                         h=length)
                    ])

            while True:
                try:
                    r = await self.send(
                        raw.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,
                                      (raw.types.UpdateNewMessage,
                                       raw.types.UpdateNewChannelMessage,
                                       raw.types.UpdateNewScheduledMessage)):
                            return await types.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, raw.types.UpdateNewScheduledMessage))
        except StopTransmission:
            return None
Esempio n. 13
0
    async def send_media_group(
        self: "pyrogram.Client",
        chat_id: Union[int, str],
        media: List[Union["types.InputMediaPhoto", "types.InputMediaVideo",
                          "types.InputMediaAudio",
                          "types.InputMediaDocument"]],
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: datetime = None,
        protect_content: bool = None,
    ) -> List["types.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:`~pyrogram.types.InputMediaPhoto`, :obj:`~pyrogram.types.InputMediaVideo`, :obj:`~pyrogram.types.InputMediaAudio` and :obj:`~pyrogram.types.InputMediaDocument`):
                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.

            schedule_date (:py:obj:`~datetime.datetime`, *optional*):
                Date when the message will be automatically sent.

            protect_content (``bool``, *optional*):
                Protects the contents of the sent message from forwarding and saving.

        Returns:
            List of :obj:`~pyrogram.types.Message`: On success, a list of the sent messages is returned.

        Example:
            .. code-block:: python

                from pyrogram.types import InputMediaPhoto, InputMediaVideo

                await app.send_media_group(
                    "me",
                    [
                        InputMediaPhoto("photo1.jpg"),
                        InputMediaPhoto("photo2.jpg", caption="photo caption"),
                        InputMediaVideo("video.mp4", caption="video caption")
                    ]
                )
        """
        multi_media = []

        for i in media:
            if isinstance(i, types.InputMediaPhoto):
                if isinstance(i.media, str):
                    if os.path.isfile(i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaUploadedPhoto(
                                    file=await self.save_file(i.media))))

                        media = raw.types.InputMediaPhoto(
                            id=raw.types.InputPhoto(
                                id=media.photo.id,
                                access_hash=media.photo.access_hash,
                                file_reference=media.photo.file_reference))
                    elif re.match("^https?://", i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaPhotoExternal(
                                    url=i.media)))

                        media = raw.types.InputMediaPhoto(
                            id=raw.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, FileType.PHOTO)
                else:
                    media = await self.invoke(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaUploadedPhoto(
                                file=await self.save_file(i.media))))

                    media = raw.types.InputMediaPhoto(id=raw.types.InputPhoto(
                        id=media.photo.id,
                        access_hash=media.photo.access_hash,
                        file_reference=media.photo.file_reference))
            elif isinstance(i, types.InputMediaVideo):
                if isinstance(i.media, str):
                    if os.path.isfile(i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaUploadedDocument(
                                    file=await self.save_file(i.media),
                                    thumb=await self.save_file(i.thumb),
                                    mime_type=self.guess_mime_type(i.media)
                                    or "video/mp4",
                                    attributes=[
                                        raw.types.DocumentAttributeVideo(
                                            supports_streaming=i.
                                            supports_streaming or None,
                                            duration=i.duration,
                                            w=i.width,
                                            h=i.height),
                                        raw.types.DocumentAttributeFilename(
                                            file_name=os.path.basename(
                                                i.media))
                                    ])))

                        media = raw.types.InputMediaDocument(
                            id=raw.types.InputDocument(
                                id=media.document.id,
                                access_hash=media.document.access_hash,
                                file_reference=media.document.file_reference))
                    elif re.match("^https?://", i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaDocumentExternal(
                                    url=i.media)))

                        media = raw.types.InputMediaDocument(
                            id=raw.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, FileType.VIDEO)
                else:
                    media = await self.invoke(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaUploadedDocument(
                                file=await self.save_file(i.media),
                                thumb=await self.save_file(i.thumb),
                                mime_type=self.guess_mime_type(
                                    getattr(i.media, "name", "video.mp4"))
                                or "video/mp4",
                                attributes=[
                                    raw.types.DocumentAttributeVideo(
                                        supports_streaming=i.supports_streaming
                                        or None,
                                        duration=i.duration,
                                        w=i.width,
                                        h=i.height),
                                    raw.types.DocumentAttributeFilename(
                                        file_name=getattr(
                                            i.media, "name", "video.mp4"))
                                ])))

                    media = raw.types.InputMediaDocument(
                        id=raw.types.InputDocument(
                            id=media.document.id,
                            access_hash=media.document.access_hash,
                            file_reference=media.document.file_reference))
            elif isinstance(i, types.InputMediaAudio):
                if isinstance(i.media, str):
                    if os.path.isfile(i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaUploadedDocument(
                                    mime_type=self.guess_mime_type(i.media)
                                    or "audio/mpeg",
                                    file=await self.save_file(i.media),
                                    thumb=await self.save_file(i.thumb),
                                    attributes=[
                                        raw.types.DocumentAttributeAudio(
                                            duration=i.duration,
                                            performer=i.performer,
                                            title=i.title),
                                        raw.types.DocumentAttributeFilename(
                                            file_name=os.path.basename(
                                                i.media))
                                    ])))

                        media = raw.types.InputMediaDocument(
                            id=raw.types.InputDocument(
                                id=media.document.id,
                                access_hash=media.document.access_hash,
                                file_reference=media.document.file_reference))
                    elif re.match("^https?://", i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaDocumentExternal(
                                    url=i.media)))

                        media = raw.types.InputMediaDocument(
                            id=raw.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, FileType.AUDIO)
                else:
                    media = await self.invoke(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaUploadedDocument(
                                mime_type=self.guess_mime_type(
                                    getattr(i.media, "name", "audio.mp3"))
                                or "audio/mpeg",
                                file=await self.save_file(i.media),
                                thumb=await self.save_file(i.thumb),
                                attributes=[
                                    raw.types.DocumentAttributeAudio(
                                        duration=i.duration,
                                        performer=i.performer,
                                        title=i.title),
                                    raw.types.DocumentAttributeFilename(
                                        file_name=getattr(
                                            i.media, "name", "audio.mp3"))
                                ])))

                    media = raw.types.InputMediaDocument(
                        id=raw.types.InputDocument(
                            id=media.document.id,
                            access_hash=media.document.access_hash,
                            file_reference=media.document.file_reference))
            elif isinstance(i, types.InputMediaDocument):
                if isinstance(i.media, str):
                    if os.path.isfile(i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaUploadedDocument(
                                    mime_type=self.guess_mime_type(i.media)
                                    or "application/zip",
                                    file=await self.save_file(i.media),
                                    thumb=await self.save_file(i.thumb),
                                    attributes=[
                                        raw.types.DocumentAttributeFilename(
                                            file_name=os.path.basename(
                                                i.media))
                                    ])))

                        media = raw.types.InputMediaDocument(
                            id=raw.types.InputDocument(
                                id=media.document.id,
                                access_hash=media.document.access_hash,
                                file_reference=media.document.file_reference))
                    elif re.match("^https?://", i.media):
                        media = await self.invoke(
                            raw.functions.messages.UploadMedia(
                                peer=await self.resolve_peer(chat_id),
                                media=raw.types.InputMediaDocumentExternal(
                                    url=i.media)))

                        media = raw.types.InputMediaDocument(
                            id=raw.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, FileType.DOCUMENT)
                else:
                    media = await self.invoke(
                        raw.functions.messages.UploadMedia(
                            peer=await self.resolve_peer(chat_id),
                            media=raw.types.InputMediaUploadedDocument(
                                mime_type=self.guess_mime_type(
                                    getattr(i.media, "name", "file.zip"))
                                or "application/zip",
                                file=await self.save_file(i.media),
                                thumb=await self.save_file(i.thumb),
                                attributes=[
                                    raw.types.DocumentAttributeFilename(
                                        file_name=getattr(
                                            i.media, "name", "file.zip"))
                                ])))

                    media = raw.types.InputMediaDocument(
                        id=raw.types.InputDocument(
                            id=media.document.id,
                            access_hash=media.document.access_hash,
                            file_reference=media.document.file_reference))
            else:
                raise ValueError(
                    f"{i.__class__.__name__} is not a supported type for send_media_group"
                )

            multi_media.append(
                raw.types.InputSingleMedia(media=media,
                                           random_id=self.rnd_id(),
                                           **await self.parser.parse(
                                               i.caption, i.parse_mode)))

        r = await self.invoke(raw.functions.messages.SendMultiMedia(
            peer=await self.resolve_peer(chat_id),
            multi_media=multi_media,
            silent=disable_notification or None,
            reply_to_msg_id=reply_to_message_id,
            schedule_date=utils.datetime_to_timestamp(schedule_date),
            noforwards=protect_content),
                              sleep_threshold=60)

        return await utils.parse_messages(
            self,
            raw.types.messages.Messages(messages=[
                m.message for m in filter(
                    lambda u: isinstance(u, (raw.types.UpdateNewMessage, raw.
                                             types.UpdateNewChannelMessage, raw
                                             .types.UpdateNewScheduledMessage)
                                         ), r.updates)
            ],
                                        users=r.users,
                                        chats=r.chats))
Esempio n. 14
0
    async def send_photo(
        self,
        chat_id: Union[int, str],
        photo: Union[str, BinaryIO],
        file_ref: str = None,
        caption: str = "",
        parse_mode: Union[str, None] = object,
        ttl_seconds: int = None,
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: int = None,
        reply_markup: Union["types.InlineKeyboardMarkup",
                            "types.ReplyKeyboardMarkup",
                            "types.ReplyKeyboardRemove",
                            "types.ForceReply"] = None,
        progress: callable = None,
        progress_args: tuple = ()
    ) -> Union["types.Message", None]:
        """Send photos.

        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).

            photo (``str`` | ``BinaryIO``):
                Photo to send.
                Pass a file_id as string to send a photo that exists on the Telegram servers,
                pass an HTTP URL as a string for Telegram to get a photo from the Internet,
                pass a file path as string to upload a new photo that exists on your local machine, or
                pass a binary file-like object with its attribute ".name" set for in-memory uploads.

            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*):
                Photo 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.

            ttl_seconds (``int``, *optional*):
                Self-Destruct Timer.
                If you set a timer, the photo will self-destruct in *ttl_seconds*
                seconds after it was viewed.

            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:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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:`~pyrogram.types.Message` | ``None``: On success, the sent photo message is returned, otherwise, in
            case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is returned.

        Example:
            .. code-block:: python

                # Send photo by uploading from local file
                app.send_photo("me", "photo.jpg")

                # Send photo by uploading from URL
                app.send_photo("me", "https://i.imgur.com/BQBTP7d.png")

                # Add caption to a photo
                app.send_photo("me", "photo.jpg", caption="Holidays!")

                # Send self-destructing photo
                app.send_photo("me", "photo.jpg", ttl_seconds=10)
        """
        file = None

        try:
            if isinstance(photo, str):
                if os.path.isfile(photo):
                    file = await self.save_file(photo,
                                                progress=progress,
                                                progress_args=progress_args)
                    media = raw.types.InputMediaUploadedPhoto(
                        file=file, ttl_seconds=ttl_seconds)
                elif re.match("^https?://", photo):
                    media = raw.types.InputMediaPhotoExternal(
                        url=photo, ttl_seconds=ttl_seconds)
                else:
                    media = utils.get_input_media_from_file_id(
                        photo, file_ref, 2)
            else:
                file = await self.save_file(photo,
                                            progress=progress,
                                            progress_args=progress_args)
                media = raw.types.InputMediaUploadedPhoto(
                    file=file, ttl_seconds=ttl_seconds)

            while True:
                try:
                    r = await self.send(
                        raw.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,
                            **await self.parser.parse(caption, parse_mode)))
                except FilePartMissing as e:
                    await self.save_file(photo, file_id=file.id, file_part=e.x)
                else:
                    for i in r.updates:
                        if isinstance(i,
                                      (raw.types.UpdateNewMessage,
                                       raw.types.UpdateNewChannelMessage,
                                       raw.types.UpdateNewScheduledMessage)):
                            return await types.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, raw.types.UpdateNewScheduledMessage))
        except pyrogram.StopTransmission:
            return None
Esempio n. 15
0
    async def send_cached_media(
        self: "pyrogram.Client",
        chat_id: Union[int, str],
        file_id: str,
        caption: str = "",
        parse_mode: Optional["enums.ParseMode"] = None,
        caption_entities: List["types.MessageEntity"] = None,
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: datetime = None,
        protect_content: bool = None,
        reply_markup: Union[
            "types.InlineKeyboardMarkup",
            "types.ReplyKeyboardMarkup",
            "types.ReplyKeyboardRemove",
            "types.ForceReply"
        ] = None
    ) -> Optional["types.Message"]:
        """Send any media stored on the Telegram servers using a file_id.

        This convenience method works with any valid file_id only.
        It does the same as calling the relevant method for sending media using a file_id, thus saving you from the
        hassle of using the correct method for the media the file_id is pointing to.

        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).

            file_id (``str``):
                Media to send.
                Pass a file_id as string to send a media that exists on the Telegram servers.

            caption (``str``, *optional*):
                Media caption, 0-1024 characters.

            parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*):
                By default, texts are parsed using both Markdown and HTML styles.
                You can combine both syntaxes together.

            caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
                List of special entities that appear in the caption, which can be specified instead of *parse_mode*.

            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 (:py:obj:`~datetime.datetime`, *optional*):
                Date when the message will be automatically sent.
            
            protect_content (``bool``, *optional*):
                Protects the contents of the sent message from forwarding and saving.

            reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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.

        Returns:
            :obj:`~pyrogram.types.Message`: On success, the sent media message is returned.

        Example:
            .. code-block:: python

                await app.send_cached_media("me", file_id)
        """

        r = await self.invoke(
            raw.functions.messages.SendMedia(
                peer=await self.resolve_peer(chat_id),
                media=utils.get_input_media_from_file_id(file_id),
                silent=disable_notification or None,
                reply_to_msg_id=reply_to_message_id,
                random_id=self.rnd_id(),
                schedule_date=utils.datetime_to_timestamp(schedule_date),
                noforwards=protect_content,
                reply_markup=await reply_markup.write(self) if reply_markup else None,
                **await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
            )
        )

        for i in r.updates:
            if isinstance(i, (raw.types.UpdateNewMessage,
                              raw.types.UpdateNewChannelMessage,
                              raw.types.UpdateNewScheduledMessage)):
                return await types.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, raw.types.UpdateNewScheduledMessage)
                )
Esempio n. 16
0
    async def edit_inline_media(
            self: "pyrogram.Client",
            inline_message_id: str,
            media: "types.InputMedia",
            reply_markup: "types.InlineKeyboardMarkup" = None) -> bool:
        """Edit inline animation, audio, document, photo or video messages.

        When the inline message is edited, a new file can't be uploaded. Use a previously uploaded file via its file_id
        or specify a URL.

        Parameters:
            inline_message_id (``str``):
                Required if *chat_id* and *message_id* are not specified.
                Identifier of the inline message.

            media (:obj:`~pyrogram.types.InputMedia`):
                One of the InputMedia objects describing an animation, audio, document, photo or video.

            reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
                An InlineKeyboardMarkup object.

        Returns:
            ``bool``: On success, True is returned.

        Example:
            .. code-block:: python

                from pyrogram.types import InputMediaPhoto, InputMediaVideo, InputMediaAudio

                # Bots only

                # Replace the current media with a local photo
                await app.edit_inline_media(inline_message_id, InputMediaPhoto("new_photo.jpg"))

                # Replace the current media with a local video
                await app.edit_inline_media(inline_message_id, InputMediaVideo("new_video.mp4"))

                # Replace the current media with a local audio
                await app.edit_inline_media(inline_message_id, InputMediaAudio("new_audio.mp3"))
        """
        caption = media.caption
        parse_mode = media.parse_mode

        if isinstance(media, types.InputMediaPhoto):
            if os.path.isfile(media.media):
                media = raw.types.InputMediaUploadedPhoto(
                    file=await self.save_file(media.media))
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaPhotoExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.PHOTO)
        elif isinstance(media, types.InputMediaVideo):
            if os.path.isfile(media.media):
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(media.media) or "video/mp4",
                    thumb=await self.save_file(media.thumb),
                    file=await self.save_file(media.media),
                    attributes=[
                        raw.types.DocumentAttributeVideo(
                            supports_streaming=media.supports_streaming
                            or None,
                            duration=media.duration,
                            w=media.width,
                            h=media.height),
                        raw.types.DocumentAttributeFilename(
                            file_name=os.path.basename(media.media))
                    ])
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.VIDEO)
        elif isinstance(media, types.InputMediaAudio):
            if os.path.isfile(media.media):
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(media.media)
                    or "audio/mpeg",
                    thumb=await self.save_file(media.thumb),
                    file=await self.save_file(media.media),
                    attributes=[
                        raw.types.DocumentAttributeAudio(
                            duration=media.duration,
                            performer=media.performer,
                            title=media.title),
                        raw.types.DocumentAttributeFilename(
                            file_name=os.path.basename(media.media))
                    ])
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.AUDIO)
        elif isinstance(media, types.InputMediaAnimation):
            if os.path.isfile(media.media):
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(media.media) or "video/mp4",
                    thumb=await self.save_file(media.thumb),
                    file=await self.save_file(media.media),
                    attributes=[
                        raw.types.DocumentAttributeVideo(
                            supports_streaming=True,
                            duration=media.duration,
                            w=media.width,
                            h=media.height),
                        raw.types.DocumentAttributeFilename(
                            file_name=os.path.basename(media.media)),
                        raw.types.DocumentAttributeAnimated()
                    ])
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.ANIMATION)
        elif isinstance(media, types.InputMediaDocument):
            if os.path.isfile(media.media):
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(media.media)
                    or "application/zip",
                    thumb=await self.save_file(media.thumb),
                    file=await self.save_file(media.media),
                    attributes=[
                        raw.types.DocumentAttributeFilename(
                            file_name=os.path.basename(media.media))
                    ])
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.DOCUMENT)

        unpacked = utils.unpack_inline_message_id(inline_message_id)
        dc_id = unpacked.dc_id

        session = await get_session(self, dc_id)

        return await session.invoke(
            raw.functions.messages.EditInlineBotMessage(
                id=unpacked,
                media=media,
                reply_markup=await reply_markup.write(self)
                if reply_markup else None,
                **await self.parser.parse(caption, parse_mode)),
            sleep_threshold=self.sleep_threshold)
    async def send_sticker(
        self,
        chat_id: Union[int, str],
        sticker: Union[str, BinaryIO],
        disable_notification: bool = None,
        reply_to_message_id: int = None,
        schedule_date: int = None,
        reply_markup: Union["types.InlineKeyboardMarkup",
                            "types.ReplyKeyboardMarkup",
                            "types.ReplyKeyboardRemove",
                            "types.ForceReply"] = None,
        progress: callable = None,
        progress_args: tuple = ()
    ) -> Optional["types.Message"]:
        """Send static .webp or animated .tgs stickers.

        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).

            sticker (``str`` | ``BinaryIO``):
                Sticker to send.
                Pass a file_id as string to send a sticker that exists on the Telegram servers,
                pass an HTTP URL as a string for Telegram to get a .webp sticker file from the Internet,
                pass a file path as string to upload a new sticker that exists on your local machine, or
                pass a binary file-like object with its attribute ".name" set for in-memory uploads.

            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:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.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:`~pyrogram.types.Message` | ``None``: On success, the sent sticker message is returned, otherwise,
            in case the upload is deliberately stopped with :meth:`~pyrogram.Client.stop_transmission`, None is
            returned.

        Example:
            .. code-block:: python

                # Send sticker by uploading from local file
                app.send_sticker("me", "sticker.webp")

                # Send sticker using file_id
                app.send_sticker("me", "CAADBAADzg4AAvLQYAEz_x2EOgdRwBYE")
        """
        file = None

        try:
            if isinstance(sticker, str):
                if os.path.isfile(sticker):
                    file = await self.save_file(sticker,
                                                progress=progress,
                                                progress_args=progress_args)
                    media = raw.types.InputMediaUploadedDocument(
                        mime_type=self.guess_mime_type(sticker)
                        or "image/webp",
                        file=file,
                        attributes=[
                            raw.types.DocumentAttributeFilename(
                                file_name=os.path.basename(sticker))
                        ])
                elif re.match("^https?://", sticker):
                    media = raw.types.InputMediaDocumentExternal(url=sticker)
                else:
                    media = utils.get_input_media_from_file_id(
                        sticker, FileType.STICKER)
            else:
                file = await self.save_file(sticker,
                                            progress=progress,
                                            progress_args=progress_args)
                media = raw.types.InputMediaUploadedDocument(
                    mime_type=self.guess_mime_type(sticker.name)
                    or "image/webp",
                    file=file,
                    attributes=[
                        raw.types.DocumentAttributeFilename(
                            file_name=sticker.name)
                    ])

            while True:
                try:
                    r = await self.send(
                        raw.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(sticker,
                                         file_id=file.id,
                                         file_part=e.x)
                else:
                    for i in r.updates:
                        if isinstance(i,
                                      (raw.types.UpdateNewMessage,
                                       raw.types.UpdateNewChannelMessage,
                                       raw.types.UpdateNewScheduledMessage)):
                            return await types.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, raw.types.UpdateNewScheduledMessage))
        except StopTransmission:
            return None
Esempio n. 18
0
    async def edit_message_media(
            self,
            chat_id: Union[int, str],
            message_id: int,
            media: "types.InputMedia",
            reply_markup: "types.InlineKeyboardMarkup" = None,
            file_name: str = None) -> "types.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:`~pyrogram.types.InputMedia`):
                One of the InputMedia objects describing an animation, audio, document, photo or video.

            reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
                An InlineKeyboardMarkup object.

            file_name (``str``, *optional*):
                File name of the media to be sent. Not applicable to photos.
                Defaults to file's path basename.

        Returns:
            :obj:`~pyrogram.types.Message`: On success, the edited message is returned.

        Example:
            .. code-block:: python

                from pyrogram.types 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

        message, entities = None, None

        if caption is not None:
            message, entities = (await self.parser.parse(caption,
                                                         parse_mode)).values()

        if isinstance(media, types.InputMediaPhoto):
            if os.path.isfile(media.media):
                media = await self.send(
                    raw.functions.messages.UploadMedia(
                        peer=await self.resolve_peer(chat_id),
                        media=raw.types.InputMediaUploadedPhoto(
                            file=await self.save_file(media.media))))

                media = raw.types.InputMediaPhoto(id=raw.types.InputPhoto(
                    id=media.photo.id,
                    access_hash=media.photo.access_hash,
                    file_reference=media.photo.file_reference))
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaPhotoExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.PHOTO)
        elif isinstance(media, types.InputMediaVideo):
            if os.path.isfile(media.media):
                media = await self.send(
                    raw.functions.messages.UploadMedia(
                        peer=await self.resolve_peer(chat_id),
                        media=raw.types.InputMediaUploadedDocument(
                            mime_type=self.guess_mime_type(media.media)
                            or "video/mp4",
                            thumb=await self.save_file(media.thumb),
                            file=await self.save_file(media.media),
                            attributes=[
                                raw.types.DocumentAttributeVideo(
                                    supports_streaming=media.supports_streaming
                                    or None,
                                    duration=media.duration,
                                    w=media.width,
                                    h=media.height),
                                raw.types.DocumentAttributeFilename(
                                    file_name=file_name
                                    or os.path.basename(media.media))
                            ])))

                media = raw.types.InputMediaDocument(
                    id=raw.types.InputDocument(
                        id=media.document.id,
                        access_hash=media.document.access_hash,
                        file_reference=media.document.file_reference))
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.VIDEO)
        elif isinstance(media, types.InputMediaAudio):
            if os.path.isfile(media.media):
                media = await self.send(
                    raw.functions.messages.UploadMedia(
                        peer=await self.resolve_peer(chat_id),
                        media=raw.types.InputMediaUploadedDocument(
                            mime_type=self.guess_mime_type(media.media)
                            or "audio/mpeg",
                            thumb=await self.save_file(media.thumb),
                            file=await self.save_file(media.media),
                            attributes=[
                                raw.types.DocumentAttributeAudio(
                                    duration=media.duration,
                                    performer=media.performer,
                                    title=media.title),
                                raw.types.DocumentAttributeFilename(
                                    file_name=file_name
                                    or os.path.basename(media.media))
                            ])))

                media = raw.types.InputMediaDocument(
                    id=raw.types.InputDocument(
                        id=media.document.id,
                        access_hash=media.document.access_hash,
                        file_reference=media.document.file_reference))
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.AUDIO)
        elif isinstance(media, types.InputMediaAnimation):
            if os.path.isfile(media.media):
                media = await self.send(
                    raw.functions.messages.UploadMedia(
                        peer=await self.resolve_peer(chat_id),
                        media=raw.types.InputMediaUploadedDocument(
                            mime_type=self.guess_mime_type(media.media)
                            or "video/mp4",
                            thumb=await self.save_file(media.thumb),
                            file=await self.save_file(media.media),
                            attributes=[
                                raw.types.DocumentAttributeVideo(
                                    supports_streaming=True,
                                    duration=media.duration,
                                    w=media.width,
                                    h=media.height),
                                raw.types.DocumentAttributeFilename(
                                    file_name=file_name
                                    or os.path.basename(media.media)),
                                raw.types.DocumentAttributeAnimated()
                            ])))

                media = raw.types.InputMediaDocument(
                    id=raw.types.InputDocument(
                        id=media.document.id,
                        access_hash=media.document.access_hash,
                        file_reference=media.document.file_reference))
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.ANIMATION)
        elif isinstance(media, types.InputMediaDocument):
            if os.path.isfile(media.media):
                media = await self.send(
                    raw.functions.messages.UploadMedia(
                        peer=await self.resolve_peer(chat_id),
                        media=raw.types.InputMediaUploadedDocument(
                            mime_type=self.guess_mime_type(media.media)
                            or "application/zip",
                            thumb=await self.save_file(media.thumb),
                            file=await self.save_file(media.media),
                            attributes=[
                                raw.types.DocumentAttributeFilename(
                                    file_name=file_name
                                    or os.path.basename(media.media))
                            ])))

                media = raw.types.InputMediaDocument(
                    id=raw.types.InputDocument(
                        id=media.document.id,
                        access_hash=media.document.access_hash,
                        file_reference=media.document.file_reference))
            elif re.match("^https?://", media.media):
                media = raw.types.InputMediaDocumentExternal(url=media.media)
            else:
                media = utils.get_input_media_from_file_id(
                    media.media, FileType.DOCUMENT)

        r = await self.send(
            raw.functions.messages.EditMessage(
                peer=await self.resolve_peer(chat_id),
                id=message_id,
                media=media,
                reply_markup=await reply_markup.write(self)
                if reply_markup else None,
                message=message,
                entities=entities))

        for i in r.updates:
            if isinstance(i, (raw.types.UpdateEditMessage,
                              raw.types.UpdateEditChannelMessage)):
                return await types.Message._parse(self, i.message,
                                                  {i.id: i
                                                   for i in r.users},
                                                  {i.id: i
                                                   for i in r.chats})