diff --git a/discord/guild.py b/discord/guild.py index 25e7d402c..4e7e38f67 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -213,6 +213,11 @@ class Guild(Hashable): def _add_member(self, member): self._members[member.id] = member + def _store_thread(self, payload) -> Thread: + thread = Thread(guild=self, data=payload) + self._threads[thread.id] = thread + return thread + def _remove_member(self, member): self._members.pop(member.id, None) diff --git a/discord/state.py b/discord/state.py index e9e4fa4d0..85a94cee9 100644 --- a/discord/state.py +++ b/discord/state.py @@ -28,6 +28,7 @@ import copy import datetime import itertools import logging +from typing import Optional import weakref import warnings import inspect @@ -56,6 +57,7 @@ from .interactions import Interaction from .ui.view import ViewStore from .stage_instance import StageInstance from .threads import Thread, ThreadMember +from discord import guild class ChunkRequest: def __init__(self, guild_id, loop, resolver, *, cache=True): @@ -724,7 +726,7 @@ class ConnectionState: return thread_id = int(data['id']) - thread = guild._get_thread(thread_id) + thread = guild.get_thread(thread_id) if thread is not None: old = copy.copy(thread) thread._update(data) @@ -734,15 +736,56 @@ class ConnectionState: guild_id = int(data['guild_id']) guild = self._get_guild(guild_id) if guild is None: - log.debug('THREAD_UPDATE referencing an unknown guild ID: %s. Discarding', guild_id) + log.debug('THREAD_DELETE referencing an unknown guild ID: %s. Discarding', guild_id) return thread_id = int(data['id']) - thread = guild._get_thread(thread_id) + thread = guild.get_thread(thread_id) if thread is not None: guild._remove_thread(thread) self.dispatch('thread_delete', thread) + def parse_thread_list_sync(self, data): + guild_id = int(data['guild_id']) + guild: Optional[Guild] = self._get_guild(guild_id) + if guild is None: + log.debug('THREAD_LIST_SYNC referencing an unknown guild ID: %s. Discarding', guild_id) + return + + threads = { + d['id']: guild._store_thread(d) + for d in data.get('threads', []) + } + + for member in data.get('members', []): + try: + # note: member['id'] is the thread_id + thread = threads[member['id']] + except KeyError: + continue + else: + thread._add_member(ThreadMember(thread, member)) + + # TODO: dispatch? + + def parse_thread_member_update(self, data): + guild_id = int(data['guild_id']) + guild: Optional[Guild] = self._get_guild(guild_id) + if guild is None: + log.debug('THREAD_MEMBER_UPDATE referencing an unknown guild ID: %s. Discarding', guild_id) + return + + thread_id = int(data['id']) + thread = guild.get_thread(thread_id) + if thread is None: + log.debug('THREAD_MEMBER_UPDATE referencing an unknown thread ID: %s. Discarding', thread_id) + return + + member = ThreadMember(thread, data) + thread._add_member(member) + + # TODO: dispatch + def parse_guild_member_add(self, data): guild = self._get_guild(int(data['guild_id'])) if guild is None: diff --git a/discord/threads.py b/discord/threads.py index 6249aff8b..696b7495a 100644 --- a/discord/threads.py +++ b/discord/threads.py @@ -23,7 +23,8 @@ DEALINGS IN THE SOFTWARE. """ from __future__ import annotations -from typing import Optional, TYPE_CHECKING +from discord.types.threads import ThreadMember +from typing import Dict, Optional, TYPE_CHECKING from .mixins import Hashable from .abc import Messageable @@ -117,6 +118,7 @@ class Thread(Messageable, Hashable): 'guild', '_type', '_state', + '_members', 'owner_id', 'parent_id', 'last_message_id', @@ -134,6 +136,7 @@ class Thread(Messageable, Hashable): def __init__(self, *, guild: Guild, data: ThreadPayload): self._state: ConnectionState = guild._state self.guild = guild + self._members: Dict[int, ThreadMember] = {} self._from_data(data) async def _get_channel(self): @@ -344,6 +347,9 @@ class Thread(Messageable, Hashable): """ await self._state.http.delete_channel(self.id) + def _add_member(self, member: ThreadMember) -> None: + self._members[member.id] = member + class ThreadMember(Hashable): """Represents a Discord thread member.