From 5adbdd6d9fc10faae0e5362e1494d9c80433f177 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sat, 22 Feb 2020 20:14:57 +0100 Subject: Add IntEnum for the 12 months This is a safe way to specify which months a command can be used in. The enum's values behave as ints when being passed to the datetime.date initialiser. --- bot/constants.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index f0656926..2e4b4369 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -1,11 +1,12 @@ +import enum import logging +from datetime import datetime from os import environ from typing import NamedTuple -from datetime import datetime __all__ = ( "bookmark_icon_url", - "AdventOfCode", "Channels", "Client", "Colours", "Emojis", "Hacktoberfest", "Roles", "Tokens", + "AdventOfCode", "Channels", "Client", "Colours", "Emojis", "Hacktoberfest", "Month", "Roles", "Tokens", "WHITELISTED_CHANNELS", "STAFF_ROLES", "MODERATION_ROLES", "POSITIVE_REPLIES", "NEGATIVE_REPLIES", "ERROR_REPLIES", ) @@ -112,6 +113,21 @@ class Hacktoberfest(NamedTuple): voice_id = 514420006474219521 +class Month(enum.IntEnum): + january = 1 + february = 2 + march = 3 + april = 4 + may = 5 + june = 6 + july = 7 + august = 8 + september = 9 + october = 10 + november = 11 + december = 12 + + class Roles(NamedTuple): admin = int(environ.get("SEASONALBOT_ADMIN_ROLE_ID", 267628507062992896)) announcements = 463658397560995840 -- cgit v1.2.3 From c67cbbb2ff3fccf00c6e54349d626f6b644ef385 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sat, 14 Mar 2020 22:13:06 +0100 Subject: Deseasonify: improve documentation for `icon_cycle_frequency` --- bot/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index 19bbe441..4d409e61 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -69,7 +69,7 @@ class Client(NamedTuple): token = environ.get("SEASONALBOT_TOKEN") debug = environ.get("SEASONALBOT_DEBUG", "").lower() == "true" season_override = environ.get("SEASON_OVERRIDE") - icon_cycle_frequency = 3 # N days to wait between cycling server icons within a single season + icon_cycle_frequency = 3 # 0: never, 1: every day, 2: every other day, ... class Colours: -- cgit v1.2.3 From 40094bf428d4e474132d9187c166a0aa373b7915 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Wed, 18 Mar 2020 21:11:24 +0100 Subject: Deseasonify: add github token env var --- bot/constants.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index d99da892..ec6d173e 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -155,6 +155,7 @@ class Tokens(NamedTuple): youtube = environ.get("YOUTUBE_API_KEY") tmdb = environ.get("TMDB_API_KEY") igdb = environ.get("IGDB_API_KEY") + github = environ.get("GITHUB_TOKEN") # Default role combinations -- cgit v1.2.3 From e987735bcb38b3f7caa8f89d5d81c20c0d37cd12 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sat, 21 Mar 2020 19:26:22 +0100 Subject: Deseasonify: remove `season_override` env var Unused and no longer relevant. --- bot/constants.py | 1 - docker-compose.yml | 1 - 2 files changed, 2 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index ec6d173e..9afbc604 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -68,7 +68,6 @@ class Client(NamedTuple): prefix = environ.get("PREFIX", ".") token = environ.get("SEASONALBOT_TOKEN") debug = environ.get("SEASONALBOT_DEBUG", "").lower() == "true" - season_override = environ.get("SEASON_OVERRIDE") icon_cycle_frequency = 3 # 0: never, 1: every day, 2: every other day, ... diff --git a/docker-compose.yml b/docker-compose.yml index 30e8a109..6cf5e9bd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,6 @@ services: # - SEASONALBOT_ADMIN_ROLE_ID= # - CHANNEL_ANNOUNCEMENTS= # - CHANNEL_DEVLOG= - # - SEASON_OVERRIDE= volumes: - /opt/pythondiscord/seasonalbot/log:/bot/bot/log -- cgit v1.2.3 From 9b9499824b6db37b35ee3a168bc342f9864ee944 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sat, 21 Mar 2020 19:46:07 +0100 Subject: Deseasonify: add class for branding config Since we'll be adding more env vars to control the branding manager, let's add a new config category. As a result, the cycle frequency constant name can be made shorter. --- bot/branding.py | 12 ++++++------ bot/constants.py | 7 +++++-- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/branding.py b/bot/branding.py index b07ca4b4..690c14c1 100644 --- a/bot/branding.py +++ b/bot/branding.py @@ -10,7 +10,7 @@ from discord.embeds import EmptyEmbed from discord.ext import commands from bot.bot import SeasonalBot -from bot.constants import Client, MODERATION_ROLES, Tokens +from bot.constants import Branding, MODERATION_ROLES, Tokens from bot.decorators import with_role from bot.seasons import SeasonBase, get_current_season, get_season @@ -155,8 +155,8 @@ class BrandingManager(commands.Cog): info_embed.add_field(name="Available icons", value=icons, inline=False) # Only display cycle frequency if we're actually cycling - if len(self.available_icons) > 1 and Client.icon_cycle_frequency: - info_embed.set_footer(text=f"Icon cycle frequency: {Client.icon_cycle_frequency}") + if len(self.available_icons) > 1 and Branding.cycle_frequency: + info_embed.set_footer(text=f"Icon cycle frequency: {Branding.cycle_frequency}") return info_embed @@ -169,13 +169,13 @@ class BrandingManager(commands.Cog): Reset the `should_cycle` counter based on configured frequency. Counter will always yield False if either holds: - - Client.icon_cycle_frequency is falsey + - Branding.cycle_frequency is falsey - There are fewer than 2 available icons for current season Cycling can be easily turned off, and we prevent re-uploading the same icon repeatedly. """ - if len(self.available_icons) > 1 and Client.icon_cycle_frequency: - wait_period = [False] * (Client.icon_cycle_frequency - 1) + if len(self.available_icons) > 1 and Branding.cycle_frequency: + wait_period = [False] * (Branding.cycle_frequency - 1) counter = itertools.cycle(wait_period + [True]) else: counter = itertools.cycle([False]) diff --git a/bot/constants.py b/bot/constants.py index 9afbc604..691e7760 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -6,7 +6,7 @@ from typing import NamedTuple __all__ = ( "bookmark_icon_url", - "AdventOfCode", "Channels", "Client", "Colours", "Emojis", "Hacktoberfest", "Month", "Roles", "Tokens", + "AdventOfCode", "Branding", "Channels", "Client", "Colours", "Emojis", "Hacktoberfest", "Month", "Roles", "Tokens", "WHITELISTED_CHANNELS", "STAFF_ROLES", "MODERATION_ROLES", "POSITIVE_REPLIES", "NEGATIVE_REPLIES", "ERROR_REPLIES", ) @@ -63,12 +63,15 @@ class Channels(NamedTuple): hacktoberfest_2019 = 628184417646411776 +class Branding: + cycle_frequency = int(environ.get("CYCLE_FREQUENCY", 3)) # 0: never, 1: every day, 2: every other day, ... + + class Client(NamedTuple): guild = int(environ.get("SEASONALBOT_GUILD", 267624335836053506)) prefix = environ.get("PREFIX", ".") token = environ.get("SEASONALBOT_TOKEN") debug = environ.get("SEASONALBOT_DEBUG", "").lower() == "true" - icon_cycle_frequency = 3 # 0: never, 1: every day, 2: every other day, ... class Colours: -- cgit v1.2.3 From 612f7a2034007c0ba993c3f991c2624328bd08f3 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sun, 22 Mar 2020 14:23:50 +0100 Subject: Deseasonify: add autostart env var During development it may be useful to not have the branding daemon start automatically - this env var will make that possible. --- bot/constants.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index 691e7760..f552aec7 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -65,6 +65,7 @@ class Channels(NamedTuple): class Branding: cycle_frequency = int(environ.get("CYCLE_FREQUENCY", 3)) # 0: never, 1: every day, 2: every other day, ... + autostart = bool(environ.get("BRANDING_AUTOSTART", True)) # Launch the branding daemon automatically on start-up class Client(NamedTuple): -- cgit v1.2.3 From f4379598c42b2c40287e632b32acecd2ebb14bf6 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sun, 22 Mar 2020 14:44:47 +0100 Subject: Deseasonify: add ok_hand emoji constant --- bot/constants.py | 1 + 1 file changed, 1 insertion(+) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index f552aec7..d2039c81 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -93,6 +93,7 @@ class Emojis: check = "\u2611" envelope = "\U0001F4E8" trashcan = "<:trashcan:637136429717389331>" + ok_hand = ":ok_hand:" terning1 = "<:terning1:431249668983488527>" terning2 = "<:terning2:462339216987127808>" -- cgit v1.2.3 From c0642a12fa64b0be7671f08f00362d96360495e4 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sun, 22 Mar 2020 18:37:29 +0100 Subject: Deseasonify: load bool env var properly Fixes a bug where the `autostart` boolean constant wasn't being loaded properly and would always be set to True, as `bool("False") is True`. The constant now defaults to False. --- bot/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index d2039c81..c2c76122 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -65,7 +65,7 @@ class Channels(NamedTuple): class Branding: cycle_frequency = int(environ.get("CYCLE_FREQUENCY", 3)) # 0: never, 1: every day, 2: every other day, ... - autostart = bool(environ.get("BRANDING_AUTOSTART", True)) # Launch the branding daemon automatically on start-up + autostart = environ.get("BRANDING_AUTOSTART", "").lower() == "true" # Launch the branding daemon on start-up class Client(NamedTuple): -- cgit v1.2.3 From 55a0daeb4536c3901976f68d3fa315729e876e74 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 24 Mar 2020 23:21:05 +0100 Subject: Deseasonify: move bookmark icon under `Icons` constants --- bot/constants.py | 10 ++++------ bot/seasons/evergreen/bookmark.py | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index c2c76122..acdd006e 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -5,7 +5,6 @@ from os import environ from typing import NamedTuple __all__ = ( - "bookmark_icon_url", "AdventOfCode", "Branding", "Channels", "Client", "Colours", "Emojis", "Hacktoberfest", "Month", "Roles", "Tokens", "WHITELISTED_CHANNELS", "STAFF_ROLES", "MODERATION_ROLES", "POSITIVE_REPLIES", "NEGATIVE_REPLIES", "ERROR_REPLIES", @@ -13,11 +12,6 @@ __all__ = ( log = logging.getLogger(__name__) -bookmark_icon_url = ( - "https://images-ext-2.discordapp.net/external/zl4oDwcmxUILY7sD9ZWE2fU5R7n6QcxEmPYSE5eddbg/" - "%3Fv%3D1/https/cdn.discordapp.com/emojis/654080405988966419.png?width=20&height=20" -) - class AdventOfCode: leaderboard_cache_age_threshold_seconds = 3600 @@ -111,6 +105,10 @@ class Emojis: class Icons: questionmark = "https://cdn.discordapp.com/emojis/512367613339369475.png" + bookmark = ( + "https://images-ext-2.discordapp.net/external/zl4oDwcmxUILY7sD9ZWE2fU5R7n6QcxEmPYSE5eddbg/" + "%3Fv%3D1/https/cdn.discordapp.com/emojis/654080405988966419.png?width=20&height=20" + ) class Lovefest: diff --git a/bot/seasons/evergreen/bookmark.py b/bot/seasons/evergreen/bookmark.py index bd7d5c11..e703e07b 100644 --- a/bot/seasons/evergreen/bookmark.py +++ b/bot/seasons/evergreen/bookmark.py @@ -4,7 +4,7 @@ import random import discord from discord.ext import commands -from bot.constants import Colours, ERROR_REPLIES, Emojis, bookmark_icon_url +from bot.constants import Colours, ERROR_REPLIES, Emojis, Icons log = logging.getLogger(__name__) @@ -43,7 +43,7 @@ class Bookmark(commands.Cog): ) embed.add_field(name="Wanna give it a visit?", value=f"[Visit original message]({target_message.jump_url})") embed.set_author(name=target_message.author, icon_url=target_message.author.avatar_url) - embed.set_thumbnail(url=bookmark_icon_url) + embed.set_thumbnail(url=Icons.bookmark) try: await ctx.author.send(embed=embed) -- cgit v1.2.3 From a5974cc0e18b1534743a655a78ebe0f4cf82a9d2 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 24 Mar 2020 23:43:39 +0100 Subject: Deseasonify: clean up `constants` module Order config classes and constants alphabetically (within groups). Add missing classes to `__all__`, and style it as a vertical list. This will make it easier to maintain, and allows it to serve as a summary of the module's contents. --- bot/constants.py | 72 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 27 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index acdd006e..bc0e4677 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -5,9 +5,24 @@ from os import environ from typing import NamedTuple __all__ = ( - "AdventOfCode", "Branding", "Channels", "Client", "Colours", "Emojis", "Hacktoberfest", "Month", "Roles", "Tokens", - "WHITELISTED_CHANNELS", "STAFF_ROLES", "MODERATION_ROLES", - "POSITIVE_REPLIES", "NEGATIVE_REPLIES", "ERROR_REPLIES", + "AdventOfCode", + "Branding", + "Channels", + "Client", + "Colours", + "Emojis", + "Hacktoberfest", + "Icons", + "Lovefest", + "Month", + "Roles", + "Tokens", + "MODERATION_ROLES", + "STAFF_ROLES", + "WHITELISTED_CHANNELS", + "ERROR_REPLIES", + "NEGATIVE_REPLIES", + "POSITIVE_REPLIES", ) log = logging.getLogger(__name__) @@ -22,6 +37,11 @@ class AdventOfCode: role_id = int(environ.get("AOC_ROLE_ID", 518565788744024082)) +class Branding: + cycle_frequency = int(environ.get("CYCLE_FREQUENCY", 3)) # 0: never, 1: every day, 2: every other day, ... + autostart = environ.get("BRANDING_AUTOSTART", "").lower() == "true" # Launch the branding daemon on start-up + + class Channels(NamedTuple): admins = 365960823622991872 advent_of_code = int(environ.get("AOC_CHANNEL_ID", 517745814039166986)) @@ -57,11 +77,6 @@ class Channels(NamedTuple): hacktoberfest_2019 = 628184417646411776 -class Branding: - cycle_frequency = int(environ.get("CYCLE_FREQUENCY", 3)) # 0: never, 1: every day, 2: every other day, ... - autostart = environ.get("BRANDING_AUTOSTART", "").lower() == "true" # Launch the branding daemon on start-up - - class Client(NamedTuple): guild = int(environ.get("SEASONALBOT_GUILD", 267624335836053506)) prefix = environ.get("PREFIX", ".") @@ -103,6 +118,10 @@ class Emojis: merge = "<:PRMerged:629695470570176522>" +class Hacktoberfest(NamedTuple): + voice_id = 514420006474219521 + + class Icons: questionmark = "https://cdn.discordapp.com/emojis/512367613339369475.png" bookmark = ( @@ -115,10 +134,6 @@ class Lovefest: role_id = int(environ.get("LOVEFEST_ROLE_ID", 542431903886606399)) -class Hacktoberfest(NamedTuple): - voice_id = 514420006474219521 - - class Month(enum.IntEnum): january = 1 february = 2 @@ -166,12 +181,28 @@ STAFF_ROLES = Roles.helpers, Roles.moderator, Roles.admin, Roles.owner # Whitelisted channels WHITELISTED_CHANNELS = ( - Channels.bot, Channels.seasonalbot_commands, - Channels.off_topic_0, Channels.off_topic_1, Channels.off_topic_2, + Channels.bot, + Channels.seasonalbot_commands, + Channels.off_topic_0, + Channels.off_topic_1, + Channels.off_topic_2, Channels.devtest, ) # Bot replies +ERROR_REPLIES = [ + "Please don't do that.", + "You have to stop.", + "Do you mind?", + "In the future, don't do that.", + "That was a mistake.", + "You blew it.", + "You're bad at computers.", + "Are you trying to kill me?", + "Noooooo!!", + "I can't believe you've done this", +] + NEGATIVE_REPLIES = [ "Noooooo!!", "Nope.", @@ -211,16 +242,3 @@ POSITIVE_REPLIES = [ "Aye aye, cap'n!", "I'll allow it.", ] - -ERROR_REPLIES = [ - "Please don't do that.", - "You have to stop.", - "Do you mind?", - "In the future, don't do that.", - "That was a mistake.", - "You blew it.", - "You're bad at computers.", - "Are you trying to kill me?", - "Noooooo!!", - "I can't believe you've done this", -] -- cgit v1.2.3 From 879960caf8461a562cec35b7f64815853844d23e Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 24 Mar 2020 23:58:16 +0100 Subject: Deseasonify: remove outdated `devtest` channel constant This channel no longer exists and creeps into error messages as #deleted-channel. Fixes: #335 --- bot/constants.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index bc0e4677..68e2b33f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -51,7 +51,6 @@ class Channels(NamedTuple): checkpoint_test = 422077681434099723 devalerts = 460181980097675264 devlog = int(environ.get("CHANNEL_DEVLOG", 622895325144940554)) - devtest = 414574275865870337 help_0 = 303906576991780866 help_1 = 303906556754395136 help_2 = 303906514266226689 @@ -186,7 +185,6 @@ WHITELISTED_CHANNELS = ( Channels.off_topic_0, Channels.off_topic_1, Channels.off_topic_2, - Channels.devtest, ) # Bot replies -- cgit v1.2.3 From bad7223930e637370891987bf2f67099d4649547 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sun, 29 Mar 2020 17:44:33 +0200 Subject: Deseasonify: add `month_override` env var --- bot/constants.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index 1a2763f0..7a8f13e7 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -82,6 +82,8 @@ class Client(NamedTuple): token = environ.get("SEASONALBOT_TOKEN") sentry_dsn = environ.get("SEASONALBOT_SENTRY_DSN") debug = environ.get("SEASONALBOT_DEBUG", "").lower() == "true" + # Override seasonal locks: 1 (january) to 12 (december) + month_override = int(environ["MONTH_OVERRIDE"]) if "MONTH_OVERRIDE" in environ else None class Colours: -- cgit v1.2.3 From 0c7d501501dbe9a30df5b21452465a81ec688516 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Sun, 29 Mar 2020 18:04:45 +0200 Subject: Deseasonify: validate configured month override --- bot/constants.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index 7a8f13e7..c739e277 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -151,6 +151,12 @@ class Month(enum.IntEnum): december = 12 +# If a month override was configured, check that it's a valid Month +# Prevents delaying an exception after the bot starts +if Client.month_override is not None: + Month(Client.month_override) + + class Roles(NamedTuple): admin = int(environ.get("SEASONALBOT_ADMIN_ROLE_ID", 267628507062992896)) announcements = 463658397560995840 -- cgit v1.2.3 From 548dc99fb5aead10c8b95dd97191be900baec3a8 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Mon, 30 Mar 2020 19:15:16 +0200 Subject: Deseasonify: remove `autostart` env var Constant is no longer used. See: 9259f985e6e327a522b4420c879a50cb4f75a09d --- bot/constants.py | 1 - 1 file changed, 1 deletion(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index c739e277..ab16be5d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -39,7 +39,6 @@ class AdventOfCode: class Branding: cycle_frequency = int(environ.get("CYCLE_FREQUENCY", 3)) # 0: never, 1: every day, 2: every other day, ... - autostart = environ.get("BRANDING_AUTOSTART", "").lower() == "true" # Launch the branding daemon on start-up class Channels(NamedTuple): -- cgit v1.2.3 From 00af207de3087a41270f216ad86e06ba7dbf9d42 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 31 Mar 2020 16:18:59 +0200 Subject: Refactor: capitalize Month enum members Co-authored-by: MarkKoz --- bot/constants.py | 24 ++++++++++++------------ bot/exts/christmas/adventofcode.py | 2 +- bot/exts/christmas/hanukkah_embed.py | 2 +- bot/exts/easter/egg_facts.py | 2 +- bot/exts/halloween/candy_collection.py | 6 +++--- bot/exts/halloween/hacktober-issue-finder.py | 2 +- bot/exts/halloween/hacktoberstats.py | 6 +++--- bot/exts/halloween/spookyreact.py | 2 +- bot/exts/pride/pride_facts.py | 2 +- bot/exts/valentines/be_my_valentine.py | 2 +- bot/seasons.py | 12 ++++++------ 11 files changed, 31 insertions(+), 31 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index ab16be5d..34bbf87f 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -136,18 +136,18 @@ class Lovefest: class Month(enum.IntEnum): - january = 1 - february = 2 - march = 3 - april = 4 - may = 5 - june = 6 - july = 7 - august = 8 - september = 9 - october = 10 - november = 11 - december = 12 + JANUARY = 1 + FEBRUARY = 2 + MARCH = 3 + APRIL = 4 + MAY = 5 + JUNE = 6 + JULY = 7 + AUGUST = 8 + SEPTEMBER = 9 + OCTOBER = 10 + NOVEMBER = 11 + DECEMBER = 12 # If a month override was configured, check that it's a valid Month diff --git a/bot/exts/christmas/adventofcode.py b/bot/exts/christmas/adventofcode.py index 8f7aa13b..cc3923c8 100644 --- a/bot/exts/christmas/adventofcode.py +++ b/bot/exts/christmas/adventofcode.py @@ -153,7 +153,7 @@ class AdventOfCode(commands.Cog): status_coro = countdown_status(self.bot) self.status_task = self.bot.loop.create_task(status_coro) - @in_month(Month.december) + @in_month(Month.DECEMBER) @commands.group(name="adventofcode", aliases=("aoc",)) @override_in_channel(AOC_WHITELIST) async def adventofcode_group(self, ctx: commands.Context) -> None: diff --git a/bot/exts/christmas/hanukkah_embed.py b/bot/exts/christmas/hanukkah_embed.py index 718ca32a..4f470a34 100644 --- a/bot/exts/christmas/hanukkah_embed.py +++ b/bot/exts/christmas/hanukkah_embed.py @@ -34,7 +34,7 @@ class HanukkahEmbed(commands.Cog): hanukkah_dates.append(date) return hanukkah_dates - @in_month(Month.december) + @in_month(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).""" diff --git a/bot/exts/easter/egg_facts.py b/bot/exts/easter/egg_facts.py index bc64d26e..83918fb0 100644 --- a/bot/exts/easter/egg_facts.py +++ b/bot/exts/easter/egg_facts.py @@ -32,7 +32,7 @@ class EasterFacts(commands.Cog): with p.open(encoding="utf8") as f: return load(f) - @seasonal_task(Month.april) + @seasonal_task(Month.APRIL) async def send_egg_fact_daily(self) -> None: """A background task that sends an easter egg fact in the event channel everyday.""" await self.bot.wait_until_ready() diff --git a/bot/exts/halloween/candy_collection.py b/bot/exts/halloween/candy_collection.py index 00061fc2..90c29eb2 100644 --- a/bot/exts/halloween/candy_collection.py +++ b/bot/exts/halloween/candy_collection.py @@ -35,7 +35,7 @@ class CandyCollection(commands.Cog): userid = userinfo['userid'] self.get_candyinfo[userid] = userinfo - @in_month(Month.october) + @in_month(Month.OCTOBER) @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Randomly adds candy or skull reaction to non-bot messages in the Event channel.""" @@ -57,7 +57,7 @@ class CandyCollection(commands.Cog): self.msg_reacted.append(d) return await message.add_reaction('\N{CANDY}') - @in_month(Month.october) + @in_month(Month.OCTOBER) @commands.Cog.listener() async def on_reaction_add(self, reaction: discord.Reaction, user: discord.Member) -> None: """Add/remove candies from a person if the reaction satisfies criteria.""" @@ -181,7 +181,7 @@ class CandyCollection(commands.Cog): with open(json_location, 'w') as outfile: json.dump(self.candy_json, outfile) - @in_month(Month.october) + @in_month(Month.OCTOBER) @commands.command() async def candy(self, ctx: commands.Context) -> None: """Get the candy leaderboard and save to JSON.""" diff --git a/bot/exts/halloween/hacktober-issue-finder.py b/bot/exts/halloween/hacktober-issue-finder.py index 3a9d38d2..b5ad1c4f 100644 --- a/bot/exts/halloween/hacktober-issue-finder.py +++ b/bot/exts/halloween/hacktober-issue-finder.py @@ -26,7 +26,7 @@ class HacktoberIssues(commands.Cog): self.cache_beginner = None self.cache_timer_beginner = datetime.datetime(1, 1, 1) - @in_month(Month.october) + @in_month(Month.OCTOBER) @commands.command() async def hacktoberissues(self, ctx: commands.Context, option: str = "") -> None: """ diff --git a/bot/exts/halloween/hacktoberstats.py b/bot/exts/halloween/hacktoberstats.py index 0c1c837c..e01ee50c 100644 --- a/bot/exts/halloween/hacktoberstats.py +++ b/bot/exts/halloween/hacktoberstats.py @@ -29,7 +29,7 @@ class HacktoberStats(commands.Cog): self.link_json = make_persistent(Path("bot", "resources", "halloween", "github_links.json")) self.linked_accounts = self.load_linked_users() - @in_month(Month.october) + @in_month(Month.OCTOBER) @commands.group(name="hacktoberstats", aliases=("hackstats",), invoke_without_command=True) @override_in_channel(HACKTOBER_WHITELIST) async def hacktoberstats_group(self, ctx: commands.Context, github_username: str = None) -> None: @@ -57,7 +57,7 @@ class HacktoberStats(commands.Cog): await self.get_stats(ctx, github_username) - @in_month(Month.october) + @in_month(Month.OCTOBER) @hacktoberstats_group.command(name="link") @override_in_channel(HACKTOBER_WHITELIST) async def link_user(self, ctx: commands.Context, github_username: str = None) -> None: @@ -92,7 +92,7 @@ class HacktoberStats(commands.Cog): logging.info(f"{author_id} tried to link a GitHub account but didn't provide a username") await ctx.send(f"{author_mention}, a GitHub username is required to link your account") - @in_month(Month.october) + @in_month(Month.OCTOBER) @hacktoberstats_group.command(name="unlink") @override_in_channel(HACKTOBER_WHITELIST) async def unlink_user(self, ctx: commands.Context) -> None: diff --git a/bot/exts/halloween/spookyreact.py b/bot/exts/halloween/spookyreact.py index a3896cfb..e5945aea 100644 --- a/bot/exts/halloween/spookyreact.py +++ b/bot/exts/halloween/spookyreact.py @@ -26,7 +26,7 @@ class SpookyReact(Cog): def __init__(self, bot: Bot): self.bot = bot - @in_month(Month.october) + @in_month(Month.OCTOBER) @Cog.listener() async def on_message(self, ctx: discord.Message) -> None: """ diff --git a/bot/exts/pride/pride_facts.py b/bot/exts/pride/pride_facts.py index bd9c087b..f759dcb1 100644 --- a/bot/exts/pride/pride_facts.py +++ b/bot/exts/pride/pride_facts.py @@ -32,7 +32,7 @@ class PrideFacts(commands.Cog): with open(Path("bot/resources/pride/facts.json"), "r", encoding="utf-8") as f: return json.load(f) - @seasonal_task(Month.june) + @seasonal_task(Month.JUNE) async def send_pride_fact_daily(self) -> None: """Background task to post the daily pride fact every day.""" await self.bot.wait_until_ready() diff --git a/bot/exts/valentines/be_my_valentine.py b/bot/exts/valentines/be_my_valentine.py index 4b0818da..e5e71d25 100644 --- a/bot/exts/valentines/be_my_valentine.py +++ b/bot/exts/valentines/be_my_valentine.py @@ -31,7 +31,7 @@ class BeMyValentine(commands.Cog): valentines = load(json_data) return valentines - @in_month(Month.february) + @in_month(Month.FEBRUARY) @commands.group(name="lovefest") async def lovefest_role(self, ctx: commands.Context) -> None: """ diff --git a/bot/seasons.py b/bot/seasons.py index 1376d50b..30979d2a 100644 --- a/bot/seasons.py +++ b/bot/seasons.py @@ -43,7 +43,7 @@ class Christmas(SeasonBase): branding_path = "seasonal/christmas" - months = {Month.december} + months = {Month.DECEMBER} class Easter(SeasonBase): @@ -60,7 +60,7 @@ class Easter(SeasonBase): branding_path = "seasonal/easter" - months = {Month.april} + months = {Month.APRIL} class Halloween(SeasonBase): @@ -74,7 +74,7 @@ class Halloween(SeasonBase): branding_path = "seasonal/halloween" - months = {Month.october} + months = {Month.OCTOBER} class Pride(SeasonBase): @@ -94,7 +94,7 @@ class Pride(SeasonBase): branding_path = "seasonal/pride" - months = {Month.june} + months = {Month.JUNE} class Valentines(SeasonBase): @@ -108,7 +108,7 @@ class Valentines(SeasonBase): branding_path = "seasonal/valentines" - months = {Month.february} + months = {Month.FEBRUARY} class Wildcard(SeasonBase): @@ -120,7 +120,7 @@ class Wildcard(SeasonBase): colour = Colours.purple description = "A season full of surprises!" - months = {Month.august} + months = {Month.AUGUST} def get_all_seasons() -> t.List[t.Type[SeasonBase]]: -- cgit v1.2.3 From 3902f9dcd81fbd8cc8c3082e20608e4b16638c77 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Tue, 31 Mar 2020 17:35:48 +0200 Subject: Refactor: adjust docstrings based on feedback * Capitalize month names * Add backticks to `sha` attr reference * Avoid misusing the term 'poll' Co-authored-by: MarkKoz --- bot/constants.py | 2 +- bot/exts/evergreen/branding.py | 16 ++++++---------- bot/seasons.py | 12 ++++++------ 3 files changed, 13 insertions(+), 17 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index 34bbf87f..22ea9177 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -81,7 +81,7 @@ class Client(NamedTuple): token = environ.get("SEASONALBOT_TOKEN") sentry_dsn = environ.get("SEASONALBOT_SENTRY_DSN") debug = environ.get("SEASONALBOT_DEBUG", "").lower() == "true" - # Override seasonal locks: 1 (january) to 12 (december) + # Override seasonal locks: 1 (January) to 12 (December) month_override = int(environ["MONTH_OVERRIDE"]) if "MONTH_OVERRIDE" in environ else None diff --git a/bot/exts/evergreen/branding.py b/bot/exts/evergreen/branding.py index 8fd8d6eb..754e8cfa 100644 --- a/bot/exts/evergreen/branding.py +++ b/bot/exts/evergreen/branding.py @@ -43,7 +43,7 @@ class GithubFile(t.NamedTuple): """ Represents a remote file on Github. - The sha hash is kept so that we can determine that a file has changed, + The `sha` hash is kept so that we can determine that a file has changed, despite its filename remaining unchanged. """ @@ -266,7 +266,7 @@ class BrandingManager(commands.Cog): async def _get_files(self, path: str, include_dirs: bool = False) -> t.Dict[str, GithubFile]: """ - Poll `path` in branding repo for information about present files. + Get files at `path` in the branding repository. If `include_dirs` is False (default), only returns files at `path`. Otherwise, will return both files and directories. Never returns symlinks. @@ -292,10 +292,10 @@ class BrandingManager(commands.Cog): async def refresh(self) -> bool: """ - Poll Github API to refresh currently available icons. + Synchronize available assets with branding repository. If the current season is not the evergreen, and lacks at least one asset, - we also poll the evergreen seasonal dir as fallback for missing assets. + we use the evergreen seasonal dir as fallback for missing assets. Finally, if neither the seasonal nor fallback branding directories contain an asset, it will simply be ignored. @@ -455,7 +455,7 @@ class BrandingManager(commands.Cog): @branding_cmds.command(name="info", aliases=["status"]) async def branding_info(self, ctx: commands.Context) -> None: """ - Show assets for current season. + Show available assets for current season. This can be used to confirm that assets have been resolved properly. When `apply` is used, it attempts to upload exactly the assets listed here. @@ -464,11 +464,7 @@ class BrandingManager(commands.Cog): @branding_cmds.command(name="refresh") async def branding_refresh(self, ctx: commands.Context) -> None: - """ - Refresh current season from branding repository. - - Polls Github API to refresh assets available for current season. - """ + """Sync currently available assets with branding repository.""" async with ctx.typing(): await self.refresh() await self.branding_info(ctx) diff --git a/bot/seasons.py b/bot/seasons.py index 30979d2a..cb74ec89 100644 --- a/bot/seasons.py +++ b/bot/seasons.py @@ -30,7 +30,7 @@ class SeasonBase: class Christmas(SeasonBase): - """Branding for december.""" + """Branding for December.""" season_name = "Festive season" bot_name = "Merrybot" @@ -47,7 +47,7 @@ class Christmas(SeasonBase): class Easter(SeasonBase): - """Branding for april.""" + """Branding for April.""" season_name = "Easter" bot_name = "BunnyBot" @@ -64,7 +64,7 @@ class Easter(SeasonBase): class Halloween(SeasonBase): - """Branding for october.""" + """Branding for October.""" season_name = "Halloween" bot_name = "NeonBot" @@ -78,7 +78,7 @@ class Halloween(SeasonBase): class Pride(SeasonBase): - """Branding for june.""" + """Branding for June.""" season_name = "Pride" bot_name = "ProudBot" @@ -98,7 +98,7 @@ class Pride(SeasonBase): class Valentines(SeasonBase): - """Branding for february.""" + """Branding for February.""" season_name = "Valentines" bot_name = "TenderBot" @@ -112,7 +112,7 @@ class Valentines(SeasonBase): class Wildcard(SeasonBase): - """Branding for august.""" + """Branding for August.""" season_name = "Wildcard" bot_name = "RetroBot" -- cgit v1.2.3 From a74debb82dba47ac843ac6b769d8d6d50f3e2f30 Mon Sep 17 00:00:00 2001 From: kwzrd Date: Wed, 1 Apr 2020 09:40:30 +0200 Subject: Deseasonify: implement __str__ for Month enum This way, we can standardize the way Months are shown to both the user and the developer. Note that if passing a Month member to an f-string, the `!s` format code must be specified to ensure our __str__ is used. Co-authored-by: MarkKoz --- bot/constants.py | 3 +++ bot/exts/evergreen/branding.py | 7 +++---- bot/utils/__init__.py | 7 ++++++- bot/utils/decorators.py | 19 +++++++++---------- 4 files changed, 21 insertions(+), 15 deletions(-) (limited to 'bot/constants.py') diff --git a/bot/constants.py b/bot/constants.py index 22ea9177..638448ea 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -149,6 +149,9 @@ class Month(enum.IntEnum): NOVEMBER = 11 DECEMBER = 12 + def __str__(self) -> str: + return self.name.title() + # If a month override was configured, check that it's a valid Month # Prevents delaying an exception after the bot starts diff --git a/bot/exts/evergreen/branding.py b/bot/exts/evergreen/branding.py index 140613e9..96acd587 100644 --- a/bot/exts/evergreen/branding.py +++ b/bot/exts/evergreen/branding.py @@ -15,6 +15,7 @@ from discord.ext import commands from bot.bot import SeasonalBot from bot.constants import Branding, Colours, Emojis, MODERATION_ROLES, Tokens from bot.seasons import SeasonBase, get_all_seasons, get_current_season, get_season +from bot.utils import human_months from bot.utils.decorators import with_role from bot.utils.exceptions import BrandingError from bot.utils.persist import make_persistent @@ -219,8 +220,7 @@ class BrandingManager(commands.Cog): # If we're in a non-evergreen season, also show active months if self.current_season is not SeasonBase: - active_months = ", ".join(m.name.title() for m in self.current_season.months) - title = f"{self.current_season.season_name} ({active_months})" + title = f"{self.current_season.season_name} ({human_months(self.current_season.months)})" else: title = self.current_season.season_name @@ -406,8 +406,7 @@ class BrandingManager(commands.Cog): if season is SeasonBase: active_when = "always" else: - months = ", ".join(m.name.title() for m in season.months) - active_when = f"in {months}" + active_when = f"in {human_months(season.months)}" description = ( f"Active {active_when}\n" diff --git a/bot/utils/__init__.py b/bot/utils/__init__.py index 69bff4de..35ef0a7b 100644 --- a/bot/utils/__init__.py +++ b/bot/utils/__init__.py @@ -3,7 +3,7 @@ import contextlib import re import string from datetime import datetime -from typing import List +from typing import Iterable, List import discord from discord.ext.commands import BadArgument, Context @@ -12,6 +12,11 @@ from bot.constants import Client, Month from bot.utils.pagination import LinePaginator +def human_months(months: Iterable[Month]) -> str: + """Build a comma separated list of `months`.""" + return ", ".join(str(m) for m in months) + + def resolve_current_month() -> Month: """ Determine current month w.r.t. `Client.month_override` env var. diff --git a/bot/utils/decorators.py b/bot/utils/decorators.py index 1e0a1715..519e61a9 100644 --- a/bot/utils/decorators.py +++ b/bot/utils/decorators.py @@ -12,7 +12,7 @@ from discord.ext import commands from discord.ext.commands import CheckFailure, Command, Context from bot.constants import Client, ERROR_REPLIES, Month -from bot.utils import resolve_current_month +from bot.utils import human_months, resolve_current_month ONE_DAY = 24 * 60 * 60 @@ -47,7 +47,7 @@ def seasonal_task(*allowed_months: Month, sleep_time: t.Union[float, int] = ONE_ @functools.wraps(task_body) async def decorated_task(*args, **kwargs) -> None: """Call `task_body` once every `sleep_time` seconds in `allowed_months`.""" - log.info(f"Starting seasonal task {task_body.__qualname__} ({allowed_months})") + log.info(f"Starting seasonal task {task_body.__qualname__} ({human_months(allowed_months)})") while True: current_month = resolve_current_month() @@ -55,7 +55,7 @@ def seasonal_task(*allowed_months: Month, sleep_time: t.Union[float, int] = ONE_ if current_month in allowed_months: await task_body(*args, **kwargs) else: - log.debug(f"Seasonal task {task_body.__qualname__} sleeps in {current_month.name}") + log.debug(f"Seasonal task {task_body.__qualname__} sleeps in {current_month!s}") await asyncio.sleep(sleep_time) return decorated_task @@ -78,7 +78,7 @@ def in_month_listener(*allowed_months: Month) -> t.Callable: # Propagate return value although it should always be None return await listener(*args, **kwargs) else: - log.debug(f"Guarded {listener.__qualname__} from invoking in {current_month.name}") + log.debug(f"Guarded {listener.__qualname__} from invoking in {current_month!s}") return guarded_listener return decorator @@ -93,15 +93,14 @@ def in_month_command(*allowed_months: Month) -> t.Callable: current_month = resolve_current_month() can_run = current_month in allowed_months - human_months = ", ".join(m.name for m in allowed_months) log.debug( - f"Command '{ctx.command}' is locked to months {human_months}. " - f"Invoking it in month {current_month} is {'allowed' if can_run else 'disallowed'}." + f"Command '{ctx.command}' is locked to months {human_months(allowed_months)}. " + f"Invoking it in month {current_month!s} is {'allowed' if can_run else 'disallowed'}." ) if can_run: return True else: - raise InMonthCheckFailure(f"Command can only be used in {human_months}") + raise InMonthCheckFailure(f"Command can only be used in {human_months(allowed_months)}") return commands.check(predicate) @@ -127,12 +126,12 @@ def in_month(*allowed_months: Month) -> t.Callable: def decorator(callable_: t.Callable) -> t.Callable: # Functions decorated as commands are turned into instances of `Command` if isinstance(callable_, Command): - logging.debug(f"Command {callable_.qualified_name} will be locked to {allowed_months}") + logging.debug(f"Command {callable_.qualified_name} will be locked to {human_months(allowed_months)}") actual_deco = in_month_command(*allowed_months) # D.py will assign this attribute when `callable_` is registered as a listener elif hasattr(callable_, "__cog_listener__"): - logging.debug(f"Listener {callable_.__qualname__} will be locked to {allowed_months}") + logging.debug(f"Listener {callable_.__qualname__} will be locked to {human_months(allowed_months)}") actual_deco = in_month_listener(*allowed_months) # Otherwise we're unsure exactly what has been decorated -- cgit v1.2.3