From a1aa2816148710c9455fcf64657b76581d6c3d7a Mon Sep 17 00:00:00 2001 From: wulan17 Date: Fri, 9 Dec 2022 01:51:35 +0700 Subject: [PATCH] Pyrogram: Add ForumTopic and some cleanup Signed-off-by: wulan17 --- pyrogram/types/messages_and_media/message.py | 25 ++- pyrogram/types/user_and_chats/__init__.py | 6 + pyrogram/types/user_and_chats/forum_topic.py | 155 ++++++++++++++++++ .../user_and_chats/forum_topic_created.py | 12 +- .../user_and_chats/forum_topic_edited.py | 6 +- pyrogram/types/user_and_chats/peer_channel.py | 46 ++++++ pyrogram/types/user_and_chats/peer_user.py | 46 ++++++ pyrogram/utils.py | 6 +- 8 files changed, 285 insertions(+), 17 deletions(-) create mode 100644 pyrogram/types/user_and_chats/forum_topic.py create mode 100644 pyrogram/types/user_and_chats/peer_channel.py create mode 100644 pyrogram/types/user_and_chats/peer_user.py diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index 1759bc6b..b5cebb22 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -82,6 +82,10 @@ class Message(Object, Update): chat (:obj:`~pyrogram.types.Chat`, *optional*): Conversation the message belongs to. + topics (:obj:`~pyrogram.types.ForumTopic`, *optional*): + 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. @@ -333,6 +337,7 @@ class Message(Object, Update): sender_chat: "types.Chat" = None, date: datetime = None, chat: "types.Chat" = None, + topics: "types.ForumTopic" = None, forward_from: "types.User" = None, forward_sender_name: str = None, forward_from_chat: "types.Chat" = None, @@ -415,6 +420,7 @@ class Message(Object, Update): self.sender_chat = sender_chat self.date = date self.chat = chat + self.topics = topics self.forward_from = forward_from self.forward_sender_name = forward_sender_name self.forward_from_chat = forward_from_chat @@ -490,6 +496,7 @@ class Message(Object, Update): message: raw.base.Message, users: dict, chats: dict, + topics: dict = None, is_scheduled: bool = False, replies: int = 1 ): @@ -610,6 +617,7 @@ class Message(Object, Update): message_thread_id=message_thread_id, date=utils.timestamp_to_datetime(message.date), chat=types.Chat._parse(client, message, users, chats, is_chat=True), + topics=None, from_user=from_user, sender_chat=sender_chat, service=service_type, @@ -820,6 +828,7 @@ class Message(Object, Update): message_thread_id=message_thread_id, date=utils.timestamp_to_datetime(message.date), chat=types.Chat._parse(client, message, users, chats, is_chat=True), + topics=None, from_user=from_user, sender_chat=sender_chat, text=( @@ -887,10 +896,16 @@ class Message(Object, Update): if message.reply_to.forum_topic: if message.reply_to.reply_to_top_id: - parsed_message.message_thread_id = 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 else: - parsed_message.message_thread_id = message.reply_to.reply_to_msg_id - parsed_message.is_topic_message = True + thread_id = message.reply_to.reply_to_msg_id + parsed_message.message_thread_id = thread_id + if topics: + parsed_message.topics = types.ForumTopic._parse(topics[thread_id]) + else: + 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 replies: try: @@ -903,8 +918,8 @@ class Message(Object, Update): reply_to_message_ids=message.id, replies=replies - 1 ) - - parsed_message.reply_to_message = reply_to_message + if not reply_to_message.forum_topic_created: + parsed_message.reply_to_message = reply_to_message except MessageIdsEmpty: pass diff --git a/pyrogram/types/user_and_chats/__init__.py b/pyrogram/types/user_and_chats/__init__.py index 19788885..e233984a 100644 --- a/pyrogram/types/user_and_chats/__init__.py +++ b/pyrogram/types/user_and_chats/__init__.py @@ -35,10 +35,13 @@ from .emoji_status import EmojiStatus from .invite_link_importer import InviteLinkImporter from .restriction import Restriction from .user import User +from .forum_topic import ForumTopic from .forum_topic_created import ForumTopicCreated from .forum_topic_closed import ForumTopicClosed from .forum_topic_reopened import ForumTopicReopened from .forum_topic_edited import ForumTopicEdited +from .peer_channel import PeerChannel +from .peer_user import PeerUser from .video_chat_ended import VideoChatEnded from .video_chat_members_invited import VideoChatMembersInvited from .video_chat_scheduled import VideoChatScheduled @@ -58,10 +61,13 @@ __all__ = [ "ChatInviteLink", "InviteLinkImporter", "ChatAdminWithInviteLinks", + "ForumTopic", "ForumTopicCreated", "ForumTopicClosed", "ForumTopicReopened", "ForumTopicEdited", + "PeerChannel", + "PeerUser", "VideoChatStarted", "VideoChatEnded", "VideoChatMembersInvited", diff --git a/pyrogram/types/user_and_chats/forum_topic.py b/pyrogram/types/user_and_chats/forum_topic.py new file mode 100644 index 00000000..241bde0e --- /dev/null +++ b/pyrogram/types/user_and_chats/forum_topic.py @@ -0,0 +1,155 @@ +# 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 pyrogram import raw, types +from typing import Union +from ..object import Object + + +class ForumTopic(Object): + """A forum topic. + + + Parameters: + id (``Integer``): + Id of the topic + + date (``Integer``): + Date topic created + + title (``String``): + Name of the topic + + icon_color (``Integer``): + Color of the topic icon in RGB format + + top_message (``Integer``): + N/A + + read_inbox_max_id (``Integer``): + N/A + + read_outbox_max_id (``Integer``): + N/A + + unread_count (``Integer``): + N/A + + unread_mentions_count (``Integer``): + N/A + + unread_reactions_count (``Integer``): + N/A + + from_id (:obj:``~pyrogram.Union[types.PeerChannel``|:obj:``~pyrogram.types.PeerUser``): + Topic creator. + + #notify_settings (:obj:``~pyrogram.types.PeerNotifySettings``): //todo + N/A + + my (``Boolean``, *optional*): + N/A + + closed (``Boolean``, *optional*): + N/A + + pinned (``Boolean``, *optional*): + N/A + + short (``Boolean``, *optional*): + N/A + + icon_emoji_id (``Integer``, *optional*): + Unique identifier of the custom emoji shown as the topic icon + + #draft (:obj:``~pyrogram.types.DraftMessage``, *optional*): //todo + N/A + + """ + + def __init__( + self, + *, + id: int, + date: int, + title: str, + icon_color: int, + top_message: int, + read_inbox_max_id: int, + read_outbox_max_id: int, + unread_count: int, + unread_mentions_count: int, + unread_reactions_count: int, + from_id: Union["types.PeerChannel", "types.PeerUser"], + #notify_settings: "types.PeerNotifySettings", //todo + my: bool = None, + closed: bool = None, + pinned: bool = None, + short: bool = None, + icon_emoji_id: int = None, + #draft: "types.DraftMessage" = None //todo + ): + super().__init__() + + self.id = id + self.date = date + self.title = title + self.icon_color = icon_color + self.top_message = top_message + self.read_inbox_max_id = read_inbox_max_id + self.read_outbox_max_id = read_outbox_max_id + self.unread_count = unread_count + self.unread_mentions_count = unread_mentions_count + self.unread_reactions_count = unread_reactions_count + self.from_id = from_id + #self.notify_settings = notify_settings //todo + self.my = my + self.closed = closed + self.pinned = pinned + self.short = short + self.icon_emoji_id = icon_emoji_id + #self.draft = draft //todo + + @staticmethod + def _parse(forum_topic: "raw.types.forum_topic") -> "ForumTopic": + from_id = forum_topic.from_id + if isinstance(from_id, raw.types.PeerChannel): + peer = types.PeerChannel._parse(from_id) + if isinstance(from_id, raw.types.PeerUser): + peer = types.PeerUser._parse(from_id) + + return ForumTopic( + id=getattr(forum_topic,"id", None), + date=getattr(forum_topic,"date", None), + title=getattr(forum_topic,"title", None), + icon_color=getattr(forum_topic,"icon_color", None), + top_message=getattr(forum_topic,"top_message", None), + read_inbox_max_id=getattr(forum_topic,"read_inbox_max_id", None), + read_outbox_max_id=getattr(forum_topic,"read_outbox_max_id", 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), + from_id=peer, + #notify_settings=None, //todo + my=getattr(forum_topic,"my", None), + closed=getattr(forum_topic,"closed", None), + pinned=getattr(forum_topic,"pinned", None), + short=getattr(forum_topic,"short", None), + icon_emoji_id=getattr(forum_topic,"icon_emoji_id", None), + #draft=None //todo + ) diff --git a/pyrogram/types/user_and_chats/forum_topic_created.py b/pyrogram/types/user_and_chats/forum_topic_created.py index 701beb4c..f7d22ccd 100644 --- a/pyrogram/types/user_and_chats/forum_topic_created.py +++ b/pyrogram/types/user_and_chats/forum_topic_created.py @@ -31,21 +31,21 @@ class ForumTopicCreated(Object): icon_color (``Integer``): Color of the topic icon in RGB format - icon_custom_emoji_id (``String``, *optional*): + icon_emoji_id (``Integer``, *optional*): Unique identifier of the custom emoji shown as the topic icon """ def __init__( self, *, - title: str = None, - icon_color: int = None, - icon_custom_emoji_id: str = None + title: str, + icon_color: int, + icon_emoji_id: int = None ): super().__init__() self.title = title self.icon_color = icon_color - self.icon_custom_emoji_id = icon_custom_emoji_id + self.icon_emoji_id = icon_emoji_id @staticmethod def _parse(action: "raw.types.MessageActionTopicCreate") -> "ForumTopicCreated": @@ -54,5 +54,5 @@ class ForumTopicCreated(Object): return ForumTopicCreated( title=getattr(action,"title", None), icon_color=getattr(action,"icon_color", None), - icon_custom_emoji_id=getattr(action,"icon_custom_emoji_id", None) + icon_emoji_id=getattr(action,"icon_emoji_id", None) ) diff --git a/pyrogram/types/user_and_chats/forum_topic_edited.py b/pyrogram/types/user_and_chats/forum_topic_edited.py index d6fc8382..a0b5992c 100644 --- a/pyrogram/types/user_and_chats/forum_topic_edited.py +++ b/pyrogram/types/user_and_chats/forum_topic_edited.py @@ -39,13 +39,13 @@ class ForumTopicEdited(Object): self, *, title: str = None, icon_color: int = None, - icon_custom_emoji_id: str = None + icon_emoji_id: str = None ): super().__init__() self.title = title self.icon_color = icon_color - self.icon_custom_emoji_id = icon_custom_emoji_id + self.icon_emoji_id = icon_emoji_id @staticmethod def _parse(action: "raw.types.MessageActionTopicEdit") -> "ForumTopicEdited": @@ -54,5 +54,5 @@ class ForumTopicEdited(Object): return ForumTopicEdited( title=getattr(action,"title", None), icon_color=getattr(action,"icon_color", None), - icon_custom_emoji_id=getattr(action,"icon_custom_emoji_id", None) + icon_emoji_id=getattr(action,"icon_emoji_id", None) ) diff --git a/pyrogram/types/user_and_chats/peer_channel.py b/pyrogram/types/user_and_chats/peer_channel.py new file mode 100644 index 00000000..d8add128 --- /dev/null +++ b/pyrogram/types/user_and_chats/peer_channel.py @@ -0,0 +1,46 @@ +# 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 pyrogram import raw +from ..object import Object + + +class PeerChannel(Object): + """A PeerChannel. + + + Parameters: + channel_id (``Integer``): + Id of the channel. + """ + + def __init__( + self, *, + channel_id: int + ): + super().__init__() + + self.channel_id = channel_id + + @staticmethod + def _parse(action: "raw.types.PeerChannel") -> "PeerChannel": + + + return PeerChannel( + channel_id=getattr(action,"channel_id", None) + ) diff --git a/pyrogram/types/user_and_chats/peer_user.py b/pyrogram/types/user_and_chats/peer_user.py new file mode 100644 index 00000000..f5ad3c3e --- /dev/null +++ b/pyrogram/types/user_and_chats/peer_user.py @@ -0,0 +1,46 @@ +# 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 pyrogram import raw +from ..object import Object + + +class PeerUser(Object): + """A PeerUser. + + + Parameters: + user_id (``Integer``): + Id of the user. + """ + + def __init__( + self, *, + user_id: int + ): + super().__init__() + + self.user_id = user_id + + @staticmethod + def _parse(action: "raw.types.PeerUser") -> "PeerUser": + + + return PeerUser( + user_id=getattr(action,"user_id", None) + ) diff --git a/pyrogram/utils.py b/pyrogram/utils.py index f7fe5970..ef7a492e 100644 --- a/pyrogram/utils.py +++ b/pyrogram/utils.py @@ -91,14 +91,14 @@ async def parse_messages( ) -> 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 not messages.messages: return types.List() parsed_messages = [] for message in messages.messages: - parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0)) + parsed_messages.append(await types.Message._parse(client, message, users, chats, topics, replies=0)) if replies: messages_with_replies = { @@ -127,7 +127,7 @@ async def parse_messages( reply_id = messages_with_replies.get(message.id, None) for reply in reply_messages: - if reply.id == reply_id: + if reply.id == reply_id and not reply.forum_topic_created: message.reply_to_message = reply return types.List(parsed_messages)