mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-06-07 12:18:59 +00:00
Fix long-standing issue with user updates not dispatching properly.
This fix is long coming. For a long time due to the addition of a global user cache, the on_member_update event would only have the updated user in the very first dispatch due to a quirk in the reference only being updated once. In order to fix this issue two things had to change: 1. There had to be a new event, `on_user_update` to complement the equivalent member event. 2. Unnecessary copies of User had to be removed to compensate for the performance hit from the diffing. While doing these two fixes I also re-evaluated some more unnecessary copies done during the PRESENCE_UPDATE to add member case while fetch_offline_members=False is set or due to chunking issues. The number of copies was brought down from 2 to 1, discounting the original Member creation. Unsure on the benefits of this one, however. N.B: this doesn't change the pre-existing behaviour of on_member_update
This commit is contained in:
parent
1a9726087a
commit
f8999b63ae
@ -189,6 +189,17 @@ class Member(discord.abc.Messageable, _BaseUser):
|
|||||||
}
|
}
|
||||||
return cls(data=data, guild=message.guild, state=message._state)
|
return cls(data=data, guild=message.guild, state=message._state)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _from_presence_update(cls, *, data, guild, state):
|
||||||
|
clone = cls(data=data, guild=guild, state=state)
|
||||||
|
to_return = cls(data=data, guild=guild, state=state)
|
||||||
|
to_return._client_status = {
|
||||||
|
key: value
|
||||||
|
for key, value in data.get('client_status', {}).items()
|
||||||
|
}
|
||||||
|
to_return._client_status[None] = data['status']
|
||||||
|
return to_return, clone
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _copy(cls, member):
|
def _copy(cls, member):
|
||||||
self = cls.__new__(cls) # to bypass __init__
|
self = cls.__new__(cls) # to bypass __init__
|
||||||
@ -200,7 +211,10 @@ class Member(discord.abc.Messageable, _BaseUser):
|
|||||||
self.nick = member.nick
|
self.nick = member.nick
|
||||||
self.activities = member.activities
|
self.activities = member.activities
|
||||||
self._state = member._state
|
self._state = member._state
|
||||||
self._user = User._copy(member._user)
|
|
||||||
|
# Reference will not be copied unless necessary by PRESENCE_UPDATE
|
||||||
|
# See below
|
||||||
|
self._user = member._user
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def _get_channel(self):
|
async def _get_channel(self):
|
||||||
@ -230,9 +244,15 @@ class Member(discord.abc.Messageable, _BaseUser):
|
|||||||
|
|
||||||
if len(user) > 1:
|
if len(user) > 1:
|
||||||
u = self._user
|
u = self._user
|
||||||
u.name = user.get('username', u.name)
|
original = (u.name, u.avatar, u.discriminator)
|
||||||
u.avatar = user.get('avatar', u.avatar)
|
# These keys seem to always be available
|
||||||
u.discriminator = user.get('discriminator', u.discriminator)
|
modified = (user['username'], user['avatar'], user['discriminator'])
|
||||||
|
if original != modified:
|
||||||
|
to_return = User._copy(self._user)
|
||||||
|
u.name, u.avatar, u.discriminator = modified
|
||||||
|
# Signal to dispatch on_user_update
|
||||||
|
return to_return, u
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def status(self):
|
def status(self):
|
||||||
|
@ -461,11 +461,14 @@ class ConnectionState:
|
|||||||
# skip these useless cases.
|
# skip these useless cases.
|
||||||
return
|
return
|
||||||
|
|
||||||
member = Member(guild=guild, data=data, state=self)
|
member, old_member = Member._from_presence_update(guild=guild, data=data, state=self)
|
||||||
guild._add_member(member)
|
guild._add_member(member)
|
||||||
|
else:
|
||||||
|
old_member = Member._copy(member)
|
||||||
|
user_update = member._presence_update(data=data, user=user)
|
||||||
|
if user_update:
|
||||||
|
self.dispatch('user_update', user_update[0], user_update[1])
|
||||||
|
|
||||||
old_member = Member._copy(member)
|
|
||||||
member._presence_update(data=data, user=user)
|
|
||||||
self.dispatch('member_update', old_member, member)
|
self.dispatch('member_update', old_member, member)
|
||||||
|
|
||||||
def parse_user_update(self, data):
|
def parse_user_update(self, data):
|
||||||
|
14
docs/api.rst
14
docs/api.rst
@ -439,13 +439,25 @@ to handle it, which defaults to print a traceback and ignoring the exception.
|
|||||||
|
|
||||||
- status
|
- status
|
||||||
- game playing
|
- game playing
|
||||||
- avatar
|
|
||||||
- nickname
|
- nickname
|
||||||
- roles
|
- roles
|
||||||
|
|
||||||
:param before: The :class:`Member` that updated their profile with the old info.
|
:param before: The :class:`Member` that updated their profile with the old info.
|
||||||
:param after: The :class:`Member` that updated their profile with the updated info.
|
:param after: The :class:`Member` that updated their profile with the updated info.
|
||||||
|
|
||||||
|
.. function:: on_user_update(before, after)
|
||||||
|
|
||||||
|
Called when a :class:`User` updates their profile.
|
||||||
|
|
||||||
|
This is called when one or more of the following things change:
|
||||||
|
|
||||||
|
- avatar
|
||||||
|
- username
|
||||||
|
- discriminator
|
||||||
|
|
||||||
|
:param before: The :class:`User` that updated their profile with the old info.
|
||||||
|
:param after: The :class:`User` that updated their profile with the updated info.
|
||||||
|
|
||||||
.. function:: on_guild_join(guild)
|
.. function:: on_guild_join(guild)
|
||||||
|
|
||||||
Called when a :class:`Guild` is either created by the :class:`Client` or when the
|
Called when a :class:`Guild` is either created by the :class:`Client` or when the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user