127 lines
4.3 KiB
Python
127 lines
4.3 KiB
Python
import discord
|
||
from discord.ext import commands
|
||
from discord import app_commands
|
||
import config
|
||
|
||
class HelpView(discord.ui.View):
|
||
def __init__(self, mapping, ctx):
|
||
super().__init__(timeout=180)
|
||
self.ctx = ctx
|
||
self.mapping = mapping
|
||
self.add_item(HelpSelect(mapping, ctx))
|
||
|
||
class HelpSelect(discord.ui.Select):
|
||
def __init__(self, mapping, ctx):
|
||
self.mapping = mapping
|
||
self.ctx = ctx
|
||
|
||
options = [
|
||
discord.SelectOption(
|
||
label='Home',
|
||
description='Back to main menu',
|
||
emoji='🏠',
|
||
value='home'
|
||
)
|
||
]
|
||
|
||
# Dynamically add categories (Cogs)
|
||
for cog, cmds in mapping.items():
|
||
if not cmds: continue
|
||
|
||
# Use attributes safely
|
||
cog_name = getattr(cog, "name", "Other").replace("🎶 ", "")
|
||
emoji = getattr(cog, "emoji", "📄")
|
||
|
||
options.append(discord.SelectOption(
|
||
label=cog_name,
|
||
description=f"{len(cmds)} commands available",
|
||
emoji=emoji,
|
||
value=cog_name
|
||
))
|
||
|
||
super().__init__(placeholder="Select a category...", min_values=1, max_values=1, options=options)
|
||
|
||
async def callback(self, interaction: discord.Interaction):
|
||
if interaction.user != self.ctx.author:
|
||
return await interaction.response.send_message("Create your own help command with /help", ephemeral=True)
|
||
|
||
value = self.values[0]
|
||
|
||
if value == 'home':
|
||
await interaction.response.edit_message(embed=get_home_embed(self.ctx), view=self.view)
|
||
return
|
||
|
||
# Find the selected cog
|
||
selected_cog = None
|
||
selected_commands = []
|
||
|
||
for cog, cmds in self.mapping.items():
|
||
cog_name_clean = getattr(cog, "name", "Other").replace("🎶 ", "")
|
||
if cog_name_clean == value:
|
||
selected_cog = cog
|
||
selected_commands = cmds
|
||
break
|
||
|
||
embed = discord.Embed(
|
||
title=f"{getattr(selected_cog, 'emoji', '')} {value} Commands",
|
||
color=config.get_color("main") if hasattr(config, 'get_color') else discord.Color.blue()
|
||
)
|
||
|
||
for cmd in selected_commands:
|
||
# Get description
|
||
desc = cmd.short_doc or cmd.description or "No description provided."
|
||
embed.add_field(
|
||
name=f"/{cmd.name}",
|
||
value=desc,
|
||
inline=False
|
||
)
|
||
|
||
await interaction.response.edit_message(embed=embed, view=self.view)
|
||
|
||
def get_home_embed(ctx):
|
||
embed = discord.Embed(
|
||
title="🤖 Bot Help Menu",
|
||
description=f"Hello **{ctx.author.name}**! Select a category below to see available commands.",
|
||
color=discord.Color.purple()
|
||
)
|
||
if ctx.bot.user.avatar:
|
||
embed.set_thumbnail(url=ctx.bot.user.avatar.url)
|
||
embed.add_field(name="ℹ️ How to use", value="Use the dropdown menu below to navigate categories.\nMost commands work as `/command` or `=command`.", inline=False)
|
||
return embed
|
||
|
||
class GroovyHelp(commands.Cog):
|
||
def __init__(self, client):
|
||
self.client = client
|
||
self.name = "Help"
|
||
self.emoji = "🆘"
|
||
|
||
@commands.hybrid_command(name="help", description="Show the help menu")
|
||
async def help(self, ctx: commands.Context):
|
||
bot = ctx.bot
|
||
mapping = {}
|
||
|
||
for cog_name in bot.cogs:
|
||
cog = bot.get_cog(cog_name)
|
||
|
||
# --- FIXED FILTERING LOGIC ---
|
||
visible_cmds = []
|
||
for cmd in cog.get_commands():
|
||
if cmd.hidden:
|
||
continue
|
||
try:
|
||
# Check if user has permission to run this command
|
||
if await cmd.can_run(ctx):
|
||
visible_cmds.append(cmd)
|
||
except commands.CommandError:
|
||
continue
|
||
# -----------------------------
|
||
|
||
if visible_cmds:
|
||
# Sort alphabetically
|
||
visible_cmds.sort(key=lambda x: x.name)
|
||
mapping[cog] = visible_cmds
|
||
|
||
embed = get_home_embed(ctx)
|
||
view = HelpView(mapping, ctx)
|
||
await ctx.send(embed=embed, view=view)
|