diff --git a/discord/enums.py b/discord/enums.py index d51d7ce21..0cd57341b 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -794,11 +794,6 @@ class RelationshipAction(Enum): remove_pending_request = 'remove' -class UnavailableGuildType(Enum): - existing = 'ready' - joined = 'joined' - - class RequiredActionType(Enum): update_agreements = 'AGREEMENTS' acknowledge_tos_update = 'TOS_UPDATE_ACKNOWLEDGMENT' diff --git a/discord/state.py b/discord/state.py index 9fc2ffbac..622683c12 100644 --- a/discord/state.py +++ b/discord/state.py @@ -72,7 +72,6 @@ from .enums import ( RequiredActionType, Status, try_enum, - UnavailableGuildType, ) from . import utils from .flags import MemberCacheFlags @@ -607,8 +606,6 @@ class ConnectionState: self._emojis: Dict[int, Emoji] = {} self._stickers: Dict[int, GuildSticker] = {} self._guilds: Dict[int, Guild] = {} - self._queued_guilds: Dict[int, Guild] = {} - self._unavailable_guilds: Dict[int, UnavailableGuildType] = {} self._calls: Dict[int, Call] = {} self._call_message_cache: Dict[int, Message] = {} # Hopefully this won't be a memory leak @@ -774,10 +771,7 @@ class ConnectionState: def _get_guild(self, guild_id: Optional[int]) -> Optional[Guild]: # The keys of self._guilds are ints - guild = self._guilds.get(guild_id) # type: ignore - if guild is None: - guild = self._queued_guilds.get(guild_id) # type: ignore - return guild + return self._guilds.get(guild_id) # type: ignore def _get_or_create_unavailable_guild(self, guild_id: int) -> Guild: return self._guilds.get(guild_id) or Guild._create_unavailable(state=self, guild_id=guild_id) @@ -857,21 +851,13 @@ class ConnectionState: else utils.find(lambda m: m.id == msg_id, reversed(self._call_message_cache.values())) ) - def _add_guild_from_data(self, data: GuildPayload, *, from_ready: bool = False) -> Optional[Guild]: - guild_id = int(data['id']) - unavailable = data.get('unavailable', False) - - if not unavailable: - guild = Guild(data=data, state=self) - self._add_guild(guild) - return guild - else: - self._unavailable_guilds[guild_id] = UnavailableGuildType.existing if from_ready else UnavailableGuildType.joined - _log.debug('Forcing GUILD_CREATE for unavailable guild %s.' % guild_id) - asyncio.ensure_future(self.request_guild(guild_id), loop=self.loop) + def _add_guild_from_data(self, data: GuildPayload) -> Optional[Guild]: + guild = Guild(data=data, state=self) + self._add_guild(guild) + return guild def _guild_needs_chunking(self, guild: Guild) -> bool: - return self._chunk_guilds and not guild.chunked and not guild._offline_members_hidden + return self._chunk_guilds and not guild.chunked and not guild._offline_members_hidden and not guild.unavailable def _get_guild_channel( self, data: PartialMessagePayload, guild_id: Optional[int] = None @@ -1010,7 +996,7 @@ class ConnectionState: # Guild parsing for guild_data in data.get('guilds', []): - self._add_guild_from_data(guild_data, from_ready=True) + self._add_guild_from_data(guild_data) # Relationship parsing for relationship in data.get('relationships', []): @@ -1083,6 +1069,7 @@ class ConnectionState: if 'last_pin_timestamp' in channel_data and hasattr(channel, 'last_pin_timestamp'): channel.last_pin_timestamp = utils.parse_time(channel_data['last_pin_timestamp']) # type: ignore + # Apparently, voice states not being in the payload means there are no longer any voice states guild._voice_states = {} members = {int(m['user']['id']): m for m in data.get('members', [])} for voice_state in data.get('voice_states', []): @@ -1093,10 +1080,7 @@ class ConnectionState: guild._update_voice_state(voice_state, utils._get_as_snowflake(voice_state, 'channel_id')) def parse_message_create(self, data: gw.MessageCreateEvent) -> None: - guild_id = utils._get_as_snowflake(data, 'guild_id') channel, _ = self._get_guild_channel(data) - if guild_id in self._unavailable_guilds: # I don't know how I feel about this :( - return # channel will be the correct type here message = Message(channel=channel, data=data, state=self) # type: ignore @@ -1685,8 +1669,6 @@ class ConnectionState: for message in data.get('most_recent_messages', []): guild_id = utils._get_as_snowflake(message, 'guild_id') channel, _ = self._get_guild_channel(message) - if guild_id in self._unavailable_guilds: # I don't know how I feel about this :( - continue # channel will be the correct type here message = Message(channel=channel, data=message, state=self) @@ -2070,15 +2052,19 @@ class ConnectionState: execution = AutoModAction(data=data, state=self) self.dispatch('automod_action', execution) - def _get_create_guild(self, data: gw.GuildCreateEvent): + def _get_create_guild(self, data: gw.GuildCreateEvent) -> Optional[Guild]: guild = self._get_guild(int(data['id'])) + unavailable = data.get('unavailable') + # Discord being Discord sometimes sends a GUILD_CREATE after an OPCode 14 is sent (a la bots) - # However, we want that if we forced a GUILD_CREATE for an unavailable guild + # In this case, we just update it and return None to avoid a double dispatch + # However, if the guild became available, then we gotta go through the motions if guild is not None: guild._from_data(data) - return + if unavailable != False: + return - return self._add_guild_from_data(data) + return guild or self._add_guild_from_data(data) def is_guild_evicted(self, guild: Guild) -> bool: return guild.id not in self._guilds @@ -2212,9 +2198,7 @@ class ConnectionState: return await request.wait() return request.get_future() - async def _chunk_and_dispatch(self, guild, chunk) -> None: - self._queued_guilds[guild.id] = guild - + async def _chunk_and_dispatch(self, guild: Guild, chunk: bool, unavailable: Optional[bool]) -> None: if chunk: try: await asyncio.wait_for(self.chunk_guild(guild), timeout=10) @@ -2223,15 +2207,8 @@ class ConnectionState: except (ClientException, InvalidData): pass - self._queued_guilds.pop(guild.id) - - # Dispatch available/join depending on circumstances - if guild.id in self._unavailable_guilds: - type = self._unavailable_guilds.pop(guild.id) - if type is UnavailableGuildType.existing: - self.dispatch('guild_available', guild) - else: - self.dispatch('guild_join', guild) + if unavailable is False: + self.dispatch('guild_available', guild) else: self.dispatch('guild_join', guild) @@ -2243,12 +2220,12 @@ class ConnectionState: if guild is None: return - if self._request_guilds: + if self._request_guilds and not guild.unavailable: asyncio.ensure_future(self.request_guild(guild.id), loop=self.loop) # Chunk if needed needs_chunking = self._guild_needs_chunking(guild) - asyncio.ensure_future(self._chunk_and_dispatch(guild, needs_chunking), loop=self.loop) + asyncio.ensure_future(self._chunk_and_dispatch(guild, needs_chunking, data.get('unavailable')), loop=self.loop) def parse_guild_update(self, data: gw.GuildUpdateEvent) -> None: guild = self._get_guild(int(data['id']))