Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal unsafe partial class ApplicationCommandInteractionHandler<TInteraction,
private readonly IServiceScopeFactory? _scopeFactory;
private readonly delegate*<ApplicationCommandInteractionHandler<TInteraction, TContext>, Interaction, GatewayClient?, ValueTask> _handleAsync;
private readonly Func<TInteraction, GatewayClient?, IServiceProvider, TContext> _createContext;
private readonly Func<IExecutionResult, TInteraction, TContext, GatewayClient?, ILogger, IServiceProvider, ValueTask> _handleResultAsync;
private readonly IApplicationCommandResultHandler<TContext> _resultHandler;
private readonly GatewayClient? _client;

public ApplicationCommandInteractionHandler(IServiceProvider services,
Expand All @@ -44,7 +44,7 @@ public ApplicationCommandInteractionHandler(IServiceProvider services,
_handleAsync = &HandleInteractionAsync;

_createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate<TInteraction, GatewayClient?, TContext>();
_handleResultAsync = optionsValue.HandleResultAsync;
_resultHandler = optionsValue.ResultHandler;
_client = client;
}

Expand Down Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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<TContext>(MessageFlags? messageFlags = null) : IApplicationCommandResultHandler<TContext> 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)));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Microsoft.Extensions.Logging;

using NetCord.Gateway;
using NetCord.Rest;
using NetCord.Services;
using NetCord.Services.ApplicationCommands;

Expand All @@ -15,20 +14,7 @@ public class ApplicationCommandServiceOptions<TInteraction, TContext> where TInt

public Func<TInteraction, GatewayClient?, IServiceProvider, TContext>? CreateContext { get; set; }

public Func<IExecutionResult, TInteraction, TContext, GatewayClient?, ILogger, IServiceProvider, ValueTask> 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<TContext> ResultHandler { get; set; } = new ApplicationCommandResultHandler<TContext>();
}

public class ApplicationCommandServiceOptions<TInteraction, TContext, TAutocompleteContext> : ApplicationCommandServiceOptions<TInteraction, TContext> where TInteraction : ApplicationCommandInteraction where TContext : IApplicationCommandContext where TAutocompleteContext : IAutocompleteInteractionContext
Expand Down
Original file line number Diff line number Diff line change
@@ -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<TContext> where TContext : IApplicationCommandContext
{
public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services);
}
6 changes: 3 additions & 3 deletions Hosting/NetCord.Hosting.Services/Commands/CommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal unsafe partial class CommandHandler<TContext> : IGatewayEventHandler<Me
private readonly delegate*<CommandHandler<TContext>, Message, GatewayClient, ValueTask> _handleAsync;
private readonly Func<Message, GatewayClient, IServiceProvider, ValueTask<int>> _getPrefixLengthAsync;
private readonly Func<Message, GatewayClient, IServiceProvider, TContext> _createContext;
private readonly Func<IExecutionResult, Message, TContext, GatewayClient, ILogger, IServiceProvider, ValueTask> _handleResultAsync;
private readonly ICommandResultHandler<TContext> _resultHandler;
private readonly GatewayClient? _client;

public CommandHandler(IServiceProvider services,
Expand All @@ -46,7 +46,7 @@ public CommandHandler(IServiceProvider services,

_getPrefixLengthAsync = GetGetPrefixLengthAsyncDelegate(optionsValue);
_createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate<Message, GatewayClient, TContext>();
_handleResultAsync = optionsValue.HandleResultAsync;
_resultHandler = optionsValue.ResultHandler;
_client = client;
}

Expand Down Expand Up @@ -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)
{
Expand Down
30 changes: 30 additions & 0 deletions Hosting/NetCord.Hosting.Services/Commands/CommandResultHandler.cs
Original file line number Diff line number Diff line change
@@ -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<TContext>(MessageFlags? messageFlags = null) : ICommandResultHandler<TContext> 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,
}));
}
}
24 changes: 2 additions & 22 deletions Hosting/NetCord.Hosting.Services/Commands/CommandServiceOptions.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -20,22 +17,5 @@ public class CommandServiceOptions<TContext> where TContext : ICommandContext

public Func<Message, GatewayClient, IServiceProvider, TContext>? CreateContext { get; set; }

public Func<IExecutionResult, Message, TContext, GatewayClient, ILogger, IServiceProvider, ValueTask> 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<TContext> ResultHandler { get; set; } = new CommandResultHandler<TContext>();
}
12 changes: 12 additions & 0 deletions Hosting/NetCord.Hosting.Services/Commands/ICommandResultHandler.cs
Original file line number Diff line number Diff line change
@@ -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<TContext> where TContext : ICommandContext
{
public ValueTask HandleResultAsync(IExecutionResult result, Message message, TContext context, GatewayClient client, ILogger logger, IServiceProvider services);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal unsafe partial class ComponentInteractionHandler<TInteraction, TContext
private readonly IServiceScopeFactory? _scopeFactory;
private readonly delegate*<ComponentInteractionHandler<TInteraction, TContext>, Interaction, GatewayClient?, ValueTask> _handleAsync;
private readonly Func<TInteraction, GatewayClient?, IServiceProvider, TContext> _createContext;
private readonly Func<IExecutionResult, TInteraction, TContext, GatewayClient?, ILogger, IServiceProvider, ValueTask> _handleResultAsync;
private readonly IComponentInteractionResultHandler<TContext> _resultHandler;
private readonly GatewayClient? _client;

public ComponentInteractionHandler(IServiceProvider services,
Expand All @@ -44,7 +44,7 @@ public ComponentInteractionHandler(IServiceProvider services,
_handleAsync = &HandleInteractionAsync;

_createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate<TInteraction, GatewayClient?, TContext>();
_handleResultAsync = optionsValue.HandleResultAsync;
_resultHandler = optionsValue.ResultHandler;
_client = client;
}

Expand Down Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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<TContext>(MessageFlags? messageFlags = null) : IComponentInteractionResultHandler<TContext> 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)));
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -15,18 +11,5 @@ public class ComponentInteractionServiceOptions<TInteraction, TContext> where TI

public Func<TInteraction, GatewayClient?, IServiceProvider, TContext>? CreateContext { get; set; }

public Func<IExecutionResult, TInteraction, TContext, GatewayClient?, ILogger, IServiceProvider, ValueTask> 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<TContext> ResultHandler { get; set; } = new ComponentInteractionResultHandler<TContext>();
}
Original file line number Diff line number Diff line change
@@ -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<TContext> where TContext : IComponentInteractionContext
{
public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services);
}
20 changes: 20 additions & 0 deletions Tests/NetCord.Test.Hosting/CustomSlashCommandResultHandler.cs
Original file line number Diff line number Diff line change
@@ -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<SlashCommandContext>
{
private static readonly ApplicationCommandResultHandler<SlashCommandContext> _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);
}
}
5 changes: 4 additions & 1 deletion Tests/NetCord.Test.Hosting/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@
{
Intents = GatewayIntents.All,
})
.AddApplicationCommands<SlashCommandInteraction, SlashCommandContext, AutocompleteInteractionContext>()
.AddApplicationCommands<SlashCommandInteraction, SlashCommandContext, AutocompleteInteractionContext>(options =>
{
options.ResultHandler = new CustomSlashCommandResultHandler();
})
.AddApplicationCommands<UserCommandInteraction, UserCommandContext>()
.AddApplicationCommands<MessageCommandInteraction, MessageCommandContext>()
.AddComponentInteractions<ButtonInteraction, ButtonInteractionContext>()
Expand Down