From cf2925978b5d5221264db0a0fd665e39924944ab Mon Sep 17 00:00:00 2001 From: Twentysix Date: Sat, 13 May 2017 23:55:14 +0200 Subject: [PATCH] [Core] Interactive configuration --- core/bot.py | 12 ++++------- core/cli.py | 41 ++++++++++++++++++++++++++++++++++++++ core/interactive_config.py | 0 core/settings.py | 4 ---- main.py | 36 ++++++++++++++++++++++++--------- 5 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 core/cli.py delete mode 100644 core/interactive_config.py diff --git a/core/bot.py b/core/bot.py index 6ac80c947..0e9e66cf5 100644 --- a/core/bot.py +++ b/core/bot.py @@ -12,20 +12,16 @@ class Red(commands.Bot): relative_path=False) def prefix_manager(bot, message): - global_prefix = self.db.get_global("prefix", []) + if not cli_flags.prefix: + global_prefix = self.db.get_global("prefix", []) + else: + global_prefix = cli_flags.prefix if message.guild is None: return global_prefix server_prefix = self.db.get(message.guild, "prefix", []) return server_prefix if server_prefix else global_prefix - # Priority: args passed > cli flags > db if "command_prefix" not in kwargs: - if cli_flags.prefix: - kwargs["command_prefix"] = lambda bot, message: cli_flags.prefix - else: - kwargs["command_prefix"] = None - - if kwargs["command_prefix"] is None: kwargs["command_prefix"] = prefix_manager self.counter = Counter() diff --git a/core/cli.py b/core/cli.py new file mode 100644 index 000000000..81193985b --- /dev/null +++ b/core/cli.py @@ -0,0 +1,41 @@ +import asyncio + + +def confirm(m=""): + return input(m).lower().strip() in ("y", "yes") + + +def interactive_config(red, token_set, prefix_set): + loop = asyncio.get_event_loop() + token = "" + + print("Red - Discord Bot | Configuration process\n") + + if not token_set: + print("Please enter a valid token:") + while not token: + token = input("> ") + if not len(token) >= 50: + print("That doesn't look like a valid token.") + token = "" + if token: + loop.run_until_complete(red.db.set_global("token", token)) + + if not prefix_set: + prefix = "" + print("\nPick a prefix. A prefix is what you type before a " + "command. Example:\n" + "!help\n^ The exclamation mark is the prefix in this case.\n" + "Can be multiple characters. You will be able to change it " + "later and add more of them.\nChoose your prefix:\n") + while not prefix: + prefix = input("Prefix> ") + if len(prefix) > 10: + print("Your prefix seems overly long. Are you sure it " + "is correct? (y/n)") + if not confirm("> "): + prefix = "" + if prefix: + loop.run_until_complete(red.db.set_global("prefix", [prefix])) + + return token diff --git a/core/interactive_config.py b/core/interactive_config.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/settings.py b/core/settings.py index 02ea56d3c..c3e95fc41 100644 --- a/core/settings.py +++ b/core/settings.py @@ -9,10 +9,6 @@ class CoreDB(JsonGuildDB): of settings, both global and guild specific """ - def can_login(self): - """Used on start to determine if Red is setup enough to login""" - raise NotImplementedError - def get_admin_role(self, guild): """Returns the guild's admin role diff --git a/main.py b/main.py index 6f6bb5972..7ad1c16b9 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ from core.bot import Red, ExitCodes from core.global_checks import init_global_checks from core.events import init_events from core.settings import parse_cli_flags +from core.cli import interactive_config, confirm import asyncio import discord import logging.handlers @@ -49,6 +50,7 @@ def init_loggers(cli_flags): return logger + if __name__ == '__main__': cli_flags = parse_cli_flags() log = init_loggers(cli_flags) @@ -61,20 +63,35 @@ if __name__ == '__main__': pass # load dev cog here? token = os.environ.get("RED_TOKEN", red.db.get_global("token", None)) + prefix = cli_flags.prefix or red.db.get_global("prefix", []) - if token is None: - log.critical("No token to login with") - sys.exit(1) + if token is None or not prefix: + if cli_flags.no_prompt is False: + new_token = interactive_config(red, token_set=bool(token), + prefix_set=bool(prefix)) + if new_token: + token = new_token + else: + log.critical("Token and prefix must be set in order to login.") + sys.exit(1) loop = asyncio.get_event_loop() + cleanup_tasks = True try: loop.run_until_complete(red.start(token, bot=not cli_flags.not_bot)) except discord.LoginFailure: + cleanup_tasks = False # No login happened, no need for this log.critical("This token doesn't seem to be valid. If it belongs to " "a user account, remember that the --not-bot flag " "must be used. For self-bot functionalities instead, " "--self-bot") + db_token = red.db.get_global("token") + if db_token and not cli_flags.no_prompt: + print("\nDo you want to reset the token? (y/n)") + if confirm("> "): + loop.run_until_complete(red.db.remove_global("token")) + print("Token has been reset.") except KeyboardInterrupt: log.info("Keyboard interrupt detected. Quitting...") loop.run_until_complete(red.logout()) @@ -83,10 +100,11 @@ if __name__ == '__main__': log.critical("Fatal exception", exc_info=e) loop.run_until_complete(red.logout()) finally: - pending = asyncio.Task.all_tasks(loop=red.loop) - gathered = asyncio.gather(*pending, loop=red.loop) - gathered.cancel() - red.loop.run_until_complete(gathered) - gathered.exception() - sys.exit(red._shutdown_mode.value) + if cleanup_tasks: + pending = asyncio.Task.all_tasks(loop=red.loop) + gathered = asyncio.gather(*pending, loop=red.loop) + gathered.cancel() + red.loop.run_until_complete(gathered) + gathered.exception() + sys.exit(red._shutdown_mode.value)