aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2015-10-15 01:02:15 -0400
committerRapptz <[email protected]>2015-10-15 01:37:55 -0400
commitab2512785b16d76a78f33e61a60ce90a2b225233 (patch)
treee18c594f06cea4d8eddca171da967944133e1306
parentHandle GUILD_ROLE_UPDATE websocket events. (diff)
downloaddiscord.py-ab2512785b16d76a78f33e61a60ce90a2b225233.tar.xz
discord.py-ab2512785b16d76a78f33e61a60ce90a2b225233.zip
Handle VOICE_STATE_UPDATE websocket events.
This adds a lot of new attributes into the Member class such as giving a voice_channel that the user is currently connected to. Initially there was a plan to have a voice_members attribute in the Channel class but this proved to be difficult when it came to actually removing users from the voice channel as the response would return channel_id as null. Fixes #16.
-rw-r--r--discord/client.py19
-rw-r--r--discord/server.py26
-rw-r--r--docs/api.rst12
3 files changed, 54 insertions, 3 deletions
diff --git a/discord/client.py b/discord/client.py
index 383ab54d..2a04bb28 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -115,7 +115,7 @@ class WebSocket(WebSocketBaseClient):
'GUILD_MEMBER_ADD', 'GUILD_MEMBER_REMOVE',
'GUILD_MEMBER_UPDATE', 'GUILD_CREATE', 'GUILD_DELETE',
'GUILD_ROLE_CREATE', 'GUILD_ROLE_DELETE',
- 'GUILD_ROLE_UPDATE'):
+ 'GUILD_ROLE_UPDATE', 'VOICE_STATE_UPDATE'):
self.dispatch('socket_update', event, data)
else:
@@ -137,6 +137,15 @@ class ConnectionState(object):
def _get_server(self, guild_id):
return utils.find(lambda g: g.id == guild_id, self.servers)
+ def _update_voice_state(self, server, data):
+ user_id = data.get('user_id')
+ member = utils.find(lambda m: m.id == user_id, server.members)
+ if member is not None:
+ ch_id = data.get('channel_id')
+ channel = utils.find(lambda c: c.id == ch_id, server.channels)
+ member.update_voice_state(voice_channel=channel, **data)
+ return member
+
def _add_server(self, guild):
guild['roles'] = [Role(**role) for role in guild['roles']]
members = guild['members']
@@ -170,6 +179,8 @@ class ConnectionState(object):
channels = [Channel(server=server, **channel)
for channel in guild['channels']]
server.channels = channels
+ for obj in guild.get('voice_states', []):
+ self._update_voice_state(server, obj)
self.servers.append(server)
def handle_ready(self, data):
@@ -332,6 +343,12 @@ class ConnectionState(object):
role.update(**data['role'])
self.dispatch('server_role_update', role)
+ def handle_voice_state_update(self, data):
+ server = self._get_server(data.get('guild_id'))
+ if server is not None:
+ updated_member = self._update_voice_state(server, data)
+ self.dispatch('voice_state_update', updated_member)
+
def get_channel(self, id):
if id is None:
return None
diff --git a/discord/server.py b/discord/server.py
index 51e5670b..8ddc9f0f 100644
--- a/discord/server.py
+++ b/discord/server.py
@@ -88,10 +88,23 @@ class Member(User):
.. attribute:: deaf
- Specifies if the member is currently deafened by the user.
+ A boolean that specifies if the member is currently deafened by the server.
.. attribute:: mute
- Specifies if the member is currently muted by the user.
+ A boolean that specifies if the member is currently muted by the server.
+ .. attribute:: self_mute
+
+ A boolean that specifies if the member is currently muted by their own accord.
+ .. attribute:: self_deaf
+
+ A boolean that specifies if the member is currently deafened by their own accord.
+ .. attribute:: is_afk
+
+ A boolean that specifies if the member is currently in the AFK channel in the server.
+ .. attribute:: voice_channel
+
+ A voice :class:`Channel` that the member is currently connected to. None if the member
+ is not currently in a voice channel.
.. attribute:: roles
An array of :class:`Role` that the member belongs to.
@@ -119,6 +132,15 @@ class Member(User):
self.status = 'offline'
self.game_id = kwargs.get('game_id', None)
self.server = kwargs.get('server', None)
+ self.update_voice_state(mute=mute, deaf=deaf)
+
+ def update_voice_state(self, **kwargs):
+ self.self_mute = kwargs.get('self_mute', False)
+ self.self_deaf = kwargs.get('self_deaf', False)
+ self.is_afk = kwargs.get('suppress', False)
+ self.mute = kwargs.get('mute', False)
+ self.deaf = kwargs.get('deaf', False)
+ self.voice_channel = kwargs.get('voice_channel')
class Server(object):
"""Represents a Discord server.
diff --git a/docs/api.rst b/docs/api.rst
index 7c15020d..62e41e4d 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -174,6 +174,18 @@ to handle it, which defaults to log a traceback and ignore the exception.
:param role: The :class:`Role` that was updated.
+.. function:: on_voice_state_update(member)
+
+ Called when a :class:`Member` changes their voice state.
+
+ The following, but not limited to, examples illustrate when this event is called:
+
+ - A member joins a voice room.
+ - A member leaves a voice room.
+ - A member is muted or deafened by their own accord.
+ - A member is muted or deafened by a server administrator.
+
+ :param member: The :class:`Member` whose voice state changed.
Utility Functions
-----------------