<commit_before>﻿using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using CompatApiClient.Utils;
using CompatBot.Commands.Attributes;
using CompatBot.Database;
using CompatBot.Database.Providers;
using CompatBot.EventHandlers;
using CompatBot.Utils;
using DSharpPlus.CommandsNext;
using DSharpPlus.CommandsNext.Attributes;
using Microsoft.EntityFrameworkCore;

namespace CompatBot.Commands
{
    [Group("invite"), Aliases("invites"), RequiresBotModRole]
    [Description("Used to manage Discord invites whitelist")]
    internal sealed class Invites: BaseCommandModuleCustom
    {
        [Command("list"), Aliases("show")]
        [Description("Lists all filters")]
        public async Task List(CommandContext ctx)
        {
            const string linkPrefix = "discord.gg/";
            await using var db = new BotDb();
            var whitelistedInvites = await db.WhitelistedInvites.ToListAsync().ConfigureAwait(false);
            if (whitelistedInvites.Count == 0)
            {
                await ctx.Channel.SendMessageAsync("There are no whitelisted discord servers").ConfigureAwait(false);
                return;
            }

            var table = new AsciiTable(
                new AsciiColumn("ID", alignToRight: true),
                new AsciiColumn("Server ID", alignToRight: true),
                new AsciiColumn("Invite", disabled: !ctx.Channel.IsPrivate),
                new AsciiColumn("Server Name")
            );
            foreach (var item in whitelistedInvites)
            {
                string? guildName = null;
                if (!string.IsNullOrEmpty(item.InviteCode))
                    try
                    {
                        var invite = await ctx.Client.GetInviteByCodeAsync(item.InviteCode).ConfigureAwait(false);
                        guildName = invite.Guild.Name;
                    }
                    catch { }
                if (string.IsNullOrEmpty(guildName))
                    try
                    {
                        var guild = await ctx.Client.GetGuildAsync(item.GuildId).ConfigureAwait(false);
                        guildName = guild.Name;
                    }
                    catch { }
                if (string.IsNullOrEmpty(guildName))
                    guildName = item.Name ?? "";
                var link = "";
                if (!string.IsNullOrEmpty(item.InviteCode))
                    link = linkPrefix + item.InviteCode;
                //discord expands invite links even if they're inside the code block for some reason
                table.Add(item.Id.ToString(), item.GuildId.ToString(), link + StringUtils.InvisibleSpacer, guildName.Sanitize());
            }
            var result = new StringBuilder()
                .AppendLine("Whitelisted discord servers:")
                .Append(table);
            await ctx.SendAutosplitMessageAsync(result).ConfigureAwait(false);
        }

        [Command("whitelist"), Aliases("add", "allow"), Priority(10)]
        [Description("Adds a new guild to the whitelist")]
        public async Task Add(CommandContext ctx, [Description("A Discord server IDs to whitelist")] params ulong[] guildIds)
        {
            var errors = 0;
            foreach (var guildId in guildIds)
                if (!await InviteWhitelistProvider.AddAsync(guildId).ConfigureAwait(false))
                    errors++;

            if (errors == 0)
                await ctx.ReactWithAsync(Config.Reactions.Success, "Invite whitelist was successfully updated!").ConfigureAwait(false);
            else
                await ctx.ReactWithAsync(Config.Reactions.Failure, $"Failed to add {errors} invite{StringUtils.GetSuffix(errors)} to the whitelist").ConfigureAwait(false);
            await List(ctx).ConfigureAwait(false);
        }

