aboutsummaryrefslogtreecommitdiff
path: root/discord/client.py
diff options
context:
space:
mode:
Diffstat (limited to 'discord/client.py')
-rw-r--r--discord/client.py37
1 files changed, 23 insertions, 14 deletions
diff --git a/discord/client.py b/discord/client.py
index 068e3d65..a0e27d8e 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -480,19 +480,6 @@ class Client:
"""
await self.close()
- async def _connect(self):
- coro = DiscordWebSocket.from_client(self, initial=True, shard_id=self.shard_id)
- self.ws = await asyncio.wait_for(coro, timeout=180.0)
- while True:
- try:
- await self.ws.poll_event()
- except ReconnectWebSocket as e:
- log.info('Got a request to %s the websocket.', e.op)
- self.dispatch('disconnect')
- coro = DiscordWebSocket.from_client(self, shard_id=self.shard_id, session=self.ws.session_id,
- sequence=self.ws.sequence, resume=e.resume)
- self.ws = await asyncio.wait_for(coro, timeout=180.0)
-
async def connect(self, *, reconnect=True):
"""|coro|
@@ -519,9 +506,22 @@ class Client:
"""
backoff = ExponentialBackoff()
+ ws_params = {
+ 'initial': True,
+ 'shard_id': self.shard_id,
+ }
while not self.is_closed():
try:
- await self._connect()
+ coro = DiscordWebSocket.from_client(self, **ws_params)
+ self.ws = await asyncio.wait_for(coro, timeout=60.0)
+ ws_params['initial'] = False
+ while True:
+ await self.ws.poll_event()
+ except ReconnectWebSocket as e:
+ log.info('Got a request to %s the websocket.', e.op)
+ self.dispatch('disconnect')
+ ws_params.update(sequence=self.ws.sequence, resume=e.resume, session=self.ws.session_id)
+ continue
except (OSError,
HTTPException,
GatewayNotFound,
@@ -540,6 +540,11 @@ class Client:
if self.is_closed():
return
+ # If we get connection reset by peer then try to RESUME
+ if isinstance(exc, OSError) and exc.errno in (54, 10054):
+ ws_params.update(sequence=self.ws.sequence, initial=False, resume=True, session=self.ws.session_id)
+ continue
+
# We should only get this when an unhandled close code happens,
# such as a clean disconnect (1000) or a bad state (bad token, no sharding, etc)
# sometimes, discord sends us 1000 for unknown reasons so we should reconnect
@@ -552,6 +557,10 @@ class Client:
retry = backoff.delay()
log.exception("Attempting a reconnect in %.2fs", retry)
await asyncio.sleep(retry)
+ # Always try to RESUME the connection
+ # If the connection is not RESUME-able then the gateway will invalidate the session.
+ # This is apparently what the official Discord client does.
+ ws_params.update(sequence=self.ws.sequence, resume=True, session=self.ws.session_id)
async def close(self):
"""|coro|