diff --git a/leaderboard/leaderboard.py b/leaderboard/leaderboard.py index ad53830..3818b41 100644 --- a/leaderboard/leaderboard.py +++ b/leaderboard/leaderboard.py @@ -87,7 +87,12 @@ class Leaderboard(commands.Cog): "cooldown": 60, } + default_user = { + "opted_out": False + } + self.config.register_guild(**default_guild) + self.config.register_user(**default_user) async def initialize(self): """Initialize optional API connection.""" @@ -106,8 +111,7 @@ class Leaderboard(commands.Cog): async def get_user_credits(self, user: discord.Member) -> int: """Get a user's total credits from Red's bank system.""" try: - # For per-server banks, get the balance from the user's current guild - return await bank.get_balance(user, guild=user.guild) + return await bank.get_balance(user) except Exception as e: log.error(f"Error getting bank balance for {user}: {e}") return 0 @@ -115,16 +119,21 @@ class Leaderboard(commands.Cog): async def get_all_balances(self) -> List[dict]: """Get all users' credit balances across all servers.""" all_users = {} + min_credits = 10000 # Minimum credits to show on leaderboard # Collect all unique members and sum their balances across all guilds for guild in self.bot.guilds: for member in guild.members: if member.bot: continue + + # Skip opted-out users + if await self.config.user(member).opted_out(): + continue try: # Get balance for this guild - credits = await bank.get_balance(member, guild=guild) + credits = await bank.get_balance(member) if member.id not in all_users: all_users[member.id] = { @@ -140,9 +149,9 @@ class Leaderboard(commands.Cog): log.error(f"Error getting balance for {member} in {guild}: {e}") continue - # Filter out users with no credits and sort by total + # Filter out users with less than minimum credits and sort by total sorted_users = sorted( - [user for user in all_users.values() if user["points"] > 0], + [user for user in all_users.values() if user["points"] >= min_credits], key=lambda x: x["points"], reverse=True ) @@ -185,19 +194,20 @@ class Leaderboard(commands.Cog): leaderboard_data = await self.get_all_balances() if not leaderboard_data: - return await ctx.send("The leaderboard is currently empty!") + return await ctx.send("No users have 10,000 or more credits!") items_per_page = 10 chunks = [leaderboard_data[i:i + items_per_page] for i in range(0, len(leaderboard_data), items_per_page)] if not chunks: - return await ctx.send("The leaderboard is currently empty!") + return await ctx.send("No users have 10,000 or more credits!") embeds = [] for page_num, entries in enumerate(chunks, 1): embed = discord.Embed( title="🏆 Global Credits Leaderboard", + description="*Only showing users with 10,000+ credits*", color=await ctx.embed_color() ) @@ -213,17 +223,52 @@ class Leaderboard(commands.Cog): f"`{i}.` <@{user_id}> • **{humanize_number(credits)}** credits" ) - embed.description = "\n".join(description) + embed.description = embed.description + "\n\n" + "\n".join(description) embed.set_footer(text=f"Page {page_num}/{len(chunks)} • Total Users: {len(leaderboard_data)}") embeds.append(embed) view = LeaderboardView(self, ctx, embeds) view.message = await ctx.send(embed=embeds[0], view=view) + @globalboard.command(name="optout") + async def opt_out(self, ctx: commands.Context): + """Opt out of the global leaderboard. Your credits will no longer be visible.""" + user_settings = self.config.user(ctx.author) + current_status = await user_settings.opted_out() + + if current_status: + await ctx.send("You are already opted out of the global leaderboard.") + return + + await user_settings.opted_out.set(True) + await ctx.send("You have been opted out of the global leaderboard. Your credits will no longer be visible.") + + @globalboard.command(name="optin") + async def opt_in(self, ctx: commands.Context): + """Opt back into the global leaderboard.""" + user_settings = self.config.user(ctx.author) + current_status = await user_settings.opted_out() + + if not current_status: + await ctx.send("You are already opted into the global leaderboard.") + return + + await user_settings.opted_out.set(False) + await ctx.send("You have been opted back into the global leaderboard. Your credits will now be visible.") + @globalboard.command(name="credits") async def check_credits(self, ctx: commands.Context, member: commands.MemberConverter = None): """Check your credits or another member's credits.""" member = member or ctx.author + + # Check if the target user has opted out + if await self.config.user(member).opted_out(): + if member == ctx.author: + await ctx.send("You have opted out of the global leaderboard. Use `[p]globalboard optin` to show your credits again.") + else: + await ctx.send(f"{member.display_name} has opted out of the global leaderboard.") + return + credits = await self.get_user_credits(member) # Get user's rank @@ -239,7 +284,7 @@ class Leaderboard(commands.Cog): color=await ctx.embed_color() ) - if credits > 0: + if credits >= 10000: embed.description = ( f"**User:** <@{member.id}>\n" f"**Credits:** {humanize_number(credits)}\n" @@ -247,7 +292,7 @@ class Leaderboard(commands.Cog): f"**ID:** {member.id}" ) else: - embed.description = f"<@{member.id}> has no credits yet!" + embed.description = f"<@{member.id}> has less than 10,000 credits." embed.set_thumbnail(url=member.display_avatar.url) await ctx.send(embed=embed)