Implement API connection testing and enhance user credit retrieval in Leaderboard cog
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
Add a test for the API connection during initialization, improving error logging for connection failures. Update the user credit retrieval method to aggregate credits from all servers the user is a member of, enhancing accuracy. Introduce a cleanup command for removing old leaderboard entries, with appropriate error handling and user feedback for API interactions.
This commit is contained in:
parent
f1c5eef019
commit
cbc2fb5ba9
1 changed files with 94 additions and 12 deletions
|
@ -100,21 +100,35 @@ class Leaderboard(commands.Cog):
|
|||
self.admin_secret = await self.bot.get_shared_api_tokens("ruby_api")
|
||||
if self.admin_secret.get("admin_secret"):
|
||||
self.session = aiohttp.ClientSession()
|
||||
# Test API connection
|
||||
async with self.session.get(
|
||||
f"{self.api_base_url}/leaderboard",
|
||||
headers={"Authorization": self.admin_secret["admin_secret"]}
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
log.error(f"Failed to connect to API: Status {resp.status}")
|
||||
except Exception as e:
|
||||
log.error(f"Failed to initialize API connection: {e}")
|
||||
# Don't return anything - initialization is optional
|
||||
|
||||
async def cog_load(self):
|
||||
"""Initialize the cog when it's loaded."""
|
||||
await self.initialize()
|
||||
|
||||
async def get_user_credits(self, user: discord.Member) -> int:
|
||||
"""Get a user's total credits from Red's bank system."""
|
||||
try:
|
||||
return await bank.get_balance(user)
|
||||
except Exception as e:
|
||||
log.error(f"Error getting bank balance for {user}: {e}")
|
||||
return 0
|
||||
"""Get a user's total credits from all servers."""
|
||||
total_credits = 0
|
||||
|
||||
# Get credits from all servers the user is in
|
||||
for guild in self.bot.guilds:
|
||||
if user in guild.members: # Only check servers where the user is a member
|
||||
try:
|
||||
credits = await bank.get_balance(user)
|
||||
total_credits += credits
|
||||
except Exception as e:
|
||||
log.error(f"Error getting bank balance for {user} in {guild}: {e}")
|
||||
continue
|
||||
|
||||
return total_credits
|
||||
|
||||
async def get_all_balances(self) -> List[dict]:
|
||||
"""Get all users' credit balances across all servers."""
|
||||
|
@ -164,23 +178,61 @@ class Leaderboard(commands.Cog):
|
|||
return False
|
||||
|
||||
try:
|
||||
if credits < 0:
|
||||
credits = 0 # API doesn't accept negative values
|
||||
|
||||
async with self.session.post(
|
||||
f"{self.api_base_url}/leaderboard",
|
||||
headers={
|
||||
"Authorization": self.admin_secret.get("admin_secret"),
|
||||
"Authorization": self.admin_secret["admin_secret"],
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
json={
|
||||
"userId": user_id,
|
||||
"username": username,
|
||||
"userId": str(user_id),
|
||||
"username": str(username),
|
||||
"points": credits
|
||||
}
|
||||
) as resp:
|
||||
return resp.status == 200
|
||||
if resp.status == 200:
|
||||
data = await resp.json()
|
||||
if data.get("success"):
|
||||
log.info(f"Updated leaderboard for {username}: {credits} credits")
|
||||
return True
|
||||
else:
|
||||
log.error(f"API update failed: {data.get('error', 'Unknown error')}")
|
||||
elif resp.status == 401:
|
||||
log.error("Unauthorized: Invalid admin secret")
|
||||
else:
|
||||
log.error(f"API update failed: Status {resp.status}")
|
||||
return False
|
||||
except Exception as e:
|
||||
log.error(f"API update failed: {e}")
|
||||
return False
|
||||
|
||||
async def _get_api_leaderboard(self) -> Optional[list]:
|
||||
"""Fetch the leaderboard from the API."""
|
||||
if not self.session or not self.admin_secret or not self.admin_secret.get("admin_secret"):
|
||||
return None
|
||||
|
||||
try:
|
||||
async with self.session.get(
|
||||
f"{self.api_base_url}/leaderboard",
|
||||
headers={"Authorization": self.admin_secret["admin_secret"]}
|
||||
) as resp:
|
||||
if resp.status == 200:
|
||||
data = await resp.json()
|
||||
if "leaderboard" in data:
|
||||
return data["leaderboard"]
|
||||
log.error("Invalid API response format")
|
||||
elif resp.status == 401:
|
||||
log.error("Unauthorized: Invalid admin secret")
|
||||
else:
|
||||
log.error(f"Failed to fetch leaderboard: Status {resp.status}")
|
||||
return None
|
||||
except Exception as e:
|
||||
log.error(f"Error fetching leaderboard: {e}")
|
||||
return None
|
||||
|
||||
@commands.group(name="globalboard", aliases=["glb"])
|
||||
async def globalboard(self, ctx: commands.Context):
|
||||
"""Global leaderboard commands."""
|
||||
|
@ -332,7 +384,37 @@ class Leaderboard(commands.Cog):
|
|||
if member.bot:
|
||||
return
|
||||
|
||||
await self._try_api_update(str(member.id), str(member), after)
|
||||
total_credits = await self.get_user_credits(member)
|
||||
await self._try_api_update(str(member.id), str(member), total_credits)
|
||||
|
||||
@globalboard.command(name="cleanup")
|
||||
@commands.is_owner()
|
||||
async def cleanup_leaderboard(self, ctx: commands.Context):
|
||||
"""Clean up old leaderboard entries (older than 30 days)."""
|
||||
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
|
||||
|
||||
try:
|
||||
async with self.session.delete(
|
||||
f"{self.api_base_url}/leaderboard",
|
||||
headers={"Authorization": self.admin_secret["admin_secret"]}
|
||||
) as resp:
|
||||
if resp.status == 200:
|
||||
data = await resp.json()
|
||||
if data.get("success"):
|
||||
await ctx.send(
|
||||
f"Cleaned up {data['removedCount']} old entries. "
|
||||
f"{data['remainingCount']} entries remaining."
|
||||
)
|
||||
else:
|
||||
await ctx.send("Failed to clean up leaderboard.")
|
||||
elif resp.status == 401:
|
||||
await ctx.send("Unauthorized: Invalid admin secret")
|
||||
else:
|
||||
await ctx.send(f"Failed to clean up leaderboard: Status {resp.status}")
|
||||
except Exception as e:
|
||||
await ctx.send(f"Error cleaning up leaderboard: {e}")
|
||||
|
||||
def cog_unload(self):
|
||||
"""Clean up when cog is unloaded."""
|
||||
|
|
Loading…
Add table
Reference in a new issue