diff options
| author | Rapptz <[email protected]> | 2016-04-29 05:48:48 -0400 |
|---|---|---|
| committer | Rapptz <[email protected]> | 2016-05-01 20:54:13 -0400 |
| commit | d9c780b8a8d479507cb517076c39d2020ea761a0 (patch) | |
| tree | e57d0382a248fe9aaa7564cff6bad93c65de21e2 /discord/client.py | |
| parent | Fix typo in Message.role_mentions documentation. (diff) | |
| download | discord.py-d9c780b8a8d479507cb517076c39d2020ea761a0.tar.xz discord.py-d9c780b8a8d479507cb517076c39d2020ea761a0.zip | |
Working multi-server voice support.
Diffstat (limited to 'discord/client.py')
| -rw-r--r-- | discord/client.py | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/discord/client.py b/discord/client.py index 4e364af9..3d7b8afa 100644 --- a/discord/client.py +++ b/discord/client.py @@ -90,10 +90,10 @@ class Client: ----------- user : Optional[:class:`User`] Represents the connected client. None if not logged in. - voice : Optional[:class:`VoiceClient`] - Represents the current voice connection. None if you are not connected - to a voice channel. To connect to voice use :meth:`join_voice_channel`. - To query the voice connection state use :meth:`is_voice_connected`. + voice_clients : iterable of :class:`VoiceClient` + Represents a list of voice connections. To connect to voice use + :meth:`join_voice_channel`. To query the voice connection state use + :meth:`is_voice_connected`. servers : iterable of :class:`Server` The servers that the connected client is a member of. private_channels : iterable of :class:`PrivateChannel` @@ -114,7 +114,6 @@ class Client: def __init__(self, *, loop=None, **options): self.ws = None self.token = None - self.voice = None self.loop = asyncio.get_event_loop() if loop is None else loop self._listeners = [] self.cache_auth = options.get('cache_auth', True) @@ -227,14 +226,14 @@ class Client: raise InvalidArgument('Destination must be Channel, PrivateChannel, User, or Object') def __getattr__(self, name): - if name in ('user', 'servers', 'private_channels', 'messages'): + if name in ('user', 'servers', 'private_channels', 'messages', 'voice_clients'): return getattr(self.connection, name) else: msg = "'{}' object has no attribute '{}'" raise AttributeError(msg.format(self.__class__, name)) def __setattr__(self, name, value): - if name in ('user', 'servers', 'private_channels', 'messages'): + if name in ('user', 'servers', 'private_channels', 'messages', 'voice_clients'): return setattr(self.connection, name, value) else: object.__setattr__(self, name, value) @@ -418,13 +417,13 @@ class Client: if self.is_closed: return - if self.is_voice_connected(): - yield from self.voice.disconnect() - self.voice = None - if self.ws is not None and self.ws.open: yield from self.ws.close() + for voice in list(self.voice_clients): + yield from voice.disconnect() + self.connection._remove_voice_client(voice.server.id) + yield from self.session.close() self._closed.set() self._is_ready.clear() @@ -2415,15 +2414,17 @@ class Client: :class:`VoiceClient` A voice client that is fully connected to the voice server. """ - if self.is_voice_connected(): - raise ClientException('Already connected to a voice channel') - if isinstance(channel, Object): channel = self.get_channel(channel.id) if getattr(channel, 'type', ChannelType.text) != ChannelType.voice: raise InvalidArgument('Channel passed must be a voice channel') + server = channel.server + + if self.is_voice_connected(server): + raise ClientException('Already connected to a voice channel in this server') + log.info('attempting to join voice channel {0.name}'.format(channel)) def session_id_found(data): @@ -2435,14 +2436,10 @@ class Client: voice_data_future = self.ws.wait_for('VOICE_SERVER_UPDATE', lambda d: True) # request joining - yield from self.ws.voice_state(channel.server.id, channel.id) + yield from self.ws.voice_state(server.id, channel.id) session_id_data = yield from asyncio.wait_for(session_id_future, timeout=10.0, loop=self.loop) data = yield from asyncio.wait_for(voice_data_future, timeout=10.0, loop=self.loop) - # todo: multivoice - if self.is_voice_connected(): - self.voice.channel = self.get_channel(session_id_data.get('channel_id')) - kwargs = { 'user': self.user, 'channel': channel, @@ -2452,10 +2449,36 @@ class Client: 'main_ws': self.ws } - self.voice = VoiceClient(**kwargs) - yield from self.voice.connect() - return self.voice + voice = VoiceClient(**kwargs) + yield from voice.connect() + self.connection._add_voice_client(server.id, voice) + return voice + + def is_voice_connected(self, server): + """Indicates if we are currently connected to a voice channel in the + specified server. + + Parameters + ----------- + server : :class:`Server` + The server to query if we're connected to it. + """ + voice = self.voice_client_in(server) + return voice is not None + + def voice_client_in(self, server): + """Returns the voice client associated with a server. + + If no voice client is found then ``None`` is returned. - def is_voice_connected(self): - """bool : Indicates if we are currently connected to a voice channel.""" - return self.voice is not None and self.voice.is_connected() + Parameters + ----------- + server : :class:`Server` + The server to query if we have a voice client for. + + Returns + -------- + :class:`VoiceClient` + The voice client associated with the server. + """ + return self.connection._get_voice_client(server.id) |