diff --git a/modrinthtracker/modrinthtracker.py b/modrinthtracker/modrinthtracker.py index ff66083..3e2267b 100644 --- a/modrinthtracker/modrinthtracker.py +++ b/modrinthtracker/modrinthtracker.py @@ -24,14 +24,17 @@ class ModrinthTracker(commands.Cog): self.request_lock = asyncio.Lock() async def cog_load(self): + """Initialize the cog.""" self.session = aiohttp.ClientSession() self.bg_task = self.bot.loop.create_task(self.update_checker()) async def cog_unload(self): - if self.session: - await self.session.close() + """Clean up when cog shuts down.""" if self.bg_task: self.bg_task.cancel() + if self.session: + await self.session.close() + self.session = None async def _rate_limit(self): """Implements rate limiting for API requests""" @@ -54,32 +57,34 @@ class ModrinthTracker(commands.Cog): self.request_timestamps.append(current_time) - async def _make_request(self, url, params=None): + async def _make_request(self, url, params=None, retries=3): """Make a rate-limited request to the Modrinth API""" await self._rate_limit() - # Ensure session is available - if self.session is None or self.session.closed: - self.session = aiohttp.ClientSession() - - try: - async with self.session.get(url, params=params) as response: - if response.status == 429: # Too Many Requests - retry_after = int(response.headers.get('Retry-After', 60)) - await asyncio.sleep(retry_after) - return await self._make_request(url, params) - return response - except aiohttp.ClientConnectorError: - # Connection error, try to recreate session and retry once - if self.session and not self.session.closed: - await self.session.close() - self.session = aiohttp.ClientSession() - async with self.session.get(url, params=params) as response: - return response - except Exception as e: - # Log the error for debugging - self.bot.logger.error(f"Error in _make_request: {str(e)}", exc_info=True) - raise + for attempt in range(retries): + try: + # Ensure session is available + if self.session is None or self.session.closed: + self.session = aiohttp.ClientSession() + + async with self.session.get(url, params=params) as response: + if response.status == 429: # Too Many Requests + retry_after = int(response.headers.get('Retry-After', 60)) + await asyncio.sleep(retry_after) + continue + return response + + except (aiohttp.ClientConnectorError, aiohttp.ClientError) as e: + if attempt == retries - 1: # Last attempt + raise + # Close and recreate session + if self.session and not self.session.closed: + await self.session.close() + self.session = aiohttp.ClientSession() + await asyncio.sleep(1) # Wait a bit before retrying + except Exception as e: + self.bot.logger.error(f"Error in _make_request: {str(e)}", exc_info=True) + raise @commands.group() @checks.admin() @@ -170,12 +175,12 @@ class ModrinthTracker(commands.Cog): except aiohttp.ClientConnectorError: await ctx.send("Error: Failed to connect to Modrinth API. Please try again in a few moments.") except aiohttp.ClientError as e: - await ctx.send(f"Error: Network error occurred while contacting Modrinth API: {str(e)}") + await ctx.send(f"Error: Network error occurred while contacting Modrinth API. Please try again in a few moments.") except asyncio.TimeoutError: await ctx.send("Error: Request to Modrinth API timed out. Please try again.") except Exception as e: self.bot.logger.error(f"Error in modrinth add command: {str(e)}", exc_info=True) - await ctx.send(f"An unexpected error occurred. Please try again later or contact the bot owner if the issue persists.") + await ctx.send("An unexpected error occurred. Please try again later or contact the bot owner if the issue persists.") @modrinth.command() async def remove(self, ctx, project_id: str):