Begin working on the rewrite.

This commit is contained in:
Rapptz
2016-10-09 01:05:07 -04:00
parent 643950abf8
commit 044b0824e6
11 changed files with 318 additions and 239 deletions

View File

@@ -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: