Repository: Pycord-Development/pycord

Issue:
Thread member cache not accurate
### Summary

Thread member cache not accurate

### Reproduction Steps

Craft an event listener for `on_thread_join`:
- Make the bot add itself to threads if it isn't already present according to `Thread.me`

Craft an event listener for `on_thread_update`:
- Make the bot add itself to unarchived threads if it isn't already present according to `Thread.me`
- Log the cached thread details, including `Thread.me` and `Thread.members`

Craft an event listener for `on_thread_remove`:
- Log the cached thread details, including `Thread.me` and `Thread.members`

Start the bot

In your Discord client on a guild where the bot is present:
- Create a thread through your Discord client, and observe the bot join it
- Remove the bot from the thread
- Archive the thread
- Unarchive the thread

### Minimal Reproducible Code

```python
import logging
from typing import (Optional, Union)
from discord import (Thread, Guild)
from discord.ext import commands
from bot import Bot

logger = logging.getLogger(__name__)

class ThreadManager(commands.Cog):
    """Manages the bot's presence in threads as it receives events about them."""

    def __init__(self, bot: Bot) -> None:
        super().__init__()
        self.bot = bot

    async def _get_thread_details(self, event: str, thread: Union[int, Thread], guild: Optional[Guild] = None) -> Thread:
        text = f">>> {event}: Cached thread details; "
        if guild and isinstance(thread, int):
            thread: Thread = guild.get_thread(thread)
        text += f"'{thread.name}' ({thread.id}); thread.me={thread.me}, "
        text += f"Thread.members:List[ThreadMember]={thread.members}"
        if thread.members:
            members = [thread.guild.get_member(m.id) for m in thread.members]
            text += f", Thread.members:List[Member]={members}"
        logger.debug(text)
        return thread

    async def _join_thread(self, thread: Thread) -> None:
        await thread.join()
        logger.debug(f">>> THREAD_JOIN: Joined thread '{thread.name}' ({thread.id})")

    @commands.Cog.listener("on_thread_join")
    async def create_handler(self, thread: Thread) -> None:
        thread = await self._get_thread_details("THREAD_JOIN", thread, guild=after.guild)
        if not thread.me:
            await self._join_thread(thread)

    @commands.Cog.listener("on_thread_update")
    async def update_handler(self, before: Thread, after: Thread) -> None:
        thread = await self._get_thread_details("THREAD_UPDATE", after.id, guild=after.guild)
        if (
            (before.archived and not after.archived)
            and not thread.me
        ):
            await self._join_thread(thread)

    @commands.Cog.listener("on_thread_remove")
    async def remove_handler(self, thread: Thread) -> None:
        await self._get_thread_details("THREAD_REMOVE", thread, guild=after.guild)


def setup(bot: Bot):
    bot.add_cog(ThreadManager(bot))
```


### Expected Results

On handling the `THREAD_MEMBERS_UPDATE` websocket event and subsequent `thread_remove` PyCord event:
- `Thread.me` would be `None`, and `Thread.members` would contain the remaining members of the thread.

On handling the `thread_update` event:
- `Thread.me` would be `None`, and `Thread.members` would contain the remaining members of the thread.
- The bot rejoins the thread.


### Actual Results

On handling the `THREAD_MEMBERS_UPDATE` websocket event and subsequent `thread_remove` PyCord event:
- Logs show the raw websocket event payload contains a `removed_members` attribute. Despite this, the `thread_remove` PyCord event continues to return the bot user in `Thread.me` when handling this event.

On handling the `thread_update` event:
- Logs show the `Thread` object cache is inaccurate - the `me` property is a `ThreadMember` that is of the bot user and the `members` property is an empty list.
- The bot does not rejoin the thread.

### Intents

```py
intents = discord.Intents.default()
intents.members = True
```

### System Information

```
- Python v3.10.4-final
- py-cord v2.0.0-beta
    - py-cord pkg_resources: v2.0.0b3
- aiohttp v3.8.1
- system info: Linux 5.17.4-zen1-1-zen #1 ZEN SMP PREEMPT Wed, 20 Apr 2022 18:29:30 +0000
```

### Checklist

- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.

### Additional Context

This is the bot's logs when the steps to reproduced are followed with my own bot, which includes code that isn't in the minimal reproduction code provided. I've heavily redacted identifiers, but left those that are important for discerning unique members.

```
2022-04-26 10:39:53 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'THREAD_CREATE', 's': 16, 'op': 0, 'd': {'type': 11, 'thread_metadata': {'locked': False, 'create_timestamp': '2022-04-26T17:39:53.535000+00:00', 'auto_archive_duration': 10080, 'archived': False, 'archive_timestamp': '2022-04-26T17:39:53.535000+00:00'}, 'rate_limit_per_user': 0, 'parent_id': '[redacted]', 'owner_id': '[redacted]', 'newly_created': True, 'name': 'test', 'message_count': 0, 'member_count': 1, 'last_message_id': None, 'id': '[redacted]', 'guild_id': '[redacted]', 'flags': 0}}
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event thread_join
2022-04-26 10:39:53 bot.events.threads DEBUG    !!! THREAD_JOIN: Handling event
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_JOIN: Event details; 'test' ([redacted]); me=None, Thread.members:List[ThreadMember]=[]
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_JOIN: Cached thread details; 'test' ([redacted]); thread.me=None, Thread.members:List[ThreadMember]=[]
2022-04-26 10:39:53 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'THREAD_MEMBERS_UPDATE', 's': 17, 'op': 0, 'd': {'member_count': 2, 'id': '[redacted]', 'added_members': [{'user_id': '890400000000000000', 'presence': {'user': {'username': 'bot', 'public_flags': 0, 'id': '890400000000000000', 'discriminator': '[redacted]', 'bot': True, 'avatar': '7f3b35011a5cdefa9b73c07aa36d3fdd'}, 'status': 'online', 'game': {'type': 0, 'session_id': None, 'name': 'in buggy waters', 'id': 'ec0b28a579ecb4bd', 'created_at': 1650423664256}, 'client_status': {'web': 'online'}, 'activities': [{'type': 0, 'name': 'in buggy waters', 'id': 'ec0b28a579ecb4bd', 'created_at': 1650423664256}]}, 'member': {'user': {'username': 'bot', 'public_flags': 0, 'id': '890400000000000000', 'discriminator': '[redacted]', 'bot': True, 'avatar': '7f3b35011a5cdefa9b73c07aa36d3fdd'}, 'roles': ['[redacted]', '[redacted]'], 'mute': False, 'joined_at': '2022-02-03T21:40:31.159000+00:00', 'hoisted_role': '[redacted]', 'flags': 0, 'deaf': False}, 'join_timestamp': '2022-04-26T17:39:53.757651+00:00', 'id': '[redacted]', 'flags': 0}], 'guild_id': '[redacted]'}}
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event thread_member_join
2022-04-26 10:39:53 bot.events.threads DEBUG    !!! THREAD_MEMBER_JOIN: Handling event
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_MEMBER_JOIN: Event details; 'test' ([redacted]); ThreadMember=<ThreadMember id=890400000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 757651, tzinfo=datetime.timezone.utc)>, Member=bot#[redacted]
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_MEMBER_JOIN: Cached thread details; 'test' ([redacted]); thread.me=None, Thread.members:List[ThreadMember]=[<ThreadMember id=890400000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 757651, tzinfo=datetime.timezone.utc)>], Thread.members:List[Member]=[<Member id=890400000000000000 name='bot' discriminator='[redacted]' bot=True nick=None guild=<Guild id=[redacted] name="bot development" shard_id=0 chunked=True member_count=11>>]
2022-04-26 10:39:53 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'THREAD_MEMBERS_UPDATE', 's': 18, 'op': 0, 'd': {'member_count': 3, 'id': '[redacted]', 'added_members': [{'user_id': '897100000000000000', 'presence': {'user': {'username': 'gay bot', 'id': '897100000000000000', 'discriminator': '[redacted]', 'bot': True, 'avatar': '39801670320babab422e028653bd7225'}, 'status': 'online', 'game': {'type': 0, 'session_id': None, 'name': 'in buggy waters', 'id': 'ec0b28a579ecb4bd', 'created_at': 1650994751513}, 'client_status': {'web': 'online'}, 'activities': [{'type': 0, 'name': 'in buggy waters', 'id': 'ec0b28a579ecb4bd', 'created_at': 1650994751513}]}, 'muted': False, 'mute_config': None, 'member': {'user': {'username': 'gay bot', 'id': '897100000000000000', 'discriminator': '[redacted]', 'bot': True, 'avatar': '39801670320babab422e028653bd7225'}, 'roles': ['[redacted]', '[redacted]'], 'mute': False, 'joined_at': '2022-04-21T02:55:43.620000+00:00', 'hoisted_role': '[redacted]', 'flags': 1, 'deaf': False}, 'join_timestamp': '2022-04-26T17:39:53.846437+00:00', 'id': '[redacted]', 'flags': 1}], 'guild_id': '[redacted]'}}
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event thread_join
2022-04-26 10:39:53 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'THREAD_CREATE', 's': 19, 'op': 0, 'd': {'type': 11, 'thread_metadata': {'locked': False, 'create_timestamp': '2022-04-26T17:39:53.535000+00:00', 'auto_archive_duration': 10080, 'archived': False, 'archive_timestamp': '2022-04-26T17:39:53.535000+00:00'}, 'rate_limit_per_user': 0, 'parent_id': '[redacted]', 'owner_id': '[redacted]', 'name': 'test', 'message_count': 0, 'member_count': 3, 'member': {'user_id': '897100000000000000', 'muted': False, 'mute_config': None, 'join_timestamp': '2022-04-26T17:39:53.846437+00:00', 'id': '[redacted]', 'flags': 1}, 'last_message_id': None, 'id': '[redacted]', 'guild_id': '[redacted]', 'flags': 0}}
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:39:53 bot.events.threads DEBUG    !!! THREAD_JOIN: Handling event
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_JOIN: Event details; 'test' ([redacted]); me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[<ThreadMember id=890400000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 757651, tzinfo=datetime.timezone.utc)>]
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_JOIN: Cached thread details; 'test' ([redacted]); thread.me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[]
2022-04-26 10:39:53 discord.http         DEBUG    POST https://discord.com/api/v9/channels/[redacted]/thread-members/@me with None has returned 204
2022-04-26 10:39:53 discord.http         DEBUG    POST https://discord.com/api/v9/channels/[redacted]/thread-members/@me has received 
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_JOIN: Joined thread 'test' ([redacted])
2022-04-26 10:39:53 bot.events.threads DEBUG    >>> THREAD_JOIN: Cached thread details; 'test' ([redacted]); thread.me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[]
2022-04-26 10:39:53 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'MESSAGE_CREATE', 's': 20, 'op': 0, 'd': {'type': 0, 'tts': False, 'timestamp': '2022-04-26T17:39:53.913000+00:00', 'referenced_message': None, 'pinned': False, 'nonce': '968567108596137984', 'mentions': [], 'mention_roles': [], 'mention_everyone': False, 'member': {'roles': ['[redacted]'], 'mute': False, 'joined_at': '2021-10-08T01:35:51.577000+00:00', 'hoisted_role': None, 'flags': 0, 'deaf': False}, 'id': '[redacted]', 'flags': 0, 'embeds': [], 'edited_timestamp': None, 'content': 'test', 'components': [], 'channel_id': '[redacted]', 'author': {'username': '[redacted]', 'public_flags': 0, 'id': '[reacted]', 'discriminator': '[redacted]', 'avatar_decoration': None, 'avatar': '8f6be73f6c4854b0785fff75adf80076'}, 'attachments': [], 'guild_id': '[redacted]'}}
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:39:53 discord.client       DEBUG    Dispatching event message
2022-04-26 10:39:54 discord.http         DEBUG    POST https://discord.com/api/v9/channels/[redacted]/thread-members/@me with None has returned 204
2022-04-26 10:39:54 discord.http         DEBUG    POST https://discord.com/api/v9/channels/[redacted]/thread-members/@me has received 
2022-04-26 10:39:54 bot.events.threads DEBUG    >>> THREAD_MEMBER_JOIN: Joined thread 'test' ([redacted])
2022-04-26 10:39:54 bot.events.threads DEBUG    >>> THREAD_MEMBER_JOIN: Cached thread details; 'test' ([redacted]); thread.me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[]
2022-04-26 10:39:58 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'THREAD_MEMBERS_UPDATE', 's': 21, 'op': 0, 'd': {'removed_member_ids': ['897100000000000000'], 'member_count': 2, 'id': '[redacted]', 'guild_id': '[redacted]'}}
2022-04-26 10:39:58 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:39:58 discord.client       DEBUG    Dispatching event thread_remove
2022-04-26 10:39:58 bot.events.threads DEBUG    !!! Handling thread_remove event
2022-04-26 10:39:58 bot.events.threads DEBUG    >>> THREAD_REMOVE: Event before payload; 'test' ([redacted]); me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[]
2022-04-26 10:39:58 bot.events.threads DEBUG    >>> THREAD_REMOVE: Cached thread details; 'test' ([redacted]); thread.me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[]
2022-04-26 10:39:58 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'MESSAGE_CREATE', 's': 22, 'op': 0, 'd': {'type': 2, 'tts': False, 'timestamp': '2022-04-26T17:39:58.639000+00:00', 'pinned': False, 'mentions': [{'username': 'gay bot', 'public_flags': 0, 'member': {'roles': ['[redacted]', '[redacted]'], 'mute': False, 'joined_at': '2022-04-21T02:55:43.620000+00:00', 'hoisted_role': '[redacted]', 'flags': 1, 'deaf': False}, 'id': '897100000000000000', 'discriminator': '[redacted]', 'bot': True, 'avatar_decoration': None, 'avatar': '39801670320babab422e028653bd7225'}], 'mention_roles': [], 'mention_everyone': False, 'member': {'roles': ['[redacted]'], 'mute': False, 'joined_at': '2021-10-08T01:35:51.577000+00:00', 'hoisted_role': None, 'flags': 0, 'deaf': False}, 'id': '[redacted]', 'flags': 0, 'embeds': [], 'edited_timestamp': None, 'content': '', 'components': [], 'channel_id': '[redacted]', 'author': {'username': '[redacted]', 'public_flags': 0, 'id': '[redacted]', 'discriminator': '[redacted]', 'avatar_decoration': None, 'avatar': '8f6be73f6c4854b0785fff75adf80076'}, 'attachments': [], 'guild_id': '[redacted]'}}
2022-04-26 10:39:58 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:39:58 discord.client       DEBUG    Dispatching event message
2022-04-26 10:40:02 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'THREAD_UPDATE', 's': 23, 'op': 0, 'd': {'type': 11, 'thread_metadata': {'locked': False, 'create_timestamp': '2022-04-26T17:39:53.535000+00:00', 'auto_archive_duration': 10080, 'archived': True, 'archive_timestamp': '2022-04-26T17:40:02.737778+00:00'}, 'rate_limit_per_user': 0, 'parent_id': '[redacted]', 'owner_id': '[redacted]', 'name': 'test', 'message_count': 2, 'member_count': 2, 'last_message_id': '[redacted]', 'id': '[redacted]', 'guild_id': '[redacted]', 'flags': 0}}
2022-04-26 10:40:02 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:40:02 discord.client       DEBUG    Dispatching event thread_update
2022-04-26 10:40:02 bot.events.threads DEBUG    !!! Handling thread_update event
2022-04-26 10:40:02 bot.events.threads DEBUG    >>> THREAD_UPDATE: Event before payload; 'test' ([redacted]); archived=False, Thread.members:List[ThreadMember]=[], Thread.members:List[Member]=[]
2022-04-26 10:40:02 bot.events.threads DEBUG    >>> THREAD_UPDATE: Event after payload; 'test' ([redacted]); archived=True, Thread.members:List[ThreadMember]=[], Thread.members:List[Member]=[]
2022-04-26 10:40:02 bot.events.threads DEBUG    >>> THREAD_UPDATE: Cached thread details; 'test' ([redacted]); thread.me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[]
2022-04-26 10:40:05 discord.gateway      DEBUG    For Shard ID None: WebSocket Event: {'t': 'THREAD_UPDATE', 's': 24, 'op': 0, 'd': {'type': 11, 'thread_metadata': {'locked': False, 'create_timestamp': '2022-04-26T17:39:53.535000+00:00', 'auto_archive_duration': 10080, 'archived': False, 'archive_timestamp': '2022-04-26T17:40:04.983287+00:00'}, 'rate_limit_per_user': 0, 'parent_id': '[redacted]', 'owner_id': '[redacted]', 'name': 'test', 'message_count': 2, 'member_count': 2, 'last_message_id': '[redacted]', 'id': '[redacted]', 'guild_id': '[redacted]', 'flags': 0}}
2022-04-26 10:40:05 discord.client       DEBUG    Dispatching event socket_event_type
2022-04-26 10:40:05 discord.client       DEBUG    Dispatching event thread_update
2022-04-26 10:40:05 bot.events.threads DEBUG    !!! Handling thread_update event
2022-04-26 10:40:05 bot.events.threads DEBUG    >>> THREAD_UPDATE: Event before payload; 'test' ([redacted]); archived=True, Thread.members:List[ThreadMember]=[], Thread.members:List[Member]=[]
2022-04-26 10:40:05 bot.events.threads DEBUG    >>> THREAD_UPDATE: Event after payload; 'test' ([redacted]); archived=False, Thread.members:List[ThreadMember]=[], Thread.members:List[Member]=[]
2022-04-26 10:40:05 bot.events.threads DEBUG    >>> THREAD_UPDATE: Cached thread details; 'test' ([redacted]); thread.me=<ThreadMember id=897100000000000000 thread_id=[redacted] joined_at=datetime.datetime(2022, 4, 26, 17, 39, 53, 846437, tzinfo=datetime.timezone.utc)>, Thread.members:List[ThreadMember]=[]
```

