Add a way to lookup all bot commands in the bot assembly without using the commandService provided by discord.net

This commit is contained in:
Daan Boerlage 2021-11-09 00:51:37 +01:00
parent ae1b28ff77
commit 4f4e16d674
Signed by: daan
GPG key ID: FCE070E1E4956606
3 changed files with 106 additions and 0 deletions

View file

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Geekbot.Core.BotCommandLookup;
public struct CommandInfo
{
public string Name { get; set; }
public Dictionary<string, ParameterInfo> Parameters { get; set; }
public List<string> Aliases { get; set; }
public string Summary { get; set; }
}

View file

@ -0,0 +1,87 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Discord.Commands;
namespace Geekbot.Core.BotCommandLookup;
public class CommandLookup
{
private readonly Assembly _assembly;
public CommandLookup(Assembly assembly)
{
_assembly = assembly;
}
public List<CommandInfo> GetCommands()
{
var commands = SearchCommands(_assembly);
var result = new List<CommandInfo>();
commands.ForEach(x => GetCommandDefinition(ref result, x));
return result;
}
private List<TypeInfo> SearchCommands(Assembly assembly)
{
bool IsLoadableModule(TypeInfo info) => info.DeclaredMethods.Any(x => x.GetCustomAttribute<CommandAttribute>() != null || x.GetCustomAttribute<GroupAttribute>() != null);
return assembly
.DefinedTypes
.Where(typeInfo => typeInfo.IsPublic || typeInfo.IsNestedPublic)
.Where(IsLoadableModule)
.ToList();
}
private void GetCommandDefinition(ref List<CommandInfo> commandInfos, TypeInfo commandType)
{
var methods = commandType
.GetMethods()
.Where(x => x.GetCustomAttribute<CommandAttribute>() != null)
.ToList();
var commandGroup = (commandType.GetCustomAttributes().FirstOrDefault(attr => attr is GroupAttribute) as GroupAttribute)?.Prefix;
foreach (var command in methods)
{
var commandInfo = new CommandInfo()
{
Parameters = new Dictionary<string, ParameterInfo>(),
};
foreach (var attr in command.GetCustomAttributes())
{
switch (attr)
{
case SummaryAttribute name:
commandInfo.Summary = name.Text;
break;
case CommandAttribute name:
commandInfo.Name = string.IsNullOrEmpty(commandGroup) ? name.Text : $"{commandGroup} {name.Text}";
break;
case AliasAttribute name:
commandInfo.Aliases = name.Aliases.ToList() ?? new List<string>();
break;
}
}
foreach (var param in command.GetParameters())
{
var paramName = param.Name ?? string.Empty;
var paramInfo = new ParameterInfo()
{
Summary = param.GetCustomAttribute<SummaryAttribute>()?.Text ?? string.Empty,
Type = param.ParameterType.Name,
DefaultValue = param.DefaultValue?.ToString() ?? string.Empty
};
commandInfo.Parameters.Add(paramName, paramInfo);
}
if (!string.IsNullOrEmpty(commandInfo.Name))
{
commandInfos.Add(commandInfo);
}
}
}
}

View file

@ -0,0 +1,8 @@
namespace Geekbot.Core.BotCommandLookup;
public struct ParameterInfo
{
public string Summary { get; set; }
public string Type { get; set; }
public string DefaultValue { get; set; }
}