diff options
author | 2020-03-30 19:09:40 +0200 | |
---|---|---|
committer | 2020-03-30 19:22:48 +0200 | |
commit | 9259f985e6e327a522b4420c879a50cb4f75a09d (patch) | |
tree | b9409277e9557e66aae023beae8217b2966654ef | |
parent | Deseasonify: add default persistent config file for branding cog (diff) |
Deseasonify: add persistent branding configuration
A persistent config file will remember whether the daemon is supposed
to be running, or not. This means that instead of relying on the env
variable, the daemon can be turned on or off "once and for all"
via a command, and will not violate this decision on restart.
This effectively deprecates the `Branding.autostart` env var. It is
believed that having two ways to configure the same thing would
be more confusing than useful. The env var will be removed.
The two helper functions for reading and writing have been implemented
in a generic manner, meaning that should a new config key be added in
the future, the helpers shouldn't require any further adjustments.
Suggested by lemon and scragly.
Co-authored-by: Leon Sandøy <[email protected]>
Co-authored-by: scragly <[email protected]>
-rw-r--r-- | bot/exts/evergreen/branding.py | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/bot/exts/evergreen/branding.py b/bot/exts/evergreen/branding.py index c674699e..8fd8d6eb 100644 --- a/bot/exts/evergreen/branding.py +++ b/bot/exts/evergreen/branding.py @@ -1,9 +1,11 @@ import asyncio import itertools +import json import logging import random import typing as t from datetime import datetime, time, timedelta +from pathlib import Path import arrow import discord @@ -15,6 +17,7 @@ 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.decorators import with_role from bot.utils.exceptions import BrandingError +from bot.utils.persist import make_persistent log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) @@ -77,10 +80,11 @@ class BrandingManager(commands.Cog): via Github's API, resolving download urls for them, and delegating to the `bot` instance to upload them to the guild. - The cog is designed to be entirely autonomous. The `daemon` background task awakens once - a day (see `time_until_midnight`) to detect new seasons, or to cycle icons within a single - season. If the `Branding.autostart` constant is True, the `daemon` will launch on start-up, - otherwise it can be controlled via the `daemon` cmd group. + BrandingManager is designed to be entirely autonomous. Its `daemon` background task awakens + once a day (see `time_until_midnight`) to detect new seasons, or to cycle icons within a single + season. The daemon can be turned on and off via the `daemon` cmd group. The value set via + its `start` and `stop` commands is persisted across sessions. If turned on, the daemon will + automatically start on the next bot start-up. Otherwise, it will wait to be started manually. All supported operations, e.g. setting seasons, applying the branding, or cycling icons, can also be invoked manually, via the following API: @@ -129,6 +133,8 @@ class BrandingManager(commands.Cog): should_cycle: t.Iterator + config_file: Path + daemon: t.Optional[asyncio.Task] def __init__(self, bot: SeasonalBot) -> None: @@ -150,7 +156,10 @@ class BrandingManager(commands.Cog): self.available_icons = [] self.remaining_icons = [] - if Branding.autostart: + self.config_file = make_persistent(Path("bot", "resources", "evergreen", "branding.json")) + should_run = self._read_config()["daemon_active"] + + if should_run: self.daemon = self.bot.loop.create_task(self._daemon_func()) else: self.daemon = None @@ -160,6 +169,19 @@ class BrandingManager(commands.Cog): """True if the daemon is currently active, False otherwise.""" return self.daemon is not None and not self.daemon.done() + def _read_config(self) -> t.Dict[str, bool]: + """Read and return persistent config file.""" + with self.config_file.open("r") as persistent_file: + return json.load(persistent_file) + + def _write_config(self, key: str, value: bool) -> None: + """Write a `key`, `value` pair to persistent config file.""" + current_config = self._read_config() + current_config[key] = value + + with self.config_file.open("w") as persistent_file: + json.dump(current_config, persistent_file) + async def _daemon_func(self) -> None: """ Manage all automated behaviour of the BrandingManager cog. @@ -507,6 +529,8 @@ class BrandingManager(commands.Cog): raise BrandingError("Daemon already running!") self.daemon = self.bot.loop.create_task(self._daemon_func()) + self._write_config("daemon_active", True) + response = discord.Embed(description=f"Daemon started {Emojis.ok_hand}", colour=Colours.soft_green) await ctx.send(embed=response) @@ -517,6 +541,8 @@ class BrandingManager(commands.Cog): raise BrandingError("Daemon not running!") self.daemon.cancel() + self._write_config("daemon_active", False) + response = discord.Embed(description=f"Daemon stopped {Emojis.ok_hand}", colour=Colours.soft_green) await ctx.send(embed=response) |