From deaa1aabb8a64927208a12a38f9edd011999359b Mon Sep 17 00:00:00 2001 From: Valerie Date: Mon, 26 May 2025 06:10:33 -0400 Subject: [PATCH] Refine leaderboard sync process in Leaderboard cog to focus on users with 10,000+ credits. Update logging for clarity on sync results and user credit checks. Enhance error handling and ensure accurate data aggregation while maintaining detailed debug information for better tracking of user states. --- leaderboard/leaderboard.py | 71 +++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/leaderboard/leaderboard.py b/leaderboard/leaderboard.py index 14de4cc..b0f8818 100644 --- a/leaderboard/leaderboard.py +++ b/leaderboard/leaderboard.py @@ -123,7 +123,7 @@ class Leaderboard(commands.Cog): while True: try: success_count, fail_count = await self._perform_full_sync() - log.info(f"Completed automatic leaderboard sync: {success_count} successes, {fail_count} failures") + log.info(f"Completed automatic leaderboard sync: {success_count} users with 10,000+ credits synced, {fail_count} failures") await asyncio.sleep(21600) # 6 hours in seconds except asyncio.CancelledError: break @@ -138,8 +138,9 @@ class Leaderboard(commands.Cog): fail_count = 0 processed_users = set() users_to_sync = [] + min_credits = 10000 # Minimum credits to show on leaderboard - # First, collect all users and their credits + # First, collect all eligible users and their credits for guild in self.bot.guilds: for member in guild.members: if member.bot or member.id in processed_users: @@ -147,25 +148,24 @@ class Leaderboard(commands.Cog): try: credits = await self.get_user_credits(member) - opted_out = await self.config.user(member).opted_out() - # Only include users with sufficient credits or who are opted out - # (we need to sync opted-out status even for users below threshold) - if credits >= 10000 or opted_out: + # Only sync users with 10,000+ credits + if credits >= min_credits: users_to_sync.append({ "member": member, - "credits": credits, - "opted_out": opted_out + "credits": credits }) + log.debug(f"Queued for sync: {member} ({member.id}) with {credits} credits") + processed_users.add(member.id) except Exception as e: log.error(f"Error processing user {member} ({member.id}): {e}") fail_count += 1 # Debug logging - log.info(f"Found {len(users_to_sync)} users to sync") + log.info(f"Found {len(users_to_sync)} users with {min_credits}+ credits to sync") - # Now perform the sync + # Now perform the sync for eligible users for user_data in users_to_sync: member = user_data["member"] try: @@ -175,7 +175,7 @@ class Leaderboard(commands.Cog): user_data["credits"] ): success_count += 1 - log.debug(f"Successfully synced {member} ({member.id})") + log.debug(f"Successfully synced {member} ({member.id}) with {user_data['credits']} credits") else: fail_count += 1 log.error(f"Failed to sync {member} ({member.id})") @@ -193,6 +193,8 @@ class Leaderboard(commands.Cog): data = await resp.json() if "leaderboard" in data: log.info(f"API verification: {len(data['leaderboard'])} users in leaderboard after sync") + if len(data['leaderboard']) != len(users_to_sync): + log.warning(f"Mismatch in user count: {len(users_to_sync)} synced vs {len(data['leaderboard'])} in API") else: log.error("API verification failed: Invalid response format") else: @@ -211,7 +213,9 @@ class Leaderboard(commands.Cog): try: # Use Red's bank API to get the user's balance # This automatically handles the global bank if enabled - return await bank.get_balance(user) + balance = await bank.get_balance(user) + log.debug(f"Got balance for {user} ({user.id}): {balance} credits") + return balance except Exception as e: log.error(f"Error getting credits for {user}: {e}") return 0 @@ -240,32 +244,41 @@ class Leaderboard(commands.Cog): credits = await self.get_user_credits(member) # Debug logging for credit calculation - log.debug(f"Calculated credits for {member} ({member.id}): {credits}") + log.debug(f"Checking credits for {member} ({member.id}): {credits} credits, minimum: {min_credits}") - if credits >= min_credits: - all_users[member.id] = { - "userId": str(member.id), - "username": str(member), - "points": credits - } + # Store user data regardless of credits amount + all_users[member.id] = { + "userId": str(member.id), + "username": str(member), + "points": credits + } processed_users.add(member.id) except Exception as e: log.error(f"Error getting balance for {member}: {e}") continue - # Sort by total credits + # Filter and sort users after collecting all data + qualified_users = [ + user for user in all_users.values() + if user["points"] >= min_credits + ] + sorted_users = sorted( - all_users.values(), + qualified_users, key=lambda x: x["points"], reverse=True ) # Debug logging - log.info(f"Found {len(sorted_users)} users with {min_credits}+ credits") - for user in sorted_users[:10]: # Log top 10 for debugging - log.info(f"User {user['username']} has {user['points']} credits") - + log.info(f"Found {len(all_users)} total users, {len(sorted_users)} with {min_credits}+ credits") + if sorted_users: + log.info("Top 10 users:") + for user in sorted_users[:10]: + log.info(f"User {user['username']} ({user['userId']}) has {user['points']} credits") + else: + log.warning("No users found with sufficient credits!") + return sorted_users async def _try_api_update(self, user_id: str, username: str, credits: int) -> bool: @@ -349,6 +362,8 @@ class Leaderboard(commands.Cog): leaderboard_data = await self.get_all_balances() if not leaderboard_data: + # Debug info in log + log.warning(f"No leaderboard data returned for guild {ctx.guild.id}") return await ctx.send("No users have 10,000 or more credits!") items_per_page = 10 @@ -468,13 +483,13 @@ class Leaderboard(commands.Cog): @globalboard.command(name="resync") @commands.is_owner() async def resync_leaderboard(self, ctx: commands.Context): - """Force a resync of all users' credits with the API (if configured).""" + """Force a resync of all users with 10,000+ credits to the API.""" if not self.session or not self.admin_secret or not self.admin_secret.get("admin_secret"): await ctx.send("API is not configured.") return async with ctx.typing(): - message = await ctx.send("🔄 Starting global leaderboard resync...") + message = await ctx.send("🔄 Starting global leaderboard resync (10,000+ credits only)...") try: success_count, fail_count = await self._perform_full_sync() @@ -482,7 +497,7 @@ class Leaderboard(commands.Cog): embed = discord.Embed( title="🔄 Global Leaderboard Resync Complete", description=( - f"Successfully updated: **{success_count}** users\n" + f"Successfully updated: **{success_count}** users with 10,000+ credits\n" f"Failed to update: **{fail_count}** users\n\n" "Note: Updates may take a few moments to appear on the website." ),