diff options
-rw-r--r-- | bot/exts/events/advent_of_code/_cog.py | 72 | ||||
-rw-r--r-- | bot/exts/events/advent_of_code/_helpers.py | 25 |
2 files changed, 66 insertions, 31 deletions
diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 2c1f4541..7f35c306 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -180,24 +180,18 @@ class AdventOfCode(commands.Cog): @in_month(Month.DECEMBER) @adventofcode_group.command( - name="leaderboard", - aliases=("board", "lb"), - brief="Get a snapshot of the PyDis private AoC leaderboard", + name="dayandstar", + aliases=("daynstar", "daystar"), + brief="Get a view that lets you filter the leaderboard by day and star", ) @whitelist_override(channels=AOC_WHITELIST_RESTRICTED) - async def aoc_leaderboard( + async def aoc_day_and_star_leaderboard( self, ctx: commands.Context, - day_and_star: Optional[bool] = False, - maximum_scorers: Optional[int] = 10 + maximum_scorers_day_and_star: Optional[int] = 10 ) -> None: - """ - Get the current top scorers of the Python Discord Leaderboard. - - Additionally, you can provide an argument `day_and_star` (Boolean) to have the bot send a View - that will let you filter by day and star. - """ - if maximum_scorers > AocConfig.max_day_and_star_results or maximum_scorers <= 0: + """Have the bot send a View that will let you filter the leaderboard by day and star.""" + if maximum_scorers_day_and_star > AocConfig.max_day_and_star_results or maximum_scorers_day_and_star <= 0: raise commands.BadArgument( f"The maximum number of results you can query is {AocConfig.max_day_and_star_results}" ) @@ -207,25 +201,12 @@ class AdventOfCode(commands.Cog): except _helpers.FetchingLeaderboardFailedError: await ctx.send(":x: Unable to fetch leaderboard!") return - if not day_and_star: - - number_of_participants = leaderboard["number_of_participants"] - - top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants) - header = f"Here's our current top {top_count}! {Emojis.christmas_tree * 3}" - - table = f"```\n{leaderboard['top_leaderboard']}\n```" - info_embed = _helpers.get_summary_embed(leaderboard) - - await ctx.send(content=f"{header}\n\n{table}", embed=info_embed) - return - # This is a dictionary that contains solvers in respect of day, and star. # e.g. 1-1 means the solvers of the first star of the first day and their completion time per_day_and_star = json.loads(leaderboard['leaderboard_per_day_and_star']) view = AoCDropdownView( day_and_star_data=per_day_and_star, - maximum_scorers=maximum_scorers, + maximum_scorers=maximum_scorers_day_and_star, original_author=ctx.author ) message = await ctx.send( @@ -237,6 +218,43 @@ class AdventOfCode(commands.Cog): @in_month(Month.DECEMBER) @adventofcode_group.command( + name="leaderboard", + aliases=("board", "lb"), + brief="Get a snapshot of the PyDis private AoC leaderboard", + ) + @whitelist_override(channels=AOC_WHITELIST_RESTRICTED) + async def aoc_leaderboard( + self, + ctx: commands.Context, + self_placement_name: Optional[str] = None, + ) -> None: + """ + Get the current top scorers of the Python Discord Leaderboard. + + Additionaly you can specify a `self_placement_name` + that will append the specified profile's personal stats to the top of the leaderboard + """ + async with ctx.typing(): + try: + leaderboard = await _helpers.fetch_leaderboard(self_placement_name=self_placement_name) + except _helpers.FetchingLeaderboardFailedError: + await ctx.send(":x: Unable to fetch leaderboard!") + return + + number_of_participants = leaderboard["number_of_participants"] + + top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants) + self_placement_header = "(and your personal stats compared to the top 10)" if self_placement_name else "" + header = f"Here's our current top {top_count}{self_placement_header}! {Emojis.christmas_tree * 3}" + + table = f"```\n{leaderboard['top_leaderboard']}\n```" + info_embed = _helpers.get_summary_embed(leaderboard) + + await ctx.send(content=f"{header}\n\n{table}", embed=info_embed) + return + + @in_month(Month.DECEMBER) + @adventofcode_group.command( name="global", aliases=("globalboard", "gb"), brief="Get a link to the global leaderboard", diff --git a/bot/exts/events/advent_of_code/_helpers.py b/bot/exts/events/advent_of_code/_helpers.py index af64bc81..58fc3054 100644 --- a/bot/exts/events/advent_of_code/_helpers.py +++ b/bot/exts/events/advent_of_code/_helpers.py @@ -10,6 +10,7 @@ from typing import Any, Optional import aiohttp import arrow import discord +from discord.ext import commands from bot.bot import Bot from bot.constants import AdventOfCode, Channels, Colours @@ -160,10 +161,23 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict: return {"daily_stats": daily_stats, "leaderboard": sorted_leaderboard, 'per_day_and_star': per_day_star_stats} -def _format_leaderboard(leaderboard: dict[str, dict]) -> str: +def _format_leaderboard(leaderboard: dict[str, dict], self_placement_name: str = None) -> str: """Format the leaderboard using the AOC_TABLE_TEMPLATE.""" leaderboard_lines = [HEADER] + self_placement_exists = False for rank, data in enumerate(leaderboard.values(), start=1): + if self_placement_name and data["name"].lower() == self_placement_name.lower(): + leaderboard_lines.insert( + 1, + AOC_TABLE_TEMPLATE.format( + rank=rank, + name=f"(You) {data['name']}", + score=str(data["score"]), + stars=f"({data['star_1']}, {data['star_2']})" + ) + ) + self_placement_exists = True + continue leaderboard_lines.append( AOC_TABLE_TEMPLATE.format( rank=rank, @@ -172,7 +186,10 @@ def _format_leaderboard(leaderboard: dict[str, dict]) -> str: stars=f"({data['star_1']}, {data['star_2']})" ) ) - + if self_placement_name and not self_placement_exists: + raise commands.BadArgument( + "Sorry, your profile does not exist in this leaderboard." + ) return "\n".join(leaderboard_lines) @@ -260,7 +277,7 @@ def _get_top_leaderboard(full_leaderboard: str) -> str: @_caches.leaderboard_cache.atomic_transaction -async def fetch_leaderboard(invalidate_cache: bool = False) -> dict: +async def fetch_leaderboard(invalidate_cache: bool = False, self_placement_name: str = None) -> dict: """ Get the current Python Discord combined leaderboard. @@ -284,7 +301,7 @@ async def fetch_leaderboard(invalidate_cache: bool = False) -> dict: leaderboard = parsed_leaderboard_data["leaderboard"] number_of_participants = len(leaderboard) - formatted_leaderboard = _format_leaderboard(leaderboard) + formatted_leaderboard = _format_leaderboard(leaderboard, self_placement_name) full_leaderboard_url = await _upload_leaderboard(formatted_leaderboard) leaderboard_fetched_at = datetime.datetime.utcnow().isoformat() |