diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index 367852b08..745df6b77 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -22,7 +22,7 @@ from redbot.core import i18n from redbot.core import rpc from redbot.core.context import RedContext from .utils import TYPE_CHECKING -from .utils.chat_formatting import pagify, box +from .utils.chat_formatting import pagify, box, inline if TYPE_CHECKING: from redbot.core.bot import Red @@ -312,71 +312,155 @@ class Core: @commands.command() @checks.is_owner() async def load(self, ctx, *, cog_name: str): - """Loads a package""" - try: - spec = await ctx.bot.cog_mgr.find_cog(cog_name) - except RuntimeError: - await ctx.send(_("No module by that name was found in any" - " cog path.")) + """Loads packages""" + + failed_packages = [] + loaded_packages = [] + notfound_packages = [] + + cognames = [c.strip() for c in cog_name.split(' ')] + cogspecs = [] + + for c in cognames: + try: + spec = await ctx.bot.cog_mgr.find_cog(c) + cogspecs.append((spec, c)) + except RuntimeError: + notfound_packages.append(inline(c)) + #await ctx.send(_("No module named '{}' was found in any" + # " cog path.").format(c)) + + if len(cogspecs) == 0: return - try: - await ctx.bot.load_extension(spec) - except Exception as e: - log.exception("Package loading failed", exc_info=e) + for spec, name in cogspecs: + try: + await ctx.bot.load_extension(spec) + except Exception as e: + log.exception("Package loading failed", exc_info=e) - exception_log = ("Exception in command '{}'\n" - "".format(ctx.command.qualified_name)) - exception_log += "".join(traceback.format_exception(type(e), - e, e.__traceback__)) - self.bot._last_exception = exception_log + exception_log = ("Exception in command '{}'\n" + "".format(ctx.command.qualified_name)) + exception_log += "".join(traceback.format_exception(type(e), + e, e.__traceback__)) + self.bot._last_exception = exception_log + failed_packages.append(inline(name)) + else: + await ctx.bot.add_loaded_package(name) + loaded_packages.append(inline(name)) - await ctx.send(_("Failed to load package. Check your console or " - "logs for details.")) - else: - await ctx.bot.add_loaded_package(cog_name) - await ctx.send(_("Done.")) + if loaded_packages: + fmt = "Loaded {packs}" + formed = self.get_package_strings(loaded_packages, fmt) + await ctx.send(_(formed)) + + if failed_packages: + fmt = ("Failed to load package{plural} {packs}. Check your console or " + "logs for details.") + formed = self.get_package_strings(failed_packages, fmt) + await ctx.send(_(formed)) + + if notfound_packages: + fmt = 'The package{plural} {packs} {other} not found in any cog path.' + formed = self.get_package_strings(notfound_packages, fmt, ('was', 'were')) + await ctx.send(_(formed)) @commands.group() @checks.is_owner() async def unload(self, ctx, *, cog_name: str): - """Unloads a package""" - if cog_name in ctx.bot.extensions: - ctx.bot.unload_extension(cog_name) - await ctx.bot.remove_loaded_package(cog_name) - await ctx.send(_("Done.")) - else: - await ctx.send(_("That extension is not loaded.")) + """Unloads packages""" + cognames = [c.strip() for c in cog_name.split(' ')] + failed_packages = [] + unloaded_packages = [] + + for c in cognames: + if c in ctx.bot.extensions: + ctx.bot.unload_extension(c) + await ctx.bot.remove_loaded_package(c) + unloaded_packages.append(inline(c)) + else: + failed_packages.append(inline(c)) + + if unloaded_packages: + fmt = "Package{plural} {packs} {other} unloaded." + formed = self.get_package_strings(unloaded_packages, fmt, ('was', 'were')) + await ctx.send(_(formed)) + + if failed_packages: + fmt = "The package{plural} {packs} {other} not loaded." + formed = self.get_package_strings(failed_packages, fmt, ('is', 'are')) + await ctx.send(_(formed)) @commands.command(name="reload") @checks.is_owner() async def _reload(self, ctx, *, cog_name: str): - """Reloads a package""" - ctx.bot.unload_extension(cog_name) + """Reloads packages""" - try: - spec = await ctx.bot.cog_mgr.find_cog(cog_name) - except RuntimeError: - await ctx.send(_("No module by that name was found in any" - " cog path.")) - return + cognames = [c.strip() for c in cog_name.split(' ')] + + for c in cognames: + ctx.bot.unload_extension(c) - try: - self.cleanup_and_refresh_modules(spec.name) - await ctx.bot.load_extension(spec) - except Exception as e: - log.exception("Package reloading failed", exc_info=e) + cogspecs = [] + failed_packages = [] + loaded_packages = [] + notfound_packages = [] - exception_log = ("Exception in command '{}'\n" - "".format(ctx.command.qualified_name)) - exception_log += "".join(traceback.format_exception(type(e), - e, e.__traceback__)) - self.bot._last_exception = exception_log + for c in cognames: + try: + spec = await ctx.bot.cog_mgr.find_cog(c) + cogspecs.append((spec, c)) + except RuntimeError: + notfound_packages.append(inline(c)) - await ctx.send(_("Failed to reload package. Check your console or " - "logs for details.")) - else: - await ctx.send(_("Done.")) + for spec, name in cogspecs: + try: + self.cleanup_and_refresh_modules(spec.name) + await ctx.bot.load_extension(spec) + loaded_packages.append(inline(name)) + except Exception as e: + log.exception("Package reloading failed", exc_info=e) + + exception_log = ("Exception in command '{}'\n" + "".format(ctx.command.qualified_name)) + exception_log += "".join(traceback.format_exception(type(e), + e, e.__traceback__)) + self.bot._last_exception = exception_log + + failed_packages.append(inline(name)) + + if loaded_packages: + fmt = "Package{plural} {packs} {other} reloaded." + formed = self.get_package_strings(loaded_packages, fmt, ('was', 'were')) + await ctx.send(_(formed)) + + if failed_packages: + fmt = ("Failed to reload package{plural} {packs}. Check your " + "logs for details") + formed = self.get_package_strings(failed_packages, fmt) + await ctx.send(_(formed)) + + if notfound_packages: + fmt = 'The package{plural} {packs} {other} not found in any cog path.' + formed = self.get_package_strings(notfound_packages, fmt, ('was', 'were')) + await ctx.send(_(formed)) + + def get_package_strings(self, packages: list, fmt: str, other: tuple=None): + """ + Gets the strings needed for the load, unload and reload commands + """ + if other is None: + other = ('', '') + plural = 's' if len(packages) > 1 else '' + use_and, other = ('', other[0]) if len(packages) == 1 else (' and ', other[1]) + packages_string = ', '.join(packages[:-1]) + use_and + packages[-1] + + form = {'plural': plural, + 'packs' : packages_string, + 'other' : other + } + final_string = fmt.format(**form) + return final_string @commands.command(name="shutdown") @checks.is_owner()