From 0e4ccad32ae45a660d0670548e70299a416c5f78 Mon Sep 17 00:00:00 2001 From: Rapptz Date: Wed, 26 Aug 2015 21:20:18 -0400 Subject: [PATCH] Parse permission_overwrites in every Channel instance. --- discord/channel.py | 7 ++++++- discord/client.py | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index 734ad64a5..a7f04ad7d 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -46,15 +46,20 @@ class Channel(object): .. attribute:: type The channel type. Usually ``'voice'`` or ``'text'``. + .. attribute:: changed_roles + + An array of :class:`Roles` that have been overridden from their default + values in the :attr:`Server.roles` attribute. """ - def __init__(self, name, server, id, position, type, **kwargs): + def __init__(self, name, server, id, position, type, permission_overwrites=None, **kwargs): self.name = name self.server = server self.id = id self.is_private = False self.position = position self.type = type + self.changed_roles = permission_overwrites if permission_overwrites is not None else [] class PrivateChannel(object): """Represents a Discord private channel. diff --git a/discord/client.py b/discord/client.py index d2a1abe16..f3d12b078 100644 --- a/discord/client.py +++ b/discord/client.py @@ -151,9 +151,37 @@ class Client(object): guild['roles'] = [Role(**role) for role in guild['roles']] guild['members'] = [Member(**member) for member in guild['members']] - self.servers.append(Server(**guild)) - channels = [Channel(server=self.servers[-1], **channel) for channel in guild['channels']] - self.servers[-1].channels = channels + server = Server(**guild) + for channel in guild['channels']: + changed_roles = [] + permission_overwrites = channel['permission_overwrites'] + + for overridden in permission_overwrites: + # this is pretty inefficient due to the deep nested loops unfortunately + role = next((role for role in guild['roles'] if role.id == overridden['id']), None) + if role is None: + continue + denied = overridden.get('deny', 0) + allowed = overridden.get('allow', 0) + override = copy.deepcopy(role) + + # Basically this is what's happening here. + # We have an original bit array, e.g. 1010 + # Then we have another bit array that is 'denied', e.g. 1111 + # And then we have the last one which is 'allowed', e.g. 0101 + # We want original OP denied to end up resulting in whatever is in denied to be set to 0. + # So 1010 OP 1111 -> 0000 + # Then we take this value and look at the allowed values. And whatever is allowed is set to 1. + # So 0000 OP2 0101 -> 0101 + # The OP is (base ^ denied) & ~denied. + # The OP2 is base | allowed. + override.permissions.value = ((override.permissions.value ^ denied) & ~denied) | allowed + changed_roles.append(override) + + channel['permission_overwrites'] = changed_roles + channels = [Channel(server=server, **channel) for channel in guild['channels']] + server.channels = channels + self.servers.append(server) for pm in data.get('private_channels'): self.private_channels.append(PrivateChannel(id=pm['id'], user=User(**pm['recipient'])))