Ejemplo n.º 1
0
    def download_media(
        self,
        message: Union["pyrogram.Message", str],
        file_name: str = "",
        block: bool = True,
        progress: callable = None,
        progress_args: tuple = ()) -> Union[str, None]:
        """Use this method to download the media from a Message.

        Args:
            message (:obj:`Message <pyrogram.Message>` | ``str``):
                Pass a Message containing the media, the media itself (message.audio, message.video, ...) or
                the file id as string.

            file_name (``str``, *optional*):
                A custom *file_name* to be used instead of the one provided by Telegram.
                By default, all files are downloaded in the *downloads* folder in your working directory.
                You can also specify a path for downloading files in a custom location: paths that end with "/"
                are considered directories. All non-existent folders will be created automatically.

            block (``bool``, *optional*):
                Blocks the code execution until the file has been downloaded.
                Defaults to True.

            progress (``callable``):
                Pass a callback function to view the download progress.
                The function must take *(client, current, total, \*args)* as positional arguments (look at the section
                below for a detailed description).

            progress_args (``tuple``):
                Extra custom arguments for the progress callback function. Useful, for example, if you want to pass
                a chat_id and a message_id in order to edit a message with the updated progress.

        Other Parameters:
            client (:obj:`Client <pyrogram.Client>`):
                The Client itself, useful when you want to call other API methods inside the callback function.

            current (``int``):
                The amount of bytes downloaded so far.

            total (``int``):
                The size of the file.

            *args (``tuple``, *optional*):
                Extra custom arguments as defined in the *progress_args* parameter.
                You can either keep *\*args* or add every single extra argument in your function signature.

        Returns:
            On success, the absolute path of the downloaded file as string is returned, None otherwise.
            In case the download is deliberately stopped with :meth:`stop_transmission`, None is returned as well.

        Raises:
            :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
            ``ValueError`` if the message doesn't contain any downloadable media
        """
        error_message = "This message doesn't contain any downloadable media"

        if isinstance(message, pyrogram.Message):
            if message.photo:
                media = pyrogram.Document(
                    file_id=message.photo.sizes[-1].file_id,
                    file_size=message.photo.sizes[-1].file_size,
                    mime_type="",
                    date=message.photo.date,
                    client=self)
            elif message.audio:
                media = message.audio
            elif message.document:
                media = message.document
            elif message.video:
                media = message.video
            elif message.voice:
                media = message.voice
            elif message.video_note:
                media = message.video_note
            elif message.sticker:
                media = message.sticker
            elif message.animation:
                media = message.animation
            else:
                raise ValueError(error_message)
        elif isinstance(
                message,
            (pyrogram.Photo, pyrogram.PhotoSize, pyrogram.Audio,
             pyrogram.Document, pyrogram.Video, pyrogram.Voice,
             pyrogram.VideoNote, pyrogram.Sticker, pyrogram.Animation)):
            if isinstance(message, pyrogram.Photo):
                media = pyrogram.Document(
                    file_id=message.sizes[-1].file_id,
                    file_size=message.sizes[-1].file_size,
                    mime_type="",
                    date=message.date,
                    client=self)
            else:
                media = message
        elif isinstance(message, str):
            media = pyrogram.Document(file_id=message,
                                      file_size=0,
                                      mime_type="",
                                      client=self)
        else:
            raise ValueError(error_message)

        done = Event()
        path = [None]

        self.download_queue.put(
            (media, file_name, done, progress, progress_args, path))

        if block:
            done.wait()

        return path[0]
