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.
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								docs/api.rst
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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
 | 
			
		||||
-----------------
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user