From ee22753e9e82879363a3c9540166f51d4aa29988 Mon Sep 17 00:00:00 2001 From: NatrixAeria Date: Mon, 28 Sep 2020 00:48:17 +0200 Subject: Add a command interface --- bot.py | 48 +++++++++++++++++++++---------------- command_utils.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ config.py | 9 +++++++ 3 files changed, 110 insertions(+), 20 deletions(-) create mode 100644 command_utils.py create mode 100644 config.py diff --git a/bot.py b/bot.py index 7a794c6..d860397 100644 --- a/bot.py +++ b/bot.py @@ -1,20 +1,28 @@ -import discord -from discord.ext import commands - -BOT_NAME = "Cupido" - -client = discord.Client() -bot = commands.Bot(command_prefix='!<3') - - -@client.event -async def on_ready(): - print('{0} is logged in as {1.user}'.format(BOT_NAME, client)) - - -@bot.command() -async def init(ctx): - pass - - -client.run('token') +import config +from command_utils import Command, CommandClient + + +class Client(CommandClient): + async def on_ready(self): + print(f'the bot {config.NAME} is logged in as "{self.user}"') + + @Command.help_command + @Command.names('help', 'hepl', 'h', '?') + @Command.description('display this help message') + async def help(self, ctx): + await ctx.answer(config.HELP_TEXT) + + @Command.names('init', 'create', 'inti', 'craete', 'cretae', 'c', 'i', '+') + @Command.description('create a new lobby') + async def init(self, ctx): + await ctx.answer(f'NIY') + + +if __name__ == '__main__': + from os import getenv + token = getenv(config.TOKEN_ENV_VAR) + if token is None: + print('error: no token was given') + exit(1) + bot = Client() + bot.run(token) diff --git a/command_utils.py b/command_utils.py new file mode 100644 index 0000000..2dc84c8 --- /dev/null +++ b/command_utils.py @@ -0,0 +1,73 @@ +import discord + +import config + + +def istrue(value, key): + return hasattr(value, key) and getattr(value, key) + + +class Context: + def __init__(self, msg, args): + self.msg = msg + self.args = args + + async def answer(self, value): + await self.msg.channel.send(f'{self.msg.author.mention} {value}') + + +class CommandClientMeta(type): + def __new__(cls, name, bases, dct): + commands = [] + for item in dct.copy().values(): + if callable(item) and istrue(item, 'command'): + if istrue(item, 'help_command'): + dct['help_command'] = item + commands.append(item) + dct['commands'] = commands + return super().__new__(cls, name, bases, dct) + + +class CommandClient(discord.Client, metaclass=CommandClientMeta): + def get_commands(self): + return type(self).commands.copy() + + async def run_help(self, ctx): + return await type(self).help_command(self, ctx) + + async def on_message(self, msg): + text = msg.content.strip() + if not text.startswith(config.COMMAND_PREFIX): + return + try: + cmd, *args = [v for v in text[len(config.COMMAND_PREFIX):].split(' ') if v] + except ValueError: + return await self.run_help(Context(msg, [])) + ctx = Context(msg, args) + for command in self.get_commands(): + if cmd in command.names: + return await command(self, ctx) + return await self.run_help(ctx) + + +class Command: + @classmethod + def names(cls, *names): + def meta(f): + f.command = True + f.names = names + return f + return meta + + @classmethod + def description(cls, *names): + def meta(f): + f.command = True + f.names = names + return f + return meta + + @classmethod + def help_command(cls, f): + f.help_command = True + return f diff --git a/config.py b/config.py new file mode 100644 index 0000000..85d009d --- /dev/null +++ b/config.py @@ -0,0 +1,9 @@ +NAME = 'cupido' +TOKEN_ENV_VAR = 'DISCORD_TOKEN' + +COMMAND_PREFIX = '!<3' + +HELP_TEXT = f'''{NAME.title()} - your partner for getting shuffled. +{NAME.title()} is a discord bot to get to know your people. +This software is open-source !" +''' -- cgit v1.2.3-54-g00ecf