def parse_messages(client, messages: list or types.Message or types.MessageService or types.MessageEmpty, users: dict, chats: dict, replies: int = 1) -> pyrogram_types.Message or list: is_list = isinstance(messages, list) messages = messages if is_list else [messages] parsed_messages = [] for message in messages: if isinstance(message, types.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 animation = 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_types.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) photo_sizes.append(photo_size) photo = pyrogram_types.Photo(id=b64encode( pack("<qq", photo.id, photo.access_hash), b"-_").decode().rstrip("="), date=photo.date, sizes=photo_sizes) elif isinstance(media, types.MessageMediaGeo): geo_point = media.geo if isinstance(geo_point, types.GeoPoint): location = pyrogram_types.Location( longitude=geo_point.long, latitude=geo_point.lat) elif isinstance(media, types.MessageMediaContact): contact = pyrogram_types.Contact( phone_number=media.phone_number, first_name=media.first_name, last_name=media.last_name or None, vcard=media.vcard or None, user_id=media.user_id or None) elif isinstance(media, types.MessageMediaVenue): venue = pyrogram_types.Venue( location=pyrogram_types.Location( longitude=media.geo.long, latitude=media.geo.lat), title=media.title, address=media.address, foursquare_id=media.venue_id or None, foursquare_type=media.venue_type) 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_types.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, waveform=audio_attributes.waveform, date=doc.date) else: audio = pyrogram_types.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: video_attributes = attributes.get( types.DocumentAttributeVideo, None) animation = pyrogram_types.Animation( file_id=encode( pack("<iiqq", 10, doc.dc_id, doc.id, doc.access_hash)), width=getattr(video_attributes, "w", 0), height=getattr(video_attributes, "h", 0), duration=getattr(video_attributes, "duration", 0), thumb=parse_thumb(doc.thumb), mime_type=doc.mime_type, file_size=doc.size, file_name=file_name, date=doc.date) elif types.DocumentAttributeVideo in attributes: video_attributes = attributes[ types.DocumentAttributeVideo] if video_attributes.round_message: video_note = pyrogram_types.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, mime_type=doc.mime_type, date=doc.date) else: video = pyrogram_types.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.get( types.DocumentAttributeImageSize, None) 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_types.Sticker( file_id=encode( pack("<iiqq", 8, doc.dc_id, doc.id, doc.access_hash)), width=image_size_attributes.w if image_size_attributes else 0, height=image_size_attributes.h if image_size_attributes else 0, 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_types.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 reply_markup = message.reply_markup if reply_markup: if isinstance(reply_markup, types.ReplyKeyboardForceReply): reply_markup = pyrogram_types.ForceReply.read(reply_markup) elif isinstance(reply_markup, types.ReplyKeyboardMarkup): reply_markup = pyrogram_types.ReplyKeyboardMarkup.read( reply_markup) elif isinstance(reply_markup, types.ReplyInlineMarkup): reply_markup = pyrogram_types.InlineKeyboardMarkup.read( reply_markup) elif isinstance(reply_markup, types.ReplyKeyboardHide): reply_markup = pyrogram_types.ReplyKeyboardRemove.read( reply_markup) else: reply_markup = None m = pyrogram_types.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=Str(message.message) or None if media is None else None, caption=Str(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, mentioned=message.mentioned, media=bool(media) or None, edit_date=message.edit_date, media_group_id=message.grouped_id, photo=photo, location=location, contact=contact, venue=venue, audio=audio, voice=voice, animation=animation, video=video, video_note=video_note, sticker=sticker, document=document, views=message.views, via_bot=parse_user(users.get(message.via_bot_id, None)), outgoing=message.out, client=proxy(client), reply_markup=reply_markup) if m.text: m.text.init(m._client, m.entities or []) if m.caption: m.caption.init(m._client, m.caption_entities or []) if message.reply_to_msg_id and replies: try: m.reply_to_message = client.get_messages( m.chat.id, reply_to_message_ids=message.id, replies=replies - 1) except MessageIdsEmpty: pass elif isinstance(message, types.MessageService): action = message.action new_chat_members = None left_chat_member = None new_chat_title = None delete_chat_photo = None migrate_to_chat_id = None migrate_from_chat_id = None group_chat_created = None channel_chat_created = None new_chat_photo = None if isinstance(action, types.MessageActionChatAddUser): new_chat_members = [parse_user(users[i]) for i in action.users] elif isinstance(action, types.MessageActionChatJoinedByLink): new_chat_members = [parse_user(users[message.from_id])] elif isinstance(action, types.MessageActionChatDeleteUser): left_chat_member = parse_user(users[action.user_id]) elif isinstance(action, types.MessageActionChatEditTitle): new_chat_title = action.title elif isinstance(action, types.MessageActionChatDeletePhoto): delete_chat_photo = True elif isinstance(action, types.MessageActionChatMigrateTo): migrate_to_chat_id = action.channel_id elif isinstance(action, types.MessageActionChannelMigrateFrom): migrate_from_chat_id = action.chat_id elif isinstance(action, types.MessageActionChatCreate): group_chat_created = True elif isinstance(action, types.MessageActionChannelCreate): channel_chat_created = True elif isinstance(action, types.MessageActionChatEditPhoto): photo = action.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_types.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) photo_sizes.append(photo_size) new_chat_photo = pyrogram_types.Photo(id=b64encode( pack("<qq", photo.id, photo.access_hash), b"-_").decode().rstrip("="), date=photo.date, sizes=photo_sizes) m = pyrogram_types.Message( message_id=message.id, date=message.date, chat=parse_chat(message, users, chats), from_user=parse_user(users.get(message.from_id, None)), service=True, new_chat_members=new_chat_members, left_chat_member=left_chat_member, new_chat_title=new_chat_title, new_chat_photo=new_chat_photo, delete_chat_photo=delete_chat_photo, migrate_to_chat_id=int("-100" + str(migrate_to_chat_id)) if migrate_to_chat_id else None, migrate_from_chat_id=-migrate_from_chat_id if migrate_from_chat_id else None, group_chat_created=group_chat_created, channel_chat_created=channel_chat_created, client=proxy(client) # TODO: supergroup_chat_created ) if isinstance(action, types.MessageActionPinMessage): try: m.pinned_message = client.get_messages( m.chat.id, reply_to_message_ids=message.id, replies=0) except MessageIdsEmpty: pass else: m = pyrogram_types.Message(message_id=message.id, client=proxy(client), empty=True) parsed_messages.append(m) return parsed_messages if is_list else parsed_messages[0]
def download_media(self, message: pyrogram_types.Message or str, file_name: str = "", block: bool = True, progress: callable = None, progress_args: tuple = 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. Raises: :class:`Error <pyrogram.Error>` """ if isinstance(message, pyrogram_types.Message): if message.photo: media = message.photo[-1] 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.gif: media = message.gif else: return elif isinstance(message, (pyrogram_types.PhotoSize, pyrogram_types.Audio, pyrogram_types.Document, pyrogram_types.Video, pyrogram_types.Voice, pyrogram_types.VideoNote, pyrogram_types.Sticker, pyrogram_types.GIF)): media = message elif isinstance(message, str): media = pyrogram_types.Document(file_id=message, file_size=0, mime_type="") else: return done = Event() path = [None] self.download_queue.put( (media, file_name, done, progress, progress_args, path)) if block: done.wait() return path[0]
def parse_message(client, message: types.Message, users: dict, chats: dict, replies: int = 1) -> pyrogram_types.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_types.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_types.Location(longitude=geo_point.long, latitude=geo_point.lat) elif isinstance(media, types.MessageMediaContact): contact = pyrogram_types.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_types.Venue(location=pyrogram_types.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_types.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_types.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_types.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_types.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_types.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.get( types.DocumentAttributeImageSize, None) 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_types.Sticker( file_id=encode( pack("<iiqq", 8, doc.dc_id, doc.id, doc.access_hash)), width=image_size_attributes.w if image_size_attributes else 0, height=image_size_attributes.h if image_size_attributes else 0, 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_types.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 reply_markup = message.reply_markup if reply_markup: if isinstance(reply_markup, types.ReplyKeyboardForceReply): reply_markup = pyrogram_types.ForceReply.read(reply_markup) elif isinstance(reply_markup, types.ReplyKeyboardMarkup): reply_markup = pyrogram_types.ReplyKeyboardMarkup.read( reply_markup) elif isinstance(reply_markup, types.ReplyInlineMarkup): reply_markup = pyrogram_types.InlineKeyboardMarkup.read( reply_markup) elif isinstance(reply_markup, types.ReplyKeyboardHide): reply_markup = pyrogram_types.ReplyKeyboardRemove.read( reply_markup) else: reply_markup = None m = pyrogram_types.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)), outgoing=message.out, client=proxy(client), reply_markup=reply_markup) if message.reply_to_msg_id and replies: m.reply_to_message = client.get_messages(m.chat.id, message.reply_to_msg_id, replies=replies - 1) return m