From 2ae1eb9ec92be3c45743f29ad8cb7f2b5326640d Mon Sep 17 00:00:00 2001 From: Jakub Kuczys Date: Wed, 27 Mar 2024 05:57:47 +0100 Subject: [PATCH] Ask for confirmation when path passed to addpath seems incorrect (#6330) --- docs/guide_cog_creation.rst | 2 +- redbot/core/_cog_manager.py | 80 ++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/docs/guide_cog_creation.rst b/docs/guide_cog_creation.rst index 0bde5a68a..bb033d574 100644 --- a/docs/guide_cog_creation.rst +++ b/docs/guide_cog_creation.rst @@ -147,7 +147,7 @@ have successfully created a cog! ------ __init__.py ------ coolcog.py - You would then use :code:`[p]addpath D:\red-cogs` to add the path + You would then use :code:`[p]addpath D:\\red-cogs` to add the path and then you can use :code:`[p]load mycog` or :code:`[p]load coolcog` to load them diff --git a/redbot/core/_cog_manager.py b/redbot/core/_cog_manager.py index ad9287c72..9f195aa65 100644 --- a/redbot/core/_cog_manager.py +++ b/redbot/core/_cog_manager.py @@ -1,6 +1,8 @@ import contextlib import keyword import pkgutil +import sys +import textwrap from importlib import import_module, invalidate_caches from importlib.machinery import ModuleSpec from pathlib import Path @@ -9,12 +11,13 @@ from typing import Union, List, Optional import redbot.cogs from redbot.core.commands import positive_int from redbot.core.utils import deduplicate_iterables +from redbot.core.utils.views import ConfirmView import discord from . import commands from .config import Config from .i18n import Translator, cog_i18n -from .data_manager import cog_data_path +from .data_manager import cog_data_path, data_path from .utils.chat_formatting import box, pagify, humanize_list, inline @@ -352,6 +355,81 @@ class CogManagerUI(commands.Cog): await ctx.send(_("That path does not exist or does not point to a valid directory.")) return + path = path.resolve() + + # Path.is_relative_to() is 3.9+ + bot_data_path = data_path() + if path == bot_data_path or bot_data_path in path.parents: + await ctx.send( + _("A cog path cannot be part of bot's data path ({bot_data_path}).").format( + bot_data_path=inline(str(bot_data_path)) + ) + ) + return + + # Path.is_relative_to() is 3.9+ + core_path = ctx.bot._cog_mgr.CORE_PATH + if path == core_path or core_path in path.parents: + await ctx.send( + _("A cog path cannot be part of bot's core path ({core_path}).").format( + core_path=inline(str(core_path)) + ) + ) + return + + if (path / "__init__.py").is_file(): + view = ConfirmView(ctx.author) + # Technically, we only know the path is a package, + # not that it's a cog package specifically. + # However, this is more likely to cause the user to rethink their choice. + if sys.platform == "win32": + example_cog_path = "D:\\red-cogs" + example_dir_structure = textwrap.dedent( + """\ + - D:\\ + -- red-env + -- red-data + -- red-cogs + ---- mycog + ------ __init__.py + ------ mycog.py + ---- coolcog + ------ __init__.py + ------ coolcog.py""" + ) + else: + example_cog_path = "/home/user/red-cogs" + example_dir_structure = textwrap.dedent( + """\ + - /home/user/ + -- red-env + -- red-data + -- red-cogs + ---- mycog + ------ __init__.py + ------ mycog.py + ---- coolcog + ------ __init__.py + ------ coolcog.py""" + ) + content = ( + _( + "The provided path appears to be a cog package," + " are you sure that this is the path that you want to add as a **cog path**?\n" + "\nFor example, in the following case," + " you should be adding the {path} as a **cog path**:\n" + ).format(path=inline(example_cog_path)) + + box(example_dir_structure) + + _("\nPlease consult the Cog Manager UI documentation, if you're unsure: ") + + "https://docs.discord.red/en/stable/cog_guides/cog_manager_ui.html" + ) + view.message = await ctx.send(content, view=view) + await view.wait() + if not view.result: + await ctx.send(_("Okay, the path will not be added.")) + return + await view.message.delete() + try: await ctx.bot._cog_mgr.add_path(path) except ValueError as e: