예제 #1
0
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)
예제 #2
0
    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}
                )
예제 #3
0
    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))
예제 #4
0
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)
예제 #5
0
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
예제 #6
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
예제 #7
0
    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}
                )