Enhance leaderboard functionality in Leaderboard cog by integrating user points retrieval from both bank and LevelUp systems. Refactor leaderboard data fetching to combine results and improve error handling. Remove unnecessary point update logic as it is now derived from user data sources.
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run

This commit is contained in:
Valerie 2025-05-26 04:19:01 -04:00
parent 446c266f18
commit da273be3c3

View file

@ -1,4 +1,4 @@
from redbot.core import commands, Config from redbot.core import commands, Config, bank
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import box, pagify, humanize_number from redbot.core.utils.chat_formatting import box, pagify, humanize_number
import discord import discord
@ -109,87 +109,65 @@ class Leaderboard(commands.Cog):
self.session = aiohttp.ClientSession() self.session = aiohttp.ClientSession()
return True return True
async def _get_leaderboard(self) -> Optional[list]: async def get_user_points(self, user: discord.Member) -> int:
"""Fetch the global leaderboard from the API.""" """Get a user's total points combining bank balance and levelup XP."""
if not self.admin_secret or not self.admin_secret.get("admin_secret"): total_points = 0
log.error("Admin secret not configured")
return None # Get bank balance
if not self.session:
log.error("Session not initialized")
return None
try: try:
now = datetime.now(timezone.utc).timestamp() balance = await bank.get_balance(user)
total_points += balance
# Return cached data if available and fresh
if self._cache and now - self._last_update.get("leaderboard", 0) < self.cache_time:
return self._cache.get("leaderboard")
async with self.session.get(
f"{self.api_base_url}/leaderboard",
headers={"Authorization": self.admin_secret.get("admin_secret")}
) as resp:
if resp.status == 200:
data = await resp.json()
if not isinstance(data, dict) or "leaderboard" not in data:
log.error("Invalid API response format")
return None
self._cache["leaderboard"] = data["leaderboard"]
self._last_update["leaderboard"] = now
return self._cache["leaderboard"]
elif resp.status == 401:
log.error("Unauthorized: Invalid admin secret")
return None
else:
log.error(f"Failed to fetch leaderboard: Status {resp.status}")
return None
except aiohttp.ClientError as e:
log.error(f"API connection error: {e}")
return None
except Exception as e: except Exception as e:
log.error(f"Unexpected error fetching leaderboard: {e}") log.error(f"Error getting bank balance for {user}: {e}")
# Get LevelUp XP if cog is loaded
levelup = self.bot.get_cog("LevelUp")
if levelup:
try:
conf = levelup.db.get_conf(user.guild)
profile = conf.get_profile(user)
total_points += int(profile.xp)
except Exception as e:
log.error(f"Error getting LevelUp XP for {user}: {e}")
return total_points
async def _get_leaderboard(self) -> Optional[list]:
"""Fetch and combine leaderboard data from bank and LevelUp."""
try:
all_users = {}
# Get all guild members
for guild in self.bot.guilds:
for member in guild.members:
if member.bot:
continue
points = await self.get_user_points(member)
if points > 0:
all_users[str(member.id)] = {
"userId": str(member.id),
"username": str(member),
"points": points
}
# Sort by points and convert to list
sorted_users = sorted(
all_users.values(),
key=lambda x: x["points"],
reverse=True
)
return sorted_users
except Exception as e:
log.error(f"Error generating leaderboard: {e}")
return None return None
async def _update_points(self, user_id: str, username: str, points: int) -> bool: async def _update_points(self, user_id: str, username: str, points: int) -> bool:
"""Update a user's points in the global leaderboard.""" """Update points is no longer needed as points are pulled from bank and LevelUp."""
if not self.admin_secret or not self.admin_secret.get("admin_secret"): return True
log.error("Admin secret not configured")
return False
if not self.session:
log.error("Session not initialized")
return False
try:
async with self.session.post(
f"{self.api_base_url}/leaderboard",
headers={
"Authorization": self.admin_secret.get("admin_secret"),
"Content-Type": "application/json"
},
json={
"userId": user_id,
"username": username,
"points": points
}
) as resp:
if resp.status == 200:
# Clear cache to ensure fresh data on next fetch
self._cache.pop("leaderboard", None)
return True
elif resp.status == 401:
log.error("Unauthorized: Invalid admin secret")
return False
else:
log.error(f"Failed to update points: Status {resp.status}")
return False
except aiohttp.ClientError as e:
log.error(f"API connection error: {e}")
return False
except Exception as e:
log.error(f"Unexpected error updating points: {e}")
return False
@commands.group(name="globalboard", aliases=["glb"]) @commands.group(name="globalboard", aliases=["glb"])
async def globalboard(self, ctx: commands.Context): async def globalboard(self, ctx: commands.Context):