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 # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import AsyncGenerator, Optional from typing import AsyncGenerator
import pyrogram import pyrogram
from pyrogram import types, raw, utils 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 # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union, Optional, AsyncGenerator from typing import Union, AsyncGenerator
import pyrogram import pyrogram
from pyrogram import raw from pyrogram import types, raw, utils
from pyrogram import types
class GetForumTopics: class GetForumTopics:
@ -39,26 +38,66 @@ class GetForumTopics:
limit (``int``, *optional*): limit (``int``, *optional*):
Limits the number of topics to be retrieved. Limits the number of topics to be retrieved.
By default, no limit is applied and all topics are returned.
Returns: Returns:
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.ForumTopic` objects is returned. ``Generator``: A generator yielding :obj:`~pyrogram.types.ForumTopic` objects.
Example: Example:
.. code-block:: python .. code-block:: python
# get all forum topics # Iterate through all topics
async for topic in app.get_forum_topics(chat_id): async for topic in app.get_forum_topics(chat_id):
print(topic) print(topic)
""" """
r = await self.invoke( current = 0
raw.functions.channels.GetForumTopics( total = limit or (1 << 31) - 1
channel=await self.resolve_peer(chat_id), limit = min(100, total)
offset_date=0,
offset_id=0,
offset_topic=0,
limit=limit
)
)
for topic in r.topics: offset_date = 0
yield types.ForumTopic._parse(topic) 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() topics = types.List()
for i in r: for i in r.topics:
topics.append(types.ForumTopic._parse(i)) 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 # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # 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 from ..object import Object
@ -27,28 +28,31 @@ class ForumTopic(Object):
id (``int``): id (``int``):
Unique topic identifier inside this chat. Unique topic identifier inside this chat.
date (``int``):
Date when the topic was created.
title (``str``): title (``str``):
The topic title. The topic title.
icon_color (``int``): date (``int``, *optional*):
Color of the topic icon in RGB format Date when the topic was created.
icon_color (``str``, *optional*):
Color of the topic icon in HEX format
icon_emoji_id (``int``, *optional*): icon_emoji_id (``int``, *optional*):
Unique identifier of the custom emoji shown as the topic icon 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. The last message sent in the topic at this time.
unread_count (``int``): unread_count (``int``, *optional*):
Amount of unread messages in this topic. 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. 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. Amount of unread messages containing a reaction in this topic.
is_my (``bool``, *optional*): is_my (``bool``, *optional*):
@ -59,31 +63,41 @@ class ForumTopic(Object):
is_pinned (``bool``, *optional*): is_pinned (``bool``, *optional*):
True, if the topic is pinned. 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__( def __init__(
self, self,
*, *,
id: int, id: int,
date: int, title: str = None,
title: str, date: int = None,
icon_color: int, icon_color: str = None,
icon_emoji_id: int = None, icon_emoji_id: int = None,
top_message: int, creator: "types.Chat" = None,
unread_count: int, top_message: "types.Message" = None,
unread_mentions_count: int, unread_count: int = None,
unread_reactions_count: int, unread_mentions_count: int = None,
unread_reactions_count: int = None,
is_my: bool = None, is_my: bool = None,
is_closed: bool = None, is_closed: bool = None,
is_pinned: bool = None, is_pinned: bool = None,
is_short: bool = None,
is_hidden: bool = None
): ):
super().__init__() super().__init__()
self.id = id self.id = id
self.date = date
self.title = title self.title = title
self.date = date
self.icon_color = icon_color self.icon_color = icon_color
self.icon_emoji_id = icon_emoji_id self.icon_emoji_id = icon_emoji_id
self.creator = creator
self.top_message = top_message self.top_message = top_message
self.unread_count = unread_count self.unread_count = unread_count
self.unread_mentions_count = unread_mentions_count self.unread_mentions_count = unread_mentions_count
@ -91,20 +105,37 @@ class ForumTopic(Object):
self.is_my = is_my self.is_my = is_my
self.is_closed = is_closed self.is_closed = is_closed
self.is_pinned = is_pinned self.is_pinned = is_pinned
self.is_short = is_short
self.is_hidden = is_hidden
@staticmethod @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( return ForumTopic(
id=forum_topic.id, id=forum_topic.id,
date=utils.timestamp_to_datetime(forum_topic.date),
title=forum_topic.title, 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), 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_count=getattr(forum_topic, "unread_count", None),
unread_mentions_count=getattr(forum_topic, "unread_mentions_count", None), unread_mentions_count=getattr(forum_topic, "unread_mentions_count", None),
unread_reactions_count=getattr(forum_topic, "unread_reactions_count", None), unread_reactions_count=getattr(forum_topic, "unread_reactions_count", None),
is_my=getattr(forum_topic, "my", None), is_my=getattr(forum_topic, "my", None),
is_closed=getattr(forum_topic, "closed", None), is_closed=getattr(forum_topic, "closed", None),
is_pinned=getattr(forum_topic, "pinned", 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 parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id
else: else:
thread_id = message.reply_to.reply_to_msg_id thread_id = message.reply_to.reply_to_msg_id
parsed_message.message_thread_id = thread_id parsed_message.message_thread_id = thread_id
if topics: 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: else:
try: 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: if msg.topic:
parsed_message.topic = msg.topic parsed_message.topic = msg.topic
except Exception: except Exception:
@ -1051,6 +1053,7 @@ class Message(Object, Update):
if media is None or web_page is not None if media is None or web_page is not None
else None else None
) )
parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id 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.reply_to_top_message_id = message.reply_to.reply_to_top_id
else: else:

View File

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