using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Remora.Discord.API.Abstractions.Objects;
using Remora.Discord.API.Abstractions.Rest;
using Remora.Discord.API.Objects;
using Remora.Discord.Commands.Contexts;
using Remora.Discord.Commands.Feedback.Messages;
using Remora.Discord.Commands.Feedback.Services;
using Remora.Discord.Commands.Services;
using Remora.Discord.Extensions.Embeds;
using Remora.Discord.Extensions.Formatting;
using Remora.Results;
using TeamOctolings.Octobot.Extensions;
namespace TeamOctolings.Octobot.Commands.Events;
///
/// Handles error logging for slash command groups.
///
[UsedImplicitly]
public sealed class ErrorLoggingPostExecutionEvent : IPostExecutionEvent
{
private readonly IFeedbackService _feedback;
private readonly ILogger _logger;
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.Success;
}
var botResult = await _userApi.GetCurrentUserAsync(ct);
if (!botResult.IsDefined(out var bot))
{
return ResultExtensions.FromError(botResult);
}
var embed = new EmbedBuilder().WithSmallTitle(Messages.CommandExecutionFailed, bot)
.WithDescription(Markdown.InlineCode(result.Error.Message))
.WithFooter(Messages.ContactDevelopers)
.WithColour(ColorsList.Red)
.Build();
var issuesButton = new ButtonComponent(
ButtonComponentStyle.Link,
BuildInfo.IsDirty
? Messages.ButtonDirty
: Messages.ButtonReportIssue,
new PartialEmoji(Name: "\u26a0\ufe0f"), // 'WARNING SIGN' (U+26A0)
URL: BuildInfo.IssuesUrl,
IsDisabled: BuildInfo.IsDirty
);
return ResultExtensions.FromError(await _feedback.SendContextualEmbedResultAsync(embed,
new FeedbackMessageOptions(MessageComponents: new[]
{
new ActionRowComponent(new[] { issuesButton })
}), ct)
);
}
}