aboutsummaryrefslogtreecommitdiff
path: root/discord/voice_client.py
diff options
context:
space:
mode:
Diffstat (limited to 'discord/voice_client.py')
-rw-r--r--discord/voice_client.py124
1 files changed, 9 insertions, 115 deletions
diff --git a/discord/voice_client.py b/discord/voice_client.py
index c3286ec2..26b353cc 100644
--- a/discord/voice_client.py
+++ b/discord/voice_client.py
@@ -55,6 +55,7 @@ import nacl.secret
log = logging.getLogger(__name__)
from . import utils
+from .gateway import *
from .errors import ClientException, InvalidArgument
from .opus import Encoder as OpusEncoder
@@ -173,7 +174,6 @@ class VoiceClient:
self.sequence = 0
self.timestamp = 0
self.encoder = OpusEncoder(48000, 2)
- self.secret_key = []
log.info('created opus encoder with {0.__dict__}'.format(self.encoder))
def checked_add(self, attr, value, limit):
@@ -183,87 +183,6 @@ class VoiceClient:
else:
setattr(self, attr, val + value)
- @asyncio.coroutine
- def keep_alive_handler(self, delay):
- try:
- while True:
- payload = {
- 'op': 3,
- 'd': int(time.time())
- }
-
- msg = 'Keeping voice websocket alive with timestamp {}'
- log.debug(msg.format(payload['d']))
- yield from self.ws.send(utils.to_json(payload))
- yield from asyncio.sleep(delay)
- except asyncio.CancelledError:
- pass
-
- @asyncio.coroutine
- def received_message(self, msg):
- log.debug('Voice websocket frame received: {}'.format(msg))
- op = msg.get('op')
- data = msg.get('d')
-
- if op == 2:
- delay = (data['heartbeat_interval'] / 100.0) - 5
- self.keep_alive = utils.create_task(self.keep_alive_handler(delay), loop=self.loop)
- yield from self.initial_connection(data)
- elif op == 4:
- yield from self.connection_ready(data)
-
- @asyncio.coroutine
- def initial_connection(self, data):
- self.ssrc = data.get('ssrc')
- self.voice_port = data.get('port')
- packet = bytearray(70)
- struct.pack_into('>I', packet, 0, self.ssrc)
- self.socket.sendto(packet, (self.endpoint_ip, self.voice_port))
- recv = yield from self.loop.sock_recv(self.socket, 70)
- log.debug('received packet in initial_connection: {}'.format(recv))
-
- # the ip is ascii starting at the 4th byte and ending at the first null
- ip_start = 4
- ip_end = recv.index(0, ip_start)
- self.ip = recv[ip_start:ip_end].decode('ascii')
-
- # the port is a little endian unsigned short in the last two bytes
- # yes, this is different endianness from everything else
- self.port = struct.unpack_from('<H', recv, len(recv) - 2)[0]
-
- log.debug('detected ip: {} port: {}'.format(self.ip, self.port))
-
- payload = {
- 'op': 1,
- 'd': {
- 'protocol': 'udp',
- 'data': {
- 'address': self.ip,
- 'port': self.port,
- 'mode': 'xsalsa20_poly1305'
- }
- }
- }
-
- yield from self.ws.send(utils.to_json(payload))
- log.debug('sent {} to initialize voice connection'.format(payload))
- log.info('initial voice connection is done')
-
- @asyncio.coroutine
- def connection_ready(self, data):
- log.info('voice connection is now ready')
- self.secret_key = data.get('secret_key')
- speaking = {
- 'op': 5,
- 'd': {
- 'speaking': True,
- 'delay': 0
- }
- }
-
- yield from self.ws.send(utils.to_json(speaking))
- self._connected.set()
-
# connection related
@asyncio.coroutine
@@ -275,28 +194,15 @@ class VoiceClient:
self.socket.setblocking(False)
log.info('Voice endpoint found {0.endpoint} (IP: {0.endpoint_ip})'.format(self))
- self.ws = yield from websockets.connect('wss://' + self.endpoint, loop=self.loop)
- self.ws.max_size = None
-
- payload = {
- 'op': 0,
- 'd': {
- 'server_id': self.guild_id,
- 'user_id': self.user.id,
- 'session_id': self.session_id,
- 'token': self.token
- }
- }
-
- yield from self.ws.send(utils.to_json(payload))
+ self.ws = yield from DiscordVoiceWebSocket.from_client(self)
while not self._connected.is_set():
- msg = yield from self.ws.recv()
- if msg is None:
- yield from self.disconnect()
- raise ClientException('Unexpected websocket close on voice websocket')
-
- yield from self.received_message(json.loads(msg))
+ yield from self.ws.poll_event()
+ if hasattr(self, 'secret_key'):
+ # we have a secret key, so we don't need to poll
+ # websocket events anymore
+ self._connected.set()
+ break
@asyncio.coroutine
def disconnect(self):
@@ -310,22 +216,10 @@ class VoiceClient:
if not self._connected.is_set():
return
- self.keep_alive.cancel()
self.socket.close()
self._connected.clear()
yield from self.ws.close()
-
- payload = {
- 'op': 4,
- 'd': {
- 'guild_id': self.guild_id,
- 'channel_id': None,
- 'self_mute': True,
- 'self_deaf': False
- }
- }
-
- yield from self.main_ws.send(utils.to_json(payload))
+ yield from self.main_ws.voice_state(self.guild_id, None, self_mute=True)
def is_connected(self):
"""bool : Indicates if the voice client is connected to voice."""