Ejemplo n.º 2
0
def parse_message(client,
                  message: types.Message,
                  users: dict,
                  chats: dict,
                  replies: int = 1) -> pyrogram.Message:
    entities = parse_entities(message.entities, users)

    forward_from = None
    forward_from_chat = None
    forward_from_message_id = None
    forward_signature = None
    forward_date = None

    forward_header = message.fwd_from  # type: types.MessageFwdHeader

    if forward_header:
        forward_date = forward_header.date

        if forward_header.from_id:
            forward_from = parse_user(users[forward_header.from_id])
        else:
            forward_from_chat = parse_channel_chat(
                chats[forward_header.channel_id])
            forward_from_message_id = forward_header.channel_post
            forward_signature = forward_header.post_author

    photo = None
    location = None
    contact = None
    venue = None
    audio = None
    voice = None
    video = None
    video_note = None
    sticker = None
    document = None

    media = message.media

    if media:
        if isinstance(media, types.MessageMediaPhoto):
            photo = media.photo

            if isinstance(photo, types.Photo):
                sizes = photo.sizes
                photo_sizes = []

                for size in sizes:
                    if isinstance(size,
                                  (types.PhotoSize, types.PhotoCachedSize)):
                        loc = size.location

                        if isinstance(size, types.PhotoSize):
                            file_size = size.size
                        else:
                            file_size = len(size.bytes)

                        if isinstance(loc, types.FileLocation):
                            photo_size = pyrogram.PhotoSize(
                                file_id=encode(
                                    pack("<iiqqqqi", 2, loc.dc_id, photo.id,
                                         photo.access_hash, loc.volume_id,
                                         loc.secret, loc.local_id)),
                                width=size.w,
                                height=size.h,
                                file_size=file_size,
                                date=photo.date)

                            photo_sizes.append(photo_size)

                photo = photo_sizes
        elif isinstance(media, types.MessageMediaGeo):
            geo_point = media.geo

            if isinstance(geo_point, types.GeoPoint):
                location = pyrogram.Location(longitude=geo_point.long,
                                             latitude=geo_point.lat)
        elif isinstance(media, types.MessageMediaContact):
            contact = pyrogram.Contact(phone_number=media.phone_number,
                                       first_name=media.first_name,
                                       last_name=media.last_name or None,
                                       user_id=media.user_id or None)
        elif isinstance(media, types.MessageMediaVenue):
            venue = pyrogram.Venue(location=pyrogram.Location(
                longitude=media.geo.long, latitude=media.geo.lat),
                                   title=media.title,
                                   address=media.address,
                                   foursquare_id=media.venue_id or None)
        elif isinstance(media, types.MessageMediaDocument):
            doc = media.document

            if isinstance(doc, types.Document):
                attributes = {type(i): i for i in doc.attributes}

                file_name = getattr(
                    attributes.get(types.DocumentAttributeFilename, None),
                    "file_name", None)

                if types.DocumentAttributeAudio in attributes:
                    audio_attributes = attributes[types.DocumentAttributeAudio]

                    if audio_attributes.voice:
                        voice = pyrogram.Voice(
                            file_id=encode(
                                pack("<iiqq", 3, doc.dc_id, doc.id,
                                     doc.access_hash)),
                            duration=audio_attributes.duration,
                            mime_type=doc.mime_type,
                            file_size=doc.size,
                            thumb=parse_thumb(doc.thumb),
                            file_name=file_name,
                            date=doc.date)
                    else:
                        audio = pyrogram.Audio(
                            file_id=encode(
                                pack("<iiqq", 9, doc.dc_id, doc.id,
                                     doc.access_hash)),
                            duration=audio_attributes.duration,
                            performer=audio_attributes.performer,
                            title=audio_attributes.title,
                            mime_type=doc.mime_type,
                            file_size=doc.size,
                            thumb=parse_thumb(doc.thumb),
                            file_name=file_name,
                            date=doc.date)
                elif types.DocumentAttributeAnimated in attributes:
                    document = pyrogram.Document(file_id=encode(
                        pack("<iiqq", 10, doc.dc_id, doc.id, doc.access_hash)),
                                                 thumb=parse_thumb(doc.thumb),
                                                 file_name=file_name,
                                                 mime_type=doc.mime_type,
                                                 file_size=doc.size,
                                                 date=doc.date)
                elif types.DocumentAttributeVideo in attributes:
                    video_attributes = attributes[types.DocumentAttributeVideo]

                    if video_attributes.round_message:
                        video_note = pyrogram.VideoNote(
                            file_id=encode(
                                pack("<iiqq", 13, doc.dc_id, doc.id,
                                     doc.access_hash)),
                            length=video_attributes.w,
                            duration=video_attributes.duration,
                            thumb=parse_thumb(doc.thumb),
                            file_size=doc.size,
                            file_name=file_name,
                            mime_type=doc.mime_type,
                            date=doc.date)
                    else:
                        video = pyrogram.Video(
                            file_id=encode(
                                pack("<iiqq", 4, doc.dc_id, doc.id,
                                     doc.access_hash)),
                            width=video_attributes.w,
                            height=video_attributes.h,
                            duration=video_attributes.duration,
                            thumb=parse_thumb(doc.thumb),
                            mime_type=doc.mime_type,
                            file_size=doc.size,
                            file_name=file_name,
                            date=doc.date)
                elif types.DocumentAttributeSticker in attributes:
                    image_size_attributes = attributes[
                        types.DocumentAttributeImageSize]
                    sticker_attribute = attributes[
                        types.DocumentAttributeSticker]

                    if isinstance(sticker_attribute.stickerset,
                                  types.InputStickerSetID):
                        try:
                            set_name = client.send(
                                functions.messages.GetStickerSet(
                                    sticker_attribute.stickerset)
                            ).set.short_name
                        except StickersetInvalid:
                            set_name = None
                    else:
                        set_name = None

                    sticker = pyrogram.Sticker(
                        file_id=encode(
                            pack("<iiqq", 8, doc.dc_id, doc.id,
                                 doc.access_hash)),
                        width=image_size_attributes.w,
                        height=image_size_attributes.h,
                        thumb=parse_thumb(doc.thumb),
                        # TODO: mask_position
                        set_name=set_name,
                        emoji=sticker_attribute.alt or None,
                        file_size=doc.size,
                        mime_type=doc.mime_type,
                        file_name=file_name,
                        date=doc.date)
                else:
                    document = pyrogram.Document(file_id=encode(
                        pack("<iiqq", 5, doc.dc_id, doc.id, doc.access_hash)),
                                                 thumb=parse_thumb(doc.thumb),
                                                 file_name=file_name,
                                                 mime_type=doc.mime_type,
                                                 file_size=doc.size,
                                                 date=doc.date)
        else:
            media = None

    m = pyrogram.Message(
        message_id=message.id,
        date=message.date,
        chat=parse_chat(message, users, chats),
        from_user=parse_user(users.get(message.from_id, None)),
        text=message.message or None if media is None else None,
        caption=message.message or None if media is not None else None,
        entities=entities or None if media is None else None,
        caption_entities=entities or None if media is not None else None,
        author_signature=message.post_author,
        forward_from=forward_from,
        forward_from_chat=forward_from_chat,
        forward_from_message_id=forward_from_message_id,
        forward_signature=forward_signature,
        forward_date=forward_date,
        edit_date=message.edit_date,
        media_group_id=message.grouped_id,
        photo=photo,
        location=location,
        contact=contact,
        venue=venue,
        audio=audio,
        voice=voice,
        video=video,
        video_note=video_note,
        sticker=sticker,
        document=document,
        views=message.views,
        via_bot=parse_user(users.get(message.via_bot_id, None)))

    if message.reply_to_msg_id and replies:
        m.reply_to_message = client.get_messages(m.chat.id,
                                                 message.reply_to_msg_id)
        m.reply_to_message = m.reply_to_message

    return m