Skip to content

Commit

Permalink
Add support for cross-chat replies.
Browse files Browse the repository at this point in the history
Signed-off-by: Aliwoto <[email protected]>
  • Loading branch information
Aliwoto committed Nov 1, 2023
1 parent 997d0cb commit f08404f
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 18 deletions.
2 changes: 1 addition & 1 deletion pyrogram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>

__version__ = "2.0.131"
__version__ = "2.0.132"
__license__ = "GNU Lesser General Public License v3.0 (LGPL-3.0)"
__copyright__ = "Copyright (C) 2017-present Dan <https://github.com/delivrance>"

Expand Down
30 changes: 24 additions & 6 deletions pyrogram/types/messages_and_media/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -1013,18 +1013,36 @@ async def _parse(
parsed_message.reply_to_story_id = message.reply_to.story_id
parsed_message.reply_to_story_user_id = message.reply_to.user_id

setattr(parsed_message, "is_cross_chat", False)
if replies:
if parsed_message.reply_to_message_id:
try:
key = (parsed_message.chat.id, parsed_message.reply_to_message_id)
is_cross_chat = \
message.reply_to and \
message.reply_to.reply_to_peer_id and \
hasattr(message.reply_to.reply_to_peer_id, "channel_id") and \
message.reply_to.reply_to_peer_id.channel_id
if is_cross_chat:
key = (f"-100{message.reply_to.reply_to_peer_id.channel_id}",
message.reply_to.reply_to_msg_id)
setattr(parsed_message, "is_cross_chat", True)
else:
key = (parsed_message.chat.id, parsed_message.reply_to_message_id)
reply_to_message = client.message_cache[key]

if not reply_to_message:
reply_to_message = await client.get_messages(
parsed_message.chat.id,
reply_to_message_ids=message.id,
replies=replies - 1
)
if is_cross_chat:
reply_to_message = await client.get_messages(
chat_id=key[0],
message_ids=key[1],
replies=replies - 1
)
else:
reply_to_message = await client.get_messages(
chat_id=key[0],
reply_to_message_ids=key[1],
replies=replies - 1
)
if reply_to_message and not reply_to_message.forum_topic_created:
parsed_message.reply_to_message = reply_to_message
except MessageIdsEmpty:
Expand Down
61 changes: 50 additions & 11 deletions pyrogram/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,14 @@ def get_input_media_from_file_id(


async def parse_messages(
client,
client: "pyrogram.Client",
messages: "raw.types.messages.Messages",
replies: int = 1
) -> 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
users = {i.id: i for i in messages.users if hasattr(i, "id")}
chats = {i.id: i for i in messages.chats if hasattr(i, "id")}
topics = {i.id: i for i in messages.topics if hasattr(i, "id")} \
if hasattr(messages, "topics") else None

if not messages.messages:
return types.List()
Expand All @@ -113,7 +114,7 @@ async def parse_messages(

if replies:
messages_with_replies = {
i.id: i.reply_to.reply_to_msg_id
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)
}
Expand All @@ -128,20 +129,55 @@ async def parse_messages(
# 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, pyrogram.types.Message):
continue

if m.chat:
chat_id = m.chat.id
break
else:
chat_id = 0

reply_messages = await client.get_messages(
chat_id,
reply_to_message_ids=messages_with_replies.keys(),
replies=replies - 1
)
# whether all messages are inside of our current chat
is_all_within_chat = True
for current_message_id in messages_with_replies:
if messages_with_replies[current_message_id].reply_to_peer_id:
is_all_within_chat = False
break

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 current_message_id in messages_with_replies:
target_reply_to = messages_with_replies[current_message_id]
to_be_added_msg = None
the_chat_id = chat_id
if target_reply_to.reply_to_peer_id:
the_chat_id = f"-100{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,
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)

for message in parsed_messages:
reply_id = messages_with_replies.get(message.id, None)
reply_to = messages_with_replies.get(message.id, None)
if not reply_to:
continue

reply_id = reply_to.reply_to_msg_id

for reply in reply_messages:
if reply.id == reply_id:
Expand All @@ -150,6 +186,9 @@ async def parse_messages(

if message_reply_to_story:
for m in parsed_messages:
if not isinstance(m, pyrogram.types.Message):
continue

if m.chat:
chat_id = m.chat.id
break
Expand Down

0 comments on commit f08404f

Please sign in to comment.