aboutsummaryrefslogtreecommitdiff
path: root/discord/member.py
diff options
context:
space:
mode:
authorRapptz <[email protected]>2016-10-09 01:05:07 -0400
committerRapptz <[email protected]>2017-01-03 09:51:47 -0500
commit044b0824e68c4dacdaf26ff52a741ca1b5118c9b (patch)
tree2a275b35bd51fbb29c455eda804ab130e9b3b425 /discord/member.py
parentAdd ability to set opus encoder input signal type. (diff)
downloaddiscord.py-044b0824e68c4dacdaf26ff52a741ca1b5118c9b.tar.xz
discord.py-044b0824e68c4dacdaf26ff52a741ca1b5118c9b.zip
Begin working on the rewrite.
Diffstat (limited to 'discord/member.py')
-rw-r--r--discord/member.py130
1 files changed, 113 insertions, 17 deletions
diff --git a/discord/member.py b/discord/member.py
index 50ad184a..4d0f86b9 100644
--- a/discord/member.py
+++ b/discord/member.py
@@ -28,9 +28,11 @@ from .user import User
from .game import Game
from .permissions import Permissions
from . import utils
-from .enums import Status, ChannelType
+from .enums import Status, ChannelType, try_enum
from .colour import Colour
+
import copy
+import inspect
class VoiceState:
"""Represents a Discord user's voice state.
@@ -52,8 +54,8 @@ class VoiceState:
is not currently in a voice channel.
"""
- __slots__ = [ 'session_id', 'deaf', 'mute', 'self_mute',
- 'self_deaf', 'is_afk', 'voice_channel' ]
+ __slots__ = ( 'session_id', 'deaf', 'mute', 'self_mute',
+ 'self_deaf', 'is_afk', 'voice_channel' )
def __init__(self, **kwargs):
self.session_id = kwargs.get('session_id')
@@ -74,12 +76,57 @@ def flatten_voice_states(cls):
setattr(cls, attr, property(getter))
return cls
+def flatten_user(cls):
+ for attr, value in User.__dict__.items():
+ # ignore private/special methods
+ if attr.startswith('_'):
+ continue
+
+ # don't override what we already have
+ if attr in cls.__dict__:
+ continue
+
+ # if it's a slotted attribute or a property, redirect it
+ # slotted members are implemented as member_descriptors in Type.__dict__
+ if hasattr(value, '__get__'):
+ def getter(self, x=attr):
+ return getattr(self._user, x)
+ setattr(cls, attr, property(getter, doc='Equivalent to :attr:`User.%s`' % attr))
+ else:
+ # probably a member function by now
+ def generate_function(x):
+ def general(self, *args, **kwargs):
+ return getattr(self._user, x)(*args, **kwargs)
+
+ general.__name__ = x
+ return general
+
+ func = generate_function(attr)
+ func.__doc__ = value.__doc__
+ setattr(cls, attr, func)
+
+ return cls
+
@flatten_voice_states
-class Member(User):
+@flatten_user
+class Member:
"""Represents a Discord member to a :class:`Server`.
- This is a subclass of :class:`User` that extends more functionality
- that server members have such as roles and permissions.
+ This implements a lot of the functionality of :class:`User`.
+
+ Supported Operations:
+
+ +-----------+-----------------------------------------------+
+ | Operation | Description |
+ +===========+===============================================+
+ | x == y | Checks if two members are equal. |
+ +-----------+-----------------------------------------------+
+ | x != y | Checks if two members are not equal. |
+ +-----------+-----------------------------------------------+
+ | hash(x) | Return the member's hash. |
+ +-----------+-----------------------------------------------+
+ | str(x) | Returns the member's name with discriminator. |
+ +-----------+-----------------------------------------------+
Attributes
----------
@@ -103,18 +150,31 @@ class Member(User):
The server specific nickname of the user.
"""
- __slots__ = [ 'roles', 'joined_at', 'status', 'game', 'server', 'nick', 'voice' ]
+ __slots__ = ('roles', 'joined_at', 'status', 'game', 'server', 'nick', 'voice', '_user', '_state')
- def __init__(self, **kwargs):
- super().__init__(**kwargs.get('user'))
- self.voice = VoiceState(**kwargs)
- self.joined_at = utils.parse_time(kwargs.get('joined_at'))
- self.roles = kwargs.get('roles', [])
+ def __init__(self, *, data, server, state):
+ self._state = state
+ self._user = state.try_insert_user(data['user'])
+ self.voice = VoiceState(**data)
+ self.joined_at = utils.parse_time(data.get('joined_at'))
+ self.roles = data.get('roles', [])
self.status = Status.offline
- game = kwargs.get('game', {})
+ game = data.get('game', {})
self.game = Game(**game) if game else None
- self.server = kwargs.get('server', None)
- self.nick = kwargs.get('nick', None)
+ self.server = server
+ self.nick = data.get('nick', None)
+
+ def __str__(self):
+ return self._user.__str__()
+
+ def __eq__(self, other):
+ return isinstance(other, Member) and other._user.id == self._user.id and self.server.id == other.server.id
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return hash(self._user.id)
def _update_voice_state(self, **kwargs):
self.voice.self_mute = kwargs.get('self_mute', False)
@@ -146,6 +206,35 @@ class Member(User):
ret.voice = copy.copy(self.voice)
return ret
+ def _update(self, data, user):
+ self._user.name = user['username']
+ self._user.discriminator = user['discriminator']
+ self._user.avatar = user['avatar']
+ self._user.bot = user.get('bot', False)
+
+ # the nickname change is optional,
+ # if it isn't in the payload then it didn't change
+ if 'nick' in data:
+ self.nick = data['nick']
+
+ # update the roles
+ self.roles = [self.server.default_role]
+ for role in self.server.roles:
+ if role.id in data['roles']:
+ self.roles.append(role)
+
+ # sort the roles by ID since they can be "randomised"
+ self.roles.sort(key=lambda r: int(r.id))
+
+ def _presence_update(self, data, user):
+ self.status = try_enum(Status, data['status'])
+ game = data.get('game', {})
+ self.game = Game(**game) if game else None
+ u = self._user
+ u.name = user.get('username', u.name)
+ u.avatar = user.get('avatar', u.avatar)
+ u.discriminator = user.get('discriminator', u.discriminator)
+
@property
def colour(self):
"""A property that returns a :class:`Colour` denoting the rendered colour
@@ -173,13 +262,20 @@ class Member(User):
@property
def mention(self):
+ """Returns a string that mentions the member."""
if self.nick:
return '<@!{}>'.format(self.id)
return '<@{}>'.format(self.id)
def mentioned_in(self, message):
- mentioned = super().mentioned_in(message)
- if mentioned:
+ """Checks if the member is mentioned in the specified message.
+
+ Parameters
+ -----------
+ message: :class:`Message`
+ The message to check if you're mentioned in.
+ """
+ if self._user.mentioned_in(message):
return True
for role in message.role_mentions: