def _parse_status(user_status: "raw.base.UserStatus", is_bot: bool = False): if isinstance(user_status, raw.types.UserStatusOnline): status, date = enums.UserStatus.ONLINE, user_status.expires elif isinstance(user_status, raw.types.UserStatusOffline): status, date = enums.UserStatus.OFFLINE, user_status.was_online elif isinstance(user_status, raw.types.UserStatusRecently): status, date = enums.UserStatus.RECENTLY, None elif isinstance(user_status, raw.types.UserStatusLastWeek): status, date = enums.UserStatus.LAST_WEEK, None elif isinstance(user_status, raw.types.UserStatusLastMonth): status, date = enums.UserStatus.LAST_MONTH, None else: status, date = enums.UserStatus.LONG_AGO, None last_online_date = None next_offline_date = None if is_bot: status = None if status == enums.UserStatus.ONLINE: next_offline_date = utils.timestamp_to_datetime(date) if status == enums.UserStatus.OFFLINE: last_online_date = utils.timestamp_to_datetime(date) return { "status": status, "last_online_date": last_online_date, "next_offline_date": next_offline_date }
def _parse(client, video: "raw.types.Document", video_attributes: "raw.types.DocumentAttributeVideo", file_name: str, ttl_seconds: int = None) -> "Video": return Video(file_id=FileId( file_type=FileType.VIDEO, dc_id=video.dc_id, media_id=video.id, access_hash=video.access_hash, file_reference=video.file_reference).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=video.id).encode(), width=video_attributes.w, height=video_attributes.h, duration=video_attributes.duration, file_name=file_name, mime_type=video.mime_type, supports_streaming=video_attributes.supports_streaming, file_size=video.size, date=utils.timestamp_to_datetime(video.date), ttl_seconds=ttl_seconds, thumbs=types.Thumbnail._parse(client, video), client=client)
def _parse( client: "pyrogram.Client", update: Union["raw.types.UpdateChatParticipant", "raw.types.UpdateChannelParticipant"], users: Dict[int, "raw.types.User"], chats: Dict[int, "raw.types.Chat"] ) -> "ChatMemberUpdated": chat_id = getattr(update, "chat_id", None) or getattr(update, "channel_id") old_chat_member = None new_chat_member = None invite_link = None if update.prev_participant: old_chat_member = types.ChatMember._parse(client, update.prev_participant, users, chats) if update.new_participant: new_chat_member = types.ChatMember._parse(client, update.new_participant, users, chats) if update.invite: invite_link = types.ChatInviteLink._parse(client, update.invite, users) return ChatMemberUpdated( chat=types.Chat._parse_chat(client, chats[chat_id]), from_user=types.User._parse(client, users[update.actor_id]), date=utils.timestamp_to_datetime(update.date), old_chat_member=old_chat_member, new_chat_member=new_chat_member, invite_link=invite_link, client=client )
def _parse( client, video_note: "raw.types.Document", video_attributes: "raw.types.DocumentAttributeVideo" ) -> "VideoNote": return VideoNote( file_id=FileId( file_type=FileType.VIDEO_NOTE, dc_id=video_note.dc_id, media_id=video_note.id, access_hash=video_note.access_hash, file_reference=video_note.file_reference ).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=video_note.id ).encode(), length=video_attributes.w, duration=video_attributes.duration, file_size=video_note.size, mime_type=video_note.mime_type, date=utils.timestamp_to_datetime(video_note.date), thumbs=types.Thumbnail._parse(client, video_note), client=client )
def _parse(client: "pyrogram.Client", invite: "raw.base.ExportedChatInvite", users: Dict[int, "raw.types.User"] = None) -> "ChatInviteLink": creator = (types.User._parse(client, users[invite.admin_id]) if users is not None else None) return ChatInviteLink( invite_link=invite.link, date=utils.timestamp_to_datetime(invite.date), is_primary=invite.permanent, is_revoked=invite.revoked, creator=creator, name=invite.title, creates_join_request=invite.request_needed, start_date=utils.timestamp_to_datetime(invite.start_date), expire_date=utils.timestamp_to_datetime(invite.expire_date), member_limit=invite.usage_limit, member_count=invite.usage, pending_join_request_count=invite.requested)
def _parse(client: "pyrogram.Client", update: "raw.types.UpdateBotChatInviteRequester", users: Dict[int, "raw.types.User"], chats: Dict[int, "raw.types.Chat"]) -> "ChatJoinRequest": chat_id = utils.get_raw_peer_id(update.peer) return ChatJoinRequest( chat=types.Chat._parse_chat(client, chats[chat_id]), from_user=types.User._parse(client, users[update.user_id]), date=utils.timestamp_to_datetime(update.date), bio=update.about, invite_link=types.ChatInviteLink._parse(client, update.invite, users), client=client)
def _parse(client, invite_importers: "raw.types.messages.ChatInviteImporters"): importers = types.List() d = {i.id: i for i in invite_importers.users} for j in invite_importers.importers: importers.append( InviteLinkImporter( date=utils.timestamp_to_datetime(j.date), user=types.User._parse(client=None, user=d[j.user_id]) ) ) return importers
def _parse(client, document: "raw.types.Document", file_name: str) -> "Document": return Document(file_id=FileId( file_type=FileType.DOCUMENT, dc_id=document.dc_id, media_id=document.id, access_hash=document.access_hash, file_reference=document.file_reference).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=document.id).encode(), file_name=file_name, mime_type=document.mime_type, file_size=document.size, date=utils.timestamp_to_datetime(document.date), thumbs=types.Thumbnail._parse(client, document), client=client)
def _parse( client: "pyrogram.Client", joiner: "raw.base.ChatInviteImporter", users: Dict[int, "raw.base.User"], ) -> "ChatJoiner": return ChatJoiner( user=types.User._parse(client, users[joiner.user_id]), date=utils.timestamp_to_datetime(joiner.date), pending=joiner.requested, bio=joiner.about, approved_by=( types.User._parse(client, users[joiner.approved_by]) if joiner.approved_by else None ), client=client )
def _parse(client, photo: "raw.types.Photo", ttl_seconds: int = None) -> "Photo": if isinstance(photo, raw.types.Photo): photos: List[raw.types.PhotoSize] = [] for p in photo.sizes: if isinstance(p, raw.types.PhotoSize): photos.append(p) if isinstance(p, raw.types.PhotoSizeProgressive): photos.append( raw.types.PhotoSize(type=p.type, w=p.w, h=p.h, size=max(p.sizes))) photos.sort(key=lambda p: p.size) main = photos[-1] return Photo(file_id=FileId( file_type=FileType.PHOTO, dc_id=photo.dc_id, media_id=photo.id, access_hash=photo.access_hash, file_reference=photo.file_reference, thumbnail_source=ThumbnailSource.THUMBNAIL, thumbnail_file_type=FileType.PHOTO, thumbnail_size=main.type, volume_id=0, local_id=0).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=photo.id).encode(), width=main.w, height=main.h, file_size=main.size, date=utils.timestamp_to_datetime(photo.date), ttl_seconds=ttl_seconds, thumbs=types.Thumbnail._parse(client, photo), client=client)
def _parse(client, voice: "raw.types.Document", attributes: "raw.types.DocumentAttributeAudio") -> "Voice": return Voice( file_id=FileId( file_type=FileType.VOICE, dc_id=voice.dc_id, media_id=voice.id, access_hash=voice.access_hash, file_reference=voice.file_reference ).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=voice.id ).encode(), duration=attributes.duration, mime_type=voice.mime_type, file_size=voice.size, waveform=attributes.waveform, date=utils.timestamp_to_datetime(voice.date), client=client )
def _parse(client, animation: "raw.types.Document", video_attributes: "raw.types.DocumentAttributeVideo", file_name: str) -> "Animation": return Animation(file_id=FileId( file_type=FileType.ANIMATION, dc_id=animation.dc_id, media_id=animation.id, access_hash=animation.access_hash, file_reference=animation.file_reference).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=animation.id).encode(), width=getattr(video_attributes, "w", 0), height=getattr(video_attributes, "h", 0), duration=getattr(video_attributes, "duration", 0), mime_type=animation.mime_type, file_size=animation.size, file_name=file_name, date=utils.timestamp_to_datetime(animation.date), thumbs=types.Thumbnail._parse(client, animation), client=client)
def _parse(client, audio: "raw.types.Document", audio_attributes: "raw.types.DocumentAttributeAudio", file_name: str) -> "Audio": return Audio(file_id=FileId( file_type=FileType.AUDIO, dc_id=audio.dc_id, media_id=audio.id, access_hash=audio.access_hash, file_reference=audio.file_reference).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=audio.id).encode(), duration=audio_attributes.duration, performer=audio_attributes.performer, title=audio_attributes.title, mime_type=audio.mime_type, file_size=audio.size, file_name=file_name, date=utils.timestamp_to_datetime(audio.date), thumbs=types.Thumbnail._parse(client, audio), client=client)
async def _parse( client, sticker: "raw.types.Document", image_size_attributes: "raw.types.DocumentAttributeImageSize", sticker_attributes: "raw.types.DocumentAttributeSticker", file_name: str) -> "Sticker": sticker_set = sticker_attributes.stickerset if isinstance(sticker_set, raw.types.InputStickerSetID): input_sticker_set_id = (sticker_set.id, sticker_set.access_hash) set_name = await Sticker._get_sticker_set_name( client.invoke, input_sticker_set_id) else: set_name = None return Sticker( file_id=FileId(file_type=FileType.STICKER, dc_id=sticker.dc_id, media_id=sticker.id, access_hash=sticker.access_hash, file_reference=sticker.file_reference).encode(), file_unique_id=FileUniqueId( file_unique_type=FileUniqueType.DOCUMENT, media_id=sticker.id).encode(), width=image_size_attributes.w if image_size_attributes else 512, height=image_size_attributes.h if image_size_attributes else 512, is_animated=sticker.mime_type == "application/x-tgsticker", is_video=sticker.mime_type == "video/webm", # TODO: mask_position set_name=set_name, emoji=sticker_attributes.alt or None, file_size=sticker.size, mime_type=sticker.mime_type, file_name=file_name, date=utils.timestamp_to_datetime(sticker.date), thumbs=types.Thumbnail._parse(client, sticker), client=client)
async def _parse( client: "pyrogram.Client", event: "raw.base.ChannelAdminLogEvent", users: List["raw.base.User"], chats: List["raw.base.Chat"] ): users = {i.id: i for i in users} chats = {i.id: i for i in chats} user = types.User._parse(client, users[event.user_id]) action = event.action old_description: Optional[str] = None new_description: Optional[str] = None old_history_ttl: Optional[int] = None new_history_ttl: Optional[int] = None old_linked_chat: Optional[types.Chat] = None new_linked_chat: Optional[types.Chat] = None old_photo: Optional[types.Photo] = None new_photo: Optional[types.Photo] = None old_title: Optional[str] = None new_title: Optional[str] = None old_username: Optional[str] = None new_username: Optional[str] = None old_chat_permissions: Optional[types.ChatPermissions] = None new_chat_permissions: Optional[types.ChatPermissions] = None deleted_message: Optional[types.Message] = None old_message: Optional[types.Message] = None new_message: Optional[types.Message] = None invited_member: Optional[types.ChatMember] = None old_administrator_privileges: Optional[types.ChatMember] = None new_administrator_privileges: Optional[types.ChatMember] = None old_member_permissions: Optional[types.ChatMember] = None new_member_permissions: Optional[types.ChatMember] = None stopped_poll: Optional[types.Message] = None invites_enabled: Optional[bool] = None history_hidden: Optional[bool] = None signatures_enabled: Optional[bool] = None old_slow_mode: Optional[int] = None new_slow_mode: Optional[int] = None pinned_message: Optional[types.Message] = None unpinned_message: Optional[types.Message] = None old_invite_link: Optional[types.ChatInviteLink] = None new_invite_link: Optional[types.ChatInviteLink] = None revoked_invite_link: Optional[types.ChatInviteLink] = None deleted_invite_link: Optional[types.ChatInviteLink] = None if isinstance(action, raw.types.ChannelAdminLogEventActionChangeAbout): old_description = action.prev_value new_description = action.new_value action = enums.ChatEventAction.DESCRIPTION_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeHistoryTTL): old_history_ttl = action.prev_value new_history_ttl = action.new_value action = enums.ChatEventAction.HISTORY_TTL_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeLinkedChat): old_linked_chat = types.Chat._parse_chat(client, chats[action.prev_value]) new_linked_chat = types.Chat._parse_chat(client, chats[action.new_value]) action = enums.ChatEventAction.LINKED_CHAT_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangePhoto): old_photo = types.Photo._parse(client, action.prev_photo) new_photo = types.Photo._parse(client, action.new_photo) action = enums.ChatEventAction.PHOTO_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeTitle): old_title = action.prev_value new_title = action.new_value action = enums.ChatEventAction.TITLE_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionChangeUsername): old_username = action.prev_value new_username = action.new_value action = enums.ChatEventAction.USERNAME_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionDefaultBannedRights): old_chat_permissions = types.ChatPermissions._parse(action.prev_banned_rights) new_chat_permissions = types.ChatPermissions._parse(action.new_banned_rights) action = enums.ChatEventAction.CHAT_PERMISSIONS_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionDeleteMessage): deleted_message = await types.Message._parse(client, action.message, users, chats) action = enums.ChatEventAction.MESSAGE_DELETED elif isinstance(action, raw.types.ChannelAdminLogEventActionEditMessage): old_message = await types.Message._parse(client, action.prev_message, users, chats) new_message = await types.Message._parse(client, action.new_message, users, chats) action = enums.ChatEventAction.MESSAGE_EDITED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantInvite): invited_member = types.ChatMember._parse(client, action.participant, users, chats) action = enums.ChatEventAction.MEMBER_INVITED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantToggleAdmin): old_administrator_privileges = types.ChatMember._parse(client, action.prev_participant, users, chats) new_administrator_privileges = types.ChatMember._parse(client, action.new_participant, users, chats) action = enums.ChatEventAction.ADMINISTRATOR_PRIVILEGES_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantToggleBan): old_member_permissions = types.ChatMember._parse(client, action.prev_participant, users, chats) new_member_permissions = types.ChatMember._parse(client, action.new_participant, users, chats) action = enums.ChatEventAction.MEMBER_PERMISSIONS_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionStopPoll): stopped_poll = await types.Message._parse(client, action.message, users, chats) action = enums.ChatEventAction.POLL_STOPPED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantJoin): action = enums.ChatEventAction.MEMBER_JOINED elif isinstance(action, raw.types.ChannelAdminLogEventActionParticipantLeave): action = enums.ChatEventAction.MEMBER_LEFT elif isinstance(action, raw.types.ChannelAdminLogEventActionToggleInvites): invites_enabled = action.new_value action = enums.ChatEventAction.INVITES_ENABLED elif isinstance(action, raw.types.ChannelAdminLogEventActionTogglePreHistoryHidden): history_hidden = action.new_value action = enums.ChatEventAction.HISTORY_HIDDEN elif isinstance(action, raw.types.ChannelAdminLogEventActionToggleSignatures): signatures_enabled = action.new_value action = enums.ChatEventAction.SIGNATURES_ENABLED elif isinstance(action, raw.types.ChannelAdminLogEventActionToggleSlowMode): old_slow_mode = action.prev_value new_slow_mode = action.new_value action = enums.ChatEventAction.SLOW_MODE_CHANGED elif isinstance(action, raw.types.ChannelAdminLogEventActionUpdatePinned): message = action.message if message.pinned: pinned_message = await types.Message._parse(client, message, users, chats) action = enums.ChatEventAction.MESSAGE_PINNED else: unpinned_message = await types.Message._parse(client, message, users, chats) action = enums.ChatEventAction.MESSAGE_UNPINNED elif isinstance(action, raw.types.ChannelAdminLogEventActionExportedInviteEdit): old_invite_link = types.ChatInviteLink._parse(client, action.prev_invite, users) new_invite_link = types.ChatInviteLink._parse(client, action.new_invite, users) action = enums.ChatEventAction.INVITE_LINK_EDITED elif isinstance(action, raw.types.ChannelAdminLogEventActionExportedInviteRevoke): revoked_invite_link = types.ChatInviteLink._parse(client, action.invite, users) action = enums.ChatEventAction.INVITE_LINK_REVOKED elif isinstance(action, raw.types.ChannelAdminLogEventActionExportedInviteDelete): deleted_invite_link = types.ChatInviteLink._parse(client, action.invite, users) action = enums.ChatEventAction.INVITE_LINK_DELETED else: action = f"{enums.ChatEventAction.UNKNOWN}-{action.QUALNAME}" return ChatEvent( id=event.id, date=utils.timestamp_to_datetime(event.date), user=user, action=action, old_description=old_description, new_description=new_description, old_history_ttl=old_history_ttl, new_history_ttl=new_history_ttl, old_linked_chat=old_linked_chat, new_linked_chat=new_linked_chat, old_photo=old_photo, new_photo=new_photo, old_title=old_title, new_title=new_title, old_username=old_username, new_username=new_username, old_chat_permissions=old_chat_permissions, new_chat_permissions=new_chat_permissions, deleted_message=deleted_message, old_message=old_message, new_message=new_message, invited_member=invited_member, old_administrator_privileges=old_administrator_privileges, new_administrator_privileges=new_administrator_privileges, old_member_permissions=old_member_permissions, new_member_permissions=new_member_permissions, stopped_poll=stopped_poll, invites_enabled=invites_enabled, history_hidden=history_hidden, signatures_enabled=signatures_enabled, old_slow_mode=old_slow_mode, new_slow_mode=new_slow_mode, pinned_message=pinned_message, unpinned_message=unpinned_message, old_invite_link=old_invite_link, new_invite_link=new_invite_link, revoked_invite_link=revoked_invite_link, deleted_invite_link=deleted_invite_link )
def _parse( client: "pyrogram.Client", member: Union["raw.base.ChatParticipant", "raw.base.ChannelParticipant"], users: Dict[int, "raw.base.User"], chats: Dict[int, "raw.base.Chat"] ) -> "ChatMember": # Chat participants if isinstance(member, raw.types.ChatParticipant): return ChatMember( status=enums.ChatMemberStatus.MEMBER, user=types.User._parse(client, users[member.user_id]), joined_date=utils.timestamp_to_datetime(member.date), invited_by=types.User._parse(client, users[member.inviter_id]), client=client ) elif isinstance(member, raw.types.ChatParticipantAdmin): return ChatMember( status=enums.ChatMemberStatus.ADMINISTRATOR, user=types.User._parse(client, users[member.user_id]), joined_date=utils.timestamp_to_datetime(member.date), invited_by=types.User._parse(client, users[member.inviter_id]), client=client ) elif isinstance(member, raw.types.ChatParticipantCreator): return ChatMember( status=enums.ChatMemberStatus.OWNER, user=types.User._parse(client, users[member.user_id]), client=client ) # Channel participants if isinstance(member, raw.types.ChannelParticipant): return ChatMember( status=enums.ChatMemberStatus.MEMBER, user=types.User._parse(client, users[member.user_id]), joined_date=utils.timestamp_to_datetime(member.date), client=client ) elif isinstance(member, raw.types.ChannelParticipantAdmin): return ChatMember( status=enums.ChatMemberStatus.ADMINISTRATOR, user=types.User._parse(client, users[member.user_id]), joined_date=utils.timestamp_to_datetime(member.date), promoted_by=types.User._parse(client, users[member.promoted_by]), invited_by=( types.User._parse(client, users[member.inviter_id]) if member.inviter_id else None ), custom_title=member.rank, can_be_edited=member.can_edit, privileges=types.ChatPrivileges._parse(member.admin_rights), client=client ) elif isinstance(member, raw.types.ChannelParticipantBanned): peer = member.peer peer_id = utils.get_raw_peer_id(peer) user = ( types.User._parse(client, users[peer_id]) if isinstance(peer, raw.types.PeerUser) else None ) chat = ( types.Chat._parse_chat(client, chats[peer_id]) if not isinstance(peer, raw.types.PeerUser) else None ) return ChatMember( status=( enums.ChatMemberStatus.BANNED if member.banned_rights.view_messages else enums.ChatMemberStatus.RESTRICTED ), user=user, chat=chat, until_date=utils.timestamp_to_datetime(member.banned_rights.until_date), joined_date=utils.timestamp_to_datetime(member.date), is_member=not member.left, restricted_by=types.User._parse(client, users[member.kicked_by]), permissions=types.ChatPermissions._parse(member.banned_rights), client=client ) elif isinstance(member, raw.types.ChannelParticipantCreator): return ChatMember( status=enums.ChatMemberStatus.OWNER, user=types.User._parse(client, users[member.user_id]), custom_title=member.rank, privileges=types.ChatPrivileges._parse(member.admin_rights), client=client ) elif isinstance(member, raw.types.ChannelParticipantLeft): peer = member.peer peer_id = utils.get_raw_peer_id(peer) user = ( types.User._parse(client, users[peer_id]) if isinstance(peer, raw.types.PeerUser) else None ) chat = ( types.Chat._parse_chat(client, chats[peer_id]) if not isinstance(peer, raw.types.PeerUser) else None ) return ChatMember( status=enums.ChatMemberStatus.LEFT, user=user, chat=chat, client=client ) elif isinstance(member, raw.types.ChannelParticipantSelf): return ChatMember( status=enums.ChatMemberStatus.MEMBER, user=types.User._parse(client, users[member.user_id]), joined_date=utils.timestamp_to_datetime(member.date), invited_by=types.User._parse(client, users[member.inviter_id]), client=client )
def _parse( action: "raw.types.MessageActionGroupCallScheduled" ) -> "VideoChatScheduled": return VideoChatScheduled( start_date=utils.timestamp_to_datetime(action.schedule_date))
async def send_message( self: "pyrogram.Client", chat_id: Union[int, str], text: str, parse_mode: Optional["enums.ParseMode"] = None, entities: List["types.MessageEntity"] = None, disable_web_page_preview: bool = 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 ) -> "types.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 (:obj:`~pyrogram.enums.ParseMode`, *optional*): By default, texts are parsed using both Markdown and HTML styles. You can combine both syntaxes together. entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in message text, which can be specified instead of *parse_mode*. 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 (: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 text message is returned. Example: .. code-block:: python # Simple example await app.send_message("me", "Message sent with **Pyrogram**!") # Disable web page previews await app.send_message("me", "https://docs.pyrogram.org", disable_web_page_preview=True) # Reply to a message using its id await app.send_message("me", "this is a reply", reply_to_message_id=123) .. code-block:: python # For bots only, send messages with keyboards attached from pyrogram.types import ( ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton) # Send a normal keyboard await app.send_message( chat_id, "Look at that button!", reply_markup=ReplyKeyboardMarkup([["Nice!"]])) # Send an inline keyboard await app.send_message( chat_id, "These are inline buttons", reply_markup=InlineKeyboardMarkup( [ [InlineKeyboardButton("Data", callback_data="callback_data")], [InlineKeyboardButton("Docs", url="https://docs.pyrogram.org")] ])) """ message, entities = (await utils.parse_text_entities(self, text, parse_mode, entities)).values() r = await self.invoke( raw.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(), schedule_date=utils.datetime_to_timestamp(schedule_date), reply_markup=await reply_markup.write(self) if reply_markup else None, message=message, entities=entities, noforwards=protect_content)) if isinstance(r, raw.types.UpdateShortSentMessage): peer = await self.resolve_peer(chat_id) peer_id = (peer.user_id if isinstance( peer, raw.types.InputPeerUser) else -peer.chat_id) return types.Message(id=r.id, chat=types.Chat(id=peer_id, type=enums.ChatType.PRIVATE, client=self), text=message, date=utils.timestamp_to_datetime(r.date), outgoing=r.out, reply_markup=reply_markup, entities=[ types.MessageEntity._parse( None, entity, {}) for entity in entities ], client=self) 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))