def parse_deleted_messages(client, update) -> List["pyrogram.Message"]: messages = update.messages channel_id = getattr(update, "channel_id", None) parsed_messages = [] for message in messages: parsed_messages.append( pyrogram.Message(message_id=message, chat=pyrogram.Chat(id=get_channel_id(channel_id), type="channel", client=client) if channel_id is not None else None, client=client)) return pyrogram.List(parsed_messages)
def send_message( self, chat_id: Union[int, str], text: str, parse_mode: str = "", disable_web_page_preview: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply" ] = None ) -> "pyrogram.Message": """Use this method to send text messages. Args: chat_id (``int`` | ``str``): Unique identifier (int) or username (str) of the target chat. For your personal cloud (Saved Messages) you can simply use "me" or "self". For a contact that exists in your Telegram address book you can use his phone number (str). text (``str``): Text of the message to be sent. parse_mode (``str``, *optional*): Use :obj:`MARKDOWN <pyrogram.ParseMode.MARKDOWN>` or :obj:`HTML <pyrogram.ParseMode.HTML>` if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your message. Defaults to Markdown. disable_web_page_preview (``bool``, *optional*): Disables link previews for links in this message. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. Returns: On success, the sent :obj:`Message` is returned. Raises: :class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. """ style = self.html if parse_mode.lower() == "html" else self.markdown message, entities = style.parse(text).values() r = self.send( functions.messages.SendMessage( peer=self.resolve_peer(chat_id), no_webpage=disable_web_page_preview or None, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), reply_markup=reply_markup.write() if reply_markup else None, message=message, entities=entities ) ) if isinstance(r, types.UpdateShortSentMessage): peer = self.resolve_peer(chat_id) peer_id = ( peer.user_id if isinstance(peer, types.InputPeerUser) else -peer.chat_id ) return pyrogram.Message( message_id=r.id, chat=pyrogram.Chat( id=peer_id, type="private", client=self ), text=message, date=r.date, outgoing=r.out, entities=entities, client=self ) for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): return pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats} )
def send_message( self, chat_id: Union[int, str], text: str, parse_mode: Union[str, None] = object, disable_web_page_preview: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, reply_markup: Union["pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply"] = None ) -> "pyrogram.Message": """Send text 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). text (``str``): Text of the message to be sent. 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_web_page_preview (``bool``, *optional*): Disables link previews for links in this message. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. Returns: :obj:`Message`: On success, the sent text message is returned. Example: .. code-block:: python :emphasize-lines: 2,5,8,11,21-23,26-33 # Simple example app.send_message("haskell", "Thanks for creating **Pyrogram**!") # Disable web page previews app.send_message("me", "https://docs.pyrogram.org", disable_web_page_preview=True) # Reply to a message using its id app.send_message("me", "this is a reply", reply_to_message_id=12345) # Force HTML-only styles for this request only app.send_message("me", "**not bold**, <i>italic<i>", parse_mode="html") ## # For bots only, send messages with keyboards attached ## from pyrogram import ( ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton) # Send a normal keyboard app.send_message( chat_id, "Look at that button!", reply_markup=ReplyKeyboardMarkup([["Nice!"]])) # Send an inline keyboard app.send_message( chat_id, "These are inline buttons", reply_markup=InlineKeyboardMarkup( [ [InlineKeyboardButton("Data", callback_data="hidden_callback_data")], [InlineKeyboardButton("Docs", url="https://docs.pyrogram.org")] ])) """ message, entities = self.parser.parse(text, parse_mode).values() r = self.send( functions.messages.SendMessage( peer=self.resolve_peer(chat_id), no_webpage=disable_web_page_preview or None, 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=message, entities=entities)) if isinstance(r, types.UpdateShortSentMessage): peer = self.resolve_peer(chat_id) peer_id = (peer.user_id if isinstance(peer, types.InputPeerUser) else -peer.chat_id) return pyrogram.Message(message_id=r.id, chat=pyrogram.Chat(id=peer_id, type="private", client=self), text=message, date=r.date, outgoing=r.out, entities=entities, client=self) for i in r.updates: if isinstance( i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats}, is_scheduled=isinstance(i, types.UpdateNewScheduledMessage))
def parse_message_empty(client, message: types.MessageEmpty, users: dict, chats: dict) -> pyrogram.Message: return pyrogram.Message(message_id=message.id, date=None, chat=None)
def parse_message_service(client, message: types.MessageService, users: dict, chats: dict) -> pyrogram.Message: 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.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) new_chat_photo = photo_sizes 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)), 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 # TODO: supergroup_chat_created ) if isinstance(action, types.MessageActionPinMessage): m.pinned_message = client.get_messages(m.chat.id, message.reply_to_msg_id) m.pinned_message = m.pinned_message return m
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
async def send_message( self, chat_id: Union[int, str], text: str, parse_mode: Union[str, None] = "", disable_web_page_preview: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply" ] = None ) -> "pyrogram.Message": """Send text 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). text (``str``): Text of the message to be sent. parse_mode (``str``, *optional*): By default, texts are parsed using both Markdown and HTML styles. You can combine both syntaxes together. Pass "markdown" to enable Markdown-style parsing only. Pass "html" to enable HTML-style parsing only. Pass None to completely disable style parsing. disable_web_page_preview (``bool``, *optional*): Disables link previews for links in this message. disable_notification (``bool``, *optional*): Sends the message silently. Users will receive a notification with no sound. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. Returns: :obj:`Message`: On success, the sent text message is returned. Raises: RPCError: In case of a Telegram RPC error. """ message, entities = (await self.parser.parse(text, parse_mode)).values() r = await self.send( functions.messages.SendMessage( peer=await self.resolve_peer(chat_id), no_webpage=disable_web_page_preview or None, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), reply_markup=reply_markup.write() if reply_markup else None, message=message, entities=entities ) ) if isinstance(r, types.UpdateShortSentMessage): peer = await self.resolve_peer(chat_id) peer_id = ( peer.user_id if isinstance(peer, types.InputPeerUser) else -peer.chat_id ) return pyrogram.Message( message_id=r.id, chat=pyrogram.Chat( id=peer_id, type="private", client=self ), text=message, date=r.date, outgoing=r.out, entities=entities, client=self ) for i in r.updates: if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, {i.id: i for i in r.chats} )