From 11d00e7f846748fb87f02b5f0bfecc92feac198c Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 8 Oct 2021 14:45:02 +0100 Subject: Rename `Roles.moderator` to `Roles.moderation_team` --- bot/constants.py | 4 ++-- bot/exts/fun/snakes/_utils.py | 2 +- bot/exts/fun/trivia_quiz.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 6e45632f..c5443393 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -332,8 +332,8 @@ class Reddit: # Default role combinations -MODERATION_ROLES = Roles.moderator, Roles.admin, Roles.owner -STAFF_ROLES = Roles.helpers, Roles.moderator, Roles.admin, Roles.owner +MODERATION_ROLES = Roles.moderation_team, Roles.admin, Roles.owner +STAFF_ROLES = Roles.helpers, Roles.moderation_team, Roles.admin, Roles.owner # Whitelisted channels WHITELISTED_CHANNELS = ( diff --git a/bot/exts/fun/snakes/_utils.py b/bot/exts/fun/snakes/_utils.py index de51339d..46834c2c 100644 --- a/bot/exts/fun/snakes/_utils.py +++ b/bot/exts/fun/snakes/_utils.py @@ -718,4 +718,4 @@ class SnakeAndLaddersGame: @staticmethod def _is_moderator(user: Member) -> bool: """Return True if the user is a Moderator.""" - return any(Roles.moderator == role.id for role in user.roles) + return any(Roles.moderation_team == role.id for role in user.roles) diff --git a/bot/exts/fun/trivia_quiz.py b/bot/exts/fun/trivia_quiz.py index 712c8a12..60afbb06 100644 --- a/bot/exts/fun/trivia_quiz.py +++ b/bot/exts/fun/trivia_quiz.py @@ -550,7 +550,7 @@ class TriviaQuiz(commands.Cog): if self.game_status[ctx.channel.id]: # Check if the author is the game starter or a moderator. if ctx.author == self.game_owners[ctx.channel.id] or any( - Roles.moderator == role.id for role in ctx.author.roles + Roles.moderation_team == role.id for role in ctx.author.roles ): self.game_status[ctx.channel.id] = False del self.game_owners[ctx.channel.id] -- cgit v1.2.3 From 71d800add94df3d678786ab482747ae904290129 Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 8 Oct 2021 15:04:35 +0100 Subject: Rename `Roles.admin` to `Roles.admins` --- bot/constants.py | 10 +++++----- bot/exts/core/internal_eval/_internal_eval.py | 6 +++--- bot/exts/events/advent_of_code/_cog.py | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index c5443393..92b40914 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -280,9 +280,9 @@ if Client.month_override is not None: class Roles(NamedTuple): - owner = 267627879762755584 - admin = int(environ.get("BOT_ADMIN_ROLE_ID", 267628507062992896)) - moderator = 267629731250176001 + owners = 267627879762755584 + admins = int(environ.get("BOT_ADMIN_ROLE_ID", 267628507062992896)) + moderation_team = 267629731250176001 helpers = int(environ.get("ROLE_HELPERS", 267630620367257601)) core_developers = 587606783669829632 everyone = int(environ.get("BOT_GUILD", 267624335836053506)) @@ -332,8 +332,8 @@ class Reddit: # Default role combinations -MODERATION_ROLES = Roles.moderation_team, Roles.admin, Roles.owner -STAFF_ROLES = Roles.helpers, Roles.moderation_team, Roles.admin, Roles.owner +MODERATION_ROLES = Roles.moderation_team, Roles.admins, Roles.owner +STAFF_ROLES = Roles.helpers, Roles.moderation_team, Roles.admins, Roles.owner # Whitelisted channels WHITELISTED_CHANNELS = ( diff --git a/bot/exts/core/internal_eval/_internal_eval.py b/bot/exts/core/internal_eval/_internal_eval.py index 4f6b4321..47e564a5 100644 --- a/bot/exts/core/internal_eval/_internal_eval.py +++ b/bot/exts/core/internal_eval/_internal_eval.py @@ -146,14 +146,14 @@ class InternalEval(commands.Cog): await self._send_output(ctx, eval_context.format_output()) @commands.group(name="internal", aliases=("int",)) - @with_role(Roles.admin) + @with_role(Roles.admins) async def internal_group(self, ctx: commands.Context) -> None: """Internal commands. Top secret!""" if not ctx.invoked_subcommand: await invoke_help_command(ctx) @internal_group.command(name="eval", aliases=("e",)) - @with_role(Roles.admin) + @with_role(Roles.admins) async def eval(self, ctx: commands.Context, *, code: str) -> None: """Run eval in a REPL-like format.""" if match := list(FORMATTED_CODE_REGEX.finditer(code)): @@ -172,7 +172,7 @@ class InternalEval(commands.Cog): await self._eval(ctx, code) @internal_group.command(name="reset", aliases=("clear", "exit", "r", "c")) - @with_role(Roles.admin) + @with_role(Roles.admins) async def reset(self, ctx: commands.Context) -> None: """Reset the context and locals of the eval session.""" self.locals = {} diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index ca60e517..4d811fa4 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -251,7 +251,7 @@ class AdventOfCode(commands.Cog): info_embed = _helpers.get_summary_embed(leaderboard) await ctx.send(f"```\n{table}\n```", embed=info_embed) - @with_role(Roles.admin) + @with_role(Roles.admins) @adventofcode_group.command( name="refresh", aliases=("fetch",), -- cgit v1.2.3 From dc5f73be8c18ef11c701822e8c600c8fca7b149c Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 8 Oct 2021 15:06:07 +0100 Subject: Rename `Roles.owner` to `Roles.owners` --- bot/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index 92b40914..b4191c5e 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -332,8 +332,8 @@ class Reddit: # Default role combinations -MODERATION_ROLES = Roles.moderation_team, Roles.admins, Roles.owner -STAFF_ROLES = Roles.helpers, Roles.moderation_team, Roles.admins, Roles.owner +MODERATION_ROLES = Roles.moderation_team, Roles.admins, Roles.owners +STAFF_ROLES = Roles.helpers, Roles.moderation_team, Roles.admins, Roles.owners # Whitelisted channels WHITELISTED_CHANNELS = ( -- cgit v1.2.3 From e2da188b554aba07b6c5a7a25b8af0baa74973cb Mon Sep 17 00:00:00 2001 From: Izan Date: Sat, 9 Oct 2021 21:20:46 +0100 Subject: Check role id in MODERATION_ROLES instead of comparing to moderation_team and safeguard `.roles` attribute --- bot/exts/fun/snakes/_utils.py | 25 +++++++++++++------------ bot/exts/fun/trivia_quiz.py | 4 ++-- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'bot') diff --git a/bot/exts/fun/snakes/_utils.py b/bot/exts/fun/snakes/_utils.py index 46834c2c..182fa9d9 100644 --- a/bot/exts/fun/snakes/_utils.py +++ b/bot/exts/fun/snakes/_utils.py @@ -6,13 +6,14 @@ import math import random from itertools import product from pathlib import Path +from typing import Union from PIL import Image from PIL.ImageDraw import ImageDraw -from discord import File, Member, Reaction +from discord import File, Member, Reaction, User from discord.ext.commands import Cog, Context -from bot.constants import Roles +from bot.constants import MODERATION_ROLES SNAKE_RESOURCES = Path("bot/resources/fun/snakes").absolute() @@ -395,7 +396,7 @@ class SnakeAndLaddersGame: Listen for reactions until players have joined, and the game has been started. """ - def startup_event_check(reaction_: Reaction, user_: Member) -> bool: + def startup_event_check(reaction_: Reaction, user_: Union[User, Member]) -> bool: """Make sure that this reaction is what we want to operate on.""" return ( all(( @@ -460,7 +461,7 @@ class SnakeAndLaddersGame: await self.cancel_game() return # We're done, no reactions for the last 5 minutes - async def _add_player(self, user: Member) -> None: + async def _add_player(self, user: Union[User, Member]) -> None: """Add player to game.""" self.players.append(user) self.player_tiles[user.id] = 1 @@ -469,7 +470,7 @@ class SnakeAndLaddersGame: im = Image.open(io.BytesIO(avatar_bytes)).resize((BOARD_PLAYER_SIZE, BOARD_PLAYER_SIZE)) self.avatar_images[user.id] = im - async def player_join(self, user: Member) -> None: + async def player_join(self, user: Union[User, Member]) -> None: """ Handle players joining the game. @@ -495,7 +496,7 @@ class SnakeAndLaddersGame: delete_after=10 ) - async def player_leave(self, user: Member) -> bool: + async def player_leave(self, user: Union[User, Member]) -> bool: """ Handle players leaving the game. @@ -530,7 +531,7 @@ class SnakeAndLaddersGame: await self.channel.send("**Snakes and Ladders**: Game has been canceled.") self._destruct() - async def start_game(self, user: Member) -> None: + async def start_game(self, user: Union[User, Member]) -> None: """ Allow the game author to begin the game. @@ -551,7 +552,7 @@ class SnakeAndLaddersGame: async def start_round(self) -> None: """Begin the round.""" - def game_event_check(reaction_: Reaction, user_: Member) -> bool: + def game_event_check(reaction_: Reaction, user_: Union[User, Member]) -> bool: """Make sure that this reaction is what we want to operate on.""" return ( all(( @@ -644,7 +645,7 @@ class SnakeAndLaddersGame: if not is_surrendered: await self._complete_round() - async def player_roll(self, user: Member) -> None: + async def player_roll(self, user: Union[User, Member]) -> None: """Handle the player's roll.""" if user.id not in self.player_tiles: await self.channel.send(user.mention + " You are not in the match.", delete_after=10) @@ -691,7 +692,7 @@ class SnakeAndLaddersGame: await self.channel.send("**Snakes and Ladders**: " + winner.mention + " has won the game! :tada:") self._destruct() - def _check_winner(self) -> Member: + def _check_winner(self) -> Union[User, Member]: """Return a winning member if we're in the post-round state and there's a winner.""" if self.state != "post_round": return None @@ -716,6 +717,6 @@ class SnakeAndLaddersGame: return x_level, y_level @staticmethod - def _is_moderator(user: Member) -> bool: + def _is_moderator(user: Union[User, Member]) -> bool: """Return True if the user is a Moderator.""" - return any(Roles.moderation_team == role.id for role in user.roles) + return any(role.id in MODERATION_ROLES for role in getattr(user, 'roles', [])) diff --git a/bot/exts/fun/trivia_quiz.py b/bot/exts/fun/trivia_quiz.py index 60afbb06..4a1cec5b 100644 --- a/bot/exts/fun/trivia_quiz.py +++ b/bot/exts/fun/trivia_quiz.py @@ -16,7 +16,7 @@ from discord.ext import commands, tasks from rapidfuzz import fuzz from bot.bot import Bot -from bot.constants import Client, Colours, NEGATIVE_REPLIES, Roles +from bot.constants import Client, Colours, MODERATION_ROLES, NEGATIVE_REPLIES logger = logging.getLogger(__name__) @@ -550,7 +550,7 @@ class TriviaQuiz(commands.Cog): if self.game_status[ctx.channel.id]: # Check if the author is the game starter or a moderator. if ctx.author == self.game_owners[ctx.channel.id] or any( - Roles.moderation_team == role.id for role in ctx.author.roles + role.id in MODERATION_ROLES for role in getattr(ctx.author, 'roles', []) ): self.game_status[ctx.channel.id] = False del self.game_owners[ctx.channel.id] -- cgit v1.2.3 From aa272dbe789e86013969bc6f4e506d70ddfc63be Mon Sep 17 00:00:00 2001 From: Izan Date: Mon, 11 Oct 2021 14:47:16 +0100 Subject: Check role id in STAFF_ROLES instead of comparing to helpers --- bot/exts/events/advent_of_code/_cog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 4d811fa4..0a18c261 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -9,7 +9,7 @@ from discord.ext import commands from bot.bot import Bot from bot.constants import ( - AdventOfCode as AocConfig, Channels, Colours, Emojis, Month, Roles, WHITELISTED_CHANNELS, + AdventOfCode as AocConfig, Channels, Colours, Emojis, Month, Roles, STAFF_ROLES, WHITELISTED_CHANNELS, ) from bot.exts.events.advent_of_code import _helpers from bot.utils.decorators import InChannelCheckFailure, in_month, whitelist_override, with_role @@ -145,7 +145,7 @@ class AdventOfCode(commands.Cog): 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): + if AocConfig.staff_leaderboard_id and any(r.id in STAFF_ROLES for r in author.roles): join_code = AocConfig.leaderboards[AocConfig.staff_leaderboard_id].join_code else: try: -- cgit v1.2.3 From a94ce986832694a572ce31b8fedd2b98c2c7747a Mon Sep 17 00:00:00 2001 From: Izan Date: Mon, 11 Oct 2021 14:59:31 +0100 Subject: Make certain AOC commands guild-only --- bot/exts/events/advent_of_code/_cog.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 0a18c261..3bd4873c 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -55,6 +55,7 @@ class AdventOfCode(commands.Cog): if not ctx.invoked_subcommand: await invoke_help_command(ctx) + @commands.guild_only() @adventofcode_group.command( name="subscribe", aliases=("sub", "notifications", "notify", "notifs"), @@ -84,6 +85,7 @@ class AdventOfCode(commands.Cog): ) @in_month(Month.DECEMBER) + @commands.guild_only() @adventofcode_group.command(name="unsubscribe", aliases=("unsub",), brief="Notifications for new days") @whitelist_override(channels=AOC_WHITELIST) async def aoc_unsubscribe(self, ctx: commands.Context) -> None: @@ -133,6 +135,7 @@ class AdventOfCode(commands.Cog): """Respond with an explanation of all things Advent of Code.""" await ctx.send(embed=self.cached_about_aoc) + @commands.guild_only() @adventofcode_group.command(name="join", aliases=("j",), brief="Learn how to join the leaderboard (via DM)") @whitelist_override(channels=AOC_WHITELIST) async def join_leaderboard(self, ctx: commands.Context) -> None: -- cgit v1.2.3 From 5059e61c354054b8cd463866cbd4ab4b1c0a8c09 Mon Sep 17 00:00:00 2001 From: aru Date: Sat, 20 Nov 2021 09:55:50 -0500 Subject: Remove unnecessary edits during pagination pick 3cd4c92b1e24c8cfdae8c5c68c19607c62cc01ed from python-discord/bot remove additional unnecessary edit --- bot/utils/pagination.py | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'bot') diff --git a/bot/utils/pagination.py b/bot/utils/pagination.py index 013ef9e7..188b279f 100644 --- a/bot/utils/pagination.py +++ b/bot/utils/pagination.py @@ -211,8 +211,6 @@ class LinePaginator(Paginator): log.debug(f"Got first page reaction - changing to page 1/{len(paginator.pages)}") - embed.description = "" - await message.edit(embed=embed) embed.description = paginator.pages[current_page] if footer_text: embed.set_footer(text=f"{footer_text} (Page {current_page + 1}/{len(paginator.pages)})") @@ -226,8 +224,6 @@ class LinePaginator(Paginator): log.debug(f"Got last page reaction - changing to page {current_page + 1}/{len(paginator.pages)}") - embed.description = "" - await message.edit(embed=embed) embed.description = paginator.pages[current_page] if footer_text: embed.set_footer(text=f"{footer_text} (Page {current_page + 1}/{len(paginator.pages)})") @@ -245,8 +241,6 @@ class LinePaginator(Paginator): current_page -= 1 log.debug(f"Got previous page reaction - changing to page {current_page + 1}/{len(paginator.pages)}") - embed.description = "" - await message.edit(embed=embed) embed.description = paginator.pages[current_page] if footer_text: @@ -266,8 +260,6 @@ class LinePaginator(Paginator): current_page += 1 log.debug(f"Got next page reaction - changing to page {current_page + 1}/{len(paginator.pages)}") - embed.description = "" - await message.edit(embed=embed) embed.description = paginator.pages[current_page] if footer_text: @@ -428,8 +420,6 @@ class ImagePaginator(Paginator): reaction_type = "next" # Magic happens here, after page and reaction_type is set - embed.description = "" - await message.edit(embed=embed) embed.description = paginator.pages[current_page] image = paginator.images[current_page] or EmptyEmbed -- cgit v1.2.3 From be7da6f34e50b7a99ef6c3a7eb67a48b24b818ed Mon Sep 17 00:00:00 2001 From: Izan Date: Mon, 29 Nov 2021 09:11:17 +0000 Subject: Change `MODERATION_ROLES` and `STAFF_ROLES` constants to be a set --- bot/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'bot') diff --git a/bot/constants.py b/bot/constants.py index b4191c5e..bef7f3d1 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -332,8 +332,8 @@ class Reddit: # Default role combinations -MODERATION_ROLES = Roles.moderation_team, Roles.admins, Roles.owners -STAFF_ROLES = Roles.helpers, Roles.moderation_team, Roles.admins, Roles.owners +MODERATION_ROLES = {Roles.moderation_team, Roles.admins, Roles.owners} +STAFF_ROLES = {Roles.helpers, Roles.moderation_team, Roles.admins, Roles.owners} # Whitelisted channels WHITELISTED_CHANNELS = ( -- cgit v1.2.3 From a958d1c1f6a3308b5ffd03cb7f9ef846b0871265 Mon Sep 17 00:00:00 2001 From: Izan Date: Mon, 29 Nov 2021 09:34:31 +0000 Subject: Revert change to if statement checking if staff in `.aoc join` --- bot/exts/events/advent_of_code/_cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index c3073fd5..34ade5b1 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -148,7 +148,7 @@ class AdventOfCode(commands.Cog): 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 in STAFF_ROLES for r in author.roles): + if AocConfig.staff_leaderboard_id and any(r.id == Roles.helpers for r in author.roles): join_code = AocConfig.leaderboards[AocConfig.staff_leaderboard_id].join_code else: try: -- cgit v1.2.3 From 338fc7a0b37483feba56a8810cd2e1a344ab8b22 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Mon, 29 Nov 2021 10:48:26 +0000 Subject: Swap conditional in aoc count This is so that there is less code within the if block, making it easier to parse the whole command by eye. --- bot/exts/events/advent_of_code/_cog.py | 41 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index cd41e9ce..c91a5019 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -100,32 +100,31 @@ class AdventOfCode(commands.Cog): @whitelist_override(channels=AOC_WHITELIST) async def aoc_countdown(self, ctx: commands.Context) -> None: """Return time left until next day.""" - if not _helpers.is_in_advent(): - 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 = 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 - - # Add a finer timedelta if there's less than a day left - if delta.days == 0: - delta_str = f"approximately {delta.seconds // 3600} hours" - else: - delta_str = f"{delta.days} days" + if _helpers.is_in_advent(): + tomorrow, time_left = _helpers.time_left_to_est_midnight() + hours, minutes = time_left.seconds // 3600, time_left.seconds // 60 % 60 - await ctx.send( - "The Advent of Code event is not currently running. " - f"The next event will start in {delta_str}." - ) + await ctx.send(f"There are {hours} hours and {minutes} minutes left until day {tomorrow.day}.") return - tomorrow, time_left = _helpers.time_left_to_est_midnight() + datetime_now = arrow.now(_helpers.EST) - hours, minutes = time_left.seconds // 3600, time_left.seconds // 60 % 60 + # Calculate the delta to this & next year's December 1st to see which one is closest and not in the past + 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 - await ctx.send(f"There are {hours} hours and {minutes} minutes left until day {tomorrow.day}.") + # Add a finer timedelta if there's less than a day left + if delta.days == 0: + delta_str = f"approximately {delta.seconds // 3600} hours" + else: + delta_str = f"{delta.days} days" + + await ctx.send( + "The Advent of Code event is not currently running. " + f"The next event will start in {delta_str}." + ) @adventofcode_group.command(name="about", aliases=("ab", "info"), brief="Learn about Advent of Code") @whitelist_override(channels=AOC_WHITELIST) -- cgit v1.2.3 From 790bcdf2fedc8dd7aac8c5a2610dc8395852bce0 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Mon, 29 Nov 2021 10:49:28 +0000 Subject: Use a Discord timestamp to show countdown This gives the user the ability to hover the timestamp with their mouse to get an exact date and time. --- bot/exts/events/advent_of_code/_cog.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index c91a5019..94722005 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -115,15 +115,11 @@ class AdventOfCode(commands.Cog): 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 - # Add a finer timedelta if there's less than a day left - if delta.days == 0: - delta_str = f"approximately {delta.seconds // 3600} hours" - else: - delta_str = f"{delta.days} days" + next_aoc_timestamp = int((datetime_now + delta).timestamp()) await ctx.send( "The Advent of Code event is not currently running. " - f"The next event will start in {delta_str}." + f"The next event will start ." ) @adventofcode_group.command(name="about", aliases=("ab", "info"), brief="Learn about Advent of Code") -- cgit v1.2.3 From c81d30357db2c0950d5e781cdd5e9053907b228d Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Mon, 29 Nov 2021 15:10:29 +0000 Subject: Use Discord timestamps for aoc next day messages countdowns --- bot/exts/events/advent_of_code/_cog.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 94722005..af1cbcf5 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -101,14 +101,13 @@ class AdventOfCode(commands.Cog): async def aoc_countdown(self, ctx: commands.Context) -> None: """Return time left until next day.""" if _helpers.is_in_advent(): - tomorrow, time_left = _helpers.time_left_to_est_midnight() - hours, minutes = time_left.seconds // 3600, time_left.seconds // 60 % 60 + tomorrow, _ = _helpers.time_left_to_est_midnight() + next_day_timestamp = int(tomorrow.timestamp()) - await ctx.send(f"There are {hours} hours and {minutes} minutes left until day {tomorrow.day}.") + await ctx.send(f"Day {tomorrow.day} starts .") return 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 = arrow.get(datetime(datetime_now.year, 12, 1), _helpers.EST) next_year = arrow.get(datetime(datetime_now.year + 1, 12, 1), _helpers.EST) -- cgit v1.2.3 From 65398ed2b9fb67dbe842996e01142722bd0667f3 Mon Sep 17 00:00:00 2001 From: aru Date: Wed, 1 Dec 2021 17:15:25 -0500 Subject: fix: hanukkah command respects month boundaries rewrote hanukkah to use datetime.strptime left a helper method and some variables in order to allow extending to use a cache in the future, rather than requesting the api every invoke that is out of scope of this commit and pull, since the command is currently broken. I've only kept the same functionality, without trying to rewrite the entire command. --- bot/exts/holidays/hanukkah/hanukkah_embed.py | 84 ++++++++++++---------------- 1 file changed, 36 insertions(+), 48 deletions(-) (limited to 'bot') diff --git a/bot/exts/holidays/hanukkah/hanukkah_embed.py b/bot/exts/holidays/hanukkah/hanukkah_embed.py index ac3eab7b..5767f91e 100644 --- a/bot/exts/holidays/hanukkah/hanukkah_embed.py +++ b/bot/exts/holidays/hanukkah/hanukkah_embed.py @@ -21,45 +21,41 @@ class HanukkahEmbed(commands.Cog): def __init__(self, bot: Bot): self.bot = bot - self.hanukkah_days = [] - self.hanukkah_months = [] - self.hanukkah_years = [] + self.hanukkah_dates: list[datetime.date] = [] - async def get_hanukkah_dates(self) -> list[str]: + def _parse_time_to_datetime(self, date: list[str]) -> datetime.datetime: + """Format the times provided by the api to datetime forms.""" + try: + return datetime.datetime.strptime(date, "%Y-%m-%dT%H:%M:%S%z") + except ValueError: + # there is a possibility of an event not having a time, just a day + # to catch this, we try again without time information + return datetime.datetime.strptime(date, "%Y-%m-%d") + + async def fetch_hanukkah_dates(self) -> list[datetime.date]: """Gets the dates for hanukkah festival.""" - hanukkah_dates = [] + # clear the datetime objects to prevent a memory link + self.hanukkah_dates = [] async with self.bot.http_session.get(HEBCAL_URL) as response: json_data = await response.json() festivals = json_data["items"] for festival in festivals: if festival["title"].startswith("Chanukah"): date = festival["date"] - hanukkah_dates.append(date) - return hanukkah_dates + self.hanukkah_dates.append(self._parse_time_to_datetime(date).date()) + return self.hanukkah_dates @in_month(Month.NOVEMBER, Month.DECEMBER) @commands.command(name="hanukkah", aliases=("chanukah",)) async def hanukkah_festival(self, ctx: commands.Context) -> None: """Tells you about the Hanukkah Festivaltime of festival, festival day, etc).""" - hanukkah_dates = await self.get_hanukkah_dates() - self.hanukkah_dates_split(hanukkah_dates) - hanukkah_start_day = int(self.hanukkah_days[0]) - hanukkah_start_month = int(self.hanukkah_months[0]) - hanukkah_start_year = int(self.hanukkah_years[0]) - hanukkah_end_day = int(self.hanukkah_days[8]) - hanukkah_end_month = int(self.hanukkah_months[8]) - hanukkah_end_year = int(self.hanukkah_years[8]) - - hanukkah_start = datetime.date(hanukkah_start_year, hanukkah_start_month, hanukkah_start_day) - hanukkah_end = datetime.date(hanukkah_end_year, hanukkah_end_month, hanukkah_end_day) + hanukkah_dates = await self.fetch_hanukkah_dates() + start_day = hanukkah_dates[0] + end_day = hanukkah_dates[-1] today = datetime.date.today() - # today = datetime.date(2019, 12, 24) (for testing) - day = str(today.day) - month = str(today.month) - year = str(today.year) embed = Embed(title="Hanukkah", colour=Colours.blue) - if day in self.hanukkah_days and month in self.hanukkah_months and year in self.hanukkah_years: - if int(day) == hanukkah_start_day: + if start_day <= today <= end_day: + if start_day == today: now = datetime.datetime.utcnow() hours = now.hour + 4 # using only hours hanukkah_start_hour = 18 @@ -77,35 +73,27 @@ class HanukkahEmbed(commands.Cog): ) await ctx.send(embed=embed) return - festival_day = self.hanukkah_days.index(day) + festival_day = hanukkah_dates.index(today) number_suffixes = ["st", "nd", "rd", "th"] suffix = number_suffixes[festival_day - 1 if festival_day <= 3 else 3] message = ":menorah:" * festival_day - embed.description = f"It is the {festival_day}{suffix} day of Hanukkah!\n{message}" - await ctx.send(embed=embed) + embed.description = ( + f"It is the {festival_day}{suffix} day of Hanukkah!\n{message}" + ) + elif today < start_day: + format_start = start_day.strftime("%d of %B") + embed.description = ( + "Hanukkah has not started yet. " + f"Hanukkah will start at sundown on {format_start}." + ) else: - if today < hanukkah_start: - festival_starting_month = hanukkah_start.strftime("%B") - embed.description = ( - f"Hanukkah has not started yet. " - f"Hanukkah will start at sundown on {hanukkah_start_day}th " - f"of {festival_starting_month}." - ) - else: - festival_end_month = hanukkah_end.strftime("%B") - embed.description = ( - f"Looks like you missed Hanukkah!" - f"Hanukkah ended on {hanukkah_end_day}th of {festival_end_month}." - ) - - await ctx.send(embed=embed) + format_end = end_day.strftime("%d of %B") + embed.description = ( + "Looks like you missed Hanukkah! " + f"Hanukkah ended on {format_end}." + ) - def hanukkah_dates_split(self, hanukkah_dates: list[str]) -> None: - """We are splitting the dates for hanukkah into days, months and years.""" - for date in hanukkah_dates: - self.hanukkah_days.append(date[8:10]) - self.hanukkah_months.append(date[5:7]) - self.hanukkah_years.append(date[0:4]) + await ctx.send(embed=embed) def setup(bot: Bot) -> None: -- cgit v1.2.3 From eba75f73964a258119e16ba2abfc181055281022 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Wed, 1 Dec 2021 22:41:07 -0500 Subject: Add `.aoc link` command This new command will allow people to associate their Discord ID with their Advent of Code name. This Redis Cache idea was taken from the hacktoberfest stats command, which allows people to associate their github username to then pull the correct stats. This does not check if the name exists on the leaderboard and that is intentional. Due to the cooldown on the leaderboard I don't want to rely on that before someone can link their account. Additionally, someone may change their display name on the Advent of Code side and I don't think validation of it existing on the leaderboard gets us anything. The usefulness of this function will not be apparent in this cog, but it is necessary for something fun I'd like to do. --- bot/exts/events/advent_of_code/_cog.py | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index af1cbcf5..1b1cd9f8 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -6,6 +6,7 @@ from typing import Optional import arrow import discord +from async_rediscache import RedisCache from discord.ext import commands from bot.bot import Bot @@ -29,6 +30,8 @@ AOC_WHITELIST = AOC_WHITELIST_RESTRICTED + (Channels.advent_of_code,) class AdventOfCode(commands.Cog): """Advent of Code festivities! Ho Ho Ho!""" + account_links = RedisCache() + def __init__(self, bot: Bot): self.bot = bot @@ -172,6 +175,72 @@ class AdventOfCode(commands.Cog): else: await ctx.message.add_reaction(Emojis.envelope) + @in_month(Month.NOVEMBER, Month.DECEMBER) + @adventofcode_group.command( + name="link", + aliases=("connect",), + brief="Tie your Discord account with your Advent of Code name." + ) + @whitelist_override(channels=AOC_WHITELIST) + async def aoc_link_account(self, ctx: commands.Context, aoc_name: str = None) -> None: + """ + Link your Discord Account to your Advent of Code name. + + Stored in a Redis Cache, Discord ID: Advent of Code Name + """ + cache_items = await self.account_links.items() + + # A short circuit in case the cache is empty + if len(cache_items) == 0 and aoc_name: + log.info(f"{ctx.author} ({ctx.author.id}) is now linked to {aoc_name}.") + await self.account_links.set(ctx.author.id, aoc_name) + await ctx.reply(f"You have linked your Discord ID to {aoc_name}.") + return + elif len(cache_items) == 0: + await ctx.reply( + "You have not linked an Advent of Code account." + "Please re-run the command with one specified." + ) + return + + cache_aoc_name = [value for _, value in cache_items] + + if aoc_name: + # Let's check the current values in the cache to make sure it isn't already tied to a different account + if aoc_name == await self.account_links.get(ctx.author.id): + await ctx.reply(f"{aoc_name} is already tied to your account.") + return + elif aoc_name in cache_aoc_name: + log.info( + f"{ctx.author} ({ctx.author.id}) tried to connect their account to {aoc_name}," + " but it's already connected to another user." + ) + await ctx.reply( + f"{aoc_name} is already tied to another account." + " Please contact an admin if you believe this is an error." + ) + return + + # Update an existing link + if old_aoc_name := await self.account_links.get(ctx.author.id): + log.info(f"{ctx.author} ({ctx.author.id}) has changed their link from {old_aoc_name} to {aoc_name}.") + await self.account_links.set(ctx.author.id, aoc_name) + await ctx.reply(f"Your linked account has been changed to {aoc_name}.") + else: + # Create a new link + log.info(f"{ctx.author} ({ctx.author.id}) is now linked to {aoc_name}.") + await self.account_links.set(ctx.author.id, aoc_name) + await ctx.reply(f"You have linked your Discord ID to {aoc_name}.") + else: + # User has not supplied a name, let's check if they're in the cache or not + if cache_name := await self.account_links.get(ctx.author.id): + await ctx.reply(f"You have already linked an Advent of Code account: {cache_name}.") + else: + await ctx.reply( + "You have not linked an Advent of Code account." + " Please re-run the command with one specified." + ) + @in_month(Month.DECEMBER) @adventofcode_group.command( name="dayandstar", -- cgit v1.2.3 From 1dba7a7a7132839230f776a8ecb73b9def93174f Mon Sep 17 00:00:00 2001 From: Ben Soyka Date: Wed, 1 Dec 2021 20:44:46 -0700 Subject: Make self_placement_name keyword-only in .aoc lb --- bot/exts/events/advent_of_code/_cog.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index af1cbcf5..900c3469 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -220,6 +220,7 @@ class AdventOfCode(commands.Cog): async def aoc_leaderboard( self, ctx: commands.Context, + *, self_placement_name: Optional[str] = None, ) -> None: """ -- cgit v1.2.3 From 4959f085537421814159734070b74dadd566501f Mon Sep 17 00:00:00 2001 From: Ben Soyka Date: Wed, 1 Dec 2021 21:16:49 -0700 Subject: Strip quotes from start/end of the username for .aoc lb --- bot/exts/events/advent_of_code/_cog.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 900c3469..c6225356 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -229,6 +229,10 @@ class AdventOfCode(commands.Cog): Additionally you can specify a `self_placement_name` that will append the specified profile's personal stats to the top of the leaderboard """ + # Strip quotes from the self placement name if needed (e.g. "My Name" -> My Name) + if self_placement_name and self_placement_name[0] == self_placement_name[-1] == '"': + self_placement_name = self_placement_name[1:-1] + async with ctx.typing(): try: leaderboard = await _helpers.fetch_leaderboard(self_placement_name=self_placement_name) -- cgit v1.2.3 From aea61a096bfbf60fab9711698c9353635b13ea0c Mon Sep 17 00:00:00 2001 From: Ben Soyka Date: Wed, 1 Dec 2021 21:43:17 -0700 Subject: Shorten parameter name for .aoc lb --- bot/exts/events/advent_of_code/_cog.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index c6225356..0f6739fc 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -217,25 +217,20 @@ class AdventOfCode(commands.Cog): brief="Get a snapshot of the PyDis private AoC leaderboard", ) @whitelist_override(channels=AOC_WHITELIST_RESTRICTED) - async def aoc_leaderboard( - self, - ctx: commands.Context, - *, - self_placement_name: Optional[str] = None, - ) -> None: + async def aoc_leaderboard(self, ctx: commands.Context, *, aoc_name: Optional[str] = None) -> None: """ Get the current top scorers of the Python Discord Leaderboard. - Additionally you can specify a `self_placement_name` - that will append the specified profile's personal stats to the top of the leaderboard + Additionally you can specify an `aoc_name` that will append the + specified profile's personal stats to the top of the leaderboard """ # Strip quotes from the self placement name if needed (e.g. "My Name" -> My Name) - if self_placement_name and self_placement_name[0] == self_placement_name[-1] == '"': - self_placement_name = self_placement_name[1:-1] + if aoc_name and aoc_name.startswith('"') and aoc_name.endswith('"'): + aoc_name = aoc_name[1:-1] async with ctx.typing(): try: - leaderboard = await _helpers.fetch_leaderboard(self_placement_name=self_placement_name) + leaderboard = await _helpers.fetch_leaderboard(self_placement_name=aoc_name) except _helpers.FetchingLeaderboardFailedError: await ctx.send(":x: Unable to fetch leaderboard!") return @@ -243,10 +238,10 @@ class AdventOfCode(commands.Cog): number_of_participants = leaderboard["number_of_participants"] top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants) - self_placement_header = "(and your personal stats compared to the top 10)" if self_placement_name else "" + self_placement_header = "(and your personal stats compared to the top 10)" if aoc_name else "" header = f"Here's our current top {top_count}{self_placement_header}! {Emojis.christmas_tree * 3}" table = "```\n" \ - f"{leaderboard['placement_leaderboard'] if self_placement_name else leaderboard['top_leaderboard']}" \ + f"{leaderboard['placement_leaderboard'] if aoc_name else leaderboard['top_leaderboard']}" \ "\n```" info_embed = _helpers.get_summary_embed(leaderboard) -- cgit v1.2.3 From 4a06ec80cc9e78294475ab23c41649d47798cca4 Mon Sep 17 00:00:00 2001 From: Ben Soyka Date: Thu, 2 Dec 2021 15:33:29 -0700 Subject: Note that only one layer of quotes is stripped in .aoc lb --- bot/exts/events/advent_of_code/_cog.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 0f6739fc..9ae2d059 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -224,7 +224,9 @@ class AdventOfCode(commands.Cog): Additionally you can specify an `aoc_name` that will append the specified profile's personal stats to the top of the leaderboard """ - # Strip quotes from the self placement name if needed (e.g. "My Name" -> My Name) + # Strip quotes from the AoC username if needed (e.g. "My Name" -> My Name) + # Note: only strips one layer of quotes to allow names with quotes at the start and end + # e.g. ""My Name"" -> "My Name" if aoc_name and aoc_name.startswith('"') and aoc_name.endswith('"'): aoc_name = aoc_name[1:-1] -- cgit v1.2.3 From 914e4abe1f168167d8b1126adeb1bc27bff28e6d Mon Sep 17 00:00:00 2001 From: Ben Soyka Date: Thu, 2 Dec 2021 15:34:45 -0700 Subject: Note why .aoc lb strips quotes from names --- bot/exts/events/advent_of_code/_cog.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 9ae2d059..3f9f5787 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -225,6 +225,7 @@ class AdventOfCode(commands.Cog): specified profile's personal stats to the top of the leaderboard """ # Strip quotes from the AoC username if needed (e.g. "My Name" -> My Name) + # This is to keep compatibility with those already used to wrapping the AoC name in quotes # Note: only strips one layer of quotes to allow names with quotes at the start and end # e.g. ""My Name"" -> "My Name" if aoc_name and aoc_name.startswith('"') and aoc_name.endswith('"'): -- cgit v1.2.3 From 846c34fd8988eaede08186fa9fb342213dc85585 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Fri, 3 Dec 2021 18:46:39 -0500 Subject: Remove unneeded check and add comments Removes the unneeded check for if the cache is empty. Also adds a seconds comment about the format of the contents of the Redis cache. --- bot/exts/events/advent_of_code/_cog.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 1b1cd9f8..8d87b5bc 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -30,6 +30,7 @@ AOC_WHITELIST = AOC_WHITELIST_RESTRICTED + (Channels.advent_of_code,) class AdventOfCode(commands.Cog): """Advent of Code festivities! Ho Ho Ho!""" + # Redis Cache for linking Discord IDs to Advent of Code usernames account_links = RedisCache() def __init__(self, bot: Bot): @@ -186,23 +187,9 @@ class AdventOfCode(commands.Cog): """ Link your Discord Account to your Advent of Code name. - Stored in a Redis Cache, Discord ID: Advent of Code Name + Stored in a Redis Cache with the format of `Discord ID: Advent of Code Name` """ cache_items = await self.account_links.items() - - # A short circuit in case the cache is empty - if len(cache_items) == 0 and aoc_name: - log.info(f"{ctx.author} ({ctx.author.id}) is now linked to {aoc_name}.") - await self.account_links.set(ctx.author.id, aoc_name) - await ctx.reply(f"You have linked your Discord ID to {aoc_name}.") - return - elif len(cache_items) == 0: - await ctx.reply( - "You have not linked an Advent of Code account." - "Please re-run the command with one specified." - ) - return - cache_aoc_name = [value for _, value in cache_items] if aoc_name: -- cgit v1.2.3 From 1ac965f67fea8e5dd0e0f026aca27e3368f4e44e Mon Sep 17 00:00:00 2001 From: Janine vN Date: Fri, 3 Dec 2021 20:50:17 -0500 Subject: Add unlink AoC command Adds the ability for the user to unlink their advent of code name. It will delete the entry in the cache if it exists. --- bot/exts/events/advent_of_code/_cog.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 8d87b5bc..7f904f6b 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -228,6 +228,27 @@ class AdventOfCode(commands.Cog): " Please re-run the command with one specified." ) + @in_month(Month.NOVEMBER, Month.DECEMBER) + @adventofcode_group.command( + name="unlink", + aliases=("disconnect",), + brief="Tie your Discord account with your Advent of Code name." + ) + @whitelist_override(channels=AOC_WHITELIST) + async def aoc_unlink_account(self, ctx: commands.Context) -> None: + """ + Unlink your Discord ID with your Advent of Code leaderboard name. + + Deletes the entry that was Stored in the Redis cache. + """ + if aoc_cache_name := await self.account_links.get(ctx.author.id): + log.info(f"Unlinking {ctx.author} ({ctx.author.id}) from Advent of Code account {aoc_cache_name}") + await self.account_links.delete(ctx.author.id) + await ctx.reply(f"We have removed the link between your Discord ID and {aoc_cache_name}.") + else: + log.info(f"Attempted to unlink {ctx.author} ({ctx.author.id}), but not link was found.") + await ctx.reply("You don't have an Advent of Code account linked.") + @in_month(Month.DECEMBER) @adventofcode_group.command( name="dayandstar", -- cgit v1.2.3 From 00e3fe5bede6f8310405e143179530df0ad3ca95 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Fri, 3 Dec 2021 20:53:59 -0500 Subject: Adjust wording on log statements to present tense --- bot/exts/events/advent_of_code/_cog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 7f904f6b..b7d26cb9 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -210,12 +210,12 @@ class AdventOfCode(commands.Cog): # Update an existing link if old_aoc_name := await self.account_links.get(ctx.author.id): - log.info(f"{ctx.author} ({ctx.author.id}) has changed their link from {old_aoc_name} to {aoc_name}.") + log.info(f"Changing link for{ctx.author} ({ctx.author.id}) from {old_aoc_name} to {aoc_name}.") await self.account_links.set(ctx.author.id, aoc_name) await ctx.reply(f"Your linked account has been changed to {aoc_name}.") else: # Create a new link - log.info(f"{ctx.author} ({ctx.author.id}) is now linked to {aoc_name}.") + log.info(f"Linking {ctx.author} ({ctx.author.id}) to account {aoc_name}.") await self.account_links.set(ctx.author.id, aoc_name) await ctx.reply(f"You have linked your Discord ID to {aoc_name}.") else: @@ -246,7 +246,7 @@ class AdventOfCode(commands.Cog): await self.account_links.delete(ctx.author.id) await ctx.reply(f"We have removed the link between your Discord ID and {aoc_cache_name}.") else: - log.info(f"Attempted to unlink {ctx.author} ({ctx.author.id}), but not link was found.") + log.info(f"Attempted to unlink {ctx.author} ({ctx.author.id}), but no link was found.") await ctx.reply("You don't have an Advent of Code account linked.") @in_month(Month.DECEMBER) -- cgit v1.2.3 From b3a7c79ffb1f4220bad8ca3814d594a9b1b00826 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Fri, 3 Dec 2021 21:02:28 -0500 Subject: Make aoc_name a keyword arguemnt to accept spaces Makes `aoc_name` in the link command a keyword only argument. This allows users to link accounts with spaces in the name without having to use quotes. --- bot/exts/events/advent_of_code/_cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index b7d26cb9..55fd0ac6 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -183,7 +183,7 @@ class AdventOfCode(commands.Cog): brief="Tie your Discord account with your Advent of Code name." ) @whitelist_override(channels=AOC_WHITELIST) - async def aoc_link_account(self, ctx: commands.Context, aoc_name: str = None) -> None: + async def aoc_link_account(self, ctx: commands.Context, *, aoc_name: str = None) -> None: """ Link your Discord Account to your Advent of Code name. -- cgit v1.2.3 From b134010e1682a40d2aa9e3ce893c274388896680 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Fri, 3 Dec 2021 21:29:01 -0500 Subject: Adjust `.aoc lb` to use linked account in cache If the user has not supplied a name to use for the leaderboard, then code will check if they have an account linked. If they do, it will use the linked account in the leaderboard to show placement. --- bot/exts/events/advent_of_code/_cog.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 16176c69..49b604ab 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -311,6 +311,10 @@ class AdventOfCode(commands.Cog): if aoc_name and aoc_name.startswith('"') and aoc_name.endswith('"'): aoc_name = aoc_name[1:-1] + # Check if an advent of code account is linked in the Redis Cache if aoc_name is not given + if (aoc_cache_name := await self.account_links.get(ctx.author.id)) and aoc_name is None: + aoc_name = aoc_cache_name + async with ctx.typing(): try: leaderboard = await _helpers.fetch_leaderboard(self_placement_name=aoc_name) @@ -321,7 +325,7 @@ class AdventOfCode(commands.Cog): number_of_participants = leaderboard["number_of_participants"] top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants) - self_placement_header = "(and your personal stats compared to the top 10)" if aoc_name else "" + self_placement_header = " (and your personal stats compared to the top 10)" if aoc_name else "" header = f"Here's our current top {top_count}{self_placement_header}! {Emojis.christmas_tree * 3}" table = "```\n" \ f"{leaderboard['placement_leaderboard'] if aoc_name else leaderboard['top_leaderboard']}" \ -- cgit v1.2.3 From f4324a0f447a7791743ce9a5c4f0957f32738b78 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Sat, 4 Dec 2021 10:55:49 -0500 Subject: Adjust variable name for clarity and add space --- bot/exts/events/advent_of_code/_cog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py index 49b604ab..52254ea1 100644 --- a/bot/exts/events/advent_of_code/_cog.py +++ b/bot/exts/events/advent_of_code/_cog.py @@ -193,14 +193,14 @@ class AdventOfCode(commands.Cog): Stored in a Redis Cache with the format of `Discord ID: Advent of Code Name` """ cache_items = await self.account_links.items() - cache_aoc_name = [value for _, value in cache_items] + cache_aoc_names = [value for _, value in cache_items] if aoc_name: # Let's check the current values in the cache to make sure it isn't already tied to a different account if aoc_name == await self.account_links.get(ctx.author.id): await ctx.reply(f"{aoc_name} is already tied to your account.") return - elif aoc_name in cache_aoc_name: + elif aoc_name in cache_aoc_names: log.info( f"{ctx.author} ({ctx.author.id}) tried to connect their account to {aoc_name}," " but it's already connected to another user." @@ -213,7 +213,7 @@ class AdventOfCode(commands.Cog): # Update an existing link if old_aoc_name := await self.account_links.get(ctx.author.id): - log.info(f"Changing link for{ctx.author} ({ctx.author.id}) from {old_aoc_name} to {aoc_name}.") + log.info(f"Changing link for {ctx.author} ({ctx.author.id}) from {old_aoc_name} to {aoc_name}.") await self.account_links.set(ctx.author.id, aoc_name) await ctx.reply(f"Your linked account has been changed to {aoc_name}.") else: -- cgit v1.2.3 From 03b5464e6e37f625ba7a590d45120f4b46b1d0aa Mon Sep 17 00:00:00 2001 From: Janine vN Date: Sat, 4 Dec 2021 11:00:48 -0500 Subject: Add more information to `.aoc lb` error embed Advent of Code Leaderboard BadArgument error embed now mentions to join the leaderboard and to wait up to 30 minutes if you've joined recently. --- bot/exts/events/advent_of_code/_helpers.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'bot') diff --git a/bot/exts/events/advent_of_code/_helpers.py b/bot/exts/events/advent_of_code/_helpers.py index 35258544..807cc275 100644 --- a/bot/exts/events/advent_of_code/_helpers.py +++ b/bot/exts/events/advent_of_code/_helpers.py @@ -216,6 +216,9 @@ def _format_leaderboard(leaderboard: dict[str, dict], self_placement_name: str = if self_placement_name and not self_placement_exists: raise commands.BadArgument( "Sorry, your profile does not exist in this leaderboard." + "\n\n" + "To join our leaderboard, run the command `.aoc join`." + " If you've joined recently, please wait up to 30 minutes for our leaderboard to refresh." ) return "\n".join(leaderboard_lines) -- cgit v1.2.3