aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2017-08-21 10:40:24 -0400
committerRapptz <[email protected]>2017-08-21 10:40:33 -0400
commit84f38b166e3cc299f382cfb63a7ecb70d6feb672 (patch)
treeab4b3aad232981df74008d3183ae2fa2be5cb737
parentLazily fetch Emoji.roles and Emoji.guild to prevent memory leaks. (diff)
downloaddiscord.py-84f38b166e3cc299f382cfb63a7ecb70d6feb672.tar.xz
discord.py-84f38b166e3cc299f382cfb63a7ecb70d6feb672.zip
Add atomic keyword argument for member role editing operations.
This affects: * Member.add_roles * Member.remove_roles This is the main attempt of fixing long standing bugs like #56. Since cache consistency is too hard to ask for due to eventual consistency and this generally being one of the only main roadblocks that the cache ruins, it's best to just implement it in terms of the atomic endpoint instead. Fixes #56
-rw-r--r--discord/member.py44
1 files changed, 33 insertions, 11 deletions
diff --git a/discord/member.py b/discord/member.py
index df37ba34..e7ddce11 100644
--- a/discord/member.py
+++ b/discord/member.py
@@ -484,7 +484,7 @@ class Member(discord.abc.Messageable, _BaseUser):
yield from self.edit(voice_channel=channel, reason=reason)
@asyncio.coroutine
- def add_roles(self, *roles, reason=None):
+ def add_roles(self, *roles, reason=None, atomic=True):
"""|coro|
Gives the member a number of :class:`Role`\s.
@@ -499,6 +499,10 @@ class Member(discord.abc.Messageable, _BaseUser):
to give to the member.
reason: Optional[str]
The reason for adding these roles. Shows up on the audit log.
+ atomic: bool
+ Whether to atomically add roles. This will ensure that multiple
+ operations will always be applied regardless of the current
+ state of the cache.
Raises
-------
@@ -508,11 +512,18 @@ class Member(discord.abc.Messageable, _BaseUser):
Adding roles failed.
"""
- new_roles = utils._unique(Object(id=r.id) for s in (self.roles[1:], roles) for r in s)
- yield from self.edit(roles=new_roles, reason=reason)
+ if not atomic:
+ new_roles = utils._unique(Object(id=r.id) for s in (self.roles[1:], roles) for r in s)
+ yield from self.edit(roles=new_roles, reason=reason)
+ else:
+ req = self._state.http.add_role
+ guild_id = self.guild.id
+ user_id = self.id
+ for role in roles:
+ yield from req(guild_id, user_id, role.id, reason=reason)
@asyncio.coroutine
- def remove_roles(self, *roles, reason=None):
+ def remove_roles(self, *roles, reason=None, atomic=True):
"""|coro|
Removes :class:`Role`\s from this member.
@@ -527,6 +538,10 @@ class Member(discord.abc.Messageable, _BaseUser):
to remove from the member.
reason: Optional[str]
The reason for removing these roles. Shows up on the audit log.
+ atomic: bool
+ Whether to atomically add roles. This will ensure that multiple
+ operations will always be applied regardless of the current
+ state of the cache.
Raises
-------
@@ -536,11 +551,18 @@ class Member(discord.abc.Messageable, _BaseUser):
Removing the roles failed.
"""
- new_roles = [Object(id=r.id) for r in self.roles[1:]] # remove @everyone
- for role in roles:
- try:
- new_roles.remove(Object(id=role.id))
- except ValueError:
- pass
+ if not atomic:
+ new_roles = [Object(id=r.id) for r in self.roles[1:]] # remove @everyone
+ for role in roles:
+ try:
+ new_roles.remove(Object(id=role.id))
+ except ValueError:
+ pass
- yield from self.edit(roles=new_roles, reason=reason)
+ yield from self.edit(roles=new_roles, reason=reason)
+ else:
+ req = self._state.http.remove_role
+ guild_id = self.guild.id
+ user_id = self.id
+ for role in roles:
+ yield from req(guild_id, user_id, role.id, reason=reason)