mirror of
https://github.com/TeamPGM/pyrogram.git
synced 2024-11-16 04:35:24 +00:00
Refactor parsing message
This commit is contained in:
parent
909656b806
commit
86e26cc496
@ -69,6 +69,8 @@ class Dispatcher:
|
||||
self.groups = OrderedDict()
|
||||
|
||||
async def message_parser(update, users, chats):
|
||||
connection_id = getattr(update, "connection_id", None)
|
||||
|
||||
return (
|
||||
await pyrogram.types.Message._parse(
|
||||
self.client,
|
||||
@ -76,8 +78,9 @@ class Dispatcher:
|
||||
users,
|
||||
chats,
|
||||
is_scheduled=isinstance(update, UpdateNewScheduledMessage),
|
||||
business_connection_id=getattr(update, "connection_id", None),
|
||||
reply_to_message=getattr(update, "reply_to_message", None)
|
||||
replies=0 if getattr(update, "connection_id", None) else 1,
|
||||
business_connection_id=connection_id,
|
||||
raw_reply_to_message=getattr(update, "reply_to_message", None)
|
||||
),
|
||||
MessageHandler
|
||||
)
|
||||
|
@ -91,10 +91,7 @@ class GetDialogs:
|
||||
|
||||
chat_id = utils.get_peer_id(message.peer_id)
|
||||
|
||||
try:
|
||||
messages[chat_id] = await types.Message._parse(self, message, users, chats)
|
||||
except KeyError:
|
||||
pass
|
||||
messages[chat_id] = await types.Message._parse(self, message, users, chats)
|
||||
|
||||
dialogs = []
|
||||
|
||||
@ -102,10 +99,7 @@ class GetDialogs:
|
||||
if not isinstance(dialog, raw.types.Dialog):
|
||||
continue
|
||||
|
||||
try:
|
||||
dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats))
|
||||
except KeyError:
|
||||
pass
|
||||
dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats))
|
||||
|
||||
if not dialogs:
|
||||
return
|
||||
|
@ -117,6 +117,9 @@ class ForumTopic(Object):
|
||||
|
||||
@staticmethod
|
||||
def _parse(client: "pyrogram.Client", forum_topic: "raw.types.ForumTopic", messages: dict = {}, users: dict = {}, chats: dict = {}) -> "ForumTopic":
|
||||
if not forum_topic:
|
||||
return None
|
||||
|
||||
if isinstance(forum_topic, raw.types.ForumTopicDeleted):
|
||||
return ForumTopic(id=forum_topic.id, is_deleted=True)
|
||||
|
||||
|
@ -628,14 +628,14 @@ class Message(Object, Update):
|
||||
@staticmethod
|
||||
async def _parse(
|
||||
client: "pyrogram.Client",
|
||||
message: raw.base.Message,
|
||||
message: "raw.base.Message",
|
||||
users: dict,
|
||||
chats: dict,
|
||||
topics: dict = None,
|
||||
is_scheduled: bool = False,
|
||||
replies: int = 1,
|
||||
business_connection_id: str = None,
|
||||
reply_to_message: "raw.base.Message" = None
|
||||
raw_reply_to_message: "raw.base.Message" = None
|
||||
):
|
||||
if isinstance(message, raw.types.MessageEmpty):
|
||||
return Message(
|
||||
@ -846,10 +846,9 @@ class Message(Object, Update):
|
||||
)
|
||||
|
||||
parsed_message.service = enums.MessageServiceType.PINNED_MESSAGE
|
||||
except MessageIdsEmpty:
|
||||
except (MessageIdsEmpty, ChannelPrivate):
|
||||
pass
|
||||
|
||||
if isinstance(action, raw.types.MessageActionGameScore):
|
||||
elif isinstance(action, raw.types.MessageActionGameScore):
|
||||
parsed_message.game_high_score = types.GameHighScore._parse_action(client, message, users)
|
||||
|
||||
if message.reply_to and replies:
|
||||
@ -861,7 +860,7 @@ class Message(Object, Update):
|
||||
)
|
||||
|
||||
parsed_message.service = enums.MessageServiceType.GAME_HIGH_SCORE
|
||||
except MessageIdsEmpty:
|
||||
except (MessageIdsEmpty, ChannelPrivate):
|
||||
pass
|
||||
|
||||
client.message_cache[(parsed_message.chat.id, parsed_message.id)] = parsed_message
|
||||
@ -870,7 +869,7 @@ class Message(Object, Update):
|
||||
if message.reply_to.reply_to_top_id:
|
||||
parsed_message.message_thread_id = message.reply_to.reply_to_top_id
|
||||
else:
|
||||
parsed_message.message_thread_id = message.reply_to.reply_to_msg_id
|
||||
parsed_message.message_thread_id = message.reply_to.reply_to_msg_id or 1
|
||||
|
||||
return parsed_message
|
||||
|
||||
@ -958,11 +957,14 @@ class Message(Object, Update):
|
||||
elif isinstance(media, raw.types.MessageMediaStory):
|
||||
if media.story:
|
||||
story = await types.Story._parse(client, media.story, users, chats, media.peer)
|
||||
else:
|
||||
elif client.me and not client.me.is_bot:
|
||||
try:
|
||||
story = await client.get_stories(utils.get_peer_id(media.peer), media.id)
|
||||
except (BotMethodInvalid, ChannelPrivate):
|
||||
story = await types.Story._parse(client, media, users, chats, media.peer)
|
||||
except ChannelPrivate:
|
||||
pass
|
||||
|
||||
if not story:
|
||||
story = await types.Story._parse(client, media, users, chats, media.peer)
|
||||
|
||||
media_type = enums.MessageMediaType.STORY
|
||||
elif isinstance(media, raw.types.MessageMediaDocument):
|
||||
@ -1132,53 +1134,56 @@ class Message(Object, Update):
|
||||
parsed_message.quote = True
|
||||
|
||||
if message.reply_to:
|
||||
parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id
|
||||
parsed_message.reply_to_top_message_id = message.reply_to.reply_to_top_id
|
||||
|
||||
if isinstance(message.reply_to, raw.types.MessageReplyHeader):
|
||||
if message.reply_to.forum_topic:
|
||||
if message.reply_to.reply_to_top_id:
|
||||
thread_id = message.reply_to.reply_to_top_id
|
||||
parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id
|
||||
parsed_message.message_thread_id = message.reply_to.reply_to_top_id
|
||||
else:
|
||||
thread_id = message.reply_to.reply_to_msg_id
|
||||
|
||||
parsed_message.message_thread_id = thread_id
|
||||
parsed_message.message_thread_id = message.reply_to.reply_to_msg_id or 1
|
||||
|
||||
if topics:
|
||||
parsed_message.topic = types.ForumTopic._parse(client, topics[thread_id], users=users, chats=chats)
|
||||
else:
|
||||
if message.reply_to.quote:
|
||||
quote_entities = [types.MessageEntity._parse(client, entity, users) for entity in message.reply_to.quote_entities]
|
||||
quote_entities = types.List(filter(lambda x: x is not None, quote_entities))
|
||||
parsed_message.topic = types.ForumTopic._parse(client, topics.get(parsed_message.message_thread_id), users=users, chats=chats)
|
||||
elif message.reply_to.quote:
|
||||
quote_entities = [types.MessageEntity._parse(client, entity, users) for entity in message.reply_to.quote_entities]
|
||||
quote_entities = types.List(filter(lambda x: x is not None, quote_entities))
|
||||
|
||||
parsed_message.quote = message.reply_to.quote
|
||||
parsed_message.quote_text = (
|
||||
Str(message.reply_to.quote_text).init(quote_entities) or None
|
||||
if media is None or web_page is not None
|
||||
else None
|
||||
)
|
||||
parsed_message.quote_entities = (
|
||||
quote_entities or None
|
||||
if media is None or web_page is not None
|
||||
else None
|
||||
)
|
||||
|
||||
parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id
|
||||
parsed_message.reply_to_top_message_id = message.reply_to.reply_to_top_id
|
||||
parsed_message.quote = message.reply_to.quote
|
||||
parsed_message.quote_text = (
|
||||
Str(message.reply_to.quote_text).init(quote_entities) or None
|
||||
if media is None or web_page is not None
|
||||
else None
|
||||
)
|
||||
parsed_message.quote_entities = (
|
||||
quote_entities or None
|
||||
if media is None or web_page is not None
|
||||
else None
|
||||
)
|
||||
elif isinstance(message.reply_to, raw.types.MessageReplyStoryHeader):
|
||||
parsed_message.reply_to_story_id = message.reply_to.story_id
|
||||
parsed_message.reply_to_story_user_id = utils.get_peer_id(message.reply_to.peer)
|
||||
|
||||
if replies:
|
||||
if parsed_message.reply_to_message_id:
|
||||
is_cross_chat = getattr(message.reply_to, "reply_to_peer_id", None) and getattr(message.reply_to.reply_to_peer_id, "channel_id", None)
|
||||
if raw_reply_to_message:
|
||||
parsed_message.reply_to_message = await types.Message._parse(
|
||||
client,
|
||||
raw_reply_to_message,
|
||||
users,
|
||||
chats,
|
||||
business_connection_id=business_connection_id,
|
||||
replies=0
|
||||
)
|
||||
else:
|
||||
if isinstance(message.reply_to, raw.types.MessageReplyHeader):
|
||||
if message.reply_to.reply_to_peer_id:
|
||||
key = (utils.get_peer_id(message.reply_to.reply_to_peer_id), message.reply_to.reply_to_msg_id)
|
||||
reply_to_params = {"chat_id": key[0], 'message_ids': key[1]}
|
||||
else:
|
||||
key = (parsed_message.chat.id, parsed_message.reply_to_message_id)
|
||||
reply_to_params = {'chat_id': key[0], 'reply_to_message_ids': message.id}
|
||||
|
||||
if is_cross_chat:
|
||||
key = (utils.get_channel_id(message.reply_to.reply_to_peer_id.channel_id), message.reply_to.reply_to_msg_id)
|
||||
reply_to_params = {"chat_id": key[0], 'message_ids': key[1]}
|
||||
else:
|
||||
key = (parsed_message.chat.id, parsed_message.reply_to_message_id)
|
||||
reply_to_params = {'chat_id': key[0], 'reply_to_message_ids': message.id}
|
||||
|
||||
try:
|
||||
reply_to_message = client.message_cache[key]
|
||||
|
||||
if not reply_to_message:
|
||||
@ -1187,32 +1192,24 @@ class Message(Object, Update):
|
||||
replies=replies - 1,
|
||||
**reply_to_params
|
||||
)
|
||||
except ChannelPrivate:
|
||||
except (ChannelPrivate, MessageIdsEmpty):
|
||||
pass
|
||||
if reply_to_message and not reply_to_message.forum_topic_created:
|
||||
parsed_message.reply_to_message = reply_to_message
|
||||
except ChannelPrivate:
|
||||
pass
|
||||
except MessageIdsEmpty:
|
||||
pass
|
||||
elif parsed_message.reply_to_story_id:
|
||||
try:
|
||||
reply_to_story = await client.get_stories(
|
||||
parsed_message.reply_to_story_user_id,
|
||||
parsed_message.reply_to_story_id
|
||||
)
|
||||
except BotMethodInvalid:
|
||||
pass
|
||||
else:
|
||||
parsed_message.reply_to_story = reply_to_story
|
||||
|
||||
if parsed_message.topic is None and parsed_message.chat.is_forum:
|
||||
parsed_message.reply_to_message = reply_to_message
|
||||
elif isinstance(message.reply_to, raw.types.MessageReplyStoryHeader):
|
||||
if client.me and not client.me.is_bot:
|
||||
parsed_message.reply_to_story = await client.get_stories(
|
||||
utils.get_peer_id(message.reply_to.peer),
|
||||
message.reply_to.story_id
|
||||
)
|
||||
|
||||
if not parsed_message.topic and parsed_message.chat.is_forum and client.me and not client.me.is_bot:
|
||||
try:
|
||||
parsed_message.topic = await client.get_forum_topics_by_id(
|
||||
chat_id=parsed_message.chat.id,
|
||||
topic_ids=parsed_message.message_thread_id or 1
|
||||
)
|
||||
except (BotMethodInvalid, ChannelForumMissing):
|
||||
except (ChannelPrivate, ChannelForumMissing):
|
||||
pass
|
||||
|
||||
if not parsed_message.poll: # Do not cache poll messages
|
||||
|
@ -92,121 +92,112 @@ def get_input_media_from_file_id(
|
||||
|
||||
|
||||
async def parse_messages(
|
||||
client,
|
||||
messages: "raw.types.messages.Messages",
|
||||
client: "pyrogram.Client",
|
||||
messages: Union["raw.base.messages.Messages", "raw.base.Updates"],
|
||||
replies: int = 1,
|
||||
business_connection_id: str = None
|
||||
) -> List["types.Message"]:
|
||||
users = {i.id: i for i in messages.users}
|
||||
chats = {i.id: i for i in messages.chats}
|
||||
topics = {i.id: i for i in messages.topics} if hasattr(messages, "topics") else None
|
||||
|
||||
if not messages.messages:
|
||||
return types.List()
|
||||
users = {i.id: i for i in getattr(messages, "users", [])}
|
||||
chats = {i.id: i for i in getattr(messages, "chats", [])}
|
||||
topics = {i.id: i for i in getattr(messages, "topics", [])}
|
||||
|
||||
parsed_messages = []
|
||||
|
||||
for message in messages.messages:
|
||||
parsed_messages.append(
|
||||
await types.Message._parse(
|
||||
client,
|
||||
message,
|
||||
users,
|
||||
chats,
|
||||
topics,
|
||||
replies=0,
|
||||
business_connection_id=business_connection_id
|
||||
)
|
||||
if isinstance(
|
||||
messages,
|
||||
(
|
||||
raw.types.messages.ChannelMessages,
|
||||
raw.types.messages.Messages,
|
||||
raw.types.messages.MessagesNotModified,
|
||||
raw.types.messages.MessagesSlice
|
||||
)
|
||||
):
|
||||
if not messages.messages:
|
||||
return types.List()
|
||||
|
||||
if replies:
|
||||
messages_with_replies = {
|
||||
i.id: i.reply_to
|
||||
for i in messages.messages
|
||||
if not isinstance(i, raw.types.MessageEmpty) and i.reply_to and isinstance(i.reply_to, raw.types.MessageReplyHeader)
|
||||
}
|
||||
for message in messages.messages:
|
||||
parsed_messages.append(
|
||||
await types.Message._parse(
|
||||
client=client,
|
||||
message=message,
|
||||
users=users,
|
||||
chats=chats,
|
||||
topics=topics,
|
||||
replies=0,
|
||||
business_connection_id=business_connection_id
|
||||
)
|
||||
)
|
||||
|
||||
message_reply_to_story = {
|
||||
i.id: {'user_id': i.reply_to.user_id, 'story_id': i.reply_to.story_id}
|
||||
for i in messages.messages
|
||||
if not isinstance(i, raw.types.MessageEmpty) and i.reply_to and isinstance(i.reply_to, raw.types.MessageReplyStoryHeader)
|
||||
}
|
||||
if replies:
|
||||
messages_with_replies = {}
|
||||
messages_with_story_replies = {}
|
||||
|
||||
if messages_with_replies:
|
||||
# We need a chat id, but some messages might be empty (no chat attribute available)
|
||||
# Scan until we find a message with a chat available (there must be one, because we are fetching replies)
|
||||
for m in parsed_messages:
|
||||
if not isinstance(m, types.Message):
|
||||
for m in messages.messages:
|
||||
if isinstance(m, raw.types.MessageEmpty):
|
||||
continue
|
||||
|
||||
if m.chat:
|
||||
chat_id = m.chat.id
|
||||
break
|
||||
else:
|
||||
chat_id = 0
|
||||
if m.reply_to and isinstance(m.reply_to, raw.types.MessageReplyHeader):
|
||||
messages_with_replies[m.id] = m.reply_to
|
||||
|
||||
is_all_within_chat = not any(
|
||||
value.reply_to_peer_id
|
||||
for value in messages_with_replies.values()
|
||||
)
|
||||
reply_messages: List[pyrogram.types.Message] = []
|
||||
if is_all_within_chat:
|
||||
# fast path: fetch all messages within the same chat
|
||||
reply_messages = await client.get_messages(
|
||||
chat_id,
|
||||
reply_to_message_ids=messages_with_replies.keys(),
|
||||
replies=replies - 1
|
||||
)
|
||||
else:
|
||||
# slow path: fetch all messages individually
|
||||
for target_reply_to in messages_with_replies.values():
|
||||
to_be_added_msg = None
|
||||
the_chat_id = chat_id
|
||||
if target_reply_to.reply_to_peer_id:
|
||||
the_chat_id = get_channel_id(target_reply_to.reply_to_peer_id.channel_id)
|
||||
to_be_added_msg = await client.get_messages(
|
||||
chat_id=the_chat_id,
|
||||
message_ids=target_reply_to.reply_to_msg_id,
|
||||
if m.reply_to and isinstance(m.reply_to, raw.types.MessageReplyStoryHeader):
|
||||
messages_with_story_replies[m.id] = m.reply_to
|
||||
|
||||
if messages_with_replies:
|
||||
# We need a chat id, but some messages might be empty (no chat attribute available)
|
||||
# Scan until we find a message with a chat available (there must be one, because we are fetching replies)
|
||||
chat_id = next((m.chat.id for m in parsed_messages if m.chat), 0)
|
||||
|
||||
is_all_replies_in_same_chat = not any(m.reply_to_peer_id for m in messages_with_replies.values())
|
||||
reply_messages: List["types.Message"] = []
|
||||
|
||||
if is_all_replies_in_same_chat:
|
||||
reply_messages = await client.get_messages(
|
||||
chat_id,
|
||||
reply_to_message_ids=list(messages_with_replies.keys()),
|
||||
replies=replies - 1
|
||||
)
|
||||
if isinstance(to_be_added_msg, list):
|
||||
for current_to_be_added in to_be_added_msg:
|
||||
reply_messages.append(current_to_be_added)
|
||||
elif to_be_added_msg:
|
||||
reply_messages.append(to_be_added_msg)
|
||||
else:
|
||||
for reply_header in messages_with_replies.values():
|
||||
reply_messages.append(
|
||||
await client.get_messages(
|
||||
chat_id=get_peer_id(reply_header.reply_to_peer_id) if getattr(reply_header, "reply_to_peer_id", None) else chat_id,
|
||||
message_ids=reply_header.reply_to_msg_id,
|
||||
replies=replies - 1
|
||||
)
|
||||
)
|
||||
|
||||
for message in parsed_messages:
|
||||
reply_to = messages_with_replies.get(message.id, None)
|
||||
if not reply_to:
|
||||
continue
|
||||
for message in parsed_messages:
|
||||
reply_to = messages_with_replies.get(message.id, None)
|
||||
|
||||
reply_id = reply_to.reply_to_msg_id
|
||||
if not reply_to:
|
||||
continue
|
||||
|
||||
for reply in reply_messages:
|
||||
if reply.id == reply_id and not reply.forum_topic_created:
|
||||
message.reply_to_message = reply
|
||||
|
||||
if message_reply_to_story:
|
||||
for m in parsed_messages:
|
||||
if not isinstance(m, types.Message):
|
||||
continue
|
||||
|
||||
if m.chat:
|
||||
chat_id = m.chat.id
|
||||
break
|
||||
else:
|
||||
chat_id = 0
|
||||
|
||||
reply_messages = {}
|
||||
for msg_id in message_reply_to_story:
|
||||
reply_messages[msg_id] = await client.get_stories(
|
||||
message_reply_to_story[msg_id]['user_id'],
|
||||
message_reply_to_story[msg_id]['story_id']
|
||||
for reply in reply_messages:
|
||||
if reply.id == reply_to.reply_to_msg_id:
|
||||
message.reply_to_message = reply
|
||||
else:
|
||||
for u in getattr(messages, "updates", []):
|
||||
if isinstance(
|
||||
u,
|
||||
(
|
||||
raw.types.UpdateNewMessage,
|
||||
raw.types.UpdateNewChannelMessage,
|
||||
raw.types.UpdateNewScheduledMessage,
|
||||
raw.types.UpdateBotNewBusinessMessage,
|
||||
)
|
||||
):
|
||||
parsed_messages.append(
|
||||
await types.Message._parse(
|
||||
client,
|
||||
u.message,
|
||||
users,
|
||||
chats,
|
||||
is_scheduled=isinstance(u, raw.types.UpdateNewScheduledMessage),
|
||||
business_connection_id=getattr(u, "connection_id", business_connection_id),
|
||||
raw_reply_to_message=getattr(u, "reply_to_message", None),
|
||||
replies=0
|
||||
)
|
||||
)
|
||||
|
||||
for message in parsed_messages:
|
||||
if message.id in reply_messages:
|
||||
message.reply_to_story = reply_messages[message.id]
|
||||
|
||||
return types.List(parsed_messages)
|
||||
|
||||
@ -214,7 +205,6 @@ async def parse_messages(
|
||||
def parse_deleted_messages(client, update, users, chats) -> List["types.Message"]:
|
||||
messages = update.messages
|
||||
channel_id = getattr(update, "channel_id", None)
|
||||
business_connection_id = getattr(update, "connection_id", None)
|
||||
peer = getattr(update, "peer", None)
|
||||
|
||||
chat = None
|
||||
@ -246,7 +236,7 @@ def parse_deleted_messages(client, update, users, chats) -> List["types.Message"
|
||||
types.Message(
|
||||
id=message,
|
||||
chat=chat,
|
||||
business_connection_id=business_connection_id,
|
||||
business_connection_id=getattr(update, "connection_id", None),
|
||||
client=client
|
||||
)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user