From 8e4d979ca0529d8af1d9cd7f4bc172c0e85989f4 Mon Sep 17 00:00:00 2001 From: Lilly Rose Berner Date: Sun, 10 Dec 2023 17:37:03 +0100 Subject: [PATCH] Add thread getters to Message --- discord/message.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/discord/message.py b/discord/message.py index 250d8ba2b..ecbec1c49 100644 --- a/discord/message.py +++ b/discord/message.py @@ -718,6 +718,20 @@ class PartialMessage(Hashable): guild_id = getattr(self.guild, 'id', '@me') return f'https://discord.com/channels/{guild_id}/{self.channel.id}/{self.id}' + @property + def thread(self) -> Optional[Thread]: + """Optional[:class:`Thread`]: The public thread created from this message, if it exists. + + .. note:: + + This does not retrieve archived threads, as they are not retained in the internal + cache. Use :meth:`fetch_thread` instead. + + .. versionadded:: 2.4 + """ + if self.guild is not None: + return self.guild.get_thread(self.id) + async def fetch(self) -> Message: """|coro| @@ -1204,6 +1218,40 @@ class PartialMessage(Hashable): """ await self.channel.read_state.ack(self.id - 1, manual=True, mention_count=mention_count) + async def fetch_thread(self) -> Thread: + """|coro| + + Retrieves the public thread attached to this message. + + .. note:: + + This method is an API call. For general usage, consider :attr:`thread` instead. + + .. versionadded:: 2.4 + + Raises + ------- + InvalidData + An unknown channel type was received from Discord + or the guild the thread belongs to is not the same + as the one in this object points to. + HTTPException + Retrieving the thread failed. + NotFound + There is no thread attached to this message. + Forbidden + You do not have permission to fetch this channel. + + Returns + -------- + :class:`.Thread` + The public thread attached to this message. + """ + if self.guild is None: + raise ValueError('This message does not have guild info attached') + + return await self.guild.fetch_channel(self.id) # type: ignore # Can only be Thread in this case + @overload async def reply( self, @@ -1535,6 +1583,7 @@ class Message(PartialMessage, Hashable): '_cs_raw_channel_mentions', '_cs_raw_role_mentions', '_cs_system_content', + '_thread', 'tts', 'content', 'webhook_id', @@ -1613,8 +1662,27 @@ class Message(PartialMessage, Hashable): else: guild_id = channel.guild_id # type: ignore +<<<<<<< HEAD self.guild_id: Optional[int] = guild_id self.guild = state._get_guild(guild_id) +======= + self._thread: Optional[Thread] = None + + if self.guild is not None: + try: + thread = data['thread'] + except KeyError: + pass + else: + self._thread = self.guild.get_thread(int(thread['id'])) + + if self._thread is not None: + self._thread._update(thread) + else: + self._thread = Thread(guild=self.guild, state=state, data=thread) + + self.interaction: Optional[MessageInteraction] = None +>>>>>>> 29344b9c (Add thread getters to Message) self.application: Optional[IntegrationApplication] = None try: @@ -1997,6 +2065,21 @@ class Message(PartialMessage, Hashable): """Optional[:class:`datetime.datetime`]: An aware UTC datetime object containing the edited time of the message.""" return self._edited_timestamp + @property + def thread(self) -> Optional[Thread]: + """Optional[:class:`Thread`]: The public thread created from this message, if it exists. + + .. note:: + + For messages received via the gateway this does not retrieve archived threads, as they + are not retained in the internal cache. Use :meth:`fetch_thread` instead. + + .. versionadded:: 2.4 + """ + if self.guild is not None: + # Fall back to guild threads in case one was created after the message + return self._thread or self.guild.get_thread(self.id) + def is_system(self) -> bool: """:class:`bool`: Whether the message is a system message.