Skip to content

Commit fb4763c

Browse files
committed
Add a task to automatically create AoC spoilers daily posts
1 parent 1a67d49 commit fb4763c

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

bot/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def _parse_aoc_leaderboard_env() -> dict[str, AdventOfCodeLeaderboard]:
8484
class _Channels(EnvConfig, env_prefix="CHANNEL_"):
8585
advent_of_code: int = 897932085766004786
8686
advent_of_code_commands: int = 897932607545823342
87+
advent_of_code_spoilers: int = 1047673173447020564
8788
bot_commands: int = 267659945086812160
8889
devlog: int = 622895325144940554
8990
code_jam_planning: int = 490217981872177157

bot/exts/advent_of_code/_caches.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
class AoCSettingOption(Enum):
77
COMPLETIONIST_ENABLED = "completionist_enabled"
8+
AUTO_POSTING_ENABLED = "auto_posting_enabled"
89

910

1011
# How many people are in each leaderboard

bot/exts/advent_of_code/_cog.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
2-
from datetime import UTC, datetime, timedelta
2+
from datetime import UTC, datetime, time, timedelta
33
from pathlib import Path
4+
from zoneinfo import ZoneInfo
45

56
import arrow
67
import discord
@@ -79,6 +80,9 @@ async def cog_load(self) -> None:
7980
if await _caches.aoc_settings.get(_caches.AoCSettingOption.COMPLETIONIST_ENABLED.value):
8081
self.completionist_task.start()
8182

83+
if await _caches.aoc_settings.get(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value):
84+
self.daily_posting_task.start()
85+
8286
@tasks.loop(minutes=10.0)
8387
async def completionist_task(self) -> None:
8488
"""
@@ -131,6 +135,29 @@ async def completionist_task(self) -> None:
131135
log.debug(f"Giving completionist role to {member.name} ({member.mention}).")
132136
await members.handle_role_change(member, member.add_roles, completionist_role)
133137

138+
@tasks.loop(time=time(0, 0, 0, tzinfo=ZoneInfo(_helpers.EST)))
139+
async def daily_posting_task(self) -> None:
140+
"""
141+
Create a spoilers post for the new puzzle posted at this time.
142+
143+
Runs every day at midnight EST during the event.
144+
"""
145+
today = arrow.now(_helpers.EST).date()
146+
147+
if not _helpers.is_in_advent():
148+
log.info("AoC daily posting is on, but it's not the AoC period. Skipping.")
149+
return
150+
151+
guild = self.bot.get_guild(Bot.guild)
152+
aoc_spoilers_channel: discord.ForumChannel = guild.get_channel(Channels.advent_of_code_spoilers)
153+
if not aoc_spoilers_channel:
154+
log.info("Couldn't find the AoC spoilers channel. Skipping.")
155+
156+
await aoc_spoilers_channel.create_thread(
157+
name=f"AoC {today.year} | Day {today.day}",
158+
content=f"Spoilers discussion for day {today.day} — <{_helpers.aoc_puzzle_link(today.day)}>",
159+
)
160+
134161
@commands.group(name="adventofcode", aliases=("aoc",))
135162
async def adventofcode_group(self, ctx: commands.Context) -> None:
136163
"""All of the Advent of Code commands."""
@@ -140,7 +167,7 @@ async def adventofcode_group(self, ctx: commands.Context) -> None:
140167
@with_role(Roles.admins, Roles.events_lead, fail_silently=True)
141168
@adventofcode_group.command(
142169
name="completionist_toggle",
143-
aliases=("ct", "toggle"),
170+
aliases=("ct",),
144171
brief="Toggle whether or not the completionist role is issued to new users.",
145172
)
146173
async def completionist_toggle(self, ctx: commands.Context) -> None:
@@ -157,6 +184,38 @@ async def completionist_toggle(self, ctx: commands.Context) -> None:
157184
await _caches.aoc_settings.set(_caches.AoCSettingOption.COMPLETIONIST_ENABLED.value, new_state)
158185
await ctx.send(f":+1: Completionist role issuing is now {state_string}.")
159186

187+
@with_role(Roles.admins, Roles.events_lead, fail_silently=True)
188+
@adventofcode_group.command(
189+
name="posting_toggle",
190+
aliases=("pt",),
191+
)
192+
async def daily_posting_toggle(self, ctx: commands.Context) -> None:
193+
"""Toggle whether a daily post is to be created every midnight EST throughout the event."""
194+
current_state = await _caches.aoc_settings.get(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value)
195+
new_state = not current_state
196+
if new_state:
197+
self.daily_posting_task.start()
198+
state_string = "on"
199+
else:
200+
self.daily_posting_task.cancel()
201+
state_string = "off"
202+
203+
await _caches.aoc_settings.set(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value, new_state)
204+
await ctx.send(f":+1: Daily posting is now {state_string}.")
205+
206+
@with_role(Roles.admins, Roles.events_lead, fail_silently=True)
207+
@adventofcode_group.command()
208+
async def status(self, ctx: commands.Context) -> None:
209+
"""Show status of the AoC cog."""
210+
completionist_state = await _caches.aoc_settings.get(_caches.AoCSettingOption.COMPLETIONIST_ENABLED.value)
211+
daily_posting_state = await _caches.aoc_settings.get(_caches.AoCSettingOption.AUTO_POSTING_ENABLED.value)
212+
213+
embed = discord.Embed(title="AoC Cog Status", colour=discord.Colour.green())
214+
embed.add_field(name="Completionist role", value="On" if completionist_state else "Off")
215+
embed.add_field(name="Daily posting", value="On" if daily_posting_state else "Off")
216+
217+
await ctx.reply(embed=embed)
218+
160219
@with_role(Roles.admins, fail_silently=True)
161220
@adventofcode_group.command(
162221
name="block",

bot/exts/advent_of_code/_helpers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,11 @@ async def countdown_status(bot: SirRobin) -> None:
555555
await asyncio.sleep(delay)
556556

557557

558+
def aoc_puzzle_link(day: int) -> str:
559+
"""Get a link to the AoC puzzle page for the given day."""
560+
return f"https://adventofcode.com/{AdventOfCode.year}/day/{day}"
561+
562+
558563
async def new_puzzle_notification(bot: SirRobin) -> None:
559564
"""Announce the release of a new Advent of Code puzzle when published."""
560565
log.info("The Advent of Code has started or will start soon, waking up notification task.")
@@ -584,7 +589,7 @@ async def new_puzzle_notification(bot: SirRobin) -> None:
584589
log.trace(f"The puzzle notification task will sleep for {sleep_seconds} seconds")
585590
await asyncio.sleep(sleep_seconds)
586591

587-
puzzle_url = f"https://adventofcode.com/{AdventOfCode.year}/day/{tomorrow.day}"
592+
puzzle_url = aoc_puzzle_link(tomorrow.day)
588593

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

0 commit comments

Comments
 (0)