diff --git a/discord-rare-monitor/discord_rare_monitor.py b/discord-rare-monitor/discord_rare_monitor.py index 849d3963..7063691c 100644 --- a/discord-rare-monitor/discord_rare_monitor.py +++ b/discord-rare-monitor/discord_rare_monitor.py @@ -73,7 +73,22 @@ class DiscordRareMonitor: # Setup Discord event handlers self.setup_discord_handlers() - + + async def cancel_websocket_task(self): + """Safely cancel the existing websocket task if running. + + This prevents duplicate tasks from running in parallel, which would + cause duplicate Discord messages for each rare event. + """ + if self.websocket_task and not self.websocket_task.done(): + logger.info("🛑 Cancelling existing WebSocket task before creating new one") + self.websocket_task.cancel() + try: + await self.websocket_task + except asyncio.CancelledError: + pass + logger.info("✅ Old WebSocket task cancelled") + def setup_discord_handlers(self): """Setup Discord client event handlers.""" @@ -110,13 +125,22 @@ class DiscordRareMonitor: logger.info(f"📍 Great rares channel: #{great_channel.name}") logger.info("🎯 Bot ready to receive messages!") - + + # Cancel any existing WebSocket task first (prevents duplicates if on_ready fires twice) + await self.cancel_websocket_task() + # Start WebSocket monitoring self.running = True self.websocket_task = asyncio.create_task(self.monitor_websocket()) logger.info("🔄 Started WebSocket monitoring task") - - # Start health monitoring task + + # Start health monitoring task (also cancel if exists) + if self.health_monitor_task and not self.health_monitor_task.done(): + self.health_monitor_task.cancel() + try: + await self.health_monitor_task + except asyncio.CancelledError: + pass self.health_monitor_task = asyncio.create_task(self.monitor_websocket_health()) logger.info("💓 Started WebSocket health monitoring task") @@ -133,6 +157,8 @@ class DiscordRareMonitor: if not self.websocket_task or self.websocket_task.done(): logger.warning("🔧 WebSocket task was lost during Discord disconnect - restarting") await self.post_status_to_aclog("🔄 Discord resumed: WebSocket was lost, restarting connection") + # Cancel any zombie task first (safety measure) + await self.cancel_websocket_task() self.websocket_task = asyncio.create_task(self.monitor_websocket()) else: logger.info("✅ WebSocket task still healthy after Discord resume") @@ -221,6 +247,8 @@ class DiscordRareMonitor: # Restart the WebSocket monitoring task logger.info("🔧 Restarting WebSocket monitoring task") await self.post_status_to_aclog("🚨 Health check detected WebSocket failure - restarting connection") + # Cancel any existing task first to prevent duplicates + await self.cancel_websocket_task() self.websocket_task = asyncio.create_task(self.monitor_websocket()) else: logger.debug("💓 WebSocket task health check passed")