Files
Syntrel/cogs/help.py
2025-11-02 23:32:52 -05:00

259 lines
9.6 KiB
Python

import discord
from discord import app_commands
from discord.ext import commands
from discord.ext.commands import Context
class Help(commands.Cog, name="help"):
def __init__(self, bot) -> None:
self.bot = bot
async def category_autocomplete(
self,
interaction: discord.Interaction,
current: str,
) -> list[app_commands.Choice[str]]:
categories = [
"general",
"fun",
"moderation",
"owner",
"sidestore",
"idevice",
"melonx",
"media",
"miscellaneous",
"utilities",
"events",
]
suggestions = []
for category in categories:
if current.lower() in category.lower():
suggestions.append(
app_commands.Choice(
name=f"{category.capitalize()} Commands", value=category
)
)
return suggestions[:25]
@commands.hybrid_command(
name="help", description="List all commands the bot has loaded."
)
@app_commands.allowed_contexts(guilds=True, dms=True, private_channels=True)
@app_commands.allowed_installs(guilds=True, users=True)
@app_commands.describe(category="Choose a specific category to view its commands")
@app_commands.autocomplete(category=category_autocomplete)
async def help(self, context: Context, category: str = None) -> None:
category_mapping = {
"general": "general",
"fun": "fun",
"idevice": "idevice",
"melonx": "melonx",
"media": "media",
"misc": "miscellaneous",
"miscellaneous": "miscellaneous",
"moderation": "moderation",
"sidestore": "sidestore",
"utils": "utilities",
"utilities": "utilities",
"events": "events",
"sync": "owner",
"logs": "owner",
"invite": "owner",
"load": "owner",
"unload": "owner",
"reload": "owner",
"shutdown": "owner",
"say": "owner",
}
category_descriptions = {
"general": "General commands",
"fun": "Fun commands",
"moderation": "Administration commands",
"owner": "Owner commands",
"sidestore": "SideStore troubleshooting commands",
"idevice": "idevice troubleshooting commands",
"melonx": "MeloNX troubleshooting commands",
"media": "Media commands",
"utilities": "Utility commands",
"miscellaneous": "Miscellaneous commands",
"events": "Events commands",
}
if category is None:
embed = discord.Embed(title="Help", color=0x7289DA)
embed.set_author(
name="Help", icon_url="https://yes.nighty.works/raw/T9mnBO.png"
)
standalone_commands = []
botinfo_cmd = self.bot.tree.get_command("botinfo")
if botinfo_cmd:
standalone_commands.append(
"**/botinfo** » Get information about this bot"
)
if standalone_commands:
embed.add_field(
name="", value="".join(standalone_commands) + "\n", inline=False
)
available_categories = set()
for cog_name in self.bot.cogs:
mapped_category = category_mapping.get(cog_name.lower())
if mapped_category:
available_categories.add(mapped_category)
category_list = []
for cat in sorted(available_categories):
description = category_descriptions.get(
cat, f"{cat.capitalize()} commands"
)
category_list.append(f"**/help {cat}** » {description}")
if category_list:
embed.add_field(name="", value="\n".join(category_list), inline=False)
if context.interaction:
await context.interaction.response.send_message(
embed=embed, ephemeral=True
)
else:
try:
await context.send(embed=embed)
except (discord.Forbidden, discord.HTTPException):
try:
await context.author.send(embed=embed)
except discord.Forbidden:
pass # User has DMs disabled
return
category = category.lower()
if category not in category_descriptions:
embed = discord.Embed(
title="Error",
description=f"Category '{category}' not found. Use `/help` to see available categories.",
color=0x7289DA,
)
if context.interaction:
await context.interaction.response.send_message(
embed=embed, ephemeral=True
)
else:
try:
await context.send(embed=embed)
except (discord.Forbidden, discord.HTTPException):
try:
await context.author.send(embed=embed)
except discord.Forbidden:
pass
return
commands_in_category = []
seen_names = set()
for cog_name in self.bot.cogs:
if category_mapping.get(cog_name.lower()) == category:
cog = self.bot.get_cog(cog_name)
if cog:
commands_list = cog.get_commands()
for command in commands_list:
has_prefix_subcommands = (
hasattr(command, "commands")
and len(getattr(command, "commands", [])) > 0
)
if has_prefix_subcommands:
continue
name = command.name
if name in seen_names:
continue
description = (
command.description.partition("\n")[0]
if command.description
else "No description available"
)
commands_in_category.append((name, description))
seen_names.add(name)
for app_command in self.bot.tree.get_commands():
bound_cog = getattr(app_command, "binding", None)
if bound_cog is None:
continue
bound_cog_name = getattr(bound_cog, "qualified_name", "").lower()
if category_mapping.get(bound_cog_name) != category:
continue
has_subcommands = (
hasattr(app_command, "commands")
and len(getattr(app_command, "commands", [])) > 0
)
if has_subcommands and category not in ["owner"]:
for subcommand in app_command.commands:
if subcommand.name in seen_names:
continue
sub_desc = (
subcommand.description.partition("\n")[0]
if getattr(subcommand, "description", None)
else "No description available"
)
commands_in_category.append(
(f"{app_command.name} {subcommand.name}", sub_desc)
)
seen_names.add(f"{app_command.name} {subcommand.name}")
else:
if app_command.name in seen_names:
continue
description = (
app_command.description.partition("\n")[0]
if getattr(app_command, "description", None)
else "No description available"
)
commands_in_category.append((app_command.name, description))
seen_names.add(app_command.name)
if not commands_in_category:
embed = discord.Embed(
title="Error",
description=f"No commands found in category '{category}'.",
color=0x7289DA,
)
if context.interaction:
await context.interaction.response.send_message(
embed=embed, ephemeral=True
)
else:
try:
await context.send(embed=embed)
except (discord.Forbidden, discord.HTTPException):
try:
await context.author.send(embed=embed)
except discord.Forbidden:
pass
return
embed = discord.Embed(title=f"/help » {category.lower()}", color=0x7289DA)
embed.set_author(
name="Help", icon_url="https://yes.nighty.works/raw/T9mnBO.png"
)
data = []
for command_name, description in sorted(commands_in_category):
data.append(f"**/{command_name}** » {description}")
help_text = "\n".join(data)
embed.add_field(name="", value=help_text, inline=False)
if context.interaction:
await context.interaction.response.send_message(embed=embed, ephemeral=True)
else:
try:
await context.send(embed=embed)
except (discord.Forbidden, discord.HTTPException):
try:
await context.author.send(embed=embed)
except discord.Forbidden:
pass
async def setup(bot) -> None:
await bot.add_cog(Help(bot))