Example #1
0
 async def config_unset(self, ctx: commands.Context, option: str):
     """This command allows for the removal of configuration options. Removing configuration options which are
     required by commands or modules will stop these from working."""
     option = option.lower()
     if option in self.bot.config:
         del self.bot.config[option]
         async with self.bot.db.acquire() as conn:
             await conn.execute("DELETE FROM config WHERE key = $1", option)
             option = tbb.clean(ctx, option, False, True)
         line = f"Configuration option `{option}` has been unset."
         await ctx.send(line if len(line) < 2000 else f"{line[:1996]}...")
     else:
         option = tbb.clean(ctx, option, False, True)
         line = f"No configuration option `{option}` exists."
         await ctx.send(line if len(line) < 2000 else f"{line[:1996]}...")
Example #2
0
 async def lasterror(self, ctx: commands.Context):
     """This command shows the last error the bot has encountered. Errors encountered while loading modules will
     not be listed by this command. To see the last error encountered while loading modules see the `module error`
     command. This command retains this information until another error replaces it, or the bot shuts down."""
     if self.bot.last_error:
         await ctx.send(tbb.clean(ctx, self.bot.last_error))
     else:
         await ctx.send("There have not been any errors since the last restart.")
Example #3
0
 async def config_set(self, ctx: commands.Context, option: str, *, value: str):
     """This command sets a configuration option. Configuration options are used by other modules or commands.
     Setting an option which already exists will overwrite the option. Setting an option which does not exist will
     create it. The keyword all cannot be used as a configuration option as it is used by the get command to get all
     options."""
     option = option.lower()
     if option == "all":
         await ctx.send("The keyword `all` cannot be used as a configuration option.")
     else:
         self.bot.config[option] = value
         async with self.bot.db.acquire() as conn:
             await conn.execute(
                 "INSERT INTO config VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = $2", option, value
             )
         option = tbb.clean(ctx, option, False, True)
         value = tbb.clean(ctx, value, False, True)
         line = f"Configuration option `{option}` has been set to `{value}`."
         await ctx.send(line if len(line) < 2000 else f"{line[:1996]}...")
Example #4
0
 async def config_get(self, ctx: commands.Context, option: str):
     """This command is used to get the value of config options. Using this, one can check what configuration
     options are set to. Using the keyword `all` instead of an option name will print all options and their
     values."""
     option = option.lower()
     if option == "all":
         if not self.bot.config:
             await ctx.send("No configuration options are set.")
             return
         paginator = commands.Paginator()
         for line in [f"{key}: {value}" for key, value in self.bot.config.items()]:
             line = tbb.clean(ctx, line, False, True)
             paginator.add_line(line if len(line) < 1992 else f"{line[:1989]}...")
         for page in paginator.pages:
             await ctx.send(page)
     elif option.lower() in self.bot.config:
         value = tbb.clean(ctx, self.bot.config[option], False, True)
         option = tbb.clean(ctx, option, False, True)
         line = f"Option: `{option}`, value: `{value}`"
         await ctx.send(line if len(line) < 1994 else f"{line[:1991]}...")
     else:
         option = tbb.clean(ctx, option, False, True)
         await ctx.send(f"No configuration option `{option if len(option) < 1960 else option[:1959]}...` is set.")
Example #5
0
    async def _module_operation(self, ctx: commands.Context, operation: str, mod: str):
        """To avoid code duplication in the except blocks all module command functionality is grouped together."""

        async def load():
            """Contains the logic for loading a module."""
            if f"{mod}.py" in listdir("modules"):
                await self.bot.load_extension(f"modules.{mod}")
                await self.bot.update_command_states()
                await ctx.send(f"Module `{mod_name}` successfully loaded.")
                self.log.info(f"{ctx.author.id}: loaded '{mod}' module.")
            else:
                await ctx.send(f"No `{mod_name}` module was found.")

        async def unload():
            """Contains the logic for unloading a module."""
            await self.bot.unload_extension(f"modules.{mod}")
            await ctx.send(f"Module `{mod_name}` successfully unloaded.")
            self.log.info(f"{ctx.author.id}: unloaded '{mod}' module.")

        async def reload():
            """Contains the logic for reloading a module."""
            if f"{mod}.py" in listdir("modules"):
                await self.bot.reload_extension(f"modules.{mod}")
                await self.bot.update_command_states()
                await ctx.send(f"Module `{mod_name}` successfully reloaded.")
                self.log.info(f"{ctx.author.id}: reloaded '{mod}' module.")
            else:
                if mod in self.bot.modules:
                    await ctx.send(f"The `{mod_name}` module file is no longer found on disk. Reload canceled.")
                else:
                    await ctx.send(f"No `{mod_name}` module was found.")

        old_help = dict(self.bot.help)  # Save old help and module info in we need to roll back.
        old_modules = dict(self.bot.modules)
        self.bot.extension_ctx = ctx  # Save context in case loaded module has use for it.
        mod_name = clean(ctx, mod, False, True)
        try:
            if operation == "load":
                await load()
            elif operation == "unload":
                await unload()
            elif operation == "reload":
                await reload()
        except commands.ExtensionAlreadyLoaded:  # If module was already loaded.
            await ctx.send(f"The `{mod_name}` module was already loaded.")
        except commands.ExtensionNotLoaded:  # If module wasn't loaded to begin with.
            await ctx.send(f"No `{mod_name}` module is loaded.")
        except commands.ExtensionFailed as e:
            self.bot.help = old_help
            self.bot.modules = old_modules
            if isinstance(e.original, tbb.DependencyError):
                missing_deps = [f"`{clean(ctx, elem, False, True)}`" for elem in e.original.missing_dependencies]
                await ctx.send(f"Module `{mod_name}` requires these missing dependencies: {', '.join(missing_deps)}")
            else:
                await ctx.send(
                    "**Error! Something went really wrong! Contact module maintainer.**\nError logged to console and "
                    "stored in module error command."
                )
            self.log.error(f"{ctx.author.id}: tried loading '{mod}' module, and it failed:\n\n{str(e)}")
            self.bot.last_module_error = (
                f"The `{clean(ctx, mod, False)}` module failed while loading. The error was:\n\n{clean(ctx, str(e))}"
            )
        except Exception as e:
            self.bot.help = old_help
            self.bot.modules = old_modules
            await ctx.send(
                "**Error! Something went really wrong! Contact module maintainer.**\nError logged to console and "
                "stored in module error command."
            )
            if isinstance(e, commands.ExtensionNotFound):  # Clarify error further in case it was an import error.
                e = e.__cause__
            self.log.error(f"{ctx.author.id}: tried loading '{mod}' module, and it failed:\n\n{str(e)}")
            self.bot.last_module_error = (
                f"The `{clean(ctx, mod, False)}` module failed while loading. The error was:\n\n{clean(ctx, str(e))}"
            )
        finally:  # Reset context as loading has concluded.
            self.bot.extension_ctx = None