aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/seasons/christmas/adventofcode.py69
1 files changed, 46 insertions, 23 deletions
diff --git a/bot/seasons/christmas/adventofcode.py b/bot/seasons/christmas/adventofcode.py
index 5a34d608..fcd3e171 100644
--- a/bot/seasons/christmas/adventofcode.py
+++ b/bot/seasons/christmas/adventofcode.py
@@ -1,10 +1,11 @@
import asyncio
import json
import logging
+import math
import re
from datetime import datetime, timedelta
from pathlib import Path
-from typing import List
+from typing import List, Tuple
import aiohttp
import discord
@@ -12,8 +13,7 @@ from bs4 import BeautifulSoup
from discord.ext import commands
from pytz import timezone
-from bot.constants import AdventOfCode as AocConfig
-from bot.constants import Colours, Emojis, Tokens
+from bot.constants import AdventOfCode as AocConfig, Colours, Emojis, Tokens
log = logging.getLogger(__name__)
@@ -21,6 +21,7 @@ AOC_REQUEST_HEADER = {"user-agent": "PythonDiscord AoC Event Bot"}
AOC_SESSION_COOKIE = {"session": Tokens.aoc_session_cookie}
EST = timezone("EST")
+COUNTDOWN_STEP = 60 * 5
def is_in_advent() -> bool:
@@ -31,7 +32,7 @@ def is_in_advent() -> bool:
return datetime.now(EST).day in range(1, 26) and datetime.now(EST).month == 12
-def time_left_to_aoc_midnight() -> timedelta:
+def time_left_to_aoc_midnight() -> Tuple[datetime, timedelta]:
"""
This calculates the amount of time left until midnight in
UTC-5 (Advent of Code maintainer timezone).
@@ -51,25 +52,32 @@ def time_left_to_aoc_midnight() -> timedelta:
async def countdown_status(bot: commands.Bot):
"""
- Every 2 minutes set the playing status of the bot to
- the number of minutes & hours left until the next day
- release.
+ Every `COUNTDOWN_STEP` seconds set the playing status of the bot to
+ the number of minutes & hours left until the next day's release.
"""
while is_in_advent():
_, time_left = time_left_to_aoc_midnight()
- hours, minutes = time_left.seconds // 3600, time_left.seconds // 60 % 60
-
- if hours == 0:
- game = discord.Game(f"in {minutes} minutes")
+ aligned_seconds = int(math.ceil(time_left.seconds / COUNTDOWN_STEP)) * COUNTDOWN_STEP
+ hours, minutes = aligned_seconds // 3600, aligned_seconds // 60 % 60
+
+ if aligned_seconds == 0:
+ playing = f"right now!"
+ elif aligned_seconds == COUNTDOWN_STEP:
+ playing = f"in less than {minutes} minutes"
+ elif hours == 0:
+ playing = f"in {minutes} minutes"
+ elif hours == 23:
+ playing = f"since {60 - minutes} minutes ago"
else:
- game = discord.Game(f"in {hours} hours and {minutes} minutes")
+ playing = f"in {hours} hours and {minutes} minutes"
# Status will look like "Playing in 5 hours and 30 minutes"
- await bot.change_presence(activity=game)
+ await bot.change_presence(activity=discord.Game(playing))
- # Sleep 2 minutes
- await asyncio.sleep(120)
+ # Sleep until next aligned time or a full step if already aligned
+ delay = time_left.seconds % COUNTDOWN_STEP or COUNTDOWN_STEP
+ await asyncio.sleep(delay)
async def day_countdown(bot: commands.Bot):
@@ -133,23 +141,38 @@ class AdventOfCode:
await ctx.invoke(self.bot.get_command("help"), "adventofcode")
- @adventofcode_group.command(name="notifications", aliases=("notify", "notifs"), brief="Notifications for new days")
- async def aoc_notifications(self, ctx: commands.Context):
+ @adventofcode_group.command(
+ name="subscribe",
+ aliases=("sub", "notifications", "notify", "notifs"),
+ brief="Notifications for new days"
+ )
+ async def aoc_subscribe(self, ctx: commands.Context):
"""
Assign the role for notifications about new days being ready.
+ """
+ role = ctx.guild.get_role(AocConfig.role_id)
+ unsubscribe_command = f"{ctx.prefix}{ctx.command.root_parent} unsubscribe"
+
+ if role not in ctx.author.roles:
+ await ctx.author.add_roles(role)
+ await ctx.send("Okay! You have been __subscribed__ to notifications about new Advent of Code tasks. "
+ f"You can run `{unsubscribe_command}` to disable them again for you.")
+ else:
+ await ctx.send("Hey, you already are receiving notifications about new Advent of Code tasks. "
+ f"If you don't want them any more, run `{unsubscribe_command}` instead.")
- Call the same command again to end notifications and remove the role.
+ @adventofcode_group.command(name="unsubscribe", aliases=("unsub",), brief="Notifications for new days")
+ async def aoc_unsubscribe(self, ctx: commands.Context):
+ """
+ Remove the role for notifications about new days being ready.
"""
role = ctx.guild.get_role(AocConfig.role_id)
if role in ctx.author.roles:
await ctx.author.remove_roles(role)
- await ctx.send("Okay! You have been unsubscribed from notifications. If in future you want to"
- " resubscribe just run this command again.")
+ await ctx.send("Okay! You have been __unsubscribed__ from notifications about new Advent of Code tasks.")
else:
- await ctx.author.add_roles(role)
- await ctx.send("Okay! You have been subscribed to notifications about new Advent of Code tasks."
- " To unsubscribe in future run the same command again.")
+ await ctx.send("Hey, you don't even get any notifications about new Advent of Code tasks currently anyway.")
@adventofcode_group.command(name="countdown", aliases=("count", "c"), brief="Return time left until next day")
async def aoc_countdown(self, ctx: commands.Context):