def deserialize_integration_delete_event( self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject ) -> guild_events.IntegrationDeleteEvent: application_id: typing.Optional[snowflakes.Snowflake] = None if (raw_application_id := payload.get("application_id")) is not None: application_id = snowflakes.Snowflake(raw_application_id)
def deserialize_channel_pins_update_event( self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject ) -> channel_events.PinsUpdateEvent: channel_id = snowflakes.Snowflake(payload["channel_id"]) # Turns out this _can_ be None or not present. Only set it if it is actually available. if (raw := payload.get("last_pin_timestamp")) is not None: last_pin_timestamp: typing.Optional[datetime.datetime] = time.iso8601_datetime_string_to_datetime(raw)
async def on_guild_delete(self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None: """See https://discord.com/developers/docs/topics/gateway#guild-delete for more info.""" event: typing.Union[guild_events.GuildUnavailableEvent, guild_events.GuildLeaveEvent] if payload.get("unavailable", False): event = self._app.event_factory.deserialize_guild_unavailable_event( shard, payload) if self._cache: self._cache.set_guild_availability(event.guild_id, False) else: event = self._app.event_factory.deserialize_guild_leave_event( shard, payload) if self._cache: # TODO: this doesn't work in all intent scenarios self._cache.delete_guild(event.guild_id) self._cache.clear_voice_states_for_guild(event.guild_id) self._cache.clear_invites_for_guild(event.guild_id) self._cache.clear_members_for_guild(event.guild_id) self._cache.clear_presences_for_guild(event.guild_id) self._cache.clear_guild_channels_for_guild(event.guild_id) self._cache.clear_emojis_for_guild(event.guild_id) self._cache.clear_roles_for_guild(event.guild_id) await self.dispatch(event)
async def on_guild_delete(self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None: """See https://discord.com/developers/docs/topics/gateway#guild-delete for more info.""" if payload.get("unavailable", False): await self.dispatch( self._app.event_factory.deserialize_guild_unavailable_event( shard, payload)) else: await self.dispatch( self._app.event_factory.deserialize_guild_leave_event( shard, payload))
def deserialize_guild_member_chunk_event( self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> shard_events.MemberChunkEvent: guild_id = snowflakes.Snowflake(payload["guild_id"]) index = int(payload["chunk_index"]) count = int(payload["chunk_count"]) members = { snowflakes.Snowflake(m["user"]["id"]): self._app.entity_factory.deserialize_member(m, guild_id=guild_id) for m in payload["members"] } # Note, these IDs may be returned as ints or strings based on whether they're over a certain value. not_found = [snowflakes.Snowflake(sn) for sn in payload["not_found"] ] if "not_found" in payload else [] if presence_payloads := payload.get("presences"): presences = { snowflakes.Snowflake(p["user"]["id"]): self._app.entity_factory.deserialize_member_presence( p, guild_id=guild_id) for p in presence_payloads }
def _split_reaction_emoji( self, emoji_payload: data_binding.JSONObject, / ) -> typing.Tuple[typing.Optional[snowflakes.Snowflake], typing.Union[ str, emojis_models.UnicodeEmoji, None]]: if (emoji_id := emoji_payload.get("id")) is not None: return snowflakes.Snowflake(emoji_id), emoji_payload["name"]
async def on_guild_create( # noqa: C901 - Function too complex self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None: """See https://discord.com/developers/docs/topics/gateway#guild-create for more info.""" event: typing.Union[guild_events.GuildAvailableEvent, guild_events.GuildJoinEvent, None] if "unavailable" in payload and self._enabled_for_event( guild_events.GuildAvailableEvent): event = self._event_factory.deserialize_guild_available_event( shard, payload) elif "unavailable" not in payload and self._enabled_for_event( guild_events.GuildJoinEvent): event = self._event_factory.deserialize_guild_join_event( shard, payload) else: event = None if event: # We also filter here to prevent iterating over them and calling a function that won't do anything channels = event.channels if self._cache_enabled_for( config.CacheComponents.GUILD_CHANNELS) else None emojis = event.emojis if self._cache_enabled_for( config.CacheComponents.EMOJIS) else None guild = event.guild if self._cache_enabled_for( config.CacheComponents.GUILDS) else None guild_id = event.guild.id members = event.members if self._cache_enabled_for( config.CacheComponents.MEMBERS) else None presences = event.presences if self._cache_enabled_for( config.CacheComponents.PRESENCES) else None roles = event.roles if self._cache_enabled_for( config.CacheComponents.ROLES) else None voice_states = event.voice_states if self._cache_enabled_for( config.CacheComponents.VOICE_STATES) else None elif self._cache: _LOGGER.log( ux.TRACE, "Skipping on_guild_create dispatch due to lack of any registered listeners" ) gd = self._entity_factory.deserialize_gateway_guild(payload) channels = gd.channels() if self._cache_enabled_for( config.CacheComponents.GUILD_CHANNELS) else None emojis = gd.emojis() if self._cache_enabled_for( config.CacheComponents.EMOJIS) else None guild = gd.guild() if self._cache_enabled_for( config.CacheComponents.GUILDS) else None guild_id = gd.id members = gd.members() if self._cache_enabled_for( config.CacheComponents.MEMBERS) else None presences = gd.presences() if self._cache_enabled_for( config.CacheComponents.PRESENCES) else None roles = gd.roles() if self._cache_enabled_for( config.CacheComponents.ROLES) else None voice_states = gd.voice_states() if self._cache_enabled_for( config.CacheComponents.VOICE_STATES) else None else: _LOGGER.log( ux.TRACE, "Skipping on_guild_create raw dispatch due to lack of any registered listeners or cache need" ) channels = None emojis = None guild = None guild_id = snowflakes.Snowflake(payload["id"]) members = None presences = None roles = None voice_states = None if self._cache: if guild: self._cache.update_guild(guild) if channels: self._cache.clear_guild_channels_for_guild(guild_id) for channel in channels.values(): self._cache.set_guild_channel(channel) if emojis: self._cache.clear_emojis_for_guild(guild_id) for emoji in emojis.values(): self._cache.set_emoji(emoji) if roles: self._cache.clear_roles_for_guild(guild_id) for role in roles.values(): self._cache.set_role(role) if members: # TODO: do we really want to invalidate these all after an outage. self._cache.clear_members_for_guild(guild_id) for member in members.values(): self._cache.set_member(member) if presences: self._cache.clear_presences_for_guild(guild_id) for presence in presences.values(): self._cache.set_presence(presence) if voice_states: self._cache.clear_voice_states_for_guild(guild_id) for voice_state in voice_states.values(): self._cache.set_voice_state(voice_state) presences_declared = self._intents & intents_.Intents.GUILD_PRESENCES # When intents are enabled Discord will only send other member objects on the guild create # payload if presence intents are also declared, so if this isn't the case then we also want # to chunk small guilds. if (self._intents & intents_.Intents.GUILD_MEMBERS and (payload.get("large") or not presences_declared) and (self._cache_enabled_for(config.CacheComponents.MEMBERS) or self._enabled_for_event(shard_events.MemberChunkEvent))): # We create a task here instead of awaiting the result to avoid any rate-limits from delaying dispatch. nonce = f"{shard.id}.{_fixed_size_nonce()}" if event: event.chunk_nonce = nonce coroutine = _request_guild_members( shard, guild_id, include_presences=bool(presences_declared), nonce=nonce) asyncio.create_task( coroutine, name=f"{shard.id}:{guild_id} guild create members request") if event: await self.dispatch(event)