There are other events that are impacted by the same issue outlined here, as can be seen from the log output above. I believe y'all are aware of this behavior, in part, as [it's documented](https://docs.pycord.dev/en/master/api.html#discord.Thread.members) that, most of the time, `Thread.members` is empty due to the gateway not returning anything.

Minimally, I'd like to see the documentation updated for [`Thread.me`](https://docs.pycord.dev/en/master/api.html#discord.Thread.me). It's misleading, saying that it might not be available, but not that it might be _wrong_. Ideally, the framework would call `Thread.fetch_members()` to populate these properties with correct information.


Discussion:

Resolving patch:
diff --git a/discord/state.py b/discord/state.py
--- a/discord/state.py
+++ b/discord/state.py
@@ -43,6 +43,8 @@
     Union,
 )
 
+import discord
+
 from . import utils
 from .activity import BaseActivity
 from .audit_logs import AuditLogEntry
@@ -976,14 +978,27 @@ def parse_thread_create(self, data) -> None:
             )
             return
 
-        thread = Thread(guild=guild, state=guild._state, data=data)
-        has_thread = guild.get_thread(thread.id)
-        guild._add_thread(thread)
-        if not has_thread:
+        cached_thread = guild.get_thread(int(data["id"]))
+        if not cached_thread:
+            thread = Thread(guild=guild, state=guild._state, data=data)
+            guild._add_thread(thread)
             if data.get("newly_created"):