        [Command("whitelist"), Priority(0)]
        [Description("Adds a new guild to the whitelist")]
        public async Task Add(CommandContext ctx, [RemainingText, Description("An invite link or just an invite token")] string invite)
        {
            var (_, _, invites) = await ctx.Client.GetInvitesAsync(invite, tryMessageAsACode: true).ConfigureAwait(false);
            if (invites.Count == 0)
            {
                await ctx.ReactWithAsync(Config.Reactions.Failure, "Need to specify an invite link or token").ConfigureAwait(false);
                return;
            }

            var errors = 0;
            foreach (var i in invites)
                if (!await InviteWhitelistProvider.AddAsync(i).ConfigureAwait(false))
                    errors++;

            if (errors == 0)
                await ctx.ReactWithAsync(Config.Reactions.Success, "Invite whitelist was successfully updated!").ConfigureAwait(false);
            else
                await ctx.ReactWithAsync(Config.Reactions.Failure, $"Failed to add {errors} invite{StringUtils.GetSuffix(errors)} to the whitelist").ConfigureAwait(false);
            await List(ctx).ConfigureAwait(false);<commit_msg>Resolves #831<commit_after>﻿using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using CompatApiClient.Utils;
using CompatBot.Commands.Attributes;
using CompatBot.Database;
using CompatBot.Database.Providers;
using CompatBot.EventHandlers;
using CompatBot.Utils;
using DSharpPlus.CommandsNext;
using DSharpPlus.CommandsNext.Attributes;
using DSharpPlus.Entities;
using Microsoft.EntityFrameworkCore;

namespace CompatBot.Commands
{
    [Group("invite"), Aliases("invites"), RequiresBotModRole]
    [Description("Used to manage Discord invites whitelist")]
    internal sealed class Invites: BaseCommandModuleCustom
    {
        [Command("list"), Aliases("show")]
        [Description("Lists all filters")]
        public async Task List(CommandContext ctx)
        {
            const string linkPrefix = "discord.gg/";
            await using var db = new BotDb();
            var whitelistedInvites = await db.WhitelistedInvites.ToListAsync().ConfigureAwait(false);
            if (whitelistedInvites.Count == 0)
            {
                await ctx.Channel.SendMessageAsync("There are no whitelisted discord servers").ConfigureAwait(false);
                return;
            }

            var table = new AsciiTable(
                new AsciiColumn("ID", alignToRight: true),
                new AsciiColumn("Server ID", alignToRight: true),
                new AsciiColumn("Invite", disabled: !ctx.Channel.IsPrivate),
                new AsciiColumn("Server Name")
            );
            foreach (var item in whitelistedInvites)
            {
                string? guildName = null;
                if (!string.IsNullOrEmpty(item.InviteCode))
                    try
                    {
                        var invite = await ctx.Client.GetInviteByCodeAsync(item.InviteCode).ConfigureAwait(false);
                        guildName = invite.Guild.Name;
                    }
                    catch { }
                if (string.IsNullOrEmpty(guildName))
                    try
                    {
                        var guild = await ctx.Client.GetGuildAsync(item.GuildId).ConfigureAwait(false);
                        guildName = guild.Name;
                    }
                    catch { }
                if (string.IsNullOrEmpty(guildName))
                    guildName = item.Name ?? "";
                var link = "";
                if (!string.IsNullOrEmpty(item.InviteCode))
                    link = linkPrefix + item.InviteCode;
                //discord expands invite links even if they're inside the code block for some reason
                table.Add(item.Id.ToString(), item.GuildId.ToString(), link /* + StringUtils.InvisibleSpacer*/, guildName.Sanitize());
            }
            var result = new StringBuilder()
                .AppendLine("Whitelisted discord servers:")
                .Append(table.ToString(false));

            await using var output = Config.MemoryStreamManager.GetStream();
            await using (var writer = new StreamWriter(output, leaveOpen: true))
                await writer.WriteAsync(result.ToString()).ConfigureAwait(false);
            output.Seek(0, SeekOrigin.Begin);
            await ctx.Channel.SendMessageAsync(new DiscordMessageBuilder().WithFile("invites.txt", output)).ConfigureAwait(false);
        }

        [Command("whitelist"), Aliases("add", "allow"), Priority(10)]
        [Description("Adds a new guild to the whitelist")]
        public async Task Add(CommandContext ctx, [Description("A Discord server IDs to whitelist")] params ulong[] guildIds)
        {
            var errors = 0;
            foreach (var guildId in guildIds)
                if (!await InviteWhitelistProvider.AddAsync(guildId).ConfigureAwait(false))
                    errors++;

            if (errors == 0)
                await ctx.ReactWithAsync(Config.Reactions.Success, "Invite whitelist was successfully updated!").ConfigureAwait(false);
            else
                await ctx.ReactWithAsync(Config.Reactions.Failure, $"Failed to add {errors} invite{StringUtils.GetSuffix(errors)} to the whitelist").ConfigureAwait(false);
        }

        [Command("whitelist"), Priority(0)]
        [Description("Adds a new guild to the whitelist")]
        public async Task Add(CommandContext ctx, [RemainingText, Description("An invite link or just an invite token")] string invite)
        {
            var (_, _, invites) = await ctx.Client.GetInvitesAsync(invite, tryMessageAsACode: true).ConfigureAwait(false);
            if (invites.Count == 0)
            {
                await ctx.ReactWithAsync(Config.Reactions.Failure, "Need to specify an invite link or token").ConfigureAwait(false);
                return;
            }

            var errors = 0;
            foreach (var i in invites)
                if (!await InviteWhitelistProvider.AddAsync(i).ConfigureAwait(false))
                    errors++;

            if (errors == 0)
                await ctx.ReactWithAsync(Config.Reactions.Success, "Invite whitelist was successfully updated!").ConfigureAwait(false);
            else
                await ctx.ReactWithAsync(Config.Reactions.Failure, $"Failed to add {errors} invite{StringUtils.GetSuffix(errors)} to the whitelist").ConfigureAwait(false);
            await List(ctx).ConfigureAwait(false);
{'fraction_non_alphanumeric': 0.09754453538757824, 'fraction_numerical': 0.002118440057775638, 'mean_word_length': 2.1217312894499547, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3369905', 'n_tokens_mistral': 2757, 'n_tokens_neox': 2637, 'n_words': 627}