diff --git a/bot.py b/bot.py index d427de0..3495f82 100644 --- a/bot.py +++ b/bot.py @@ -1,5 +1,4 @@ import asyncio -import json import os import random import re @@ -10,9 +9,10 @@ import discord from discord.ext import commands from dotenv import load_dotenv +from lib.config import config, config_meta, config_load, config_save, config_get, config_set, config_get_descriptions + load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN') -CONFIG = 'config.json' PING_REGEX = re.compile(r'\b(?:ge)?ping', re.IGNORECASE) TOPFIT_REGEX = re.compile(r'\b(topfit|fit|top|micro|microsoft|virtual reality|vr|ä+h*m*|hä*)\b', re.IGNORECASE) @@ -37,31 +37,11 @@ TOPFIT_WORDS = ( # LOEH_ID = 327126546970312739 LOEH_ID = 254265844928872448 -SIP_ID = 327126546970312739 +OWNER_ID = 327126546970312739 -config: dict = { - 'loeh-timeout': 10, - 'loeh-cooldown': 20, - 'prefix': 'och!' -} last_loeh = 0 - -def load_config() -> dict: - try: - config_file = open(CONFIG, 'r') - config.update(json.load(config_file)) - except (json.JSONDecodeError, FileNotFoundError): - pass - return config - - -def save_config(): - with open(CONFIG, 'w') as config_file: - json.dump(config, config_file) - - -load_config() +config_load() bot = commands.Bot(command_prefix=config.get('prefix')) @@ -79,14 +59,14 @@ async def on_ready(): @bot.event async def on_message(message: discord.Message): - global last_loeh, config - if not message.author.bot: - if LOEH_REGEX.match(message.content): + global last_loeh + if message.guild is not None and not message.author.bot: + if config_get('loeh-enable') and LOEH_REGEX.match(message.content): if message.author.id == LOEH_ID: await message.channel.send("https://siphalor.de/img/spidy-is-that-you.jpg") else: t = time.time() - if t - config['loeh-cooldown'] <= last_loeh: + if t - config_get('loeh-cooldown', message.guild.id) <= last_loeh: await message.channel.send('Don\'t try this to often, **' + message.author.nick + '**. That might backfire.') last_loeh = t @@ -98,7 +78,7 @@ async def on_message(message: discord.Message): else: try: await loeh.edit(mute=True) - sleeper = asyncio.sleep(config.get('loeh-timeout')) + sleeper = asyncio.sleep(config_get('loeh-timeout', message.guild.id)) message: Optional[discord.Message] = await message.channel.send('Zu Befehl!') await sleeper @@ -108,61 +88,71 @@ async def on_message(message: discord.Message): except (discord.Forbidden, discord.HTTPException): await message.channel.send('Failed to complete your command, Sir') return - elif PING_REGEX.search(message.content): - embed = discord.Embed( - title="*pinken, schwaches Verb*", - description="ein Netzwerkgerät testweise ansprechen.\nOft falsch geschrieben als pin__g__en", - color=16636435 - ) - embed.add_field(name='ich', value='pinke') - embed.add_field(name='du', value='pinkst') - embed.add_field(name='er|sie|es', value='pinkt') - embed.add_field(name='wir', value='pinken') - embed.add_field(name='ihr', value='pinkt') - embed.add_field(name='sie', value='pinken') - embed.add_field(name='Partizip 2', value='gepinkt') - await message.channel.send(embed=embed) - else: - match = TOPFIT_REGEX.search(message.content) - if match is not None: - text = '' - for i in range(0, random.randint(7, 13)): - text += random.choice(TOPFIT_WORDS) + " " - text += match.group() - await message.channel.send(text) + elif config_get('inf19x-insiders-enable'): + if PING_REGEX.search(message.content): + embed = discord.Embed( + title="*pinken, schwaches Verb*", + description="ein Netzwerkgerät testweise ansprechen.\nOft falsch geschrieben als pin__g__en", + color=16636435 + ) + embed.add_field(name='ich', value='pinke') + embed.add_field(name='du', value='pinkst') + embed.add_field(name='er|sie|es', value='pinkt') + embed.add_field(name='wir', value='pinken') + embed.add_field(name='ihr', value='pinkt') + embed.add_field(name='sie', value='pinken') + embed.add_field(name='Partizip 2', value='gepinkt') + await message.channel.send(embed=embed) + else: + match = TOPFIT_REGEX.search(message.content) + if match is not None: + text = '' + for i in range(0, random.randint(7, 13)): + text += random.choice(TOPFIT_WORDS) + " " + text += match.group() + await message.channel.send(text) await bot.process_commands(message) @bot.command(name='config') async def config_prefix_command(ctx: commands.Context, cmd: str = '', key: str = '', *, val: str = ''): - if ctx.author.id != SIP_ID: - await ctx.send('You\'re not allowed to touch my most valuable piece') + if ctx.guild is None: + await ctx.send('You can\'t run config commands in private messages!') return if cmd == '': - await ctx.send('Use `config get` or `config set` to query for or update config values. Use `config list` to ' - 'see all config options') + await ctx.send('Use `' + bot.command_prefix + 'config get` or `' + bot.command_prefix + + 'config set` to query for or update config values. Use `' + bot.command_prefix + + 'config list` to see all config options') elif cmd == 'list': - await ctx.send('Available config options:\n' - ' - `prefix`: Set the bot prefix\n' - ' - `loeh-timeout`: The timeout for Löh in seconds' - ' - `loeh-cooldown`: Number of seconds between timeouts') + msg = 'Available config options:' + for (key, value) in config_get_descriptions(): + msg += '\n - `' + key + '`: ' + value[1] + await ctx.send(msg) elif cmd == 'get': if key in config: - await ctx.send('`' + key + '` is set to ' + str(config.get(key))) + await ctx.send('`' + key + '` is set to `' + str(config_get(key, ctx.guild.id)) + '`') else: - await ctx.send('Unknown config option "' + key + '"') + await ctx.send('Unknown config option `' + key + '`') elif cmd == 'set': - try: + if ctx.author.guild_permissions.administrator: + await ctx.send(config_set(key, val, ctx.guild.id)) + else: + await ctx.send('You\'re not allowed to change the configuration on this server!') + elif cmd == 'get-global': + if key in config: + await ctx.send('`' + key + '` is globally set to `' + str(config_get(key)) + '`') + else: + await ctx.send('Unknown config option `' + key + '`') + elif cmd == 'set-global': + if ctx.author.id == OWNER_ID: + msg = config_set(key, val) if key == 'prefix': - config['prefix'] = val - elif key == 'loeh-timeout': - config['loeh-timeout'] = int(val) - elif key == 'loeh-cooldown': - config['loeh-cooldown'] = int(val) - save_config() - await ctx.send('Config successfully updated') - except (ValueError, TypeError): - await ctx.send('Invalid value "' + val + '" for config `' + key + '`') + bot.command_prefix = config_get('prefix') + await ctx.send(msg) + else: + await ctx.send('You\'re not allowed to change the global configuration!') + else: + await ctx.send('Unknown command!') bot.run(TOKEN) diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/config.py b/lib/config.py new file mode 100644 index 0000000..545c478 --- /dev/null +++ b/lib/config.py @@ -0,0 +1,92 @@ +import json +from typing import Optional + +CONFIG = 'config.json' +config: dict = { + 'inf19x-insiders-enable': False, + 'loeh-cooldown': 20, + 'loeh-enable': False, + 'loeh-timeout': 10, + 'prefix': 'och!', +} +config_meta: dict = { + 'inf19x-insiders-enable': ( + True, + 'Enables university insider jokes of INF19X' + ), + 'loeh-cooldown': ( + True, + 'Number of seconds between timeouts' + ), + 'loeh-enable': ( + True, + 'Enable time-outing Löh' + ), + 'loeh-timeout': ( + True, + 'The timeout for Löh in seconds' + ), + 'prefix': ( + False, + 'Sets the prefix for this bot' + ), +} + + +def config_load() -> dict: + try: + config_file = open(CONFIG, 'r') + config.update(json.load(config_file)) + except (json.JSONDecodeError, FileNotFoundError): + pass + return config + + +def config_save(): + with open(CONFIG, 'w') as config_file: + json.dump(config, config_file) + + +def config_get(key: str, guild: Optional[int] = None): + guild = str(guild) + if guild in config: + guild = config[guild] + if key in guild: + return guild[key] + return config[key] + + +def config_set(key: str, value, guild: Optional[int] = None) -> str: + if guild is None: + return _config_set_in_scope(config, key, value, type(config[key])) + else: + if config_meta[key][0]: + return _config_set_in_scope(config[str(guild)], key, value, type(config[key])) + else: + return 'This config can only be changed globally by the bot owner!' + + +def config_get_descriptions() -> iter: + return map(lambda entry: (entry[0], entry[1]), config_meta.items()) + + +def _config_set_in_scope(scope: dict, key: str, value, cfg_type: type) -> str: + success = False + try: + if type(value) == cfg_type: + scope[key] = value + success = True + if type(value) == str: + if cfg_type == int: + scope[key] = int(value) + success = True + elif cfg_type == float: + scope[key] = float(value) + success = True + except (TypeError, ValueError): + success = False + if success: + config_save() + return 'Successfully updated config for `' + key + '`' + else: + return 'Unable to determine type of given argument'