Skip to content

Commit 36efc13

Browse files
authored
Merge pull request #173 from python-discord/aoc-daily-posting
Add a task to automatically create AoC spoilers daily posts
2 parents 1a67d49 + 9c7bc48 commit 36efc13

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-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: 62 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,30 @@ 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+
return
156+
157+
await aoc_spoilers_channel.create_thread(
158+
name=f"AoC {today.year} | Day {today.day}",
159+
content=f"Spoilers discussion for day {today.day} — <{_helpers.aoc_puzzle_link(today.day)}>",
160+
)
161+
134162
@commands.group(name="adventofcode", aliases=("aoc",))
135163
async def adventofcode_group(self, ctx: commands.Context) -> None:
136164
"""All of the Advent of Code commands."""
@@ -140,7 +168,7 @@ async def adventofcode_group(self, ctx: commands.Context) -> None:
140168
@with_role(Roles.admins, Roles.events_lead, fail_silently=True)
141169
@adventofcode_group.command(
142170
name="completionist_toggle",
143-
aliases=("ct", "toggle"),
171+
aliases=("ct",),
144172
brief="Toggle whether or not the completionist role is issued to new users.",
145173
)
146174
async def completionist_toggle(self, ctx: commands.Context) -> None:
@@ -157,6 +185,38 @@ async def completionist_toggle(self, ctx: commands.Context) -> None:
157185
await _caches.aoc_settings.set(_caches.AoCSettingOption.COMPLETIONIST_ENABLED.value, new_state)
158186
await ctx.send(f":+1: Completionist role issuing is now {state_string}.")
159187

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