Files
SkyBot/SkyBot/Commands/Info/Help.cs
2026-04-18 02:25:11 +01:00

161 lines
5.6 KiB
C#

using SkyBot.Helpers;
using SkyBot.Models;
using Valour.Sdk.Models.Messages.Embeds;
namespace SkyBot.Commands
{
public class Help : ICommand
{
public string Name => "help";
public string[] Aliases => ["cmds"];
public string Description => "Shows all commands by category.";
public string Category => "Info";
public string Usage => "help";
public string[] SubCommands => [];
private const int PageSize = 10;
public async Task Execute(CommandContext ctx)
{
if (!ctx.ChannelCache.TryGetValue(ctx.Channel.Id, out var channel)) return;
var categories = CommandRegistry.Categories
.Where(c => c.Key != "template")
.Where(c => c.Key != "dev" || PermissionHelper.IsOwner(ctx.Member))
.OrderBy(c => c.Key)
.ToList();
var categoryFirstPage = new Dictionary<string, int>();
var allChunks = new List<(string CategoryName, List<ICommand> Cmds, int ChunkIndex, int TotalChunks)>();
int nextPageIndex = 1;
foreach (var (categoryName, cmds) in categories)
{
var ordered = cmds.OrderBy(c => c.Name).ToList();
var chunks = ordered
.Select((cmd, i) => (cmd, i))
.GroupBy(x => x.i / PageSize)
.Select(g => g.Select(x => x.cmd).ToList())
.ToList();
categoryFirstPage[categoryName] = nextPageIndex;
for (int c = 0; c < chunks.Count; c++)
allChunks.Add((categoryName, chunks[c], c, chunks.Count));
nextPageIndex += chunks.Count;
}
var allCmds = allChunks
.SelectMany(chunk => chunk.Cmds)
.DistinctBy(cmd => cmd.Name)
.ToList();
var cmdDetailPage = new Dictionary<string, int>();
int detailPageIndex = nextPageIndex;
foreach (var cmd in allCmds)
cmdDetailPage[cmd.Name] = detailPageIndex++;
var builder = new EmbedBuilder();
builder.embed.HideChangePageArrows = true;
// Home page
builder.AddPage("✦ Help Menu", $"Prefix: {Config.Prefix}");
builder.AddRow()
.AddText("Select a Category")
.WithStyles(EmbedStyles.LabelText)
.CloseRow();
builder.AddRow();
foreach (var (categoryName, cmds) in categories)
{
builder.AddButton($"{categoryName.ToTitleCase()} ({cmds.Count})")
.WithStyles(EmbedStyles.CategoryBtn)
.OnClickGoToEmbedPage(categoryFirstPage[categoryName]);
}
builder.CloseRow();
// Category pages
int embedPage = 1;
foreach (var (categoryName, cmds, chunkIndex, totalChunks) in allChunks)
{
string? footer = totalChunks > 1
? $"Page {chunkIndex + 1}/{totalChunks} | Prefix: {Config.Prefix}"
: $"Prefix: {Config.Prefix}";
builder.AddPage($"✦ {categoryName.ToTitleCase()} Commands", footer);
foreach (var cmd in cmds)
{
builder.AddRow()
.AddButton(cmd.Name)
.WithStyles(EmbedStyles.CommandBtn)
.OnClickGoToEmbedPage(cmdDetailPage[cmd.Name])
.CloseRow();
}
builder.AddRow()
.AddButton("← Back")
.WithStyles(EmbedStyles.BackBtn)
.OnClickGoToEmbedPage(0);
if (chunkIndex > 0)
{
builder.AddButton("← Prev")
.WithStyles(EmbedStyles.NavBtn)
.OnClickGoToEmbedPage(embedPage - 1);
}
if (chunkIndex < totalChunks - 1)
{
builder.AddButton("Next →")
.WithStyles(EmbedStyles.NavBtn)
.OnClickGoToEmbedPage(embedPage + 1);
}
builder.CloseRow();
embedPage++;
}
// Command detail pages
foreach (var cmd in allCmds)
{
builder.AddPage($"✦ {cmd.Name.ToTitleCase()}", $"Prefix: {Config.Prefix}");
builder.AddRow()
.AddText("Description", cmd.Description)
.CloseRow();
if (cmd.Aliases.Length > 0)
{
builder.AddRow()
.AddText("Aliases", string.Join(", ", cmd.Aliases))
.CloseRow();
}
if (!string.IsNullOrWhiteSpace(cmd.Usage))
{
builder.AddRow()
.AddText("Usage", $"{Config.Prefix}{cmd.Usage}")
.CloseRow();
}
if (cmd.SubCommands.Length > 0)
{
builder.AddRow()
.AddText("Sub-commands", string.Join(", ", cmd.SubCommands.Select(s => s.ToTitleCase())))
.CloseRow();
}
builder.AddRow()
.AddButton("← Back")
.WithStyles(EmbedStyles.BackBtn)
.OnClickGoToEmbedPage(categoryFirstPage[cmd.Category.ToLower()])
.CloseRow();
}
await MessageHelper.ReplyAsync(ctx, null, builder.embed);
}
}
}