diff --git a/disco/gateway/events.py b/disco/gateway/events.py index 9d9d323..d14a13d 100644 --- a/disco/gateway/events.py +++ b/disco/gateway/events.py @@ -153,6 +153,7 @@ class GuildCreate(GatewayEvent): and if None, this is a normal guild join event. """ unavailable = Field(bool) + presences = ListField(Presence) @property def created(self): diff --git a/disco/state.py b/disco/state.py index 2983aa0..560c34c 100644 --- a/disco/state.py +++ b/disco/state.py @@ -315,15 +315,30 @@ class State(object): self.guilds[event.guild_id].emojis = HashMap({i.id: i for i in event.emojis}) def on_presence_update(self, event): - if event.user.id in self.users: - self.users[event.user.id].update(event.presence.user) - self.users[event.user.id].presence = event.presence - event.presence.user = self.users[event.user.id] - - if event.guild_id not in self.guilds: + # Grab a copy of the user, and clear it out. All the operations below + # do not want the nested user object, as the normaly structure is + # user -> presence, and without clearing this becomes recursive + user = event.presence.user + user.presence = event.presence + event.presence.user = None + + # if we have the user tracked locally, we can just use the presence + # update to update both their presence and the cached user object. + if user.id in self.users: + self.users[user.id].update(user) + else: + # Otherwise this user does not exist in our local cache, so we can + # use this opportunity to add them. They will quickly fall out of + # scope and be deleted if they aren't used below + self.users[user.id] = user + + # Some updates come with a guild_id and roles the user is in, we should + # use this to update the guild member, but only if we have the guild + # cached. + if event.roles is UNSET or event.guild_id not in self.guilds: return - if event.user.id not in self.guilds[event.guild_id].members: + if user.id not in self.guilds[event.guild_id].members: return - self.guilds[event.guild_id].members[event.user.id].user.update(event.user) + self.guilds[event.guild_id].members[user.id].roles = event.roles diff --git a/disco/types/guild.py b/disco/types/guild.py index fb59ac5..10a0d6c 100644 --- a/disco/types/guild.py +++ b/disco/types/guild.py @@ -9,7 +9,7 @@ from disco.util.functional import cached_property from disco.types.base import ( SlottedModel, Field, ListField, AutoDictField, snowflake, text, binary, enum, datetime ) -from disco.types.user import User, Presence +from disco.types.user import User from disco.types.voice import VoiceState from disco.types.channel import Channel from disco.types.message import Emoji @@ -300,7 +300,6 @@ class Guild(SlottedModel, Permissible): emojis = AutoDictField(GuildEmoji, 'id') voice_states = AutoDictField(VoiceState, 'session_id') member_count = Field(int) - presences = ListField(Presence) synced = Field(bool, default=False)