From fed146f54fe9acb9603644b50c7e317095f56e1d Mon Sep 17 00:00:00 2001 From: KurimuzonAkuma Date: Thu, 20 Mar 2025 00:57:34 +0300 Subject: [PATCH] Refactor Message - Refactor Message.quote - Add forward_origin Signed-off-by: wulan17 --- compiler/docs/compiler.py | 6 + pyrogram/enums/__init__.py | 2 + pyrogram/enums/message_origin_type.py | 37 +++++ pyrogram/types/messages_and_media/__init__.py | 14 +- pyrogram/types/messages_and_media/message.py | 144 +++++++++--------- .../messages_and_media/message_origin.py | 88 +++++++++++ .../message_origin_channel.py | 61 ++++++++ .../messages_and_media/message_origin_chat.py | 56 +++++++ .../message_origin_hidden_user.py | 51 +++++++ .../messages_and_media/message_origin_user.py | 51 +++++++ .../types/messages_and_media/text_quote.py | 83 ++++++++++ 11 files changed, 524 insertions(+), 69 deletions(-) create mode 100644 pyrogram/enums/message_origin_type.py create mode 100644 pyrogram/types/messages_and_media/message_origin.py create mode 100644 pyrogram/types/messages_and_media/message_origin_channel.py create mode 100644 pyrogram/types/messages_and_media/message_origin_chat.py create mode 100644 pyrogram/types/messages_and_media/message_origin_hidden_user.py create mode 100644 pyrogram/types/messages_and_media/message_origin_user.py create mode 100644 pyrogram/types/messages_and_media/text_quote.py diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index e22e6beb..b5c7655c 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -513,6 +513,11 @@ def pyrogram_api(): Messages & Media Message MessageEntity + MessageOriginChannel + MessageOriginChat + MessageOriginHiddenUser + MessageOriginUser + MessageOrigin Photo Thumbnail Audio @@ -540,6 +545,7 @@ def pyrogram_api(): WebPagePreview TranscribedAudio TranslatedText + TextQuote Poll PollOption Dice diff --git a/pyrogram/enums/__init__.py b/pyrogram/enums/__init__.py index 1758a242..aac9db33 100644 --- a/pyrogram/enums/__init__.py +++ b/pyrogram/enums/__init__.py @@ -30,6 +30,7 @@ from .gift_attribute_type import GiftAttributeType from .listerner_types import ListenerTypes from .message_entity_type import MessageEntityType from .message_media_type import MessageMediaType +from .message_origin_type import MessageOriginType from .message_service_type import MessageServiceType from .messages_filter import MessagesFilter from .next_code_type import NextCodeType @@ -57,6 +58,7 @@ __all__ = [ 'ListenerTypes', 'MessageEntityType', 'MessageMediaType', + 'MessageOriginType', 'MessageServiceType', 'MessagesFilter', 'NextCodeType', diff --git a/pyrogram/enums/message_origin_type.py b/pyrogram/enums/message_origin_type.py new file mode 100644 index 00000000..a48b8dbf --- /dev/null +++ b/pyrogram/enums/message_origin_type.py @@ -0,0 +1,37 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from enum import auto + +from .auto_name import AutoName + + +class MessageOriginType(AutoName): + """Message origin type enumeration used in :obj:`~pyrogram.types.MessageOrigin`.""" + + CHANNEL = auto() + "The message was originally a post in a channel" + + CHAT = auto() + "The message was originally sent on behalf of a chat" + + HIDDEN_USER = auto() + "The message was originally sent by a user, which is hidden by their privacy settings" + + USER = auto() + "The message was originally sent by a known user" diff --git a/pyrogram/types/messages_and_media/__init__.py b/pyrogram/types/messages_and_media/__init__.py index 486f4664..8176d5bf 100644 --- a/pyrogram/types/messages_and_media/__init__.py +++ b/pyrogram/types/messages_and_media/__init__.py @@ -37,6 +37,11 @@ from .media_area_channel_post import MediaAreaChannelPost from .media_area_coordinates import MediaAreaCoordinates from .message import Message from .message_entity import MessageEntity +from .message_origin import MessageOrigin +from .message_origin_channel import MessageOriginChannel +from .message_origin_chat import MessageOriginChat +from .message_origin_hidden_user import MessageOriginHiddenUser +from .message_origin_user import MessageOriginUser from .photo import Photo from .poll import Poll from .poll_option import PollOption @@ -71,6 +76,7 @@ from .wallpaper import Wallpaper from .wallpaper_settings import WallpaperSettings from .transcribed_audio import TranscribedAudio from .translated_text import TranslatedText +from .text_quote import TextQuote __all__ = [ "AlternativeVideo", @@ -92,6 +98,11 @@ __all__ = [ "MediaAreaCoordinates", "Message", "MessageEntity", + "MessageOrigin", + "MessageOriginChannel", + "MessageOriginChat", + "MessageOriginHiddenUser", + "MessageOriginUser", "Photo", "Thumbnail", "StrippedThumbnail", @@ -126,5 +137,6 @@ __all__ = [ "Wallpaper", "WallpaperSettings", "TranscribedAudio", - "TranslatedText" + "TranslatedText", + "TextQuote" ] diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index 774055f0..e62398dd 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -88,23 +88,8 @@ class Message(Object, Update): Topic the message belongs to. only returned using when client.get_messages. - forward_from (:obj:`~pyrogram.types.User`, *optional*): - For forwarded messages, sender of the original message. - - forward_sender_name (``str``, *optional*): - For messages forwarded from users who have hidden their accounts, name of the user. - - forward_from_chat (:obj:`~pyrogram.types.Chat`, *optional*): - For messages forwarded from channels, information about the original channel. For messages forwarded from anonymous group administrators, information about the original supergroup. - - forward_from_message_id (``int``, *optional*): - For messages forwarded from channels, identifier of the original message in the channel. - - forward_signature (``str``, *optional*): - For messages forwarded from channels, signature of the post author if present. - - forward_date (:py:obj:`~datetime.datetime`, *optional*): - For forwarded messages, date the original message was sent. + forward_origin (:obj:`~pyrogram.types.MessageOrigin`, *optional*): + Information about the original message for forwarded messages. is_topic_message (``bool``, *optional*): True, if the message is sent to a forum topic @@ -187,11 +172,8 @@ class Message(Object, Update): For messages with a caption, special entities like usernames, URLs, bot commands, etc. that appear in the caption. - quote_text (``str``, *optional*): - Quoted reply text. - - quote_entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*): - For quote text, special entities like usernames, URLs, bot commands, etc. that appear in the quote text. + quote (:obj:`~pyrogram.types.TextQuote`, *optional*): + Chosen quote from the replied message. effect_id (``str``, *optional*): Unique identifier of the message effect added to the message. @@ -451,12 +433,7 @@ class Message(Object, Update): date: datetime = None, chat: "types.Chat" = None, topic: "types.ForumTopic" = None, - forward_from: "types.User" = None, - forward_sender_name: str = None, - forward_from_chat: "types.Chat" = None, - forward_from_message_id: int = None, - forward_signature: str = None, - forward_date: datetime = None, + forward_origin: "types.MessageOrigin" = None, is_topic_message: bool = None, reply_to_chat_id: int = None, reply_to_message_id: int = None, @@ -481,8 +458,7 @@ class Message(Object, Update): text: Str = None, entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None, - quote_text: str = None, - quote_entities: List["types.MessageEntity"] = None, + quote: "types.TextQuote" = None, effect_id: str = None, invert_media: bool = None, audio: "types.Audio" = None, @@ -571,12 +547,7 @@ class Message(Object, Update): self.date = date self.chat = chat self.topic = topic - self.forward_from = forward_from - self.forward_sender_name = forward_sender_name - self.forward_from_chat = forward_from_chat - self.forward_from_message_id = forward_from_message_id - self.forward_signature = forward_signature - self.forward_date = forward_date + self.forward_origin = forward_origin self.is_topic_message = is_topic_message self.reply_to_chat_id = reply_to_chat_id self.reply_to_message_id = reply_to_message_id @@ -601,8 +572,7 @@ class Message(Object, Update): self.text = text self.entities = entities self.caption_entities = caption_entities - self.quote_text = quote_text - self.quote_entities = quote_entities + self.quote = quote self.effect_id = effect_id self.invert_media = invert_media self.audio = audio @@ -1008,31 +978,18 @@ class Message(Object, Update): entities = types.List(filter(lambda x: x is not None, entities)) sender_business_bot = None - forward_from = None - forward_sender_name = None - forward_from_chat = None - forward_from_message_id = None - forward_signature = None - forward_date = None is_topic_message = None forward_header = message.fwd_from # type: raw.types.MessageFwdHeader + forward_origin = None if forward_header: - forward_date = utils.timestamp_to_datetime(forward_header.date) - - if forward_header.from_id: - raw_peer_id = utils.get_raw_peer_id(forward_header.from_id) - peer_id = utils.get_peer_id(forward_header.from_id) - - if peer_id > 0: - forward_from = types.User._parse(client, users[raw_peer_id]) - else: - forward_from_chat = types.Chat._parse_channel_chat(client, chats[raw_peer_id]) - forward_from_message_id = forward_header.channel_post - forward_signature = forward_header.post_author - elif forward_header.from_name: - forward_sender_name = forward_header.from_name + forward_origin = types.MessageOrigin._parse( + client, + forward_header, + users, + chats, + ) photo = None paid_media = None @@ -1219,12 +1176,7 @@ class Message(Object, Update): author_signature=message.post_author, has_protected_content=message.noforwards, has_media_spoiler=has_media_spoiler, - forward_from=forward_from, - forward_sender_name=forward_sender_name, - forward_from_chat=forward_from_chat, - forward_from_message_id=forward_from_message_id, - forward_signature=forward_signature, - forward_date=forward_date, + forward_origin=forward_origin, is_topic_message=is_topic_message, mentioned=message.mentioned, scheduled=is_scheduled, @@ -1270,10 +1222,12 @@ class Message(Object, Update): if message.reply_to: if isinstance(message.reply_to, raw.types.MessageReplyHeader): - parsed_message.quote_text = message.reply_to.quote_text - if len(message.reply_to.quote_entities) > 0: - quote_entities = [types.MessageEntity._parse(client, entity, users) for entity in message.reply_to.quote_entities] - parsed_message.quote_entities = types.List(filter(lambda x: x is not None, quote_entities)) + if message.reply_to.quote: + parsed_message.quote = types.TextQuote._parse( + client, + users, + message.reply_to + ) if message.reply_to.forum_topic: if message.reply_to.reply_to_top_id: thread_id = message.reply_to.reply_to_top_id @@ -1362,6 +1316,60 @@ class Message(Object, Update): @property def content(self) -> str: return self.text or self.caption or Str("").init([]) + + # region Deprecated + # TODO: Remove later + @property + def forward_from(self) -> Optional["types.User"]: + log.warning( + "`message.forward_from` is deprecated and will be removed in future updates. Use `message.forward_origin.sender_user` instead." + ) + return getattr(self.forward_origin, "sender_user", None) + + @property + def forward_sender_name(self) -> Optional[str]: + log.warning( + "`message.forward_sender_name` property is deprecated and will be removed in future updates. Use `message.forward_origin.sender_user_name` instead." + ) + return getattr(self.forward_origin, "sender_user_name", None) + + @property + def forward_from_chat(self) -> Optional["types.Chat"]: + log.warning( + "`message.forward_from_chat` property is deprecated and will be removed in future updates. Use `message.forward_origin.chat.sender_chat` instead." + ) + return getattr( + self.forward_origin, + "chat", + getattr( + self.forward_origin, + "sender_chat", + None + ) + ) + + @property + def forward_from_message_id(self) -> Optional[int]: + log.warning( + "`message.forward_from_message_id` property is deprecated and will be removed in future updates. Use `message.forward_origin.message_id` instead." + ) + return getattr(self.forward_origin, "message_id", None) + + @property + def forward_signature(self) -> Optional[str]: + log.warning( + "`message.forward_signature` property is deprecated and will be removed in future updates. Use `message.forward_origin.author_signature` instead." + ) + return getattr(self.forward_origin, "author_signature", None) + + @property + def forward_date(self) -> Optional[datetime]: + log.warning( + "`message.forward_date` property is deprecated and will be removed in future updates. Use `message.forward_origin.date` instead." + ) + return getattr(self.forward_origin, "date", None) + + # endregion async def get_media_group(self) -> List["types.Message"]: """Bound method *get_media_group* of :obj:`~pyrogram.types.Message`. diff --git a/pyrogram/types/messages_and_media/message_origin.py b/pyrogram/types/messages_and_media/message_origin.py new file mode 100644 index 00000000..e2f2e449 --- /dev/null +++ b/pyrogram/types/messages_and_media/message_origin.py @@ -0,0 +1,88 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . +from datetime import datetime +from typing import Dict, Optional + +import pyrogram +from pyrogram import enums, raw, types, utils + +from ..object import Object + + +class MessageOrigin(Object): + """This object describes the origin of a message. + + It can be one of: + + - :obj:`~pyrogram.types.MessageOriginChannel` + - :obj:`~pyrogram.types.MessageOriginChat` + - :obj:`~pyrogram.types.MessageOriginHiddenUser` + - :obj:`~pyrogram.types.MessageOriginUser` + """ + + def __init__( + self, + type: "enums.MessageOriginType", + date: Optional[datetime] = None + ): + super().__init__() + + self.type = type + self.date = date + + @staticmethod + def _parse( + client: "pyrogram.Client", + fwd_from: "raw.types.MessageFwdHeader", + users: Dict[int, "raw.base.User"], + chats: Dict[int, "raw.base.Chat"] + ) -> Optional["MessageOrigin"]: + if not fwd_from: + return None + + forward_date = utils.timestamp_to_datetime(fwd_from.date) + + if fwd_from.from_id: + raw_peer_id = utils.get_raw_peer_id(fwd_from.from_id) + peer_id = utils.get_peer_id(fwd_from.from_id) + peer_type = utils.get_peer_type(peer_id) + + if peer_type == "user": + return types.MessageOriginUser( + date=forward_date, + sender_user=types.User._parse(client, users.get(raw_peer_id)) + ) + else: + if fwd_from.channel_post: + return types.MessageOriginChannel( + date=forward_date, + chat=types.Chat._parse_channel_chat(client, chats.get(raw_peer_id)), + message_id=fwd_from.channel_post, + author_signature=fwd_from.post_author + ) + else: + return types.MessageOriginChat( + date=forward_date, + sender_chat=types.Chat._parse_channel_chat(client, chats.get(raw_peer_id)), + author_signature=fwd_from.post_author + ) + elif fwd_from.from_name: + return types.MessageOriginHiddenUser( + date=forward_date, + sender_user_name=fwd_from.from_name + ) diff --git a/pyrogram/types/messages_and_media/message_origin_channel.py b/pyrogram/types/messages_and_media/message_origin_channel.py new file mode 100644 index 00000000..26ae8587 --- /dev/null +++ b/pyrogram/types/messages_and_media/message_origin_channel.py @@ -0,0 +1,61 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime + +from pyrogram import enums, types + +from .message_origin import MessageOrigin + + +class MessageOriginChannel(MessageOrigin): + """The message was originally sent to a channel chat. + + Parameters: + type (:obj:`~pyrogram.enums.MessageOriginType`): + Type of the message origin. + + date (:py:obj:`~datetime.datetime`): + Date the message was sent originally. + + chat (:obj:`~pyrogram.types.Chat`): + Channel chat to which the message was originally sent. + + message_id (``int``): + Unique message identifier inside the chat. + + author_signature (``str``, *optional*): + Signature of the original post author. + """ + def __init__( + self, + *, + type: "enums.MessageOriginType" = enums.MessageOriginType.CHANNEL, + date: datetime = None, + chat: "types.Chat" = None, + message_id: int = None, + author_signature: str = None + ): + super().__init__( + type=type, + date=date + ) + + self.chat = chat + self.message_id = message_id + self.author_signature = author_signature diff --git a/pyrogram/types/messages_and_media/message_origin_chat.py b/pyrogram/types/messages_and_media/message_origin_chat.py new file mode 100644 index 00000000..d42e0540 --- /dev/null +++ b/pyrogram/types/messages_and_media/message_origin_chat.py @@ -0,0 +1,56 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime + +from pyrogram import enums, types + +from .message_origin import MessageOrigin + + +class MessageOriginChat(MessageOrigin): + """The message was originally sent on behalf of a chat to a group chat. + + Parameters: + type (:obj:`~pyrogram.enums.MessageOriginType`): + Type of the message origin. + + date (:py:obj:`~datetime.datetime`): + Date the message was sent originally. + + sender_chat (:obj:`~pyrogram.types.Chat`): + Chat that sent the message originally. + + author_signature (``str``, *optional*): + For messages originally sent by an anonymous chat administrator, original message author signature. + """ + def __init__( + self, + *, + type: "enums.MessageOriginType" = enums.MessageOriginType.CHAT, + date: datetime = None, + sender_chat: "types.Chat" = None, + author_signature: str = None + ): + super().__init__( + type=type, + date=date + ) + + self.sender_chat = sender_chat + self.author_signature = author_signature diff --git a/pyrogram/types/messages_and_media/message_origin_hidden_user.py b/pyrogram/types/messages_and_media/message_origin_hidden_user.py new file mode 100644 index 00000000..97ee2e9a --- /dev/null +++ b/pyrogram/types/messages_and_media/message_origin_hidden_user.py @@ -0,0 +1,51 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime + +from pyrogram import enums + +from .message_origin import MessageOrigin + + +class MessageOriginHiddenUser(MessageOrigin): + """The message was originally sent by an unknown user. + + Parameters: + type (:obj:`~pyrogram.enums.MessageOriginType`): + Type of the message origin. + + date (:py:obj:`~datetime.datetime`): + Date the message was sent originally. + + sender_user_name (``str``): + Name of the user that sent the message originally. + """ + def __init__( + self, + *, + type: "enums.MessageOriginType" = enums.MessageOriginType.HIDDEN_USER, + date: datetime = None, + sender_user_name: str = None + ): + super().__init__( + type=type, + date=date + ) + + self.sender_user_name = sender_user_name diff --git a/pyrogram/types/messages_and_media/message_origin_user.py b/pyrogram/types/messages_and_media/message_origin_user.py new file mode 100644 index 00000000..f3370859 --- /dev/null +++ b/pyrogram/types/messages_and_media/message_origin_user.py @@ -0,0 +1,51 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime + +from pyrogram import enums, types + +from .message_origin import MessageOrigin + + +class MessageOriginUser(MessageOrigin): + """The message was originally sent by a known user. + + Parameters: + type (:obj:`~pyrogram.enums.MessageOriginType`): + Type of the message origin. + + date (:py:obj:`~datetime.datetime`): + Date the message was sent originally. + + sender_user (:obj:`~pyrogram.types.User`): + User that sent the message originally. + """ + def __init__( + self, + *, + type: "enums.MessageOriginType" = enums.MessageOriginType.USER, + date: datetime = None, + sender_user: "types.User" = None + ): + super().__init__( + type=type, + date=date + ) + + self.sender_user = sender_user diff --git a/pyrogram/types/messages_and_media/text_quote.py b/pyrogram/types/messages_and_media/text_quote.py new file mode 100644 index 00000000..2301f89d --- /dev/null +++ b/pyrogram/types/messages_and_media/text_quote.py @@ -0,0 +1,83 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Dict, List, Optional + +import pyrogram +from pyrogram import raw, types + +from ..messages_and_media.message import Str +from ..object import Object + + +class TextQuote(Object): + """Describes manually or automatically chosen quote from another message. + + Parameters: + text (``str``): + Text of the quoted part of a message that is replied to by the given message. + + entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*): + Special entities that appear in the quote. + Currently, only bold, italic, underline, strikethrough, spoiler, and custom_emoji entities are kept in quotes. + + position (``int``): + Approximate quote position in the original message in UTF-16 code units as specified by the sender. + + is_manual (``bool``, *optional*): + True, if the quote was chosen manually by the message sender. + Otherwise, the quote was added automatically by the server. + + """ + def __init__( + self, *, + text: Optional[str] = None, + entities: Optional[List["types.MessageEntity"]] = None, + position: Optional[int] = None, + is_manual: Optional[bool] = None + ): + super().__init__() + + self.text = text + self.entities = entities + self.position = position + self.is_manual = is_manual + + @staticmethod + def _parse( + client: "pyrogram.Client", + users: Dict[int, "raw.types.User"], + reply_to: "raw.types.MessageReplyHeader" + ) -> "TextQuote": + if isinstance(reply_to, raw.types.MessageReplyHeader): + entities = types.List( + filter( + lambda x: x is not None, + [ + types.MessageEntity._parse(client, entity, users) + for entity in getattr(reply_to, "quote_entities", []) + ] + ) + ) + + return TextQuote( + text=Str(reply_to.quote_text).init(entities) or None, + entities=entities or None, + position=reply_to.quote_offset or 0, + is_manual=reply_to.quote + )