diff --git a/discord/raw_models.py b/discord/raw_models.py index 35295a633..bca0721aa 100644 --- a/discord/raw_models.py +++ b/discord/raw_models.py @@ -42,6 +42,7 @@ if TYPE_CHECKING: IntegrationDeleteEvent, ThreadUpdateEvent, ThreadDeleteEvent, + ThreadMembersUpdate, TypingStartEvent, GuildMemberRemoveEvent, ) @@ -64,6 +65,7 @@ __all__ = ( 'RawIntegrationDeleteEvent', 'RawThreadUpdateEvent', 'RawThreadDeleteEvent', + 'RawThreadMembersUpdate', 'RawTypingEvent', 'RawMemberRemoveEvent', ) @@ -357,6 +359,32 @@ class RawThreadDeleteEvent(_RawReprMixin): self.thread: Optional[Thread] = None +class RawThreadMembersUpdate(_RawReprMixin): + """Represents the payload for a :func:`on_raw_thread_member_remove` event. + + .. versionadded:: 2.0 + + Attributes + ---------- + thread_id: :class:`int` + The ID of the thread that was updated. + guild_id: :class:`int` + The ID of the guild the thread is in. + member_count: :class:`int` + The approximate number of members in the thread. This caps at 50. + data: :class:`dict` + The raw data given by the :ddocs:`gateway `. + """ + + __slots__ = ('thread_id', 'guild_id', 'member_count', 'data') + + def __init__(self, data: ThreadMembersUpdate) -> None: + self.thread_id: int = int(data['id']) + self.guild_id: int = int(data['guild_id']) + self.member_count: int = int(data['member_count']) + self.data: ThreadMembersUpdate = data + + class RawTypingEvent(_RawReprMixin): """Represents the payload for a :func:`on_raw_typing` event. diff --git a/discord/state.py b/discord/state.py index 7b05e1a51..19a4c6843 100644 --- a/discord/state.py +++ b/discord/state.py @@ -965,6 +965,7 @@ class ConnectionState: thread_id = int(data['id']) thread: Optional[Thread] = guild.get_thread(thread_id) + raw = RawThreadMembersUpdate(data) if thread is None: _log.debug('THREAD_MEMBERS_UPDATE referencing an unknown thread ID: %s. Discarding', thread_id) return @@ -983,6 +984,7 @@ class ConnectionState: for member_id in removed_member_ids: if member_id != self_id: member = thread._pop_member(member_id) + self.dispatch('raw_thread_member_remove', raw) if member is not None: self.dispatch('thread_member_remove', member) else: diff --git a/docs/api.rst b/docs/api.rst index e07d87dda..f0c656259 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1266,6 +1266,18 @@ Threads :param member: The member who joined or left. :type member: :class:`ThreadMember` +.. function:: on_raw_thread_member_remove(payload) + + Called when a :class:`ThreadMember` leaves a :class:`Thread`. Unlike :func:`on_thread_member_remove` this + is called regardless of the member being in the internal thread's members cache or not. + + This requires :attr:`Intents.members` to be enabled. + + .. versionadded:: 2.0 + + :param payload: The raw event payload data. + :type member: :class:`RawThreadMembersUpdate` + Voice ~~~~~~ @@ -4139,6 +4151,14 @@ RawThreadUpdateEvent .. autoclass:: RawThreadUpdateEvent() :members: +RawThreadMembersUpdate +~~~~~~~~~~~~~~~~~~~~~~ + +.. attributetable:: RawThreadMembersUpdate + +.. autoclass:: RawThreadMembersUpdate() + :members: + RawThreadDeleteEvent ~~~~~~~~~~~~~~~~~~~~~~