|
@ -212,6 +212,9 @@ class KeepAliveHandler(threading.Thread): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VoiceKeepAliveHandler(KeepAliveHandler): |
|
|
class VoiceKeepAliveHandler(KeepAliveHandler): |
|
|
|
|
|
if TYPE_CHECKING: |
|
|
|
|
|
ws: DiscordVoiceWebSocket |
|
|
|
|
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None: |
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None: |
|
|
name: str = kwargs.pop('name', f'voice-keep-alive-handler:{id(self):#x}') |
|
|
name: str = kwargs.pop('name', f'voice-keep-alive-handler:{id(self):#x}') |
|
|
super().__init__(*args, name=name, **kwargs) |
|
|
super().__init__(*args, name=name, **kwargs) |
|
@ -223,7 +226,10 @@ class VoiceKeepAliveHandler(KeepAliveHandler): |
|
|
def get_payload(self) -> Dict[str, Any]: |
|
|
def get_payload(self) -> Dict[str, Any]: |
|
|
return { |
|
|
return { |
|
|
'op': self.ws.HEARTBEAT, |
|
|
'op': self.ws.HEARTBEAT, |
|
|
'd': int(time.time() * 1000), |
|
|
'd': { |
|
|
|
|
|
't': int(time.time() * 1000), |
|
|
|
|
|
'seq_ack': self.ws.seq_ack, |
|
|
|
|
|
}, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
def ack(self) -> None: |
|
|
def ack(self) -> None: |
|
@ -830,6 +836,8 @@ class DiscordVoiceWebSocket: |
|
|
self._keep_alive: Optional[VoiceKeepAliveHandler] = None |
|
|
self._keep_alive: Optional[VoiceKeepAliveHandler] = None |
|
|
self._close_code: Optional[int] = None |
|
|
self._close_code: Optional[int] = None |
|
|
self.secret_key: Optional[List[int]] = None |
|
|
self.secret_key: Optional[List[int]] = None |
|
|
|
|
|
# defaulting to -1 |
|
|
|
|
|
self.seq_ack: int = -1 |
|
|
if hook: |
|
|
if hook: |
|
|
self._hook = hook # type: ignore |
|
|
self._hook = hook # type: ignore |
|
|
|
|
|
|
|
@ -850,6 +858,7 @@ class DiscordVoiceWebSocket: |
|
|
'token': state.token, |
|
|
'token': state.token, |
|
|
'server_id': str(state.server_id), |
|
|
'server_id': str(state.server_id), |
|
|
'session_id': state.session_id, |
|
|
'session_id': state.session_id, |
|
|
|
|
|
'seq_ack': self.seq_ack, |
|
|
}, |
|
|
}, |
|
|
} |
|
|
} |
|
|
await self.send_as_json(payload) |
|
|
await self.send_as_json(payload) |
|
@ -874,14 +883,16 @@ class DiscordVoiceWebSocket: |
|
|
*, |
|
|
*, |
|
|
resume: bool = False, |
|
|
resume: bool = False, |
|
|
hook: Optional[Callable[..., Coroutine[Any, Any, Any]]] = None, |
|
|
hook: Optional[Callable[..., Coroutine[Any, Any, Any]]] = None, |
|
|
|
|
|
seq_ack: int = -1, |
|
|
) -> Self: |
|
|
) -> Self: |
|
|
"""Creates a voice websocket for the :class:`VoiceClient`.""" |
|
|
"""Creates a voice websocket for the :class:`VoiceClient`.""" |
|
|
gateway = f'wss://{state.endpoint}/?v=4' |
|
|
gateway = f'wss://{state.endpoint}/?v=8' |
|
|
client = state.voice_client |
|
|
client = state.voice_client |
|
|
http = client._state.http |
|
|
http = client._state.http |
|
|
socket = await http.ws_connect(gateway, compress=15) |
|
|
socket = await http.ws_connect(gateway, compress=15) |
|
|
ws = cls(socket, loop=client.loop, hook=hook) |
|
|
ws = cls(socket, loop=client.loop, hook=hook) |
|
|
ws.gateway = gateway |
|
|
ws.gateway = gateway |
|
|
|
|
|
ws.seq_ack = seq_ack |
|
|
ws._connection = state |
|
|
ws._connection = state |
|
|
ws._max_heartbeat_timeout = 60.0 |
|
|
ws._max_heartbeat_timeout = 60.0 |
|
|
ws.thread_id = threading.get_ident() |
|
|
ws.thread_id = threading.get_ident() |
|
@ -934,6 +945,7 @@ class DiscordVoiceWebSocket: |
|
|
_log.debug('Voice websocket frame received: %s', msg) |
|
|
_log.debug('Voice websocket frame received: %s', msg) |
|
|
op = msg['op'] |
|
|
op = msg['op'] |
|
|
data = msg['d'] # According to Discord this key is always given |
|
|
data = msg['d'] # According to Discord this key is always given |
|
|
|
|
|
self.seq_ack = msg.get('seq', self.seq_ack) # this key could not be given |
|
|
|
|
|
|
|
|
if op == self.READY: |
|
|
if op == self.READY: |
|
|
await self.initial_connection(data) |
|
|
await self.initial_connection(data) |
|
|