Merge pull request #3028 from InspectorCaracal/discord-bugs
Rework Discord reconnection logic
This commit is contained in:
commit
e15aebdf86
2 changed files with 31 additions and 49 deletions
|
|
@ -1925,6 +1925,7 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS):
|
||||||
/delete - alias to remove
|
/delete - alias to remove
|
||||||
/guild - toggle the Discord server tag on/off
|
/guild - toggle the Discord server tag on/off
|
||||||
/channel - toggle the Evennia/Discord channel tags on/off
|
/channel - toggle the Evennia/Discord channel tags on/off
|
||||||
|
/start - tell the bot to start, in case it lost its connection
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
discord2chan mydiscord = 555555555555555
|
discord2chan mydiscord = 555555555555555
|
||||||
|
|
@ -1943,6 +1944,7 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS):
|
||||||
"guild",
|
"guild",
|
||||||
"list",
|
"list",
|
||||||
"remove",
|
"remove",
|
||||||
|
"start",
|
||||||
)
|
)
|
||||||
locks = "cmd:serversetting(DISCORD_ENABLED) and pperm(Developer)"
|
locks = "cmd:serversetting(DISCORD_ENABLED) and pperm(Developer)"
|
||||||
help_category = "Comms"
|
help_category = "Comms"
|
||||||
|
|
@ -1973,6 +1975,13 @@ class CmdDiscord2Chan(COMMAND_DEFAULT_CLASS):
|
||||||
f"WARNING: The Discord bot's typeclass is '{discord_bot.typeclass_path}'. This does not match {settings.DISCORD_BOT_CLASS} in settings!"
|
f"WARNING: The Discord bot's typeclass is '{discord_bot.typeclass_path}'. This does not match {settings.DISCORD_BOT_CLASS} in settings!"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "start" in self.switches:
|
||||||
|
if discord_bot.sessions.all():
|
||||||
|
self.msg("The Discord bot is already running.")
|
||||||
|
else:
|
||||||
|
discord_bot.start()
|
||||||
|
return
|
||||||
|
|
||||||
if "guild" in self.switches:
|
if "guild" in self.switches:
|
||||||
discord_bot.db.tag_guild = not discord_bot.db.tag_guild
|
discord_bot.db.tag_guild = not discord_bot.db.tag_guild
|
||||||
self.msg(
|
self.msg(
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ def should_retry(status_code):
|
||||||
|
|
||||||
class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.ReconnectingClientFactory):
|
class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.ReconnectingClientFactory):
|
||||||
"""
|
"""
|
||||||
A variant of the websocket-factory that auto-reconnects.
|
A customized websocket client factory that navigates the Discord gateway process.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
noisy = False
|
noisy = False
|
||||||
gateway = None
|
gateway = None
|
||||||
resume_url = None
|
resume_url = None
|
||||||
do_retry = True
|
is_connecting = False
|
||||||
|
|
||||||
def __init__(self, sessionhandler, *args, **kwargs):
|
def __init__(self, sessionhandler, *args, **kwargs):
|
||||||
self.uid = kwargs.get("uid")
|
self.uid = kwargs.get("uid")
|
||||||
|
|
@ -122,8 +122,8 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
d = readBody(response)
|
d = readBody(response)
|
||||||
d.addCallback(self.websocket_init, *args, **kwargs)
|
d.addCallback(self.websocket_init, *args, **kwargs)
|
||||||
return d
|
return d
|
||||||
elif should_retry(response.code):
|
else:
|
||||||
delay(300, self.get_gateway_url, *args, **kwargs)
|
logger.log_warn("Discord gateway request failed.")
|
||||||
|
|
||||||
d.addCallback(cbResponse)
|
d.addCallback(cbResponse)
|
||||||
|
|
||||||
|
|
@ -132,6 +132,7 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
callback for when the URL is gotten
|
callback for when the URL is gotten
|
||||||
"""
|
"""
|
||||||
data = json.loads(str(payload, "utf-8"))
|
data = json.loads(str(payload, "utf-8"))
|
||||||
|
self.is_connecting = False
|
||||||
if url := data.get("url"):
|
if url := data.get("url"):
|
||||||
self.gateway = f"{url}/?v={DISCORD_API_VERSION}&encoding=json".encode("utf-8")
|
self.gateway = f"{url}/?v={DISCORD_API_VERSION}&encoding=json".encode("utf-8")
|
||||||
useragent = kwargs.pop("useragent", DISCORD_USER_AGENT)
|
useragent = kwargs.pop("useragent", DISCORD_USER_AGENT)
|
||||||
|
|
@ -179,30 +180,7 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
connector (Connector): Represents the connection.
|
connector (Connector): Represents the connection.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
logger.log_info("Attempting connection to Discord...")
|
logger.log_info("Connecting to Discord...")
|
||||||
|
|
||||||
def clientConnectionFailed(self, connector, reason):
|
|
||||||
"""
|
|
||||||
Called when Client failed to connect.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
connector (Connection): Represents the connection.
|
|
||||||
reason (str): The reason for the failure.
|
|
||||||
|
|
||||||
"""
|
|
||||||
protocol.ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
|
|
||||||
|
|
||||||
def clientConnectionLost(self, connector, reason):
|
|
||||||
"""
|
|
||||||
Called when Client loses connection.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
connector (Connection): Represents the connection.
|
|
||||||
reason (str): The reason for the failure.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self.do_retry and self.bot:
|
|
||||||
self.retry(connector)
|
|
||||||
|
|
||||||
def reconnect(self):
|
def reconnect(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -210,33 +188,30 @@ class DiscordWebsocketServerFactory(WebSocketClientFactory, protocol.Reconnectin
|
||||||
de-registering the session and then reattaching a new one.
|
de-registering the session and then reattaching a new one.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# set the retry flag to False so it doesn't attempt an automatic retry
|
|
||||||
# and duplicate the connection
|
|
||||||
self.do_retry = False
|
|
||||||
# disconnect everything
|
|
||||||
self.bot.transport.loseConnection()
|
|
||||||
self.sessionhandler.server_disconnect(self.bot)
|
|
||||||
# set up the reconnection
|
# set up the reconnection
|
||||||
if self.resume_url:
|
if self.resume_url:
|
||||||
self.url = self.resume_url
|
self.url = self.resume_url
|
||||||
elif self.gateway:
|
elif self.gateway:
|
||||||
self.url = self.gateway
|
self.url = self.gateway
|
||||||
else:
|
else:
|
||||||
# we don't know where to reconnect to! start from the beginning
|
# we don't know where to reconnect to! we'll start from the beginning
|
||||||
self.get_gateway_url()
|
self.url = None
|
||||||
return
|
# reset the internal delay, since this is a deliberate disconnect
|
||||||
self.start()
|
self.delay = self.initialDelay
|
||||||
|
# disconnect to allow the reconnection process to kick in
|
||||||
|
self.bot.sendClose()
|
||||||
|
self.sessionhandler.server_disconnect(self.bot)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"Connect protocol to remote server"
|
"Connect protocol to remote server"
|
||||||
|
|
||||||
if not self.gateway:
|
if not self.gateway:
|
||||||
# we can't actually start yet
|
# we don't know where to connect to
|
||||||
# get the gateway URL from Discord
|
# get the gateway URL from Discord
|
||||||
|
self.is_connecting = True
|
||||||
self.get_gateway_url()
|
self.get_gateway_url()
|
||||||
else:
|
elif not self.is_connecting:
|
||||||
# set the retry flag so we maintain this connection
|
# everything is good, connect
|
||||||
self.do_retry = True
|
|
||||||
connectWS(self)
|
connectWS(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -255,7 +230,6 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
WebSocketClientProtocol.__init__(self)
|
WebSocketClientProtocol.__init__(self)
|
||||||
_BASE_SESSION_CLASS.__init__(self)
|
_BASE_SESSION_CLASS.__init__(self)
|
||||||
self.restart_downtime = None
|
|
||||||
|
|
||||||
def at_login(self):
|
def at_login(self):
|
||||||
pass
|
pass
|
||||||
|
|
@ -265,8 +239,7 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS):
|
||||||
Called when connection is established.
|
Called when connection is established.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.restart_downtime = None
|
logger.log_msg("Discord connection established.")
|
||||||
self.restart_task = None
|
|
||||||
self.factory.bot = self
|
self.factory.bot = self
|
||||||
|
|
||||||
self.init_session("discord", "discord.gg", self.factory.sessionhandler)
|
self.init_session("discord", "discord.gg", self.factory.sessionhandler)
|
||||||
|
|
@ -352,11 +325,11 @@ class DiscordClient(WebSocketClientProtocol, _BASE_SESSION_CLASS):
|
||||||
"""
|
"""
|
||||||
if self.nextHeartbeatCall:
|
if self.nextHeartbeatCall:
|
||||||
self.nextHeartbeatCall.cancel()
|
self.nextHeartbeatCall.cancel()
|
||||||
self.disconnect(reason)
|
self.nextHeartbeatCall = None
|
||||||
if code >= 4000:
|
if wasClean:
|
||||||
logger.log_err(f"Discord connection closed: {reason}")
|
logger.log_info(f"Discord connection closed ({code}) reason: {reason}")
|
||||||
else:
|
else:
|
||||||
logger.log_info(f"Discord disconnected: {reason}")
|
logger.log_info(f"Discord connection lost.")
|
||||||
|
|
||||||
def _send_json(self, data):
|
def _send_json(self, data):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue