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 @@ -48,7 +48,7 @@ public ApplicationCommandInteractionHandler(IServiceProvider services,
_handleAsync = &HandleInteractionAsync;

_createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate<TInteraction, GatewayClient?, TContext>(_applicationCommandService.Configuration.ServiceResolverProvider);
_resultHandler = optionsValue.ResultHandler ?? new ApplicationCommandResultHandler<TContext>();
_resultHandler = optionsValue.ResultHandler ?? ApplicationCommandResultHandler<TContext>.Default;
_preExecutionHandler = optionsValue.PreExecutionHandler ?? new ApplicationCommandPreExecutionHandler<TContext>();
_client = client;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,53 @@

namespace NetCord.Hosting.Services.ApplicationCommands;

public class ApplicationCommandResultHandler<TContext>(MessageFlags? messageFlags = null)
: IApplicationCommandResultHandler<TContext>
public class ApplicationCommandResultHandler<TContext> : IApplicationCommandResultHandler<TContext>
where TContext : IApplicationCommandContext
{
public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services)
public static ApplicationCommandResultHandler<TContext> Default => new();

public static ApplicationCommandResultHandler<TContext> Ephemeral => new EphemeralApplicationCommandResultHandler();

protected ApplicationCommandResultHandler()
{
if (result is not IFailResult failResult)
return default;
}

private sealed class EphemeralApplicationCommandResultHandler : ApplicationCommandResultHandler<TContext>
{
public override ValueTask<InteractionMessageProperties> GetFailMessageAsync(IFailResult failResult, TContext context, IServiceProvider services)
{
return new(new InteractionMessageProperties
{
Content = failResult.Message,
Flags = MessageFlags.Ephemeral,
});
}
}

var resultMessage = failResult.Message;
public async ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services)
{
if (result is not IFailResult failResult)
return;

var interaction = context.Interaction;

var commandName = interaction.Data.Name;

if (failResult is IExceptionResult exceptionResult)
logger.LogError(exceptionResult.Exception, "Execution of an application command of name '{Name}' failed with an exception", interaction.Data.Name);
logger.LogError(exceptionResult.Exception, "Execution of an application command of name '{Name}' failed with an exception", commandName);
else
logger.LogDebug("Execution of an application command of name '{Name}' failed with '{Message}'", interaction.Data.Name, resultMessage);
logger.LogDebug("Execution of an application command of name '{Name}' failed with '{Message}'", commandName, failResult.Message);

InteractionMessageProperties message = new()
{
Content = resultMessage,
Flags = messageFlags,
};
var response = await GetFailMessageAsync(failResult, context, services).ConfigureAwait(false);

return new(interaction.SendResponseAsync(InteractionCallback.Message(message)));
await interaction.SendResponseAsync(InteractionCallback.Message(response)).ConfigureAwait(false);
}

public virtual ValueTask<InteractionMessageProperties> GetFailMessageAsync(IFailResult failResult, TContext context, IServiceProvider services)
{
return new(new InteractionMessageProperties
{
Content = failResult.Message,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public CommandHandler(IServiceProvider services,

_getCommandTextAsync = GetGetCommandTextAsyncDelegate(optionsValue);
_createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate<Message, GatewayClient, TContext>(_commandService.Configuration.ServiceResolverProvider);
_resultHandler = optionsValue.ResultHandler ?? new CommandResultHandler<TContext>();
_resultHandler = optionsValue.ResultHandler ?? CommandResultHandler<TContext>.Default;
_preExecutionHandler = optionsValue.PreExecutionHandler ?? new CommandPreExecutionHandler<TContext>();
_client = client;
}
Expand Down
37 changes: 25 additions & 12 deletions Hosting/NetCord.Hosting.Services/Commands/CommandResultHandler.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
using Microsoft.Extensions.Logging;

using NetCord.Gateway;
using NetCord.Rest;
using NetCord.Services;
using NetCord.Services.Commands;

namespace NetCord.Hosting.Services.Commands;

public class CommandResultHandler<TContext>(MessageFlags? messageFlags = null) : ICommandResultHandler<TContext>
public class CommandResultHandler<TContext> : ICommandResultHandler<TContext>
where TContext : ICommandContext
{
public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient client, ILogger logger, IServiceProvider services)
public static CommandResultHandler<TContext> Default => new();

protected CommandResultHandler()
{
if (result is not IFailResult failResult)
return default;
}

var resultMessage = failResult.Message;
public async ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient client, ILogger logger, IServiceProvider services)
{
if (result is not IFailResult failResult)
return;

var message = context.Message;

var messageContent = message.Content;

if (failResult is IExceptionResult exceptionResult)
logger.LogError(exceptionResult.Exception, "Execution of a command with content '{Content}' failed with an exception", message.Content);
logger.LogError(exceptionResult.Exception, "Execution of a command with content '{Content}' failed with an exception", messageContent);
else
logger.LogDebug("Execution of a command with content '{Content}' failed with '{Message}'", message.Content, resultMessage);
logger.LogDebug("Execution of a command with content '{Content}' failed with '{Message}'", messageContent, failResult.Message);

var response = await GetFailMessage(failResult, context, services).ConfigureAwait(false);

return new(message.ReplyAsync(new()
await message.SendAsync(response).ConfigureAwait(false);
}

public virtual ValueTask<MessageProperties> GetFailMessage(IFailResult failResult, TContext context, IServiceProvider services)
{
return new(new MessageProperties
{
Content = resultMessage,
FailIfNotExists = false,
Flags = messageFlags,
}));
MessageReference = MessageReferenceProperties.Reply(context.Message.Id, false),
Content = failResult.Message,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public ComponentInteractionHandler(IServiceProvider services,
_handleAsync = &HandleInteractionAsync;

_createContext = optionsValue.CreateContext ?? ContextHelper.CreateContextDelegate<TInteraction, GatewayClient?, TContext>(_componentInteractionService.Configuration.ServiceResolverProvider);
_resultHandler = optionsValue.ResultHandler ?? new ComponentInteractionResultHandler<TContext>();
_resultHandler = optionsValue.ResultHandler ?? ComponentInteractionResultHandler<TContext>.Default;
_preExecutionHandler = optionsValue.PreExecutionHandler ?? new ComponentInteractionPreExecutionHandler<TContext>();
_client = client;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,53 @@

namespace NetCord.Hosting.Services.ComponentInteractions;

public class ComponentInteractionResultHandler<TContext>(MessageFlags? messageFlags = null) : IComponentInteractionResultHandler<TContext>
public class ComponentInteractionResultHandler<TContext> : IComponentInteractionResultHandler<TContext>
where TContext : IComponentInteractionContext
{
public ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services)
public static ComponentInteractionResultHandler<TContext> Default => new();

public static ComponentInteractionResultHandler<TContext> Ephemeral => new EphemeralComponentInteractionResultHandler();

protected ComponentInteractionResultHandler()
{
if (result is not IFailResult failResult)
return default;
}

private sealed class EphemeralComponentInteractionResultHandler : ComponentInteractionResultHandler<TContext>
{
public override ValueTask<InteractionMessageProperties> GetFailMessageAsync(IFailResult failResult, TContext context, IServiceProvider services)
{
return new(new InteractionMessageProperties
{
Content = failResult.Message,
Flags = MessageFlags.Ephemeral,
});
}
}

var resultMessage = failResult.Message;
public async ValueTask HandleResultAsync(IExecutionResult result, TContext context, GatewayClient? client, ILogger logger, IServiceProvider services)
{
if (result is not IFailResult failResult)
return;

var interaction = context.Interaction;

var customId = interaction.Data.CustomId;

if (failResult is IExceptionResult exceptionResult)
logger.LogError(exceptionResult.Exception, "Execution of an interaction of custom ID '{Id}' failed with an exception", interaction.Data.CustomId);
logger.LogError(exceptionResult.Exception, "Execution of an interaction of custom ID '{Id}' failed with an exception", customId);
else
logger.LogDebug("Execution of an interaction of custom ID '{Id}' failed with '{Message}'", interaction.Data.CustomId, resultMessage);
logger.LogDebug("Execution of an interaction of custom ID '{Id}' failed with '{Message}'", customId, failResult.Message);

InteractionMessageProperties message = new()
{
Content = resultMessage,
Flags = messageFlags,
};
var response = await GetFailMessageAsync(failResult, context, services).ConfigureAwait(false);

return new(interaction.SendResponseAsync(InteractionCallback.Message(message)));
await interaction.SendResponseAsync(InteractionCallback.Message(response)).ConfigureAwait(false);
}

public virtual ValueTask<InteractionMessageProperties> GetFailMessageAsync(IFailResult failResult, TContext context, IServiceProvider services)
{
return new(new InteractionMessageProperties
{
Content = failResult.Message,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace NetCord.Test.Hosting;

internal class CustomApplicationCommandResultHandler : IApplicationCommandResultHandler<ApplicationCommandContext>
{
private static readonly ApplicationCommandResultHandler<ApplicationCommandContext> _defaultHandler = new(MessageFlags.Ephemeral);
private static readonly ApplicationCommandResultHandler<ApplicationCommandContext> _defaultHandler = ApplicationCommandResultHandler<ApplicationCommandContext>.Ephemeral;

public ValueTask HandleResultAsync(IExecutionResult result, ApplicationCommandContext context, GatewayClient? client, ILogger logger, IServiceProvider services)
{
Expand Down