Beispiel #1
0
        public async Task UnBanAsync(
            [Summary("The user to be un-banned.")]
            DiscordUserOrMessageAuthorEntity subject)
        {
            await ModerationService.RescindInfractionAsync(InfractionType.Ban, subject.UserId);

            await ConfirmAndReplyWithCountsAsync(subject.UserId);
        }
Beispiel #2
0
        public Task GetNewUserInfoAsync(
            [Summary("The user to retrieve information about, if any.")][Remainder]
            DiscordUserOrMessageAuthorEntity user = null)
        {
            var userId = user?.UserId ?? Context.User.Id;

            return(_mediator.Send(new UserInfoCommand(Context.Message, Context.Guild.Id, userId)));
        }
Beispiel #3
0
        private async ValueTask <bool> GetConfirmationIfRequiredAsync(DiscordUserOrMessageAuthorEntity userOrAuthor)
        {
            if (userOrAuthor.MessageId is null)
            {
                return(true);
            }

            var author = await UserService.GetUserAsync(userOrAuthor.UserId);

            Debug.Assert(author is { }); // author should be nonnull, because we have a message written by someone with that ID
Beispiel #4
0
        public async Task UnMuteAsync(
            [Summary("The user to be un-muted.")]
            DiscordUserOrMessageAuthorEntity subject)
        {
            if (!await GetConfirmationIfRequiredAsync(subject))
            {
                return;
            }

            await ModerationService.RescindInfractionAsync(InfractionType.Mute, subject.UserId);

            await ConfirmAndReplyWithCountsAsync(subject.UserId);
        }
Beispiel #5
0
        public async Task MuteAsync(
            [Summary("The user to be muted.")]
            DiscordUserOrMessageAuthorEntity subject,
            [Summary("The reason for the mute.")]
            [Remainder]
            string reason)
        {
            var reasonWithUrls = AppendUrlsFromMessage(reason);

            await ModerationService.CreateInfractionAsync(Context.Guild.Id, Context.User.Id, InfractionType.Mute, subject.UserId, reasonWithUrls, null);

            await ConfirmAndReplyWithCountsAsync(subject.UserId);
        }
Beispiel #6
0
        public async Task UnMuteAsync(
            [Summary("The user to be un-muted.")]
            DiscordUserOrMessageAuthorEntity subject,
            [Summary("The reason for the unmute (optional).")]
            [Remainder]
            string reason = null)
        {
            if (!await GetConfirmationIfRequiredAsync(subject))
            {
                return;
            }

            await ModerationService.RescindInfractionAsync(InfractionType.Mute, subject.UserId, reason);

            await ConfirmAndReplyWithCountsAsync(subject.UserId);
        }
Beispiel #7
0
        public async Task WarnAsync(
            [Summary("The user to which the warning is being issued.")]
            DiscordUserOrMessageAuthorEntity subject,
            [Summary("The reason for the warning.")]
            [Remainder]
            string reason)
        {
            if (!await GetConfirmationIfRequiredAsync(subject))
            {
                return;
            }

            var reasonWithUrls = AppendUrlsFromMessage(reason);

            await ModerationService.CreateInfractionAsync(Context.Guild.Id, Context.User.Id, InfractionType.Warning, subject.UserId, reasonWithUrls, null);

            await ConfirmAndReplyWithCountsAsync(subject.UserId);
        }
Beispiel #8
0
        public async Task UnBanAsync(
            [Summary("The user to be un-banned.")]
            DiscordUserOrMessageAuthorEntity subject,
            [Summary("The reason for the unban (optional).")]
            [Remainder]
            string reason = null)
        {
            if (!await GetConfirmationIfRequiredAsync(subject))
            {
                return;
            }

            var reasonWithUrls = AppendUrlsFromMessage(reason);

            await ModerationService.RescindInfractionAsync(InfractionType.Ban, subject.UserId, reasonWithUrls);

            await ConfirmAndReplyWithCountsAsync(subject.UserId);
        }
Beispiel #9
0
        public async Task TempMuteAsync(
            [Summary("The duration of the mute.")]
            TimeSpan duration,
            [Summary("The user to be muted.")]
            DiscordUserOrMessageAuthorEntity subject,
            [Summary("The reason for the mute.")]
            [Remainder]
            string reason)
        {
            if (!await GetConfirmationIfRequiredAsync(subject))
            {
                return;
            }

            var reasonWithUrls = AppendUrlsFromMessage(reason);

            await ModerationService.CreateInfractionAsync(Context.Guild.Id, Context.User.Id, InfractionType.Mute, subject.UserId, reasonWithUrls, duration);

            await ConfirmAndReplyWithCountsAsync(subject.UserId);
        }
Beispiel #10
0
        public async Task GetUserInfoAsync(
            [Summary("The user to retrieve information about, if any.")]
            [Remainder] DiscordUserOrMessageAuthorEntity user = null)
        {
            var userId = user?.UserId ?? Context.User.Id;

            var timer = Stopwatch.StartNew();

            var userInfo = await _userService.GetUserInformationAsync(Context.Guild.Id, userId);

            if (userInfo == null)
            {
                var embed = new EmbedBuilder()
                            .WithTitle("Retrieval Error")
                            .WithColor(Color.Red)
                            .WithDescription("Sorry, we don't have any data for that user - and we couldn't find any, either.")
                            .AddField("User Id", userId);
                await _autoRemoveMessageService.RegisterRemovableMessageAsync(
                    Context.User,
                    embed,
                    async (embedBuilder) => await ReplyAsync(embed: embedBuilder.Build()));

                return;
            }

            var builder = new StringBuilder();

            builder.AppendLine("**\u276F User Information**");
            builder.AppendLine("ID: " + userId);
            builder.AppendLine("Profile: " + MentionUtils.MentionUser(userId));

            var embedBuilder = new EmbedBuilder()
                               .WithUserAsAuthor(userInfo)
                               .WithTimestamp(_utcNow);

            var avatar = userInfo.GetDefiniteAvatarUrl();

            embedBuilder.ThumbnailUrl   = avatar;
            embedBuilder.Author.IconUrl = avatar;

            ValueTask <Color> colorTask = default;

            if ((userInfo.GetAvatarUrl(size: 16) ?? userInfo.GetDefaultAvatarUrl()) is { } avatarUrl)
            {
                colorTask = _imageService.GetDominantColorAsync(new Uri(avatarUrl));
            }

            var moderationRead = await _authorizationService.HasClaimsAsync(Context.User as IGuildUser, AuthorizationClaim.ModerationRead);

            var promotions = await _promotionsService.GetPromotionsForUserAsync(Context.Guild.Id, userId);

            if (userInfo.IsBanned)
            {
                builder.AppendLine("Status: **Banned** \\🔨");

                if (moderationRead)
                {
                    builder.AppendLine($"Ban Reason: {userInfo.BanReason}");
                }
            }

            if (userInfo.FirstSeen is DateTimeOffset firstSeen)
            {
                builder.AppendLine($"First Seen: {FormatUtilities.FormatTimeAgo(_utcNow, firstSeen)}");
            }

            if (userInfo.LastSeen is DateTimeOffset lastSeen)
            {
                builder.AppendLine($"Last Seen: {FormatUtilities.FormatTimeAgo(_utcNow, lastSeen)}");
            }

            try
            {
                var userRank = await _messageRepository.GetGuildUserParticipationStatistics(Context.Guild.Id, userId);

                var messagesByDate = await _messageRepository.GetGuildUserMessageCountByDate(Context.Guild.Id, userId, TimeSpan.FromDays(30));

                var messageCountsByChannel = await _messageRepository.GetGuildUserMessageCountByChannel(Context.Guild.Id, userId, TimeSpan.FromDays(30));

                var emojiCounts = await _emojiRepository.GetEmojiStatsAsync(Context.Guild.Id, SortDirection.Ascending, 1, userId : userId);

                await AddParticipationToEmbedAsync(userId, builder, userRank, messagesByDate, messageCountsByChannel, emojiCounts);
            }
            catch (Exception ex)
            {
                _log.LogError(ex, "An error occured while retrieving a user's message count.");
            }

            AddMemberInformationToEmbed(userInfo, builder);
            AddPromotionsToEmbed(builder, promotions);

            if (moderationRead)
            {
                await AddInfractionsToEmbedAsync(userId, builder);
            }

            embedBuilder.Description = builder.ToString();

            embedBuilder.WithColor(await colorTask);

            timer.Stop();
            embedBuilder.WithFooter(footer => footer.Text = $"Completed after {timer.ElapsedMilliseconds} ms");

            await _autoRemoveMessageService.RegisterRemovableMessageAsync(
                userInfo.Id == Context.User.Id?new[] { userInfo } : new[] { userInfo, Context.User },
                embedBuilder,
                async (embedBuilder) => await ReplyAsync(embed: embedBuilder.Build()));
        }
Beispiel #11
0
        public async Task SearchAsync(
            [Summary("The user whose infractions are to be displayed.")]
            DiscordUserOrMessageAuthorEntity subjectEntity)
        {
            var requestor = Context.User.Mention;
            var subject   = await UserService.GetGuildUserSummaryAsync(Context.Guild.Id, subjectEntity.UserId);

            var infractions = await ModerationService.SearchInfractionsAsync(
                new InfractionSearchCriteria
            {
                GuildId   = Context.Guild.Id,
                SubjectId = subjectEntity.UserId,
                IsDeleted = false
            },
                new[]
            {
                new SortingCriteria()
                {
                    PropertyName = nameof(InfractionSummary.CreateAction.Created),
                    Direction    = SortDirection.Descending,
                },
            });

            if (infractions.Count == 0)
            {
                await ReplyAsync(Format.Code("No infractions"));

                return;
            }

            var infractionQuery = infractions.Select(infraction => new
            {
                Id        = infraction.Id,
                Created   = infraction.CreateAction.Created.ToUniversalTime().ToString("yyyy MMM dd"),
                Type      = infraction.Type,
                Reason    = infraction.Reason,
                Rescinded = infraction.RescindAction != null
            });

            var counts = await ModerationService.GetInfractionCountsForUserAsync(subjectEntity.UserId);

            // https://modix.gg/infractions?subject=12345
            var url = new UriBuilder(Config.WebsiteBaseUrl)
            {
                Path  = "/infractions",
                Query = $"subject={subject.UserId}"
            }.RemoveDefaultPort().ToString();

            var builder = new EmbedBuilder()
                          .WithTitle($"Infractions for user: {subject.GetFullUsername()}")
                          .WithDescription(FormatUtilities.FormatInfractionCounts(counts))
                          .WithUrl(url)
                          .WithColor(new Color(0xA3BF0B));

            foreach (var infraction in infractionQuery)
            {
                // https://modix.gg/infractions?id=123
                var infractionUrl = new UriBuilder(Config.WebsiteBaseUrl)
                {
                    Path  = "/infractions",
                    Query = $"id={infraction.Id}"
                }.ToString();

                var emoji = GetEmojiForInfractionType(infraction.Type);

                builder.AddField(
                    $"#{infraction.Id} - \\{emoji} {infraction.Type} - Created: {infraction.Created}{(infraction.Rescinded ? " - [RESCINDED]" : "")}",
                    Format.Url($"Reason: {infraction.Reason}", infractionUrl)
                    );
            }

            var embed = builder.Build();

            await Context.Channel.SendMessageAsync(
                $"Requested by {requestor}",
                embed : embed)
            .ConfigureAwait(false);
        }