diff options
| author | 2018-07-02 19:42:20 +0000 | |
|---|---|---|
| committer | 2018-07-02 19:42:20 +0000 | |
| commit | be19e55ae459e1013b9d7ea5cf38bfa2aa13f552 (patch) | |
| tree | f8dcc4b276f0f54ef321b5013d48e607daf89ea9 | |
| parent | [Snekbox] Fix failure to send string errors (diff) | |
| parent | Add a simple OffTopicNames cog. (diff) | |
Merge branch 'add-off-topic-name-rotation' into 'master'
Add a simple OffTopicNames cog.
See merge request python-discord/projects/bot!6
| -rw-r--r-- | bot/__main__.py | 3 | ||||
| -rw-r--r-- | bot/cogs/off_topic_names.py | 114 | ||||
| -rw-r--r-- | config-default.yml | 4 |
3 files changed, 120 insertions, 1 deletions
diff --git a/bot/__main__.py b/bot/__main__.py index 42ab0f224..8eb40757d 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -66,11 +66,12 @@ bot.load_extension("bot.cogs.doc") bot.load_extension("bot.cogs.eval") bot.load_extension("bot.cogs.fun") bot.load_extension("bot.cogs.hiphopify") +bot.load_extension("bot.cogs.off_topic_names") bot.load_extension("bot.cogs.snakes") bot.load_extension("bot.cogs.snekbox") bot.load_extension("bot.cogs.tags") -bot.load_extension("bot.cogs.verification") bot.load_extension("bot.cogs.utils") +bot.load_extension("bot.cogs.verification") if has_rmq: bot.load_extension("bot.cogs.rmq") diff --git a/bot/cogs/off_topic_names.py b/bot/cogs/off_topic_names.py new file mode 100644 index 000000000..3b07a227d --- /dev/null +++ b/bot/cogs/off_topic_names.py @@ -0,0 +1,114 @@ +import asyncio +import logging +from datetime import datetime, timedelta + +from discord.ext.commands import BadArgument, Bot, Context, Converter, group + +from bot.constants import Channels, Keys, Roles, URLs +from bot.decorators import with_role + + +CHANNELS = (Channels.off_topic_0, Channels.off_topic_1, Channels.off_topic_2) +log = logging.getLogger(__name__) + + +class OffTopicName(Converter): + """A converter that ensures an added off-topic name is valid.""" + + @staticmethod + async def convert(ctx: Context, argument: str): + if not (2 <= len(argument) <= 96): + raise BadArgument("Channel name must be between 2 and 96 chars long") + + elif not all(c.isalpha() or c == '-' for c in argument): + raise BadArgument( + "Channel name must only consist of" + " alphabetic characters or minus signs" + ) + + elif not argument.islower(): + raise BadArgument("Channel name must be lowercase") + + return argument + + +async def update_names(bot: Bot, headers: dict): + """ + The background updater task that performs a channel name update daily. + + Args: + bot (Bot): + The running bot instance, used for fetching data from the + website via the bot's `http_session`. + """ + + while True: + today_at_midnight = datetime.utcnow().replace(microsecond=0, second=0, minute=0, hour=0) + next_midnight = today_at_midnight + timedelta(days=1) + seconds_to_sleep = (next_midnight - datetime.utcnow()).seconds + await asyncio.sleep(seconds_to_sleep) + + response = await bot.http_session.get( + f'{URLs.site_off_topic_names_api}?random_items=3', + headers=headers + ) + channel_0_name, channel_1_name, channel_2_name = await response.json() + channel_0, channel_1, channel_2 = (bot.get_channel(channel_id) for channel_id in CHANNELS) + + await channel_0.edit(name=f'ot0-{channel_0_name}') + await channel_1.edit(name=f'ot1-{channel_1_name}') + await channel_2.edit(name=f'ot2-{channel_2_name}') + log.debug( + "Updated off-topic channel names to" + f" {channel_0_name}, {channel_1_name} and {channel_2_name}" + ) + + +class OffTopicNames: + """Commands related to managing the off-topic category channel names.""" + + def __init__(self, bot: Bot): + self.bot = bot + self.headers = {"X-API-KEY": Keys.site_api} + self.updater_task = None + + def __cleanup(self): + if self.updater_task is not None: + self.updater_task.cancel() + + async def on_ready(self): + if self.updater_task is None: + coro = update_names(self.bot, self.headers) + self.updater_task = await self.bot.loop.create_task(coro) + + @group(name='otname') + async def otname_group(self, ctx: Context): + """Contains subcommands to manage the off-topic category names.""" + + @with_role(Roles.owner, Roles.owner, Roles.moderator) + @otname_group.command(name='add') + async def otname_add(self, ctx, name: OffTopicName): + """Adds a new off-topic name to the rotation.""" + + result = await self.bot.http_session.post( + URLs.site_off_topic_names_api, + headers=self.headers, + params={'name': name} + ) + + response = await result.json() + + if result.status == 200: + log.info( + f"{ctx.author.name}#{ctx.author.discriminator}" + f" added the off-topic channel name '{name}" + ) + await ctx.send(":ok_hand:") + else: + error_reason = response.get('message', "No reason provided.") + await ctx.send(f":warning: got non-200 from the API: {error_reason}") + + +def setup(bot: Bot): + bot.add_cog(OffTopicNames(bot)) + log.info("Cog loaded: OffTopicNames") diff --git a/config-default.yml b/config-default.yml index c22b622c0..147c2f7a6 100644 --- a/config-default.yml +++ b/config-default.yml @@ -29,6 +29,9 @@ guild: modlog: 282638479504965634 python: 267624335836053506 verification: 352442727016693763 + off_topic_0: 291284109232308226 + off_topic_1: 463035241142026251 + off_topic_2: 463035268514185226 roles: admin: 267628507062992896 @@ -73,6 +76,7 @@ urls: site_hiphopify_api: 'https://api.pythondiscord.com/bot/hiphopify' site_idioms_api: 'https://api.pythondiscord.com/bot/snake_idioms' site_names_api: 'https://api.pythondiscord.com/bot/snake_names' + site_off_topic_names_api: 'https://api.pythondiscord.com/bot/off-topic-names' site_quiz_api: 'https://api.pythondiscord.com/bot/snake_quiz' site_special_api: 'https://api.pythondiscord.com/bot/special_snakes' site_tags_api: 'https://api.pythondiscord.com/bot/tags' |