From 4a4e73ec145e9f99c876a711ce6773197758424c Mon Sep 17 00:00:00 2001 From: Rapptz Date: Tue, 4 May 2021 08:13:33 -0400 Subject: [PATCH] Update thread typings and payloads to match documentation --- discord/enums.py | 1 + discord/http.py | 35 +++++++++++++++++++++++++++-------- discord/threads.py | 14 ++++++++++++-- discord/types/channel.py | 6 +++++- discord/types/threads.py | 20 ++++++++++++++++---- docs/api.rst | 23 ++++++++++++++++------- 6 files changed, 77 insertions(+), 22 deletions(-) diff --git a/discord/enums.py b/discord/enums.py index c145c8291..98b5a1092 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -162,6 +162,7 @@ class ChannelType(Enum): category = 4 news = 5 store = 6 + news_thread = 10 public_thread = 11 private_thread = 12 stage_voice = 13 diff --git a/discord/http.py b/discord/http.py index 1d27996c4..a40d9a5e4 100644 --- a/discord/http.py +++ b/discord/http.py @@ -46,6 +46,7 @@ if TYPE_CHECKING: invite, channel, widget, + threads, ) from .types.snowflake import Snowflake @@ -741,7 +742,7 @@ class HTTPClient: name: str, auto_archive_duration: int, type: int, - ): + ) -> Response[threads.Thread]: payload = { 'name': name, 'auto_archive_duration': auto_archive_duration, @@ -760,7 +761,7 @@ class HTTPClient: name: str, auto_archive_duration: int, type: int, - ): + ) -> Response[threads.Thread]: payload = { 'name': name, 'auto_archive_duration': auto_archive_duration, @@ -775,7 +776,7 @@ class HTTPClient: def add_user_to_thread(self, channel_id: int, user_id: int): return self.request( - Route('POST', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id) + Route('PUT', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id) ) def leave_thread(self, channel_id: int): @@ -785,7 +786,9 @@ class HTTPClient: route = Route('DELETE', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id) return self.request(route) - def get_public_archived_threads(self, channel_id: int, before=None, limit: int = 50): + def get_public_archived_threads( + self, channel_id: int, before=None, limit: int = 50 + ) -> Response[threads.ThreadPaginationPayload]: route = Route('GET', '/channels/{channel_id}/threads/archived/public', channel_id=channel_id) params = {} @@ -794,7 +797,9 @@ class HTTPClient: params['limit'] = limit return self.request(route, params=params) - def get_private_archived_threads(self, channel_id: int, before=None, limit: int = 50): + def get_private_archived_threads( + self, channel_id: int, before=None, limit: int = 50 + ) -> Response[threads.ThreadPaginationPayload]: route = Route('GET', '/channels/{channel_id}/threads/archived/private', channel_id=channel_id) params = {} @@ -803,7 +808,9 @@ class HTTPClient: params['limit'] = limit return self.request(route, params=params) - def get_joined_private_archived_threads(self, channel_id, before=None, limit: int = 50): + def get_joined_private_archived_threads( + self, channel_id: int, before=None, limit: int = 50 + ) -> Response[threads.ThreadPaginationPayload]: route = Route('GET', '/channels/{channel_id}/users/@me/threads/archived/private', channel_id=channel_id) params = {} if before: @@ -811,6 +818,14 @@ class HTTPClient: params['limit'] = limit return self.request(route, params=params) + def get_active_threads(self, channel_id: int) -> Response[threads.ThreadPaginationPayload]: + route = Route('GET', '/channels/{channel_id}/threads/active', channel_id=channel_id) + return self.request(route) + + def get_thread_members(self, channel_id: int) -> Response[List[threads.ThreadMember]]: + route = Route('GET', '/channels/{channel_id}/thread-members', channel_id=channel_id) + return self.request(route) + # Webhook management def create_webhook(self, channel_id, *, name, avatar=None, reason=None): @@ -1456,7 +1471,9 @@ class HTTPClient: ) return self.request(r) - def get_guild_application_command_permissions(self, application_id, guild_id) -> Response[List[interactions.GuildApplicationCommandPermissions]]: + def get_guild_application_command_permissions( + self, application_id, guild_id + ) -> Response[List[interactions.GuildApplicationCommandPermissions]]: r = Route( 'GET', '/applications/{application_id}/guilds/{guild_id}/commands/permissions', @@ -1465,7 +1482,9 @@ class HTTPClient: ) return self.request(r) - def get_application_command_permissions(self, application_id, guild_id, command_id) -> Response[interactions.GuildApplicationCommandPermissions]: + def get_application_command_permissions( + self, application_id, guild_id, command_id + ) -> Response[interactions.GuildApplicationCommandPermissions]: r = Route( 'GET', '/applications/{application_id}/guilds/{guild_id}/commands/{command_id}/permissions', diff --git a/discord/threads.py b/discord/threads.py index 0d2b6f960..3efc4db03 100644 --- a/discord/threads.py +++ b/discord/threads.py @@ -87,6 +87,11 @@ class Thread(Messageable, Hashable): last_message_id: Optional[:class:`int`] The last message ID of the message sent to this thread. It may *not* point to an existing or valid message. + slowmode_delay: :class:`int` + The number of seconds a member must wait between sending messages + in this thread. A value of `0` denotes that it is disabled. + Bots and users with :attr:`~Permissions.manage_channels` or + :attr:`~Permissions.manage_messages` bypass slowmode. message_count: :class:`int` An approximate number of messages in this thread. This caps at 50. member_count: :class:`int` @@ -112,10 +117,13 @@ class Thread(Messageable, Hashable): '_type', '_state', 'owner_id', + 'parent_id', 'last_message_id', 'message_count', 'member_count', + 'slowmode_delay', 'me', + 'locked', 'archived', 'archiver_id', 'auto_archive_duration', @@ -135,8 +143,9 @@ class Thread(Messageable, Hashable): self.parent_id = int(data['parent_id']) self.owner_id = int(data['owner_id']) self.name = data['name'] - self.type = try_enum(ChannelType, data['type']) + self._type = try_enum(ChannelType, data['type']) self.last_message_id = utils._get_as_snowflake(data, 'last_message_id') + self.slowmode_delay = data.get('rate_limit_per_user', 0) self._unroll_metadata(data['thread_metadata']) try: @@ -151,6 +160,7 @@ class Thread(Messageable, Hashable): self.archiver_id = utils._get_as_snowflake(data, 'archiver_id') self.auto_archive_duration = data['auto_archive_duration'] self.archive_timestamp = utils.parse_time(data['archive_timestamp']) + self.locked = data.get('locked', False) def _update(self, data): try: @@ -196,7 +206,7 @@ class Thread(Messageable, Hashable): def is_private(self) -> bool: """:class:`bool`: Whether the thread is a private thread.""" - return self.type is ChannelType.private_thread + return self._type is ChannelType.private_thread async def edit( self, diff --git a/discord/types/channel.py b/discord/types/channel.py index 43a85a55f..d4f4cf3d2 100644 --- a/discord/types/channel.py +++ b/discord/types/channel.py @@ -35,7 +35,7 @@ class PermissionOverwrite(TypedDict): deny: str -ChannelType = Literal[0, 1, 2, 3, 4, 5, 6, 11, 12, 13] +ChannelType = Literal[0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13] class _BaseChannel(TypedDict): @@ -105,6 +105,10 @@ class StageChannel(_BaseGuildChannel, _StageChannelOptional): class _ThreadChannelOptional(TypedDict, total=False): member: ThreadMember + owner_id: Snowflake + rate_limit_per_user: int + last_message_id: Optional[Snowflake] + last_pin_timestamp: str class ThreadChannel(_BaseChannel, _ThreadChannelOptional): diff --git a/discord/types/threads.py b/discord/types/threads.py index 02df7307c..c0f0c10b4 100644 --- a/discord/types/threads.py +++ b/discord/types/threads.py @@ -23,11 +23,11 @@ DEALINGS IN THE SOFTWARE. """ from __future__ import annotations -from typing import Literal, Optional, TypedDict +from typing import List, Literal, Optional, TypedDict from .snowflake import Snowflake -ThreadTypes = Literal[11, 12] +ThreadTypes = Literal[10, 11, 12] ThreadArchiveDuration = Literal[60, 1440, 4320, 10080] @@ -38,9 +38,13 @@ class ThreadMember(TypedDict): flags: int -class ThreadMetadata(TypedDict): +class _ThreadMetadataOptional(TypedDict, total=False): + archiver_id: Snowflake + locked: bool + + +class ThreadMetadata(_ThreadMetadataOptional): archived: bool - archiver_id: Optional[Snowflake] auto_archive_duration: ThreadArchiveDuration archive_timestamp: str @@ -48,6 +52,7 @@ class ThreadMetadata(TypedDict): class _ThreadOptional(TypedDict, total=False): member: ThreadMember last_message_id: Optional[Snowflake] + last_pin_timestamp: Optional[Snowflake] class Thread(_ThreadOptional): @@ -59,4 +64,11 @@ class Thread(_ThreadOptional): type: ThreadTypes member_count: int message_count: int + rate_limit_per_user: int thread_metadata: ThreadMetadata + + +class ThreadPaginationPayload(TypedDict): + threads: List[Thread] + members: List[ThreadMember] + has_more: bool diff --git a/docs/api.rst b/docs/api.rst index c0c60d8c6..4282373ec 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1065,6 +1065,12 @@ of :class:`enum.Enum`. .. versionadded:: 1.7 + .. attribute:: news_thread + + A news thread + + .. versionadded:: 2.0 + .. attribute:: public_thread A public thread @@ -1096,12 +1102,12 @@ of :class:`enum.Enum`. The default message type. This is the same as regular messages. .. attribute:: recipient_add - The system message when a recipient is added to a group private - message, i.e. a private channel of type :attr:`ChannelType.group`. + The system message when a user is added to a group private + message or a thread. .. attribute:: recipient_remove - The system message when a recipient is removed from a group private - message, i.e. a private channel of type :attr:`ChannelType.group`. + The system message when a user is removed from a group private + message or a thread. .. attribute:: call The system message denoting call state, e.g. missed call, started call, @@ -1170,7 +1176,10 @@ of :class:`enum.Enum`. .. versionadded:: 1.7 .. attribute:: thread_created - The system message denoting that a thread has been created + The system message denoting that a thread has been created. This is only + sent if the thread has been created from an older message. The period of time + required for a message to be considered old cannot be relied upon and is up to + Discord. .. versionadded:: 2.0 .. attribute:: reply @@ -1190,8 +1199,8 @@ of :class:`enum.Enum`. .. versionadded:: 2.0 .. attribute:: thread_starter_message - The system message denoting that this message is the one that started a thread's - conversation topic. + The system message denoting the message in the thread that is the one that started the + thread's conversation topic. .. versionadded:: 2.0