aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/christmas/advent_of_code
diff options
context:
space:
mode:
authorGravatar Kieran Siek <[email protected]>2021-06-07 17:16:15 +0800
committerGravatar GitHub <[email protected]>2021-06-07 17:16:15 +0800
commite73fb4a2ced2fd264ec65a828c114cbbeda26d7a (patch)
treec468b60cbd00b8f6b00043635dc2d4393a001c4b /bot/exts/christmas/advent_of_code
parent(tic-tac-toe): Use embeds for showing previous game boards (diff)
parentMerge pull request #758 from OculusMode/master (diff)
Merge branch 'main' into fix/ttt
Diffstat (limited to 'bot/exts/christmas/advent_of_code')
-rw-r--r--bot/exts/christmas/advent_of_code/_cog.py32
-rw-r--r--bot/exts/christmas/advent_of_code/_helpers.py30
2 files changed, 34 insertions, 28 deletions
diff --git a/bot/exts/christmas/advent_of_code/_cog.py b/bot/exts/christmas/advent_of_code/_cog.py
index 8376987d..3d61753b 100644
--- a/bot/exts/christmas/advent_of_code/_cog.py
+++ b/bot/exts/christmas/advent_of_code/_cog.py
@@ -3,6 +3,7 @@ import logging
from datetime import datetime, timedelta
from pathlib import Path
+import arrow
import discord
from discord.ext import commands
@@ -72,11 +73,15 @@ class AdventOfCode(commands.Cog):
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.")
+ 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.")
+ 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."
+ )
@in_month(Month.DECEMBER)
@adventofcode_group.command(name="unsubscribe", aliases=("unsub",), brief="Notifications for new days")
@@ -96,11 +101,11 @@ class AdventOfCode(commands.Cog):
async def aoc_countdown(self, ctx: commands.Context) -> None:
"""Return time left until next day."""
if not _helpers.is_in_advent():
- datetime_now = datetime.now(_helpers.EST)
+ datetime_now = arrow.now(_helpers.EST)
# Calculate the delta to this & next year's December 1st to see which one is closest and not in the past
- this_year = datetime(datetime_now.year, 12, 1, tzinfo=_helpers.EST)
- next_year = datetime(datetime_now.year + 1, 12, 1, tzinfo=_helpers.EST)
+ this_year = arrow.get(datetime(datetime_now.year, 12, 1), _helpers.EST)
+ next_year = arrow.get(datetime(datetime_now.year + 1, 12, 1), _helpers.EST)
deltas = (dec_first - datetime_now for dec_first in (this_year, next_year))
delta = min(delta for delta in deltas if delta >= timedelta()) # timedelta() gives 0 duration delta
@@ -110,8 +115,10 @@ class AdventOfCode(commands.Cog):
else:
delta_str = f"{delta.days} days"
- await ctx.send(f"The Advent of Code event is not currently running. "
- f"The next event will start in {delta_str}.")
+ await ctx.send(
+ "The Advent of Code event is not currently running. "
+ f"The next event will start in {delta_str}."
+ )
return
tomorrow, time_left = _helpers.time_left_to_est_midnight()
@@ -124,7 +131,7 @@ class AdventOfCode(commands.Cog):
@whitelist_override(channels=AOC_WHITELIST)
async def about_aoc(self, ctx: commands.Context) -> None:
"""Respond with an explanation of all things Advent of Code."""
- await ctx.send("", embed=self.cached_about_aoc)
+ await ctx.send(embed=self.cached_about_aoc)
@adventofcode_group.command(name="join", aliases=("j",), brief="Learn how to join the leaderboard (via DM)")
@whitelist_override(channels=AOC_WHITELIST)
@@ -135,7 +142,7 @@ class AdventOfCode(commands.Cog):
await ctx.send(f"The Python Discord leaderboard for {current_year} is not yet available!")
return
- author = ctx.message.author
+ author = ctx.author
log.info(f"{author.name} ({author.id}) has requested a PyDis AoC leaderboard code")
if AocConfig.staff_leaderboard_id and any(r.id == Roles.helpers for r in author.roles):
@@ -273,8 +280,7 @@ class AdventOfCode(commands.Cog):
def _build_about_embed(self) -> discord.Embed:
"""Build and return the informational "About AoC" embed from the resources file."""
- with self.about_aoc_filepath.open("r", encoding="utf8") as f:
- embed_fields = json.load(f)
+ embed_fields = json.loads(self.about_aoc_filepath.read_text("utf8"))
about_embed = discord.Embed(
title=self._base_url,
diff --git a/bot/exts/christmas/advent_of_code/_helpers.py b/bot/exts/christmas/advent_of_code/_helpers.py
index a16a4871..96de90c4 100644
--- a/bot/exts/christmas/advent_of_code/_helpers.py
+++ b/bot/exts/christmas/advent_of_code/_helpers.py
@@ -9,8 +9,8 @@ import typing
from typing import Tuple
import aiohttp
+import arrow
import discord
-import pytz
from bot.bot import Bot
from bot.constants import AdventOfCode, Channels, Colours
@@ -48,7 +48,7 @@ AOC_EMBED_THUMBNAIL = (
)
# Create an easy constant for the EST timezone
-EST = pytz.timezone("EST")
+EST = "America/New_York"
# Step size for the challenge countdown status
COUNTDOWN_STEP = 60 * 5
@@ -108,7 +108,7 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
# star view. We need that per star view to compute rank scores per star.
for member in raw_leaderboard_data.values():
name = member["name"] if member["name"] else f"Anonymous #{member['id']}"
- member_id = member['id']
+ member_id = member["id"]
leaderboard[member_id] = {"name": name, "score": 0, "star_1": 0, "star_2": 0}
# Iterate over all days for this participant
@@ -119,7 +119,7 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
leaderboard[member_id][f"star_{star}"] += 1
# Record completion datetime for this participant for this day/star
- completion_time = datetime.datetime.fromtimestamp(int(data['get_star_ts']))
+ completion_time = datetime.datetime.fromtimestamp(int(data["get_star_ts"]))
star_results[(day, star)].append(
StarResult(member_id=member_id, completion_time=completion_time)
)
@@ -133,7 +133,7 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
if day in AdventOfCode.ignored_days:
continue
- sorted_result = sorted(results, key=operator.attrgetter('completion_time'))
+ sorted_result = sorted(results, key=operator.attrgetter("completion_time"))
for rank, star_result in enumerate(sorted_result):
leaderboard[star_result.member_id]["score"] += max_score - rank
@@ -307,7 +307,7 @@ async def fetch_leaderboard(invalidate_cache: bool = False) -> dict:
def get_summary_embed(leaderboard: dict) -> discord.Embed:
"""Get an embed with the current summary stats of the leaderboard."""
- leaderboard_url = leaderboard['full_leaderboard_url']
+ leaderboard_url = leaderboard["full_leaderboard_url"]
refresh_minutes = AdventOfCode.leaderboard_cache_expiry_seconds // 60
aoc_embed = discord.Embed(
@@ -395,13 +395,13 @@ def is_in_advent() -> bool:
something for the next Advent of Code challenge should run. As the puzzle
published on the 25th is the last puzzle, this check excludes that date.
"""
- return datetime.datetime.now(EST).day in range(1, 25) and datetime.datetime.now(EST).month == 12
+ return arrow.now(EST).day in range(1, 25) and arrow.now(EST).month == 12
def time_left_to_est_midnight() -> Tuple[datetime.datetime, datetime.timedelta]:
"""Calculate the amount of time left until midnight EST/UTC-5."""
# Change all time properties back to 00:00
- todays_midnight = datetime.datetime.now(EST).replace(
+ todays_midnight = arrow.now(EST).replace(
microsecond=0,
second=0,
minute=0,
@@ -412,7 +412,7 @@ def time_left_to_est_midnight() -> Tuple[datetime.datetime, datetime.timedelta]:
tomorrow = todays_midnight + datetime.timedelta(days=1)
# Calculate the timedelta between the current time and midnight
- return tomorrow, tomorrow - datetime.datetime.now(EST)
+ return tomorrow, tomorrow - arrow.now(EST)
async def wait_for_advent_of_code(*, hours_before: int = 1) -> None:
@@ -430,9 +430,9 @@ async def wait_for_advent_of_code(*, hours_before: int = 1) -> None:
if we're already past the Advent of Code edition the bot is currently
configured for.
"""
- start = datetime.datetime(AdventOfCode.year, 12, 1, 0, 0, 0, tzinfo=EST)
+ start = arrow.get(datetime.datetime(AdventOfCode.year, 12, 1), EST)
target = start - datetime.timedelta(hours=hours_before)
- now = datetime.datetime.now(EST)
+ now = arrow.now(EST)
# If we've already reached or passed to target, we
# simply return immediately.
@@ -474,10 +474,10 @@ async def countdown_status(bot: Bot) -> None:
# sleeping for the entire year, it will only wait in the currently
# configured year. This means that the task will only start hibernating once
# we start preparing the next event by changing environment variables.
- last_challenge = datetime.datetime(AdventOfCode.year, 12, 25, 0, 0, 0, tzinfo=EST)
+ last_challenge = arrow.get(datetime.datetime(AdventOfCode.year, 12, 25), EST)
end = last_challenge + datetime.timedelta(hours=1)
- while datetime.datetime.now(EST) < end:
+ while arrow.now(EST) < end:
_, time_left = time_left_to_est_midnight()
aligned_seconds = int(math.ceil(time_left.seconds / COUNTDOWN_STEP)) * COUNTDOWN_STEP
@@ -534,8 +534,8 @@ async def new_puzzle_notification(bot: Bot) -> None:
# The last event day is 25 December, so we only have to schedule
# a reminder if the current day is before 25 December.
- end = datetime.datetime(AdventOfCode.year, 12, 25, tzinfo=EST)
- while datetime.datetime.now(EST) < end:
+ end = arrow.get(datetime.datetime(AdventOfCode.year, 12, 25), EST)
+ while arrow.now(EST) < end:
log.trace("Started puzzle notification loop.")
tomorrow, time_left = time_left_to_est_midnight()