Skip to content

Commit 756835a

Browse files
feat: always show the leaderboard even if the provided user isn't in the leaderboard
closes GH-137
1 parent 3f02057 commit 756835a

File tree

2 files changed

+57
-20
lines changed

2 files changed

+57
-20
lines changed

bot/exts/advent_of_code/_cog.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -385,28 +385,49 @@ async def aoc_leaderboard(self, ctx: commands.Context, *, aoc_name: str | None =
385385
aoc_name = aoc_name[1:-1]
386386

387387
# Check if an advent of code account is linked in the Redis Cache if aoc_name is not given
388+
is_explict_name: bool = bool(aoc_name)
388389
if (aoc_cache_name := await _caches.account_links.get(ctx.author.id)) and aoc_name is None:
389390
aoc_name = aoc_cache_name
390391

392+
name_not_found: bool = False
391393
async with ctx.typing():
392394
try:
393-
leaderboard = await _helpers.fetch_leaderboard(self_placement_name=aoc_name)
395+
try:
396+
leaderboard = await _helpers.fetch_leaderboard(
397+
self_placement_name=aoc_name, use_you_for_placement=not is_explict_name
398+
)
399+
except _helpers.UserNotInLeaderboardError:
400+
if is_explict_name:
401+
raise commands.BadArgument("Sorry, the provided profile does not exist in this leaderboard.")
402+
aoc_name = None
403+
name_not_found = True
404+
leaderboard = await _helpers.fetch_leaderboard()
394405
except _helpers.FetchingLeaderboardFailedError:
395406
await ctx.send(":x: Unable to fetch leaderboard!")
396407
return
397408

398409
number_of_participants = leaderboard["number_of_participants"]
399410

400411
top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants)
401-
self_placement_header = " (and your personal stats compared to the top 10)" if aoc_name else ""
402-
header = f"Here's our current top {top_count}{self_placement_header}! {Emojis.christmas_tree * 3}"
412+
header = ""
413+
if name_not_found:
414+
header += (
415+
f"\n:x: Your linked Advent of Code account '{aoc_cache_name}' was not found in the leaderboard."
416+
" Showing top leaderboard only. "
417+
"Wait up to 30 minutes after joining the leaderboard for your stats to appear.\n\n"
418+
)
419+
header += f"Here's our current top {top_count}"
420+
if aoc_name:
421+
header += (
422+
f" (and {'the requested user (\U0001f536)' if is_explict_name else 'your'}"
423+
" personal stats compared to the top 10)"
424+
)
425+
header += f"! {Emojis.christmas_tree * 3}"
403426
table = (
404-
"```\n"
405-
f"{leaderboard['placement_leaderboard'] if aoc_name else leaderboard['top_leaderboard']}"
406-
"\n```"
427+
f"```\n{leaderboard['placement_leaderboard'] if aoc_name else leaderboard['top_leaderboard']} \n```"
407428
)
408-
info_embed = _helpers.get_summary_embed(leaderboard)
409429

430+
info_embed = _helpers.get_summary_embed(leaderboard)
410431
await ctx.send(content=f"{header}\n\n{table}", embed=info_embed)
411432
return
412433

bot/exts/advent_of_code/_helpers.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import aiohttp
1010
import arrow
1111
import discord
12-
from discord.ext import commands
1312
from pydis_core.utils import logging, paste_service
1413

1514
import bot
@@ -69,6 +68,10 @@ class FetchingLeaderboardFailedError(Exception):
6968
"""Raised when one or more leaderboards could not be fetched at all."""
7069

7170

71+
class UserNotInLeaderboardError(Exception):
72+
"""Raised when a user is not found in the requested leaderboard."""
73+
74+
7275
def leaderboard_sorting_function(entry: tuple[str, dict]) -> tuple[int, int]:
7376
"""
7477
Provide a sorting value for our leaderboard.
@@ -159,20 +162,29 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
159162
return {"daily_stats": daily_stats, "leaderboard": sorted_leaderboard, "per_day_and_star": per_day_star_stats}
160163

161164

162-
def _format_leaderboard(leaderboard: dict[str, dict], self_placement_name: str | None = None) -> str:
165+
def _format_leaderboard(
166+
leaderboard: dict[str, dict],
167+
self_placement_name: str | None = None,
168+
*,
169+
use_you_for_placement: bool = True,
170+
) -> str:
163171
"""Format the leaderboard using the AOC_TABLE_TEMPLATE."""
164172
leaderboard_lines = [HEADER]
165173
self_placement_exists = False
166174
for rank, data in enumerate(leaderboard.values(), start=1):
167175
if self_placement_name and data["name"].lower() == self_placement_name.lower():
176+
if use_you_for_placement:
177+
name = f"(You) {data['name']}"
178+
else:
179+
name = f"(\U0001f536) {data['name']}"
168180
leaderboard_lines.insert(
169181
1,
170182
AOC_TABLE_TEMPLATE.format(
171183
rank=rank,
172-
name=f"(You) {data['name']}",
184+
name=name,
173185
score=str(data["score"]),
174-
stars=f"({data['star_1']}, {data['star_2']})"
175-
)
186+
stars=f"({data['star_1']}, {data['star_2']})",
187+
),
176188
)
177189
self_placement_exists = True
178190
continue
@@ -185,12 +197,7 @@ def _format_leaderboard(leaderboard: dict[str, dict], self_placement_name: str |
185197
)
186198
)
187199
if self_placement_name and not self_placement_exists:
188-
raise commands.BadArgument(
189-
"Sorry, your profile does not exist in this leaderboard."
190-
"\n\n"
191-
"To join our leaderboard, run the command `/aoc join`."
192-
" If you've joined recently, please wait up to 30 minutes for our leaderboard to refresh."
193-
)
200+
raise UserNotInLeaderboardError
194201
return "\n".join(leaderboard_lines)
195202

196203

@@ -285,7 +292,12 @@ def _get_top_leaderboard(full_leaderboard: str) -> str:
285292

286293

287294
@_caches.leaderboard_cache.atomic_transaction
288-
async def fetch_leaderboard(invalidate_cache: bool = False, self_placement_name: str | None = None) -> dict:
295+
async def fetch_leaderboard(
296+
invalidate_cache: bool = False,
297+
self_placement_name: str | None = None,
298+
*,
299+
use_you_for_placement: bool = True,
300+
) -> dict:
289301
"""
290302
Get the current Python Discord combined leaderboard.
291303
@@ -337,7 +349,11 @@ async def fetch_leaderboard(invalidate_cache: bool = False, self_placement_name:
337349
json.loads(cached_leaderboard["placement_leaderboard"])
338350
)["leaderboard"]
339351
cached_leaderboard["placement_leaderboard"] = _get_top_leaderboard(
340-
_format_leaderboard(formatted_placement_leaderboard, self_placement_name=self_placement_name)
352+
_format_leaderboard(
353+
formatted_placement_leaderboard,
354+
self_placement_name=self_placement_name,
355+
use_you_for_placement=use_you_for_placement,
356+
)
341357
)
342358
return cached_leaderboard
343359

0 commit comments

Comments
 (0)