Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bot/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def _parse_aoc_leaderboard_env() -> dict[str, AdventOfCodeLeaderboard]:
class _Channels(EnvConfig, env_prefix="CHANNEL_"):
advent_of_code: int = 897932085766004786
advent_of_code_commands: int = 897932607545823342
advent_of_code_spoilers: int = 1047673173447020564
bot_commands: int = 267659945086812160
devlog: int = 622895325144940554
code_jam_planning: int = 490217981872177157
Expand Down
1 change: 1 addition & 0 deletions bot/exts/advent_of_code/_caches.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class AoCSettingOption(Enum):
COMPLETIONIST_ENABLED = "completionist_enabled"
AUTO_POSTING_ENABLED = "auto_posting_enabled"


# How many people are in each leaderboard
Expand Down
64 changes: 62 additions & 2 deletions bot/exts/advent_of_code/_cog.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
from datetime import UTC, datetime, timedelta
from datetime import UTC, datetime, time, timedelta
from pathlib import Path
from zoneinfo import ZoneInfo

import arrow
import discord
Expand Down Expand Up @@ -79,6 +80,9 @@ async def cog_load(self) -> None:
if await _caches.aoc_settings.get(_caches.AoCSettingOption.COMPLETIONIST_ENABLED.value):
self.completionist_task.start()

if await _caches.aoc_settings.get(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value):
self.daily_posting_task.start()

@tasks.loop(minutes=10.0)
async def completionist_task(self) -> None:
"""
Expand Down Expand Up @@ -131,6 +135,30 @@ async def completionist_task(self) -> None:
log.debug(f"Giving completionist role to {member.name} ({member.mention}).")
await members.handle_role_change(member, member.add_roles, completionist_role)

@tasks.loop(time=time(0, 0, 0, tzinfo=ZoneInfo(_helpers.EST)))
async def daily_posting_task(self) -> None:
"""
Create a spoilers post for the new puzzle posted at this time.

Runs every day at midnight EST during the event.
"""
today = arrow.now(_helpers.EST).date()

if not _helpers.is_in_advent():
log.info("AoC daily posting is on, but it's not the AoC period. Skipping.")
return

guild = self.bot.get_guild(Bot.guild)
aoc_spoilers_channel: discord.ForumChannel = guild.get_channel(Channels.advent_of_code_spoilers)
if not aoc_spoilers_channel:
log.info("Couldn't find the AoC spoilers channel. Skipping.")
return

await aoc_spoilers_channel.create_thread(
name=f"AoC {today.year} | Day {today.day}",
content=f"Spoilers discussion for day {today.day} — <{_helpers.aoc_puzzle_link(today.day)}>",
)

@commands.group(name="adventofcode", aliases=("aoc",))
async def adventofcode_group(self, ctx: commands.Context) -> None:
"""All of the Advent of Code commands."""
Expand All @@ -140,7 +168,7 @@ async def adventofcode_group(self, ctx: commands.Context) -> None:
@with_role(Roles.admins, Roles.events_lead, fail_silently=True)
@adventofcode_group.command(
name="completionist_toggle",
aliases=("ct", "toggle"),
aliases=("ct",),
brief="Toggle whether or not the completionist role is issued to new users.",
)
async def completionist_toggle(self, ctx: commands.Context) -> None:
Expand All @@ -157,6 +185,38 @@ async def completionist_toggle(self, ctx: commands.Context) -> None:
await _caches.aoc_settings.set(_caches.AoCSettingOption.COMPLETIONIST_ENABLED.value, new_state)
await ctx.send(f":+1: Completionist role issuing is now {state_string}.")

@with_role(Roles.admins, Roles.events_lead, fail_silently=True)
@adventofcode_group.command(
name="posting_toggle",
aliases=("pt",),
)
async def daily_posting_toggle(self, ctx: commands.Context) -> None:
"""Toggle whether a daily post is to be created every midnight EST throughout the event."""
current_state = await _caches.aoc_settings.get(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value)
new_state = not current_state
if new_state:
self.daily_posting_task.start()
state_string = "on"
else:
self.daily_posting_task.cancel()
state_string = "off"

await _caches.aoc_settings.set(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value, new_state)
await ctx.send(f":+1: Daily posting is now {state_string}.")

@with_role(Roles.admins, Roles.events_lead, fail_silently=True)
@adventofcode_group.command()
async def status(self, ctx: commands.Context) -> None:
"""Show status of the AoC cog."""
completionist_state = await _caches.aoc_settings.get(_caches.AoCSettingOption.COMPLETIONIST_ENABLED.value)
daily_posting_state = await _caches.aoc_settings.get(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value)

embed = discord.Embed(title="AoC Cog Status", colour=discord.Colour.green())
embed.add_field(name="Completionist role", value="On" if completionist_state else "Off")
embed.add_field(name="Daily posting", value="On" if daily_posting_state else "Off")

await ctx.reply(embed=embed)

@with_role(Roles.admins, fail_silently=True)
@adventofcode_group.command(
name="block",
Expand Down
7 changes: 6 additions & 1 deletion bot/exts/advent_of_code/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,11 @@ async def countdown_status(bot: SirRobin) -> None:
await asyncio.sleep(delay)


def aoc_puzzle_link(day: int) -> str:
"""Get a link to the AoC puzzle page for the given day."""
return f"https://adventofcode.com/{AdventOfCode.year}/day/{day}"


async def new_puzzle_notification(bot: SirRobin) -> None:
"""Announce the release of a new Advent of Code puzzle when published."""
log.info("The Advent of Code has started or will start soon, waking up notification task.")
Expand Down Expand Up @@ -584,7 +589,7 @@ async def new_puzzle_notification(bot: SirRobin) -> None:
log.trace(f"The puzzle notification task will sleep for {sleep_seconds} seconds")
await asyncio.sleep(sleep_seconds)

puzzle_url = f"https://adventofcode.com/{AdventOfCode.year}/day/{tomorrow.day}"
puzzle_url = aoc_puzzle_link(tomorrow.day)

# Check if the puzzle is already available to prevent our members from spamming
# the puzzle page before it's available by making a small HEAD request.
Expand Down