using JetBrains.Annotations; using Microsoft.Extensions.Logging; using Octobot.Extensions; using Remora.Discord.API.Abstractions.Rest; using Remora.Discord.Commands.Contexts; using Remora.Discord.Commands.Feedback.Services; using Remora.Discord.Commands.Services; using Remora.Discord.Extensions.Embeds; using Remora.Discord.Extensions.Formatting; using Remora.Results; namespace Octobot.Commands.Events; /// /// Handles error logging for slash command groups. /// [UsedImplicitly] public class ErrorLoggingPostExecutionEvent : IPostExecutionEvent { private readonly ILogger _logger; private readonly IFeedbackService _feedback; private readonly IDiscordRestUserAPI _userApi; public ErrorLoggingPostExecutionEvent(ILogger logger, IFeedbackService feedback, IDiscordRestUserAPI userApi) { _logger = logger; _feedback = feedback; _userApi = userApi; } /// /// Logs a warning using the injected if the has not /// succeeded. /// /// The context of the slash command. /// The result whose success is checked. /// The cancellation token for this operation. Unused. /// A result which has succeeded. public async Task AfterExecutionAsync( ICommandContext context, IResult commandResult, CancellationToken ct = default) { _logger.LogResult(commandResult, $"Error in slash command execution for /{context.Command.Command.Node.Key}."); var result = commandResult; while (result.Inner is not null) { result = result.Inner; } if (result.IsSuccess) { return Result.FromSuccess(); } var botResult = await _userApi.GetCurrentUserAsync(ct); if (!botResult.IsDefined(out var bot)) { return Result.FromError(botResult); } var embed = new EmbedBuilder().WithSmallTitle(Messages.CommandExecutionFailed, bot) .WithDescription(Markdown.InlineCode(result.Error.Message)) .WithFooter(Messages.ContactDevelopers) .WithColour(ColorsList.Red) .Build(); return await _feedback.SendContextualEmbedResultAsync(embed, ct); } }