async def _parse(client, chat_full: "raw.types.ChatFull", users: dict, chats: dict): if chat_full is None: return None peer_id = -chat_full.id return GroupFull( client=client, id=peer_id, can_set_username=getattr(chat_full, 'can_set_username', None), has_scheduled=getattr(chat_full, 'has_scheduled', None), about=getattr(chat_full, 'about', None), members=types.List([ types.GroupParticipant._parse(client, r, users) for r in getattr(chat_full.participants, 'participants', []) ]) or None, chat_photo=types.Photo._parse( client, getattr(chat_full, "chat_photo", None)), notify_settings=types.PeerNotifySettings._parse( client, getattr(chat_full, 'notify_settings', None)), invite_link=chat_full.exported_invite.link if isinstance( chat_full.exported_invite, raw.types.ChatInviteExported) else None, bot_infos=types.List([ types.BotInfo._parse(client, r) for r in getattr(chat_full, 'bot_info', []) ]) or None, pinned_message=await client.get_messages( peer_id, message_ids=chat_full.pinned_msg_id) if getattr( chat_full, 'pinned_msg_id', None) else None, folder_id=getattr(chat_full, 'folder_id', None), )
async def parse_messages(client, messages: "raw.types.messages.Messages", replies: int = 1) -> List["types.Message"]: users = {i.id: i for i in messages.users} chats = {i.id: i for i in messages.chats} if not messages.messages: return types.List() parsed_messages = [] for message in messages.messages: parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0)) if replies: messages_with_replies = { i.id: getattr(i, "reply_to_msg_id", None) for i in messages.messages } reply_message_ids = [ i[0] for i in filter(lambda x: x[1] is not None, messages_with_replies.items()) ] if reply_message_ids: # We need a chat id, but some messages might be empty (no chat attribute available) # Scan until we find a message with a chat available (there must be one, because we are fetching replies) for m in parsed_messages: if m.chat: chat_id = m.chat.id break else: chat_id = 0 reply_messages = await client.get_messages( chat_id, reply_to_message_ids=reply_message_ids, replies=replies - 1) for message in parsed_messages: reply_id = messages_with_replies[message.message_id] for reply in reply_messages: if reply.message_id == reply_id: message.reply_to_message = reply return types.List(parsed_messages)
async def parse_messages(client, messages: "raw.types.messages.Messages", replies: int = 1) -> List["types.Message"]: users = {i.id: i for i in messages.users} chats = {i.id: i for i in messages.chats} if not messages.messages: return types.List() parsed_messages = [] for message in messages.messages: parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0)) if replies: messages_with_replies = { i.id: i.reply_to.reply_to_msg_id for i in messages.messages if not isinstance(i, raw.types.MessageEmpty) and i.reply_to } if messages_with_replies: # We need a chat id, but some messages might be empty (no chat attribute available) # Scan until we find a message with a chat available (there must be one, because we are fetching replies) for m in parsed_messages: if m.chat: chat_id = m.chat.id break else: chat_id = 0 reply_messages = await client.get_messages( chat_id, reply_to_message_ids=messages_with_replies.keys(), replies=replies - 1) for message in parsed_messages: reply_id = messages_with_replies.get(message.message_id, None) for reply in reply_messages: if reply.message_id == reply_id: message.reply_to_message = reply return types.List(parsed_messages)
def _parse(client, user: "******") -> Optional["User"]: if user is None or isinstance(user, raw.types.UserEmpty): return None return User( id=user.id, is_self=user.is_self, is_contact=user.contact, is_mutual_contact=user.mutual_contact, is_deleted=user.deleted, is_bot=user.bot, is_verified=user.verified, is_restricted=user.restricted, is_scam=user.scam, is_fake=user.fake, is_support=user.support, first_name=user.first_name, last_name=user.last_name, **User._parse_status(user.status, user.bot), username=user.username, language_code=user.lang_code, dc_id=getattr(user.photo, "dc_id", None), phone_number=user.phone, photo=types.ChatPhoto._parse(client, user.photo, user.id, user.access_hash), restrictions=types.List( [types.Restriction._parse(r) for r in user.restriction_reason]) or None, client=client)
def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat": peer_id = utils.get_channel_id(channel.id) restriction_reason = getattr(channel, "restriction_reason", []) return Chat( id=peer_id, type="supergroup" if channel.megagroup else "channel", is_verified=getattr(channel, "verified", None), is_restricted=getattr(channel, "restricted", None), is_creator=getattr(channel, "creator", None), is_scam=getattr(channel, "scam", None), is_fake=getattr(channel, "fake", None), title=channel.title, username=getattr(channel, "username", None), photo=types.ChatPhoto._parse(client, getattr(channel, "photo", None), peer_id, channel.access_hash), restrictions=types.List( [types.Restriction._parse(r) for r in restriction_reason]) or None, permissions=types.ChatPermissions._parse( getattr(channel, "default_banned_rights", None)), members_count=getattr(channel, "participants_count", None), dc_id=getattr(getattr(channel, "photo", None), "dc_id", None), client=client)
async def get_chat_admins_with_invite_links( self: "pyrogram.Client", chat_id: Union[int, str], ): """Get the list of the administrators that have exported invite links in a chat. You must be the owner of a chat for this to work. Args: chat_id (``int`` | ``str``): Unique identifier for the target chat or username of the target channel/supergroup (in the format @username). Returns: List of :obj:`~pyrogram.types.ChatAdminWithInviteLink`: On success, the list of admins that have exported invite links is returned. """ r = await self.invoke( raw.functions.messages.GetAdminsWithInvites( peer=await self.resolve_peer(chat_id))) users = {i.id: i for i in r.users} return types.List( types.ChatAdminWithInviteLinks._parse(self, admin, users) for admin in r.admins)
async def get_media_group( self, chat_id: Union[int, str], message_id: int ) -> List["types.Message"]: """Get the media group a message belongs 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). message_id (``int``): The id of one of the messages that belong to the media group. Returns: List of :obj:`~pyrogram.types.Message`: On success, a list of messages of the media group is returned. Raises: ValueError: In case the passed message id doesn't belong to a media group. """ # There can be maximum 10 items in a media group. messages = await self.get_messages(chat_id, [msg_id for msg_id in range(message_id - 9, message_id + 10)], replies=0) media_group_id = messages[9].media_group_id if media_group_id is None: raise ValueError("The message doesn't belong to a media group") return types.List(msg for msg in messages if msg.media_group_id == media_group_id)
def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat": peer_id = utils.get_channel_id(channel.id) restriction_reason = getattr(channel, "restriction_reason", []) return Chat( id=peer_id, type=enums.ChatType.SUPERGROUP if getattr(channel, "megagroup", None) else enums.ChatType.CHANNEL, is_verified=getattr(channel, "verified", None), is_restricted=getattr(channel, "restricted", None), is_creator=getattr(channel, "creator", None), is_scam=getattr(channel, "scam", None), is_fake=getattr(channel, "fake", None), title=channel.title, username=getattr(channel, "username", None), photo=types.ChatPhoto._parse(client, getattr(channel, "photo", None), peer_id, getattr(channel, "access_hash", 0)), restrictions=types.List( [types.Restriction._parse(r) for r in restriction_reason]) or None, permissions=types.ChatPermissions._parse( getattr(channel, "default_banned_rights", None)), members_count=getattr(channel, "participants_count", None), dc_id=getattr(getattr(channel, "photo", None), "dc_id", None), has_protected_content=getattr(channel, "noforwards", None), client=client)
async def get_send_as_chats( self, chat_id: Union[int, str]) -> List["types.Chat"]: """Get the list of "send_as" chats available. Parameters: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. Returns: List[:obj:`~pyrogram.types.Chat`]: The list of chats. Example: .. code-block:: python chats = app.get_send_as_chats(chat_id) print(chats) """ r = await self.send( raw.functions.channels.GetSendAs( peer=await self.resolve_peer(chat_id))) users = {u.id: u for u in r.users} chats = {c.id: c for c in r.chats} send_as_chats = types.List() for p in r.peers: if isinstance(p, raw.types.PeerUser): send_as_chats.append( types.Chat._parse_chat(self, users[p.user_id])) else: send_as_chats.append( types.Chat._parse_chat(self, chats[p.channel_id])) return send_as_chats
async def parse_message_views(client, message_views: "raw.types.messages.MessageViews", message_ids: list) -> List["types.MessageViews"]: users = {i.id: i for i in message_views.users} chats = {i.id: i for i in message_views.chats} if not message_views.views: return types.List() parsed_views = [] for message_id, view in zip(message_ids, message_views.views): parsed_view = await types.MessageViews._parse(client, message_id, view, users, chats) if parsed_view: parsed_views.append(parsed_view) return types.List(parsed_views)
async def parse_admin_log_events( client: "pyrogram.Client", admin_log_results: raw.base.channels.AdminLogResults ) -> List["types.ChannelAdminLogEvent"]: users = {i.id: i for i in admin_log_results.users} chats = {i.id: i for i in admin_log_results.chats} if not admin_log_results.events: return types.List() parsed_events = [] for event in admin_log_results.events: parsed_event = await types.ChannelAdminLogEvent._parse( client, event, users, chats) if parsed_event: parsed_events.append(parsed_event) return types.List(parsed_events) if len(parsed_events) else types.List()
async def mixed_to_html(text: str): pyro_entity = types.List() x = Parser(userge) y = await x.parse(text, mode="combined") for i in y["entities"]: ent = await e_gen(i, userge) if ent: pyro_entity.append(ent) out = x.unparse(y["message"], pyro_entity, is_html=True) return str(soup(out, "html.parser"))
async def mixed_to_html(text: str): pyro_entity = types.List() x = Parser(setbot) y = await x.parse(text, mode='combined') for i in y['entities']: ent = await gen(i, setbot) if ent: pyro_entity.append(ent) out = x.unparse(y['message'], pyro_entity, is_html=True) return str(soup(out, 'html.parser'))
async def parse_messages(client, messages: "raw.types.messages.Messages", replies: int = 1) -> List["types.Message"]: users = {i.id: i for i in messages.users} chats = {i.id: i for i in messages.chats} if not messages.messages: return types.List() parsed_messages = [] for message in messages.messages: parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0)) if replies: messages_with_replies = { i.id: getattr(i, "reply_to_msg_id", None) for i in messages.messages } reply_message_ids = [ i[0] for i in filter(lambda x: x[1] is not None, messages_with_replies.items()) ] if reply_message_ids: reply_messages = await client.get_messages( parsed_messages[0].chat.id, reply_to_message_ids=reply_message_ids, replies=replies - 1) for message in parsed_messages: reply_id = messages_with_replies[message.message_id] for reply in reply_messages: if reply.message_id == reply_id: message.reply_to_message = reply return types.List(parsed_messages)
def _parse(client, invite_importers: "raw.types.ChatInviteImporters"): importers = types.List() d = {i.id: i for i in invite_importers.users} for j in invite_importers.importers: importers.append( InviteLinkImporter(date=j.date, user=types.User._parse(client=None, user=d[j.user_id]))) return importers
def _parse(client, bot_info: "raw.types.BotInfo"): if bot_info is None: return None return BotInfo( client=client, user_id=getattr(bot_info, 'user_id'), description=getattr(bot_info, 'description'), commands=types.List([ types.BotCommand._parse(client, r) for r in bot_info.commands ]) or None, )
def _parse(client, action: raw.base.MessageAction, users: dict, chats: dict): if action is None: return None return MessageActionChatAddUser( client=client, users=types.List([ types.User._parse(client, users.get(user_id, None)) for user_id in action.users ]) or None, )
def _parse(client, web_document: "raw.base.WebDocument") -> "WebDocument": if isinstance(web_document, raw.types.WebDocument): return WebDocument( client=client, url=web_document.url, size=web_document.size, mime_type=web_document.mime_type, attributes=types.List( [types.DocumentAttribute._parse(client, attr) for attr in web_document.attributes]) or None, access_hash=getattr(web_document, 'access_hash', None), type='normal' if isinstance(web_document, raw.types.WebDocument) else 'no_proxy', )
async def get_contacts(self) -> List["types.User"]: """Get contacts from your Telegram address book. Returns: List of :obj:`~pyrogram.types.User`: On success, a list of users is returned. Example: .. code-block:: python contacts = app.get_contacts() print(contacts) """ contacts = await self.send(raw.functions.contacts.GetContacts(hash=0)) return types.List(types.User._parse(self, user) for user in contacts.users)
async def get_nearby_chats( self, latitude: float, longitude: float ) -> List["types.Chat"]: """Get nearby chats. Parameters: latitude (``float``): Latitude of the location. longitude (``float``): Longitude of the location. Returns: List of :obj:`~pyrogram.types.Chat`: On success, a list of nearby chats is returned. Example: .. code-block:: python chats = app.get_nearby_chats(51.500729, -0.124583) print(chats) """ r = await self.send( raw.functions.contacts.GetLocated( geo_point=raw.types.InputGeoPoint( lat=latitude, long=longitude ) ) ) if not r.updates: return [] chats = types.List([types.Chat._parse_chat(self, chat) for chat in r.chats]) peers = r.updates[0].peers for peer in peers: if isinstance(peer.peer, raw.types.PeerChannel): chat_id = utils.get_channel_id(peer.peer.channel_id) for chat in chats: if chat.id == chat_id: chat.distance = peer.distance break return chats
async def parse_messages( client, messages: "raw.types.messages.Messages", replies: int = 1, is_scheduled: bool = False, ) -> List["types.Message"]: users = {i.id: i for i in messages.users} chats = {i.id: i for i in messages.chats} if not messages.messages: return types.List() parsed_messages = [] for message in messages.messages: parsed_messages.append(await types.Message._parse(client, message, users, chats, is_scheduled=is_scheduled, replies=0)) return types.List(parsed_messages)
def parse_deleted_messages(client, update) -> List["types.Message"]: messages = update.messages channel_id = getattr(update, "channel_id", None) parsed_messages = [] for message in messages: parsed_messages.append( types.Message(message_id=message, chat=types.Chat(id=get_channel_id(channel_id), type="channel", client=client) if channel_id is not None else None, client=client)) return types.List(parsed_messages)
async def _parse(client: "pyrogram.Client", message_replies: raw.base.MessageReplies, users: dict, chats: dict): if message_replies is None: return None def get_replier(peer: "raw.base.Peer"): if peer is None: return None, None if isinstance(peer, raw.types.PeerUser): return users.get(peer.user_id, None), 'user' elif isinstance(peer, raw.types.PeerChat): return chats.get(peer.chat_id, None), 'group' elif isinstance(peer, raw.types.PeerChannel): return chats.get(peer.channel_id, None), 'channel' recent_repliers = None if message_replies.recent_repliers: parsed_peers = [] for peer in message_replies.recent_repliers: _peer, _type = get_replier(peer) if peer is None and _type is None: continue if _type == 'user': parsed_peer = types.User._parse(client, _peer) else: parsed_peer = await types.Chat._parse_chat(client, _peer) if parsed_peer: parsed_peers.append(parsed_peer) if len(parsed_peers): recent_repliers = types.List(parsed_peers) return MessageReplies( client=client, comments=getattr(message_replies, 'comments', None), replies=getattr(message_replies, 'replies', None), replies_pts=getattr(message_replies, 'replies_pts', None), recent_repliers=recent_repliers, channel_id=utils.get_channel_id(message_replies.channel_id) if getattr(message_replies, 'channel_id', None) else None, max_id=getattr(message_replies, 'max_id', None), read_max_id=getattr(message_replies, 'read_max_id', None), )
def _parse(client, channel): if channel is None: return None peer_id = utils.get_channel_id(channel.id) return Channel( client=client, id=peer_id, title=getattr(channel, 'title', None), is_forbidden=isinstance(channel, raw.types.ChannelForbidden), forbidden_until=getattr(channel, 'until_date', None), username=getattr(channel, 'username', None), photo=types.ChatPhoto._parse(client, getattr(channel, "photo", None), peer_id, getattr(channel, 'access_hash', 0)), is_creator=getattr(channel, 'creator', None), left=getattr(channel, 'left', None), is_broadcast=getattr(channel, 'broadcast', None), is_verified=getattr(channel, 'verified', None), is_supergroup=getattr(channel, 'megagroup', None), is_restricted=getattr(channel, 'restricted', None), signatures_enabled=getattr(channel, 'signatures', None), min=getattr(channel, 'min', None), is_scam=getattr(channel, 'scam', None), is_fake=getattr(channel, "fake", None), has_private_join_link=getattr(channel, 'has_link', None), has_geo=getattr(channel, 'has_geo', None), slow_mode=getattr(channel, 'slowmode_enabled', None), access_hash=getattr(channel, 'access_hash', None), date=getattr(channel, 'date', None), version=getattr(channel, 'version', None), restrictions=types.List([ types.Restriction._parse(r) for r in getattr(channel, 'restriction_reason', []) ]) or None, admin_rights=types.ChatAdminRights._parse( getattr(channel, 'admin_rights', None)), banned_rights=types.ChatPermissions._parse( getattr(channel, 'banned_rights', None)), default_banned_rights=types.ChatPermissions._parse( getattr(channel, 'default_banned_rights', None)), members_count=getattr(channel, 'participants_count', None), )
def _parse_user_chat(client, user: raw.types.User) -> "Chat": peer_id = user.id return Chat( id=peer_id, type="bot" if user.bot else "private", is_verified=getattr(user, "verified", None), is_restricted=getattr(user, "restricted", None), is_scam=getattr(user, "scam", None), is_support=getattr(user, "support", None), username=user.username, first_name=user.first_name, last_name=user.last_name, photo=types.ChatPhoto._parse(client, user.photo, peer_id, user.access_hash), restrictions=types.List([types.Restriction._parse(r) for r in user.restriction_reason]) or None, dc_id=getattr(user.photo, "dc_id", None), client=client )
async def get_media_group(self: "pyrogram.Client", chat_id: Union[int, str], message_id: int) -> List["types.Message"]: """Get the media group a message belongs 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). message_id (``int``): The id of one of the messages that belong to the media group. Returns: List of :obj:`~pyrogram.types.Message`: On success, a list of messages of the media group is returned. Raises: ValueError: In case the passed message_id is negative or equal 0. In case target message doesn't belong to a media group. """ if message_id <= 0: raise ValueError("Passed message_id is negative or equal to zero.") # Get messages with id from `id - 9` to `id + 10` to get all possible media group messages. messages = await self.get_messages( chat_id=chat_id, message_ids=[ msg_id for msg_id in range(message_id - 9, message_id + 10) ], replies=0) # There can be maximum 10 items in a media group. # If/else condition to fix the problem of getting correct `media_group_id` when `message_id` is less than 10. media_group_id = messages[9].media_group_id if len( messages) == 19 else messages[message_id - 1].media_group_id if media_group_id is None: raise ValueError("The message doesn't belong to a media group") return types.List(msg for msg in messages if msg.media_group_id == media_group_id)
async def get_users( self, user_ids: Union[Iterable[Union[int, str]], int, str] ) -> Union["types.User", List["types.User"]]: """Get information about a user. You can retrieve up to 200 users at once. Parameters: user_ids (``iterable``): A list of User identifiers (id or username) or a single user id/username. For a contact that exists in your Telegram address book you can use his phone number (str). Iterators and Generators are also accepted. Returns: :obj:`~pyrogram.types.User` | List of :obj:`~pyrogram.types.User`: In case *user_ids* was an integer or string the single requested user is returned, otherwise, in case *user_ids* was an iterable a list of users is returned, even if the iterable contained one item only. Example: .. code-block:: python # Get information about one user app.get_users("me") # Get information about multiple users at once app.get_users([user1, user2, user3]) """ is_iterable = not isinstance(user_ids, (int, str)) user_ids = list(user_ids) if is_iterable else [user_ids] user_ids = await asyncio.gather(*[self.resolve_peer(i) for i in user_ids]) r = await self.send( raw.functions.users.GetUsers( id=user_ids ) ) users = types.List() for i in r: users.append(types.User._parse(self, i)) return users if is_iterable else users[0]
async def get_game_high_scores( self, user_id: Union[int, str], chat_id: Union[int, str], message_id: int = None) -> List["types.GameHighScore"]: """Get data for high score tables. Parameters: user_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). chat_id (``int`` | ``str``, *optional*): 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). Required if inline_message_id is not specified. message_id (``int``, *optional*): Identifier of the sent message. Required if inline_message_id is not specified. Returns: List of :obj:`~pyrogram.types.GameHighScore`: On success. Example: .. code-block:: python scores = app.get_game_high_scores(user_id, chat_id, message_id) print(scores) """ # TODO: inline_message_id r = await self.send( raw.functions.messages.GetGameHighScores( peer=await self.resolve_peer(chat_id), id=message_id, user_id=await self.resolve_peer(user_id))) return types.List( types.GameHighScore._parse(self, score, r.users) for score in r.scores)
async def delete_contacts( self, user_ids: Union[int, str, List[Union[int, str]]] ) -> Union["types.User", List["types.User"], None]: """Delete contacts from your Telegram address book. Parameters: user_ids (``int`` | ``str`` | List of ``int`` or ``str``): A single user id/username o a list of user identifiers (id or username). Returns: :obj:`~pyrogram.types.User` | List of :obj:`~pyrogram.types.User` | ``None``: In case *user_ids* was an integer or a string, a single User object is returned. In case *user_ids* was a list, a list of User objects is returned. In case nothing changed after calling the method (for example, when deleting a non-existent contact), None is returned. Example: .. code-block:: python app.delete_contacts(user_id) app.delete_contacts([user_id1, user_id2, user_id3]) """ is_user_ids_list = isinstance(user_ids, list) if not is_user_ids_list: user_ids = [user_ids] r = await self.send( raw.functions.contacts.DeleteContacts( id=[await self.resolve_peer(i) for i in user_ids] ) ) if not r.updates: return None users = types.List([types.User._parse(self, i) for i in r.users]) if is_user_ids_list: return users else: return users[0]
def _parse(client, user: "******") -> "User" or None: if user is None: return None is_empty = isinstance(user, raw.types.UserEmpty) status = User._parse_status(user.status, user.bot) if not is_empty else {} return User( id=user.id, is_empty=is_empty, is_self=getattr(user, 'self', None), is_contact=getattr(user, 'contact', None), is_mutual_contact=getattr(user, 'mutual_contact', None), is_deleted=getattr(user, 'deleted', None), is_bot=getattr(user, 'bot', None), is_verified=getattr(user, 'verified', None), is_restricted=getattr(user, 'restricted', None), is_scam=getattr(user, 'scam', None), is_fake=getattr(user, 'fake', None), is_support=getattr(user, 'support', None), first_name=getattr(user, 'first_name', None), last_name=getattr(user, 'last_name', None), **status, username=getattr(user, 'username', None), language_code=getattr(user, 'lang_code', None), dc_id=getattr(user.photo, "dc_id", None), phone_number=getattr(user, 'phone', None), photo=types.ChatPhoto._parse(client, user.photo, user.id, user.access_hash) if getattr( user, 'photo', None) else None, restrictions=(types.List( [types.Restriction._parse(r) for r in user.restriction_reason]) or None) if getattr( user, 'restriction_reason', None) else None, # added bot_info_version=getattr(user, 'bot_info_version', None), bot_inline_placeholder=getattr(user, 'bot_inline_placeholder', None), bot_can_be_added_to_group=getattr(user, 'bot_nochats', None), bot_can_see_history=getattr(user, 'bot_chat_history', None), bot_can_request_geo=getattr(user, 'bot_inline_geo', None), client=client)