From f14e2e903aea8b025d1bb8c12737b3ceedde9a1a Mon Sep 17 00:00:00 2001 From: perforat Date: Tue, 14 Apr 2026 15:59:34 +0000 Subject: [PATCH] add missing pre-installed cogs --- cogs/help/config.json | 15 ++++++ cogs/help/help.py | 107 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 cogs/help/config.json create mode 100644 cogs/help/help.py diff --git a/cogs/help/config.json b/cogs/help/config.json new file mode 100644 index 0000000..203872e --- /dev/null +++ b/cogs/help/config.json @@ -0,0 +1,15 @@ +{ + "description": "Shows this help message", + "usages": ["help"], + "hidden": false, + "messages": { + "upper_desc": "Commands:", + "footer": "If something's wrong, contact the bot owner.", + "pfx_message": "Prefix:" + }, + "settings": { + "command_pfx": "!", + "cogs_dir": "..", + "column_width": 20 + } +} \ No newline at end of file diff --git a/cogs/help/help.py b/cogs/help/help.py new file mode 100644 index 0000000..c7b9bcb --- /dev/null +++ b/cogs/help/help.py @@ -0,0 +1,107 @@ +import logging +from discord.ext import commands +import os +import json + +logger = logging.getLogger(__name__) + +CONFIG_FILE = 'config.json' +REQUIRED_MESSAGES = ['upper_desc', 'footer', 'pfx_message'] + +class HelpCog(commands.Cog): + def __init__(self, bot: commands.Bot): + self.bot = bot + self.help_config = self._load_and_validate_config() + self.cogs_dir = os.path.join( + os.path.dirname(__file__), + self.help_config["settings"]["cogs_dir"] + ) + + def _load_and_validate_config(self) -> dict: + path = os.path.join(os.path.dirname(__file__), CONFIG_FILE) + + if not os.path.exists(path): + raise FileNotFoundError(f"Help cog config not found at {path}") + + with open(path, 'r', encoding='utf-8') as f: + config = json.load(f) + + messages = config.get("messages", {}) + missing_msgs = [key for key in REQUIRED_MESSAGES if key not in messages] + if missing_msgs: + raise KeyError(f"Help config 'messages' is missing required keys: {missing_msgs}") + + settings = config.get("settings", {}) + settings.setdefault("cogs_dir", "..") + settings.setdefault("column_width", 20) + settings.setdefault("command_pfx", "!") + + config["messages"] = messages + config["settings"] = settings + + logger.info("Help cog config loaded successfully") + return config + + def _build_help_text(self, prefix: str) -> list[str]: + settings = self.help_config["settings"] + column_width = settings["column_width"] + lines = [] + + if not os.path.exists(self.cogs_dir): + logger.error(f"Cogs directory not found at: {self.cogs_dir}") + return lines + + for item in sorted(os.listdir(self.cogs_dir)): + cog_dir = os.path.join(self.cogs_dir, item) + if not os.path.isdir(cog_dir): + continue + + config_path = os.path.join(cog_dir, CONFIG_FILE) + if not os.path.exists(config_path): + continue + + try: + with open(config_path, 'r', encoding='utf-8') as f: + cog_config = json.load(f) + except (json.JSONDecodeError, OSError) as e: + logger.warning(f"Failed to load config for cog '{item}': {e}") + continue + + description = cog_config.get('description', '') + usages = cog_config.get('usages', []) + hidden = cog_config.get('hidden', False) + + if not usages or hidden: + continue + + for usage in usages: + usage_text = usage if usage.startswith(prefix) else f"{prefix}{usage}" + lines.append(f"{usage_text:<{column_width}} : {description}") + + return lines + + @commands.command(name="help") + async def help(self, ctx: commands.Context): + cfg_msgs = self.help_config["messages"] + cfg_sets = self.help_config["settings"] + + prefix = ctx.prefix or cfg_sets['command_pfx'] + lines = self._build_help_text(prefix) + + if not lines: + await ctx.send("No commands available.") + return + + help_text = ( + f"{cfg_msgs['upper_desc']}\n" + f"```\n" + f"{chr(10).join(lines)}\n" + f"```\n" + f"{cfg_msgs['pfx_message']} `{cfg_sets['command_pfx']}`\n" + f"{cfg_msgs['footer']}" + ) + + await ctx.send(help_text) + +async def setup(bot: commands.Bot): + await bot.add_cog(HelpCog(bot)) \ No newline at end of file