diff --git a/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandInteractionHandler.cs b/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandInteractionHandler.cs index 8548c8606..2edd0d5b2 100644 --- a/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandInteractionHandler.cs +++ b/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandInteractionHandler.cs @@ -19,7 +19,7 @@ internal unsafe partial class ApplicationCommandInteractionHandler, Interaction, GatewayClient?, ValueTask> _handleAsync; private readonly Func _createContext; - private readonly Func _handleResultAsync; + private readonly IApplicationCommandResultHandler _resultHandler; private readonly GatewayClient? _client; public ApplicationCommandInteractionHandler(IServiceProvider services, @@ -44,7 +44,7 @@ public ApplicationCommandInteractionHandler(IServiceProvider services, _handleAsync = &HandleInteractionAsync; _createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate(); - _handleResultAsync = optionsValue.HandleResultAsync; + _resultHandler = optionsValue.ResultHandler; _client = client; } @@ -89,7 +89,7 @@ private async ValueTask HandleInteractionAsyncCore(TInteraction interaction, Gat try { - await _handleResultAsync(result, interaction, context, client, _logger, services).ConfigureAwait(false); + await _resultHandler.HandleResultAsync(result, context, client, _logger, services).ConfigureAwait(false); } catch (Exception exceptionHandlerException) { diff --git a/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandResultHandler.cs b/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandResultHandler.cs new file mode 100644 index 000000000..32c6cba1b --- /dev/null +++ b/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandResultHandler.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.Logging; + +using NetCord.Gateway; +using NetCord.Rest; +using NetCord.Services; +using NetCord.Services.ApplicationCommands; + +namespace NetCord.Hosting.Services.ApplicationCommands; + +public class ApplicationCommandResultHandler(MessageFlags? messageFlags = null) : IApplicationCommandResultHandler where TContext : IApplicationCommandContext +{ + public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services) + { + if (result is not IFailResult failResult) + return default; + + var resultMessage = failResult.Message; + + if (failResult is IExceptionResult exceptionResult) + logger.LogError(exceptionResult.Exception, "Execution of an application command of name '{Name}' failed with an exception", context.Interaction.Data.Name); + else + logger.LogDebug("Execution of an application command of name '{Name}' failed with '{Message}'", context.Interaction.Data.Name, resultMessage); + + var message = new InteractionMessageProperties() + { + Content = resultMessage, + Flags = messageFlags + }; + + return new(context.Interaction.SendResponseAsync(InteractionCallback.Message(message))); + } +} diff --git a/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandServiceOptions.cs b/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandServiceOptions.cs index 74ce6cc20..50307155b 100644 --- a/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandServiceOptions.cs +++ b/Hosting/NetCord.Hosting.Services/ApplicationCommands/ApplicationCommandServiceOptions.cs @@ -1,7 +1,6 @@ using Microsoft.Extensions.Logging; using NetCord.Gateway; -using NetCord.Rest; using NetCord.Services; using NetCord.Services.ApplicationCommands; @@ -15,20 +14,7 @@ public class ApplicationCommandServiceOptions where TInt public Func? CreateContext { get; set; } - public Func HandleResultAsync { get; set; } = (result, interaction, context, client, logger, services) => - { - if (result is not IFailResult failResult) - return default; - - var message = failResult.Message; - - if (failResult is IExceptionResult exceptionResult) - logger.LogError(exceptionResult.Exception, "Execution of an application command of name '{Name}' failed with an exception", interaction.Data.Name); - else - logger.LogDebug("Execution of an application command of name '{Name}' failed with '{Message}'", interaction.Data.Name, message); - - return new(interaction.SendResponseAsync(InteractionCallback.Message(message))); - }; + public IApplicationCommandResultHandler ResultHandler { get; set; } = new ApplicationCommandResultHandler(); } public class ApplicationCommandServiceOptions : ApplicationCommandServiceOptions where TInteraction : ApplicationCommandInteraction where TContext : IApplicationCommandContext where TAutocompleteContext : IAutocompleteInteractionContext diff --git a/Hosting/NetCord.Hosting.Services/ApplicationCommands/IApplicationCommandResultHandler.cs b/Hosting/NetCord.Hosting.Services/ApplicationCommands/IApplicationCommandResultHandler.cs new file mode 100644 index 000000000..61eaf5761 --- /dev/null +++ b/Hosting/NetCord.Hosting.Services/ApplicationCommands/IApplicationCommandResultHandler.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Logging; + +using NetCord.Gateway; +using NetCord.Services; +using NetCord.Services.ApplicationCommands; + +namespace NetCord.Hosting.Services.ApplicationCommands; + +public interface IApplicationCommandResultHandler where TContext : IApplicationCommandContext +{ + public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services); +} diff --git a/Hosting/NetCord.Hosting.Services/Commands/CommandHandler.cs b/Hosting/NetCord.Hosting.Services/Commands/CommandHandler.cs index 5ef026c5d..7481aba22 100644 --- a/Hosting/NetCord.Hosting.Services/Commands/CommandHandler.cs +++ b/Hosting/NetCord.Hosting.Services/Commands/CommandHandler.cs @@ -20,7 +20,7 @@ internal unsafe partial class CommandHandler : IGatewayEventHandler, Message, GatewayClient, ValueTask> _handleAsync; private readonly Func> _getPrefixLengthAsync; private readonly Func _createContext; - private readonly Func _handleResultAsync; + private readonly ICommandResultHandler _resultHandler; private readonly GatewayClient? _client; public CommandHandler(IServiceProvider services, @@ -46,7 +46,7 @@ public CommandHandler(IServiceProvider services, _getPrefixLengthAsync = GetGetPrefixLengthAsyncDelegate(optionsValue); _createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate(); - _handleResultAsync = optionsValue.HandleResultAsync; + _resultHandler = optionsValue.ResultHandler; _client = client; } @@ -134,7 +134,7 @@ private async ValueTask HandleMessageAsyncCore(Message message, GatewayClient cl try { - await _handleResultAsync(result, message, context, client, _logger, services).ConfigureAwait(false); + await _resultHandler.HandleResultAsync(result, message, context, client, _logger, services).ConfigureAwait(false); } catch (Exception exceptionHandlerException) { diff --git a/Hosting/NetCord.Hosting.Services/Commands/CommandResultHandler.cs b/Hosting/NetCord.Hosting.Services/Commands/CommandResultHandler.cs new file mode 100644 index 000000000..6ddbc9728 --- /dev/null +++ b/Hosting/NetCord.Hosting.Services/Commands/CommandResultHandler.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Logging; + +using NetCord.Gateway; +using NetCord.Services; +using NetCord.Services.Commands; + +namespace NetCord.Hosting.Services.Commands; + +public class CommandResultHandler(MessageFlags? messageFlags = null) : ICommandResultHandler where TContext : ICommandContext +{ + public ValueTask HandleResultAsync(IExecutionResult result, Message message, TContext context, GatewayClient client, ILogger logger, IServiceProvider services) + { + if (result is not IFailResult failResult) + return default; + + string resultMessage = failResult.Message; + + if (failResult is IExceptionResult exceptionResult) + logger.LogError(exceptionResult.Exception, "Execution of a command with content '{Content}' failed with an exception", message.Content); + else + logger.LogDebug("Execution of a command with content '{Content}' failed with '{Message}'", message.Content, resultMessage); + + return new(message.ReplyAsync(new() + { + Content = resultMessage, + FailIfNotExists = false, + Flags = messageFlags, + })); + } +} diff --git a/Hosting/NetCord.Hosting.Services/Commands/CommandServiceOptions.cs b/Hosting/NetCord.Hosting.Services/Commands/CommandServiceOptions.cs index 32bcdc839..de132b816 100644 --- a/Hosting/NetCord.Hosting.Services/Commands/CommandServiceOptions.cs +++ b/Hosting/NetCord.Hosting.Services/Commands/CommandServiceOptions.cs @@ -1,7 +1,4 @@ -using Microsoft.Extensions.Logging; - -using NetCord.Gateway; -using NetCord.Services; +using NetCord.Gateway; using NetCord.Services.Commands; namespace NetCord.Hosting.Services.Commands; @@ -20,22 +17,5 @@ public class CommandServiceOptions where TContext : ICommandContext public Func? CreateContext { get; set; } - public Func HandleResultAsync { get; set; } = (result, message, context, client, logger, services) => - { - if (result is not IFailResult failResult) - return default; - - string resultMessage = failResult.Message; - - if (failResult is IExceptionResult exceptionResult) - logger.LogError(exceptionResult.Exception, "Execution of a command with content '{Content}' failed with an exception", message.Content); - else - logger.LogDebug("Execution of a command with content '{Content}' failed with '{Message}'", message.Content, resultMessage); - - return new(message.ReplyAsync(new() - { - Content = resultMessage, - FailIfNotExists = false, - })); - }; + public ICommandResultHandler ResultHandler { get; set; } = new CommandResultHandler(); } diff --git a/Hosting/NetCord.Hosting.Services/Commands/ICommandResultHandler.cs b/Hosting/NetCord.Hosting.Services/Commands/ICommandResultHandler.cs new file mode 100644 index 000000000..d4151fe33 --- /dev/null +++ b/Hosting/NetCord.Hosting.Services/Commands/ICommandResultHandler.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Logging; + +using NetCord.Gateway; +using NetCord.Services; +using NetCord.Services.Commands; + +namespace NetCord.Hosting.Services.Commands; + +public interface ICommandResultHandler where TContext : ICommandContext +{ + public ValueTask HandleResultAsync(IExecutionResult result, Message message, TContext context, GatewayClient client, ILogger logger, IServiceProvider services); +} diff --git a/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionHandler.cs b/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionHandler.cs index 04b5e37ea..e5387f1e5 100644 --- a/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionHandler.cs +++ b/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionHandler.cs @@ -19,7 +19,7 @@ internal unsafe partial class ComponentInteractionHandler, Interaction, GatewayClient?, ValueTask> _handleAsync; private readonly Func _createContext; - private readonly Func _handleResultAsync; + private readonly IComponentInteractionResultHandler _resultHandler; private readonly GatewayClient? _client; public ComponentInteractionHandler(IServiceProvider services, @@ -44,7 +44,7 @@ public ComponentInteractionHandler(IServiceProvider services, _handleAsync = &HandleInteractionAsync; _createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate(); - _handleResultAsync = optionsValue.HandleResultAsync; + _resultHandler = optionsValue.ResultHandler; _client = client; } @@ -89,7 +89,7 @@ private async ValueTask HandleInteractionAsyncCore(TInteraction interaction, Gat try { - await _handleResultAsync(result, interaction, context, client, _logger, services).ConfigureAwait(false); + await _resultHandler.HandleResultAsync(result, context, client, _logger, services).ConfigureAwait(false); } catch (Exception exceptionHandlerException) { diff --git a/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionResultHandler.cs b/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionResultHandler.cs new file mode 100644 index 000000000..c1d2ad730 --- /dev/null +++ b/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionResultHandler.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.Logging; + +using NetCord.Gateway; +using NetCord.Rest; +using NetCord.Services; +using NetCord.Services.ComponentInteractions; + +namespace NetCord.Hosting.Services.ComponentInteractions; + +public class ComponentInteractionResultHandler(MessageFlags? messageFlags = null) : IComponentInteractionResultHandler where TContext : IComponentInteractionContext +{ + public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services) + { + if (result is not IFailResult failResult) + return default; + + var resultMessage = failResult.Message; + + if (failResult is IExceptionResult exceptionResult) + logger.LogError(exceptionResult.Exception, "Execution of an interaction of custom ID '{Id}' failed with an exception", context.Interaction.Id); + else + logger.LogDebug("Execution of an interaction of custom ID '{Id}' failed with '{Message}'", context.Interaction.Id, resultMessage); + + var message = new InteractionMessageProperties() + { + Content = resultMessage, + Flags = messageFlags, + }; + + return new(context.Interaction.SendResponseAsync(InteractionCallback.Message(message))); + } +} diff --git a/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionServiceOptions.cs b/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionServiceOptions.cs index 84798d62b..21d5d51fb 100644 --- a/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionServiceOptions.cs +++ b/Hosting/NetCord.Hosting.Services/ComponentInteractions/ComponentInteractionServiceOptions.cs @@ -1,8 +1,4 @@ -using Microsoft.Extensions.Logging; - -using NetCord.Gateway; -using NetCord.Rest; -using NetCord.Services; +using NetCord.Gateway; using NetCord.Services.ComponentInteractions; namespace NetCord.Hosting.Services.ComponentInteractions; @@ -15,18 +11,5 @@ public class ComponentInteractionServiceOptions where TI public Func? CreateContext { get; set; } - public Func HandleResultAsync { get; set; } = (result, interaction, context, client, logger, services) => - { - if (result is not IFailResult failResult) - return default; - - var message = failResult.Message; - - if (failResult is IExceptionResult exceptionResult) - logger.LogError(exceptionResult.Exception, "Execution of an interaction of custom ID '{Id}' failed with an exception", interaction.Id); - else - logger.LogDebug("Execution of an interaction of custom ID '{Id}' failed with '{Message}'", interaction.Id, message); - - return new(interaction.SendResponseAsync(InteractionCallback.Message(message))); - }; + public IComponentInteractionResultHandler ResultHandler { get; set; } = new ComponentInteractionResultHandler(); } diff --git a/Hosting/NetCord.Hosting.Services/ComponentInteractions/IComponentInteractionResultHandler.cs b/Hosting/NetCord.Hosting.Services/ComponentInteractions/IComponentInteractionResultHandler.cs new file mode 100644 index 000000000..ea5b6a073 --- /dev/null +++ b/Hosting/NetCord.Hosting.Services/ComponentInteractions/IComponentInteractionResultHandler.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Logging; + +using NetCord.Gateway; +using NetCord.Services; +using NetCord.Services.ComponentInteractions; + +namespace NetCord.Hosting.Services.ComponentInteractions; + +public interface IComponentInteractionResultHandler where TContext : IComponentInteractionContext +{ + public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services); +} diff --git a/Tests/NetCord.Test.Hosting/CustomSlashCommandResultHandler.cs b/Tests/NetCord.Test.Hosting/CustomSlashCommandResultHandler.cs new file mode 100644 index 000000000..51b0dfce8 --- /dev/null +++ b/Tests/NetCord.Test.Hosting/CustomSlashCommandResultHandler.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.Logging; + +using NetCord.Gateway; +using NetCord.Hosting.Services.ApplicationCommands; +using NetCord.Services; +using NetCord.Services.ApplicationCommands; + +namespace NetCord.Test.Hosting; + +internal class CustomSlashCommandResultHandler : IApplicationCommandResultHandler +{ + private static readonly ApplicationCommandResultHandler _defaultHandler = new(MessageFlags.Ephemeral); + + public ValueTask HandleResultAsync(IExecutionResult result, SlashCommandContext context, GatewayClient? client, ILogger logger, IServiceProvider services) + { + logger.LogInformation("Handling result of slash command"); + + return _defaultHandler.HandleResultAsync(result, context, client, logger, services); + } +} diff --git a/Tests/NetCord.Test.Hosting/Program.cs b/Tests/NetCord.Test.Hosting/Program.cs index 1536c37b1..f5e546def 100644 --- a/Tests/NetCord.Test.Hosting/Program.cs +++ b/Tests/NetCord.Test.Hosting/Program.cs @@ -39,7 +39,10 @@ { Intents = GatewayIntents.All, }) - .AddApplicationCommands() + .AddApplicationCommands(options => + { + options.ResultHandler = new CustomSlashCommandResultHandler(); + }) .AddApplicationCommands() .AddApplicationCommands() .AddComponentInteractions()