diff --git a/discord/client.py b/discord/client.py index 383ab54dc..2a04bb288 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 51e5670bc..8ddc9f0f9 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 7c15020d7..62e41e4d2 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 -----------------