diff options
Diffstat (limited to 'bot')
| -rw-r--r-- | bot/seasons/christmas/adventofcode.py | 69 | 
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):  |