Skip to content

Commit

Permalink
Allow for parameters for user and message commands
Browse files Browse the repository at this point in the history
  • Loading branch information
KubaZ2 committed Nov 18, 2024
1 parent f24344e commit 30188b6
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 17 deletions.
15 changes: 9 additions & 6 deletions NetCord.Services/ApplicationCommands/MessageCommandInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ internal MessageCommandInfo(MethodInfo method,
MessageCommandAttribute attribute,
ApplicationCommandServiceConfiguration<TContext> configuration) : base(attribute, configuration)
{
MethodHelper.EnsureNoParameters(method);

_invokeAsync = InvocationHelper.CreateModuleDelegate(method, declaringType, [], configuration.ResultResolverProvider);
var messageParameter = _messageParameter = MethodHelper.EnsureSingleParameterOfTypeOrNone(method, typeof(RestMessage));
_invokeAsync = InvocationHelper.CreateModuleDelegate(method, declaringType, messageParameter ? [typeof(RestMessage)] : [], configuration.ResultResolverProvider);
Preconditions = PreconditionsHelper.GetPreconditions<TContext>(declaringType, method);
}

Expand All @@ -41,12 +40,14 @@ internal MessageCommandInfo(string name,
var method = handler.Method;

var split = ParametersHelper.SplitHandlerParameters<TContext>(method);
MethodHelper.EnsureNoParameters(split.Parameters, method);

_invokeAsync = InvocationHelper.CreateHandlerDelegate(handler, split.Services, split.HasContext, [], configuration.ResultResolverProvider);
var messageParameter = _messageParameter = MethodHelper.EnsureSingleParameterOfTypeOrNone(split.Parameters, method, typeof(RestMessage));
_invokeAsync = InvocationHelper.CreateHandlerDelegate(handler, split.Services, split.HasContext, messageParameter ? [typeof(RestMessage)] : [], configuration.ResultResolverProvider);
Preconditions = PreconditionsHelper.GetPreconditions<TContext>(method);
}

private readonly bool _messageParameter;

public IReadOnlyList<PreconditionAttribute<TContext>> Preconditions { get; }