+                thread._add_member(
+                    ThreadMember(
+                        thread,
+                        {
+                            "id": thread.id,
+                            "user_id": data["owner_id"],
+                            "join_timestamp": data["thread_metadata"][
+                                "create_timestamp"
+                            ],
+                            "flags": utils.MISSING,
+                        },
+                    )
+                )
                 self.dispatch("thread_create", thread)
-            else:
-                self.dispatch("thread_join", thread)
+        else:
+            self.dispatch("thread_join", cached_thread)
 
     def parse_thread_update(self, data) -> None:
         guild_id = int(data["guild_id"])
@@ -1095,6 +1110,7 @@ def parse_thread_member_update(self, data) -> None:
 
         member = ThreadMember(thread, data)
         thread.me = member
+        thread._add_member(member)
 
     def parse_thread_members_update(self, data) -> None:
         guild_id = int(data["guild_id"])
@@ -1123,20 +1139,21 @@ def parse_thread_members_update(self, data) -> None:
         removed_member_ids = [int(x) for x in data.get("removed_member_ids", [])]
         self_id = self.self_id
         for member in added_members:
+            thread._add_member(member)
             if member.id != self_id:
-                thread._add_member(member)
                 self.dispatch("thread_member_join", member)
             else:
                 thread.me = member
                 self.dispatch("thread_join", thread)
 
         for member_id in removed_member_ids:
+            member = thread._pop_member(member_id)
             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:
+                thread.me = None
                 self.dispatch("thread_remove", thread)
 
     def parse_guild_member_add(self, data) -> None:
diff --git a/discord/threads.py b/discord/threads.py
--- a/discord/threads.py
+++ b/discord/threads.py
@@ -288,7 +288,7 @@ def jump_url(self) -> str:
 
     @property
     def members(self) -> list[ThreadMember]:
-        """A list of thread members in this thread.
+        """A list of thread members in this thread, including the bot if it is a member of this thread.
 
         This requires :attr:`Intents.members` to be properly filled. Most of the time however,
         this data is not provided by the gateway and a call to :meth:`fetch_members` is


Test patch: