From 598ba443d504cf680335bf53a373fc991ebb0074 Mon Sep 17 00:00:00 2001 From: Conatum Date: Mon, 28 Aug 2023 23:45:17 +0300 Subject: [PATCH] fix (stats): Filter leaderboard. --- src/modules/statistics/cog.py | 21 ++++++++++++++++-- src/modules/statistics/ui/leaderboard.py | 27 +++++++++++++++++++----- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/modules/statistics/cog.py b/src/modules/statistics/cog.py index f5f241bd..b778f039 100644 --- a/src/modules/statistics/cog.py +++ b/src/modules/statistics/cog.py @@ -8,7 +8,7 @@ from discord.ui.button import ButtonStyle from meta import LionBot, LionCog, LionContext from utils.lib import error_embed -from utils.ui import LeoUI, AButton +from utils.ui import LeoUI, AButton, utc_now from wards import low_management_ward from . import babel @@ -76,7 +76,24 @@ class StatsCog(LionCog): ) @appcmds.guild_only async def leaderboard_cmd(self, ctx: LionContext): - await ctx.interaction.response.defer(thinking=True) + if not ctx.guild: + return + if not ctx.interaction: + return + if not ctx.guild.chunked: + t = self.bot.translator.t + waiting_embed = discord.Embed( + colour=discord.Colour.greyple(), + description=t(_p( + 'cmd:leaderboard|chunking|desc', + "Requesting server member list from Discord, please wait {loading}" + )).format(loading=self.bot.config.emojis.loading), + timestamp=utc_now(), + ) + await ctx.interaction.response(embed=waiting_embed) + await ctx.guild.chunk() + else: + await ctx.interaction.response.defer(thinking=True) ui = LeaderboardUI(self.bot, ctx.author, ctx.guild) await ui.run(ctx.interaction) await ui.wait() diff --git a/src/modules/statistics/ui/leaderboard.py b/src/modules/statistics/ui/leaderboard.py index 4d9668d1..4abbbfcc 100644 --- a/src/modules/statistics/ui/leaderboard.py +++ b/src/modules/statistics/ui/leaderboard.py @@ -130,9 +130,22 @@ class LeaderboardUI(StatsUI): ) else: # TODO: Anki data - ... - # TODO: Handle removing members in invisible roles - return data + data = [] + + # Filter out members which are not in the server and unranked roles and bots + # Usually hits cache + unranked_setting = await self.bot.get_cog('StatsCog').settings.UnrankedRoles.get(self.guild.id) + unranked_roleids = set(unranked_setting.data) + true_leaderboard = [] + guild = self.guild + for userid, stat_total in data: + if member := guild.get_member(userid): + if member.bot: + continue + if any(role.id in unranked_roleids for role in member.roles): + continue + true_leaderboard.append((userid, stat_total)) + return true_leaderboard async def fetch_lb_data(self, stat_type, period): """ @@ -148,6 +161,7 @@ class LeaderboardUI(StatsUI): future = asyncio.create_task(self._fetch_lb_data(*key)) self.lb_data[key] = future result = await future + return result async def current_data(self): @@ -163,7 +177,10 @@ class LeaderboardUI(StatsUI): if data: # Calculate page data page_starts_at = pagen * self.page_size - userids, times = zip(*data[page_starts_at:page_starts_at + self.page_size]) + page_data = data[page_starts_at:page_starts_at + self.page_size] + if not page_data: + return None + userids, times = zip(*page_data) positions = range(page_starts_at + 1, page_starts_at + self.page_size + 1) page_data = zip(userids, positions, times) @@ -196,7 +213,7 @@ class LeaderboardUI(StatsUI): """ lb_data = await self.fetch_lb_data(stat_type, period) if lb_data: - pagen %= (len(lb_data) // self.page_size) + 1 + pagen %= (len(lb_data) // self.page_size) + (1 if len(lb_data) % self.page_size else 0) else: pagen = 0 key = (stat_type, period, pagen)