private readonly Func<object?[]?, TContext, IServiceProvider?, ValueTask> _invokeAsync;
Expand All @@ -59,9 +60,11 @@ public override async ValueTask<IExecutionResult> InvokeAsync(TContext context,
if (preconditionResult is IFailResult)
return preconditionResult;

object?[]? parameters = _messageParameter ? [((MessageCommandInteraction)context.Interaction).Data.TargetMessage] : null;

try
{
await _invokeAsync(null, context, serviceProvider).ConfigureAwait(false);
await _invokeAsync(parameters, context, serviceProvider).ConfigureAwait(false);
}
catch (Exception ex)
{
Expand Down
15 changes: 9 additions & 6 deletions NetCord.Services/ApplicationCommands/UserCommandInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ internal UserCommandInfo(MethodInfo method,
UserCommandAttribute attribute,
ApplicationCommandServiceConfiguration<TContext> configuration) : base(attribute, configuration)
{
MethodHelper.EnsureNoParameters(method);

_invokeAsync = InvocationHelper.CreateModuleDelegate(method, declaringType, [], configuration.ResultResolverProvider);
var userParameter = _userParameter = MethodHelper.EnsureSingleParameterOfTypeOrNone(method, typeof(User));
_invokeAsync = InvocationHelper.CreateModuleDelegate(method, declaringType, userParameter ? [typeof(User)] : [], configuration.ResultResolverProvider);
Preconditions = PreconditionsHelper.GetPreconditions<TContext>(declaringType, method);
}

Expand All @@ -41,12 +40,14 @@ internal UserCommandInfo(string name,
var method = handler.Method;

var split = ParametersHelper.SplitHandlerParameters<TContext>(method);
MethodHelper.EnsureNoParameters(split.Parameters, method);

_invokeAsync = InvocationHelper.CreateHandlerDelegate(handler, split.Services, split.HasContext, [], configuration.ResultResolverProvider);
var userParameter = _userParameter = MethodHelper.EnsureSingleParameterOfTypeOrNone(split.Parameters, method, typeof(User));
_invokeAsync = InvocationHelper.CreateHandlerDelegate(handler, split.Services, split.HasContext, userParameter ? [typeof(User)] : [], configuration.ResultResolverProvider);
Preconditions = PreconditionsHelper.GetPreconditions<TContext>(method);
}

private readonly bool _userParameter;

public IReadOnlyList<PreconditionAttribute<TContext>> Preconditions { get; }

private readonly Func<object?[]?, TContext, IServiceProvider?, ValueTask> _invokeAsync;
Expand All @@ -59,9 +60,11 @@ public override async ValueTask<IExecutionResult> InvokeAsync(TContext context,
if (preconditionResult is IFailResult)
return preconditionResult;

object?[]? parameters = _userParameter ? [((UserCommandInteraction)context.Interaction).Data.TargetUser] : null;

try
{
await _invokeAsync(null, context, serviceProvider).ConfigureAwait(false);
await _invokeAsync(parameters, context, serviceProvider).ConfigureAwait(false);
}
catch (Exception ex)
{
Expand Down
20 changes: 16 additions & 4 deletions NetCord.Services/Helpers/MethodHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@ namespace NetCord.Services.Helpers;

internal static class MethodHelper
{
public static void EnsureNoParameters(MethodInfo method) => EnsureNoParameters(method.GetParameters(), method);
public static bool EnsureSingleParameterOfTypeOrNone(MethodInfo method, Type parameterType)
{
return EnsureSingleParameterOfTypeOrNone(method.GetParameters(), method, parameterType);
}

public static void EnsureNoParameters(ReadOnlySpan<ParameterInfo> parameters, MethodInfo method)
public static bool EnsureSingleParameterOfTypeOrNone(ReadOnlySpan<ParameterInfo> parameters, MethodInfo method, Type parameterType)
{
if (parameters.Length != 0)
throw new InvalidDefinitionException("The command cannot have parameters.", method);
switch (parameters.Length)
{
case 0:
return false;
case 1:
if (parameters[0].ParameterType == parameterType)
return true;
goto default;
default:
throw new InvalidDefinitionException($"The command must have no parameters or a single parameter of type '{parameterType}'.", method);
}
}
}
15 changes: 14 additions & 1 deletion Tests/NetCord.Test.Hosting/ApplicationCommandModule.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NetCord.Services.ApplicationCommands;
using NetCord.Rest;
using NetCord.Services.ApplicationCommands;

namespace NetCord.Test.Hosting;

Expand All @@ -9,4 +10,16 @@ public static string Ping()
{
return "Pong!";
}

[UserCommand("Mention")]
public static string Mention(User user)
{
return user.ToString();
}

[MessageCommand("Length")]
public static string Length(RestMessage message)
{
return message.Content.Length.ToString();
}
}
2 changes: 2 additions & 0 deletions Tests/NetCord.Test.Hosting/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
.AddSlashCommand("exception", "Exception!", (Action<string>)((string s) => throw new("Exception!")))
.AddSlashCommand("exception-button", "Exception button!", () => new InteractionMessageProperties().AddComponents(new ActionRowProperties([new ButtonProperties("exception", "Exception!", ButtonStyle.Danger)])))
.AddUserCommand("ping", () => "Pong!")
.AddMessageCommand("Content", (RestMessage message) => message.Content)
.AddUserCommand("Name", (User user) => user.Username)
.AddMessageCommand("ping", () => "Pong!")
.AddComponentInteraction<ButtonInteractionContext>("button", () => "Button!")
.AddComponentInteraction<ButtonInteractionContext>("exception", (Action<IServiceProvider, ButtonInteractionContext>)((IServiceProvider provider, ButtonInteractionContext context) => throw new("Exception!")))
Expand Down

0 comments on commit 30188b6

Please sign in to comment.