|
1 | 1 | import json |
2 | 2 | from datetime import UTC, datetime, timedelta |
3 | 3 | from pathlib import Path |
| 4 | +from typing import Literal |
4 | 5 |
|
5 | 6 | import arrow |
6 | 7 | import discord |
@@ -52,8 +53,13 @@ def __init__(self, bot: SirRobin): |
52 | 53 | self._base_url = f"https://adventofcode.com/{AocConfig.year}" |
53 | 54 | self.global_leaderboard_url = f"https://adventofcode.com/{AocConfig.year}/leaderboard" |
54 | 55 |
|
55 | | - self.about_aoc_filepath = Path("./bot/exts/advent_of_code/about.json") |
56 | | - self.cached_about_aoc = self._build_about_embed() |
| 56 | + self.aoc_files = Path("./bot/exts/advent_of_code/") |
| 57 | + self.cached_about_aoc = self._build_embed_from_json("about") |
| 58 | + self.cached_changes = self._build_embed_from_json("changes_2025") |
| 59 | + self.cached_no_global = self._build_embed_from_json( |
| 60 | + "changes_2025", only_field="What happened to the global leaderboard?" |
| 61 | + ) |
| 62 | + self.cached_no_global.colour = Colours.soft_red |
57 | 63 |
|
58 | 64 | self.scheduler = scheduling.Scheduler(self.__class__.__name__) |
59 | 65 |
|
@@ -410,22 +416,27 @@ async def aoc_leaderboard(self, ctx: commands.Context, *, aoc_name: str | None = |
410 | 416 | await ctx.send(content=f"{header}\n\n{table}", embed=info_embed) |
411 | 417 | return |
412 | 418 |
|
| 419 | + @in_month(Month.DECEMBER, Month.JANUARY, Month.FEBRUARY) |
| 420 | + @adventofcode_group.command( |
| 421 | + name="changes", |
| 422 | + brief="Frequently Asked Questions about Advent of Code changes in 2025", |
| 423 | + ) |
| 424 | + @in_whitelist(channels=AOC_WHITELIST_RESTRICTED, redirect=AOC_REDIRECT) |
| 425 | + async def aoc_changes(self, ctx: commands.Context) -> None: |
| 426 | + """Get answers to frequently asked questions about Advent of Code changes in 2025.""" |
| 427 | + await ctx.send(embed=self.cached_changes) |
| 428 | + |
413 | 429 | @in_month(Month.DECEMBER, Month.JANUARY, Month.FEBRUARY) |
414 | 430 | @adventofcode_group.command( |
415 | 431 | name="global", |
416 | 432 | aliases=("globalboard", "gb"), |
| 433 | + hidden=True, # Global leaderboard no longer exists |
417 | 434 | brief="Get a link to the global leaderboard", |
418 | 435 | ) |
419 | 436 | @in_whitelist(channels=AOC_WHITELIST_RESTRICTED, redirect=AOC_REDIRECT) |
420 | 437 | async def aoc_global_leaderboard(self, ctx: commands.Context) -> None: |
421 | | - """Get a link to the global Advent of Code leaderboard.""" |
422 | | - url = self.global_leaderboard_url |
423 | | - global_leaderboard = discord.Embed( |
424 | | - title="Advent of Code — Global Leaderboard", |
425 | | - description=f"You can find the global leaderboard [here]({url})." |
426 | | - ) |
427 | | - global_leaderboard.set_thumbnail(url=_helpers.AOC_EMBED_THUMBNAIL) |
428 | | - await ctx.send(embed=global_leaderboard) |
| 438 | + # Same behaviour as aoc changes, but change the title to "where's the global leaderboard" |
| 439 | + await ctx.send(embed=self.cached_no_global) |
429 | 440 |
|
430 | 441 | @in_month(Month.DECEMBER, Month.JANUARY, Month.FEBRUARY) |
431 | 442 | @adventofcode_group.command( |
@@ -479,19 +490,39 @@ async def refresh_leaderboard(self, ctx: commands.Context) -> None: |
479 | 490 | else: |
480 | 491 | await ctx.send("\N{OK Hand Sign} Refreshed leaderboard cache!") |
481 | 492 |
|
482 | | - def _build_about_embed(self) -> discord.Embed: |
| 493 | + def _build_embed_from_json( |
| 494 | + self, file_type: Literal["about","changes_2025"], *, only_field: str | None = None |
| 495 | + ) -> discord.Embed: |
483 | 496 | """Build and return the informational "About AoC" embed from the resources file.""" |
484 | | - embed_fields = json.loads(self.about_aoc_filepath.read_text("utf8")) |
| 497 | + if file_type == "about": |
| 498 | + filepath = self.aoc_files / "about.json" |
| 499 | + title = "Advent of Code" |
| 500 | + url = self._base_url |
| 501 | + colour = Colours.soft_green |
| 502 | + |
| 503 | + elif file_type == "changes_2025": |
| 504 | + filepath = self.aoc_files / "changes_2025.json" |
| 505 | + title = "2025 Changes" |
| 506 | + url = None |
| 507 | + colour = Colours.aoc_violet |
| 508 | + else: |
| 509 | + raise ValueError("file_type must be either 'about' or 'changes_2025'") |
485 | 510 |
|
486 | | - about_embed = discord.Embed( |
487 | | - title=self._base_url, |
488 | | - colour=Colours.soft_green, |
489 | | - url=self._base_url, |
490 | | - timestamp=datetime.now(tz=UTC) |
491 | | - ) |
492 | | - about_embed.set_author(name="Advent of Code", url=self._base_url) |
493 | | - for field in embed_fields: |
494 | | - about_embed.add_field(**field) |
| 511 | + embed = discord.Embed(title=title, url=url, colour=colour, timestamp=datetime.now(tz=UTC)) |
| 512 | + |
| 513 | + embed_fields = json.loads(filepath.read_text("utf8")) |
| 514 | + |
| 515 | + if only_field: |
| 516 | + embed_fields = [field for field in embed_fields if field["name"] == only_field] |
| 517 | + if not embed_fields: |
| 518 | + raise ValueError(f"No field named '{only_field}' found in {file_type}.json") |
| 519 | + embed.title = only_field |
| 520 | + embed.description = embed_fields[0]["value"] |
| 521 | + else: |
| 522 | + for field in embed_fields: |
| 523 | + embed.add_field(**field) |
| 524 | + |
| 525 | + embed.set_author(name="Advent of Code", url=self._base_url) |
| 526 | + embed.set_footer(text="Last Updated") |
495 | 527 |
|
496 | | - about_embed.set_footer(text="Last Updated") |
497 | | - return about_embed |
| 528 | + return embed |
0 commit comments