Update topic parsing

This commit is contained in:
KurimuzonAkuma 2023-12-02 16:07:21 +03:00
parent 70d9d2db5f
commit 82d9d9820e
6 changed files with 133 additions and 49 deletions

View File

@ -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/>.
from typing import AsyncGenerator, Optional
from typing import AsyncGenerator
import pyrogram
from pyrogram import types, raw, utils

View File

@ -16,11 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union, Optional, AsyncGenerator
from typing import Union, AsyncGenerator
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram import types, raw, utils
class GetForumTopics:
@ -39,26 +38,66 @@ class GetForumTopics:
limit (``int``, *optional*):
Limits the number of topics to be retrieved.
By default, no limit is applied and all topics are returned.
Returns:
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.ForumTopic` objects is returned.
``Generator``: A generator yielding :obj:`~pyrogram.types.ForumTopic` objects.
Example:
.. code-block:: python
# get all forum topics
# Iterate through all topics
async for topic in app.get_forum_topics(chat_id):
print(topic)
"""
r = await self.invoke(
raw.functions.channels.GetForumTopics(
channel=await self.resolve_peer(chat_id),
offset_date=0,
offset_id=0,
offset_topic=0,
limit=limit
)
)
current = 0
total = limit or (1 << 31) - 1
limit = min(100, total)
for topic in r.topics:
yield types.ForumTopic._parse(topic)
offset_date = 0
offset_id = 0
offset_topic = 0
while True:
r = await self.invoke(
raw.functions.channels.GetForumTopics(
channel=await self.resolve_peer(chat_id),
offset_date=offset_date,
offset_id=offset_id,
offset_topic=offset_topic,
limit=limit
)
)
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
messages = {}
for message in r.messages:
if isinstance(message, raw.types.MessageEmpty):
continue
messages[message.id] = await types.Message._parse(self, message, users, chats)
topics = []
for topic in r.topics:
topics.append(types.ForumTopic._parse(self, topic, messages, users, chats))
if not topics:
return
last = topics[-1]
offset_id = last.top_message.id
offset_date = utils.datetime_to_timestamp(last.top_message.date)
offset_topic = last.id
for topic in topics:
yield topic
current += 1
if current >= total:
return

View File

@ -71,9 +71,20 @@ class GetForumTopicsByID:
)
)
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
messages = {}
for message in r.messages:
if isinstance(message, raw.types.MessageEmpty):
continue
messages[message.id] = await types.Message._parse(self, message, users, chats)
topics = types.List()
for i in r:
topics.append(types.ForumTopic._parse(i))
for i in r.topics:
topics.append(types.ForumTopic._parse(self, i, messages, users, chats))
return topics if is_iterable else topics[0]
return topics if is_iterable else topics[0] if topics else None

View File

@ -16,7 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw, utils
import pyrogram
from pyrogram import types, raw, utils
from ..object import Object
@ -27,28 +28,31 @@ class ForumTopic(Object):
id (``int``):
Unique topic identifier inside this chat.
date (``int``):
Date when the topic was created.
title (``str``):
The topic title.
icon_color (``int``):
Color of the topic icon in RGB format
date (``int``, *optional*):
Date when the topic was created.
icon_color (``str``, *optional*):
Color of the topic icon in HEX format
icon_emoji_id (``int``, *optional*):
Unique identifier of the custom emoji shown as the topic icon
top_message (``int``):
creator (:obj:`~pyrogram.types.Chat`, *optional*):
Topic creator.
top_message (:obj:`~pyrogram.types.Message`, *optional*):
The last message sent in the topic at this time.
unread_count (``int``):
unread_count (``int``, *optional*):
Amount of unread messages in this topic.
unread_mentions_count (``int``):
unread_mentions_count (``int``, *optional*):
Amount of unread messages containing a mention in this topic.
unread_reactions_count (``int``):
unread_reactions_count (``int``, *optional*):
Amount of unread messages containing a reaction in this topic.
is_my (``bool``, *optional*):
@ -59,31 +63,41 @@ class ForumTopic(Object):
is_pinned (``bool``, *optional*):
True, if the topic is pinned.
is_short (``bool``, *optional*):
True, if the topic is short.
is_hidden (``bool``, *optional*):
True, if the topic is hidden.
"""
def __init__(
self,
*,
id: int,
date: int,
title: str,
icon_color: int,
title: str = None,
date: int = None,
icon_color: str = None,
icon_emoji_id: int = None,
top_message: int,
unread_count: int,
unread_mentions_count: int,
unread_reactions_count: int,
creator: "types.Chat" = None,
top_message: "types.Message" = None,
unread_count: int = None,
unread_mentions_count: int = None,
unread_reactions_count: int = None,
is_my: bool = None,
is_closed: bool = None,
is_pinned: bool = None,
is_short: bool = None,
is_hidden: bool = None
):
super().__init__()
self.id = id
self.date = date
self.title = title
self.date = date
self.icon_color = icon_color
self.icon_emoji_id = icon_emoji_id
self.creator = creator
self.top_message = top_message
self.unread_count = unread_count
self.unread_mentions_count = unread_mentions_count
@ -91,20 +105,37 @@ class ForumTopic(Object):
self.is_my = is_my
self.is_closed = is_closed
self.is_pinned = is_pinned
self.is_short = is_short
self.is_hidden = is_hidden
@staticmethod
def _parse(forum_topic: "raw.types.ForumTopic") -> "ForumTopic":
def _parse(client: "pyrogram.Client", forum_topic: "raw.types.ForumTopic", messages: dict = {}, users: dict = {}, chats: dict = {}) -> "ForumTopic":
creator = None
peer = getattr(forum_topic, "from_id", None)
if peer:
peer_id = utils.get_raw_peer_id(peer)
if isinstance(peer, raw.types.PeerUser):
creator = types.Chat._parse_user_chat(client, users[peer_id])
else:
creator = types.Chat._parse_channel_chat(client, chats[peer_id])
return ForumTopic(
id=forum_topic.id,
date=utils.timestamp_to_datetime(forum_topic.date),
title=forum_topic.title,
icon_color=getattr(forum_topic, "icon_color", None),
date=utils.timestamp_to_datetime(forum_topic.date),
icon_color=format(forum_topic.icon_color, "x") if getattr(forum_topic, "icon_color", None) else None,
icon_emoji_id=getattr(forum_topic, "icon_emoji_id", None),
top_message=getattr(forum_topic, "top_message", None),
creator=creator,
top_message=messages.get(getattr(forum_topic, "top_message", None)),
unread_count=getattr(forum_topic, "unread_count", None),
unread_mentions_count=getattr(forum_topic, "unread_mentions_count", None),
unread_reactions_count=getattr(forum_topic, "unread_reactions_count", None),
is_my=getattr(forum_topic, "my", None),
is_closed=getattr(forum_topic, "closed", None),
is_pinned=getattr(forum_topic, "pinned", None),
is_short=getattr(forum_topic, "short", None),
is_hidden=getattr(forum_topic, "hidden", None),
)

View File

@ -1025,12 +1025,14 @@ class Message(Object, Update):
parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id
else:
thread_id = message.reply_to.reply_to_msg_id
parsed_message.message_thread_id = thread_id
if topics:
parsed_message.topic = types.ForumTopic._parse(topics[thread_id])
parsed_message.topic = types.ForumTopic._parse(client, topics[thread_id], users=users, chats=chats)
else:
try:
msg = await client.get_messages(parsed_message.chat.id,message.id)
msg = await client.get_messages(parsed_message.chat.id, message.id, replies=0)
if msg.topic:
parsed_message.topic = msg.topic
except Exception:
@ -1051,6 +1053,7 @@ class Message(Object, Update):
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
else:

View File

@ -454,16 +454,16 @@ class ChatEvent(Object):
action = enums.ChatEventAction.INVITE_LINK_DELETED
elif isinstance(action, raw.types.ChannelAdminLogEventActionCreateTopic):
created_forum_topic = types.ForumTopic._parse(action.topic)
created_forum_topic = types.ForumTopic._parse(client, action.topic, users=users, chats=chats)
action = enums.ChatEventAction.CREATED_FORUM_TOPIC
elif isinstance(action, raw.types.ChannelAdminLogEventActionEditTopic):
old_forum_topic = types.ForumTopic._parse(action.prev_topic)
new_forum_topic = types.ForumTopic._parse(action.new_topic)
old_forum_topic = types.ForumTopic._parse(client, action.prev_topic, users=users, chats=chats)
new_forum_topic = types.ForumTopic._parse(client, action.new_topic, users=users, chats=chats)
action = enums.ChatEventAction.EDITED_FORUM_TOPIC
elif isinstance(action, raw.types.ChannelAdminLogEventActionDeleteTopic):
created_forum_topic = types.ForumTopic._parse(action.topic)
created_forum_topic = types.ForumTopic._parse(client, action.topic, users=users, chats=chats)
action = enums.ChatEventAction.DELETED_FORUM_TOPIC
else: