private async ValueTask <Result <bool> > GetConfirmationIfRequiredAsync(UserOrMessageAuthor userOrAuthor)
        {
            if (userOrAuthor.MessageId is null)
            {
                return(true);
            }

            var author = await _userService.GetUserAsync(userOrAuthor.User.ID.Value);

            Debug.Assert(author is not null); // author should be non-null, because we have a message written by someone with that ID

            return(await _commandConfirmationService.GetUserConfirmationAsync(_context.ChannelID, _context.User.ID,
                                                                              "Detected a message ID instead of a user ID. Do you want to perform this action on "
                                                                              + $"**{author.GetFullUsername()}** ({userOrAuthor.User.ID.Value}), the message's author?"));
        }
        private async Task <IResult> RescindInfractionAsync(UserOrMessageAuthor subject, string reason, InfractionType infractionType)
        {
            var confirmationResult = await GetConfirmationIfRequiredAsync(subject);

            if (!confirmationResult.IsSuccess || !confirmationResult.Entity)
            {
                return(Result.FromSuccess());
            }

            try
            {
                var reasonWithUrls = AppendUrlsFromMessage(reason);
                await _moderationService.RescindInfractionAsync(infractionType, _context.GuildID.Value.Value, subject.User.ID.Value, reasonWithUrls);

                return(await ConfirmAsync());
            }
            catch (Exception ex)
            {
                await _channelApi.CreateMessageAsync(_context.ChannelID, ex.Message, allowedMentions : new NoAllowedMentions());

                return(Result.FromError(new ExceptionError(ex)));
            }
        }
 public async Task <IResult> UnbanAsync(UserOrMessageAuthor subject, [Greedy] string reason = "")
 => await RescindInfractionAsync(subject, reason, InfractionType.Ban);
 public async Task <IResult> BanAsync(UserOrMessageAuthor subject, [Greedy] string reason)
 => await CreateInfractionAsync(subject, reason, InfractionType.Ban);
 public async Task <IResult> MuteAsync(TimeSpan duration, UserOrMessageAuthor subject, [Greedy] string reason)
 => await CreateInfractionAsync(subject, reason, InfractionType.Mute, duration);