Improve Discord gateway error handling and logging
This commit is contained in:
parent
7b63a787b3
commit
d82fcef91b
1 changed files with 34 additions and 22 deletions
|
|
@ -72,11 +72,11 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
async def connect(self) -> bool:
|
async def connect(self) -> bool:
|
||||||
"""Connect to Discord and start receiving events."""
|
"""Connect to Discord and start receiving events."""
|
||||||
if not DISCORD_AVAILABLE:
|
if not DISCORD_AVAILABLE:
|
||||||
print(f"[{self.name}] discord.py not installed. Run: pip install discord.py")
|
logger.error("[%s] discord.py not installed. Run: pip install discord.py", self.name)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not self.config.token:
|
if not self.config.token:
|
||||||
print(f"[{self.name}] No bot token configured")
|
logger.error("[%s] No bot token configured", self.name)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -105,7 +105,7 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
# Register event handlers
|
# Register event handlers
|
||||||
@self._client.event
|
@self._client.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
print(f"[{adapter_self.name}] Connected as {adapter_self._client.user}")
|
logger.info("[%s] Connected as %s", adapter_self.name, adapter_self._client.user)
|
||||||
|
|
||||||
# Resolve any usernames in the allowed list to numeric IDs
|
# Resolve any usernames in the allowed list to numeric IDs
|
||||||
await adapter_self._resolve_allowed_usernames()
|
await adapter_self._resolve_allowed_usernames()
|
||||||
|
|
@ -113,9 +113,9 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
# Sync slash commands with Discord
|
# Sync slash commands with Discord
|
||||||
try:
|
try:
|
||||||
synced = await adapter_self._client.tree.sync()
|
synced = await adapter_self._client.tree.sync()
|
||||||
print(f"[{adapter_self.name}] Synced {len(synced)} slash command(s)")
|
logger.info("[%s] Synced %d slash command(s)", adapter_self.name, len(synced))
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
print(f"[{adapter_self.name}] Slash command sync failed: {e}")
|
logger.warning("[%s] Slash command sync failed: %s", adapter_self.name, e, exc_info=True)
|
||||||
adapter_self._ready_event.set()
|
adapter_self._ready_event.set()
|
||||||
|
|
||||||
@self._client.event
|
@self._client.event
|
||||||
|
|
@ -138,10 +138,10 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
print(f"[{self.name}] Timeout waiting for connection")
|
logger.error("[%s] Timeout waiting for connection to Discord", self.name, exc_info=True)
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
print(f"[{self.name}] Failed to connect: {e}")
|
logger.error("[%s] Failed to connect to Discord: %s", self.name, e, exc_info=True)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def disconnect(self) -> None:
|
async def disconnect(self) -> None:
|
||||||
|
|
@ -149,13 +149,13 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
if self._client:
|
if self._client:
|
||||||
try:
|
try:
|
||||||
await self._client.close()
|
await self._client.close()
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
print(f"[{self.name}] Error during disconnect: {e}")
|
logger.warning("[%s] Error during disconnect: %s", self.name, e, exc_info=True)
|
||||||
|
|
||||||
self._running = False
|
self._running = False
|
||||||
self._client = None
|
self._client = None
|
||||||
self._ready_event.clear()
|
self._ready_event.clear()
|
||||||
print(f"[{self.name}] Disconnected")
|
logger.info("[%s] Disconnected", self.name)
|
||||||
|
|
||||||
async def send(
|
async def send(
|
||||||
self,
|
self,
|
||||||
|
|
@ -204,7 +204,8 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
raw_response={"message_ids": message_ids}
|
raw_response={"message_ids": message_ids}
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
|
logger.error("[%s] Failed to send Discord message: %s", self.name, e, exc_info=True)
|
||||||
return SendResult(success=False, error=str(e))
|
return SendResult(success=False, error=str(e))
|
||||||
|
|
||||||
async def edit_message(
|
async def edit_message(
|
||||||
|
|
@ -226,7 +227,8 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
formatted = formatted[:self.MAX_MESSAGE_LENGTH - 3] + "..."
|
formatted = formatted[:self.MAX_MESSAGE_LENGTH - 3] + "..."
|
||||||
await msg.edit(content=formatted)
|
await msg.edit(content=formatted)
|
||||||
return SendResult(success=True, message_id=message_id)
|
return SendResult(success=True, message_id=message_id)
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
|
logger.error("[%s] Failed to edit Discord message %s: %s", self.name, message_id, e, exc_info=True)
|
||||||
return SendResult(success=False, error=str(e))
|
return SendResult(success=False, error=str(e))
|
||||||
|
|
||||||
async def send_voice(
|
async def send_voice(
|
||||||
|
|
@ -263,8 +265,8 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
)
|
)
|
||||||
return SendResult(success=True, message_id=str(msg.id))
|
return SendResult(success=True, message_id=str(msg.id))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
print(f"[{self.name}] Failed to send audio: {e}")
|
logger.error("[%s] Failed to send audio, falling back to base adapter: %s", self.name, e, exc_info=True)
|
||||||
return await super().send_voice(chat_id, audio_path, caption, reply_to)
|
return await super().send_voice(chat_id, audio_path, caption, reply_to)
|
||||||
|
|
||||||
async def send_image_file(
|
async def send_image_file(
|
||||||
|
|
@ -300,8 +302,8 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
)
|
)
|
||||||
return SendResult(success=True, message_id=str(msg.id))
|
return SendResult(success=True, message_id=str(msg.id))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
print(f"[{self.name}] Failed to send local image: {e}")
|
logger.error("[%s] Failed to send local image, falling back to base adapter: %s", self.name, e, exc_info=True)
|
||||||
return await super().send_image_file(chat_id, image_path, caption, reply_to)
|
return await super().send_image_file(chat_id, image_path, caption, reply_to)
|
||||||
|
|
||||||
async def send_image(
|
async def send_image(
|
||||||
|
|
@ -353,10 +355,19 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
return SendResult(success=True, message_id=str(msg.id))
|
return SendResult(success=True, message_id=str(msg.id))
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print(f"[{self.name}] aiohttp not installed, falling back to URL. Run: pip install aiohttp")
|
logger.warning(
|
||||||
|
"[%s] aiohttp not installed, falling back to URL. Run: pip install aiohttp",
|
||||||
|
self.name,
|
||||||
|
exc_info=True,
|
||||||
|
)
|
||||||
return await super().send_image(chat_id, image_url, caption, reply_to)
|
return await super().send_image(chat_id, image_url, caption, reply_to)
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
print(f"[{self.name}] Failed to send image attachment, falling back to URL: {e}")
|
logger.error(
|
||||||
|
"[%s] Failed to send image attachment, falling back to URL: %s",
|
||||||
|
self.name,
|
||||||
|
e,
|
||||||
|
exc_info=True,
|
||||||
|
)
|
||||||
return await super().send_image(chat_id, image_url, caption, reply_to)
|
return await super().send_image(chat_id, image_url, caption, reply_to)
|
||||||
|
|
||||||
async def send_typing(self, chat_id: str) -> None:
|
async def send_typing(self, chat_id: str) -> None:
|
||||||
|
|
@ -404,7 +415,8 @@ class DiscordAdapter(BasePlatformAdapter):
|
||||||
"guild_id": str(channel.guild.id) if hasattr(channel, "guild") and channel.guild else None,
|
"guild_id": str(channel.guild.id) if hasattr(channel, "guild") and channel.guild else None,
|
||||||
"guild_name": channel.guild.name if hasattr(channel, "guild") and channel.guild else None,
|
"guild_name": channel.guild.name if hasattr(channel, "guild") and channel.guild else None,
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e: # pragma: no cover - defensive logging
|
||||||
|
logger.error("[%s] Failed to get chat info for %s: %s", self.name, chat_id, e, exc_info=True)
|
||||||
return {"name": str(chat_id), "type": "dm", "error": str(e)}
|
return {"name": str(chat_id), "type": "dm", "error": str(e)}
|
||||||
|
|
||||||
async def _resolve_allowed_usernames(self) -> None:
|
async def _resolve_allowed_usernames(self) -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue