Merged with dev
This commit is contained in:
		@@ -41,7 +41,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    var channel = msg.Channel as SocketTextChannel;
 | 
			
		||||
                    if (channel == null)
 | 
			
		||||
                        return;
 | 
			
		||||
                    if (deleteMessagesOnCommand.Contains(channel.Guild.Id) && cmd.Name != "prune")
 | 
			
		||||
                    if (deleteMessagesOnCommand.Contains(channel.Guild.Id) && cmd.Name != "prune" && cmd.Name != "pick")
 | 
			
		||||
                        await msg.DeleteAsync().ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
@@ -118,7 +118,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        {
 | 
			
		||||
            var guser = (IGuildUser)Context.User;
 | 
			
		||||
            var maxRole = guser.GetRoles().Max(x => x.Position);
 | 
			
		||||
            if (maxRole < role.Position || maxRole <= usr.GetRoles().Max(x => x.Position))
 | 
			
		||||
            if ((Context.User.Id != Context.Guild.OwnerId) && (maxRole < role.Position || maxRole <= usr.GetRoles().Max(x => x.Position)))
 | 
			
		||||
                return;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -378,12 +378,14 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        {
 | 
			
		||||
            var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            var enumerable = (await Context.Channel.GetMessagesAsync().Flatten()).AsEnumerable();
 | 
			
		||||
            enumerable = enumerable.Where(x => x.Author.Id == user.Id);
 | 
			
		||||
            var enumerable = (await Context.Channel.GetMessagesAsync().Flatten())
 | 
			
		||||
                .Where(x => x.Author.Id == user.Id && DateTime.Now - x.CreatedAt < twoWeeks);
 | 
			
		||||
            await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
 | 
			
		||||
            Context.Message.DeleteAfter(3);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private TimeSpan twoWeeks => TimeSpan.FromDays(14);
 | 
			
		||||
        // prune x
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -396,7 +398,8 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                return;
 | 
			
		||||
            await Context.Message.DeleteAsync().ConfigureAwait(false);
 | 
			
		||||
            int limit = (count < 100) ? count + 1 : 100;
 | 
			
		||||
            var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten().ConfigureAwait(false));
 | 
			
		||||
            var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten().ConfigureAwait(false))
 | 
			
		||||
                .Where(x => DateTime.Now - x.CreatedAt < twoWeeks);
 | 
			
		||||
            if (enumerable.FirstOrDefault()?.Id == Context.Message.Id)
 | 
			
		||||
                enumerable = enumerable.Skip(1).ToArray();
 | 
			
		||||
            else
 | 
			
		||||
@@ -419,7 +422,8 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                count += 1;
 | 
			
		||||
 | 
			
		||||
            int limit = (count < 100) ? count : 100;
 | 
			
		||||
            var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten()).Where(m => m.Author == user);
 | 
			
		||||
            var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten())
 | 
			
		||||
                .Where(m => m.Author == user && DateTime.Now - m.CreatedAt < twoWeeks);
 | 
			
		||||
            await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            Context.Message.DeleteAfter(3);
 | 
			
		||||
@@ -434,7 +438,9 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            foreach (var role in roles)
 | 
			
		||||
            {
 | 
			
		||||
                send += $"\n**{role.Name}**\n";
 | 
			
		||||
                send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.GetRoles().Contains(role)).Take(50).Select(u => u.Mention));
 | 
			
		||||
                send += string.Join(", ", (await Context.Guild.GetUsersAsync())
 | 
			
		||||
                    .Where(u => u.GetRoles().Contains(role))
 | 
			
		||||
                    .Take(50).Select(u => u.Mention));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            while (send.Length > 2000)
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
@@ -35,30 +37,51 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                = new ConcurrentDictionary<ulong, UserSpamStats>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public class UserSpamStats
 | 
			
		||||
        public class UserSpamStats : IDisposable
 | 
			
		||||
        {
 | 
			
		||||
            public int Count { get; set; }
 | 
			
		||||
            public int Count => timers.Count;
 | 
			
		||||
            public string LastMessage { get; set; }
 | 
			
		||||
 | 
			
		||||
            public UserSpamStats(string msg)
 | 
			
		||||
            {
 | 
			
		||||
                Count = 1;
 | 
			
		||||
                LastMessage = msg.ToUpperInvariant();
 | 
			
		||||
            }
 | 
			
		||||
            private ConcurrentQueue<Timer> timers { get; }
 | 
			
		||||
 | 
			
		||||
            public UserSpamStats(IUserMessage msg)
 | 
			
		||||
            {
 | 
			
		||||
                LastMessage = msg.Content.ToUpperInvariant();
 | 
			
		||||
                timers = new ConcurrentQueue<Timer>();
 | 
			
		||||
 | 
			
		||||
                ApplyNextMessage(msg);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            private readonly object applyLock = new object();
 | 
			
		||||
            public void ApplyNextMessage(IUserMessage message)
 | 
			
		||||
            {
 | 
			
		||||
                var upperMsg = message.Content.ToUpperInvariant();
 | 
			
		||||
                if (upperMsg != LastMessage || (string.IsNullOrWhiteSpace(upperMsg) && message.Attachments.Any()))
 | 
			
		||||
                {
 | 
			
		||||
                    LastMessage = upperMsg;
 | 
			
		||||
                    Count = 0;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    Count++;
 | 
			
		||||
                lock(applyLock){
 | 
			
		||||
                    var upperMsg = message.Content.ToUpperInvariant();
 | 
			
		||||
                    if (upperMsg != LastMessage || (string.IsNullOrWhiteSpace(upperMsg) && message.Attachments.Any()))
 | 
			
		||||
                    {
 | 
			
		||||
                        LastMessage = upperMsg;
 | 
			
		||||
                        //todo c#7
 | 
			
		||||
                        Timer old;
 | 
			
		||||
                        while(timers.TryDequeue(out old))
 | 
			
		||||
                            old.Change(Timeout.Infinite, Timeout.Infinite);
 | 
			
		||||
                    }    
 | 
			
		||||
                    var t = new Timer((_) => {
 | 
			
		||||
                        //todo c#7
 | 
			
		||||
                        Timer __;
 | 
			
		||||
                        if(timers.TryDequeue(out __))
 | 
			
		||||
                            __.Change(Timeout.Infinite, Timeout.Infinite);
 | 
			
		||||
                    }, null, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(30));
 | 
			
		||||
                    timers.Enqueue(t);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public void Dispose()
 | 
			
		||||
            {
 | 
			
		||||
                //todo c#7
 | 
			
		||||
                Timer old;
 | 
			
		||||
                while(timers.TryDequeue(out old))
 | 
			
		||||
                    old.Change(Timeout.Infinite, Timeout.Infinite);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Group]
 | 
			
		||||
@@ -112,7 +135,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                                }))
 | 
			
		||||
                                return;
 | 
			
		||||
 | 
			
		||||
                            var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, new UserSpamStats(msg.Content),
 | 
			
		||||
                            var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, (id) => new UserSpamStats(msg),
 | 
			
		||||
                                (id, old) =>
 | 
			
		||||
                                {
 | 
			
		||||
                                    old.ApplyNextMessage(msg); return old;
 | 
			
		||||
@@ -122,6 +145,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                            {
 | 
			
		||||
                                if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
 | 
			
		||||
                                {
 | 
			
		||||
                                    stats.Dispose();
 | 
			
		||||
                                    await PunishUsers(spamSettings.AntiSpamSettings.Action, ProtectionType.Spamming, (IGuildUser)msg.Author)
 | 
			
		||||
                                        .ConfigureAwait(false);
 | 
			
		||||
                                }
 | 
			
		||||
@@ -317,6 +341,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                AntiSpamStats throwaway;
 | 
			
		||||
                if (_antiSpamGuilds.TryRemove(Context.Guild.Id, out throwaway))
 | 
			
		||||
                {
 | 
			
		||||
                    throwaway.UserStats.ForEach(x => x.Value.Dispose());
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    {
 | 
			
		||||
                        var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiSpamSetting)
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    var roleModels = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id).ToList();
 | 
			
		||||
                    roleCnt = roleModels.Count;
 | 
			
		||||
                    msg.AppendLine();
 | 
			
		||||
                    
 | 
			
		||||
                    foreach (var roleModel in roleModels)
 | 
			
		||||
@@ -116,11 +115,13 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                        var role = Context.Guild.Roles.FirstOrDefault(r => r.Id == roleModel.RoleId);
 | 
			
		||||
                        if (role == null)
 | 
			
		||||
                        {
 | 
			
		||||
                            toRemove.Add(roleModel);
 | 
			
		||||
                            uow.SelfAssignedRoles.Remove(roleModel);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            msg.Append($"**{role.Name}**, ");
 | 
			
		||||
                            roleCnt++;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    foreach (var role in toRemove)
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                            await guild.AddBanAsync(user).ConfigureAwait(false);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PunishmentAction.Softban:
 | 
			
		||||
                            await guild.AddBanAsync(user).ConfigureAwait(false);
 | 
			
		||||
                            await guild.AddBanAsync(user, 7).ConfigureAwait(false);
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                await guild.RemoveBanAsync(user).ConfigureAwait(false);
 | 
			
		||||
@@ -214,25 +214,15 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    var ps = uow.GuildConfigs.For(Context.Guild.Id).WarnPunishments;
 | 
			
		||||
                    var p = ps.FirstOrDefault(x => x.Count == number);
 | 
			
		||||
                    var ps = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.WarnPunishments)).WarnPunishments;
 | 
			
		||||
                    ps.RemoveAll(x => x.Count == number);
 | 
			
		||||
 | 
			
		||||
                    if (p == null)
 | 
			
		||||
                    ps.Add(new WarningPunishment()
 | 
			
		||||
                    {
 | 
			
		||||
                        ps.Add(new WarningPunishment()
 | 
			
		||||
                        {
 | 
			
		||||
                            Count = number,
 | 
			
		||||
                            Punishment = punish,
 | 
			
		||||
                            Time = time,
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        p.Count = number;
 | 
			
		||||
                        p.Punishment = punish;
 | 
			
		||||
                        p.Time = time;
 | 
			
		||||
                        uow._context.Update(p);
 | 
			
		||||
                    }
 | 
			
		||||
                        Count = number,
 | 
			
		||||
                        Punishment = punish,
 | 
			
		||||
                        Time = time,
 | 
			
		||||
                    });
 | 
			
		||||
                    uow.Complete();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -173,6 +173,8 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                    amount + CurrencySign);
 | 
			
		||||
                if (w.Affinity?.UserId == Context.User.Id)
 | 
			
		||||
                    msg += "\n" + GetText("waifu_fulfilled", target, w.Price + CurrencySign);
 | 
			
		||||
                else
 | 
			
		||||
                    msg = " " + msg;
 | 
			
		||||
                await Context.Channel.SendConfirmAsync(Context.User.Mention + msg).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -188,9 +190,15 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            private static readonly TimeSpan _divorceLimit = TimeSpan.FromHours(6);
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Divorce([Remainder]IGuildUser target)
 | 
			
		||||
            [Priority(1)]
 | 
			
		||||
            public Task Divorce([Remainder]IGuildUser target) => Divorce(target.Id);
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [Priority(0)]
 | 
			
		||||
            public async Task Divorce([Remainder]ulong targetId)
 | 
			
		||||
            {
 | 
			
		||||
                if (target.Id == Context.User.Id)
 | 
			
		||||
                if (targetId == Context.User.Id)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                DivorceResult result;
 | 
			
		||||
@@ -199,7 +207,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                WaifuInfo w = null;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    w = uow.Waifus.ByWaifuUserId(target.Id);
 | 
			
		||||
                    w = uow.Waifus.ByWaifuUserId(targetId);
 | 
			
		||||
                    var now = DateTime.UtcNow;
 | 
			
		||||
                    if (w?.Claimer == null || w.Claimer.UserId != Context.User.Id)
 | 
			
		||||
                        result = DivorceResult.NotYourWife;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Games.Hangman
 | 
			
		||||
{
 | 
			
		||||
    public class HangmanTermPool
 | 
			
		||||
    {
 | 
			
		||||
        const string termsPath = "data/hangman2.json";
 | 
			
		||||
        const string termsPath = "data/hangman3.json";
 | 
			
		||||
        public static IReadOnlyDictionary<string, HangmanObject[]> data { get; }
 | 
			
		||||
        static HangmanTermPool()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -82,9 +82,9 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
                                var prefix = NadekoBot.ModulePrefixes[typeof(Games).Name];
 | 
			
		||||
                                var toSend = dropAmount == 1 
 | 
			
		||||
                                    ? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign) 
 | 
			
		||||
                                        + GetLocalText(channel, "pick_sn", prefix)
 | 
			
		||||
                                        + " " + GetLocalText(channel, "pick_sn", prefix)
 | 
			
		||||
                                    : GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign)
 | 
			
		||||
                                        + GetLocalText(channel, "pick_pl", prefix);
 | 
			
		||||
                                        + " " + GetLocalText(channel, "pick_pl", prefix);
 | 
			
		||||
                                var file = GetRandomCurrencyImage();
 | 
			
		||||
                                using (var fileStream = file.Value.ToStream())
 | 
			
		||||
                                {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,11 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
    {
 | 
			
		||||
        public SongInfo SongInfo { get; }
 | 
			
		||||
        public MusicPlayer MusicPlayer { get; set; }
 | 
			
		||||
        public string QueuerName { get; set; }
 | 
			
		||||
 | 
			
		||||
        private string _queuerName;
 | 
			
		||||
        public string QueuerName { get{
 | 
			
		||||
            return Discord.Format.Sanitize(_queuerName);
 | 
			
		||||
        } set { _queuerName = value; } }
 | 
			
		||||
 | 
			
		||||
        public TimeSpan TotalTime { get; set; } = TimeSpan.Zero;
 | 
			
		||||
        public TimeSpan CurrentTime => TimeSpan.FromSeconds(BytesSent / (float)_frameBytes / (1000 / (float)_milliseconds));
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,9 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
 | 
			
		||||
            private async Task Blacklist(AddRemove action, ulong id, BlacklistType type)
 | 
			
		||||
            {
 | 
			
		||||
                if(action == AddRemove.Add && NadekoBot.Credentials.OwnerIds.Contains(id))
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    if (action == AddRemove.Add)
 | 
			
		||||
 
 | 
			
		||||
@@ -190,7 +190,7 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
                {
 | 
			
		||||
                    var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FilteredWords));
 | 
			
		||||
 | 
			
		||||
                    removed = config.FilteredWords.RemoveWhere(fw => fw.Word == word);
 | 
			
		||||
                    removed = config.FilteredWords.RemoveWhere(fw => fw.Word.Trim().ToLowerInvariant() == word);
 | 
			
		||||
 | 
			
		||||
                    if (removed == 0)
 | 
			
		||||
                        config.FilteredWords.Add(new Services.Database.Models.FilteredWord() { Word = word });
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await Context.Channel.EmbedAsync(new EmbedBuilder()
 | 
			
		||||
                .WithTitle(GetText("activity_page", page))
 | 
			
		||||
                .WithTitle(GetText("activity_page", page + 1))
 | 
			
		||||
                .WithOkColor()
 | 
			
		||||
                .WithFooter(efb => efb.WithText(GetText("activity_users_total",
 | 
			
		||||
                    NadekoBot.CommandHandler.UserMessagesSent.Count)))
 | 
			
		||||
 
 | 
			
		||||
@@ -123,8 +123,19 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequireUserPermission(GuildPermission.ManageMessages)]
 | 
			
		||||
            [Priority(0)]
 | 
			
		||||
            public Task Remind(ITextChannel channel, string timeStr, [Remainder] string message) =>
 | 
			
		||||
                RemindInternal(channel.Id, false, timeStr, message);
 | 
			
		||||
            public async Task Remind(ITextChannel channel, string timeStr, [Remainder] string message)
 | 
			
		||||
            {
 | 
			
		||||
                var perms = ((IGuildUser)Context.User).GetPermissions((ITextChannel)channel);
 | 
			
		||||
                if (!perms.SendMessages || !perms.ReadMessages)
 | 
			
		||||
                {
 | 
			
		||||
                    await ReplyErrorLocalized("cant_read_or_send").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    var _ = RemindInternal(channel.Id, false, timeStr, message).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public async Task RemindInternal(ulong targetId, bool isPrivate, string timeStr, [Remainder] string message)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -503,7 +503,6 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false), title, title).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Ping()
 | 
			
		||||
        {
 | 
			
		||||
            var sw = Stopwatch.StartNew();
 | 
			
		||||
 
 | 
			
		||||
@@ -418,7 +418,7 @@
 | 
			
		||||
    <value>iamnot iamn</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="iamnot_desc" xml:space="preserve">
 | 
			
		||||
    <value>Removes a role to you that you choose. Role must be on a list of self-assignable roles.</value>
 | 
			
		||||
    <value>Removes a specified role from you. Role must be on a list of self-assignable roles.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="iamnot_usage" xml:space="preserve">
 | 
			
		||||
    <value>`{0}iamn Gamer`</value>
 | 
			
		||||
@@ -2038,7 +2038,7 @@
 | 
			
		||||
    <value>chucknorris cn</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="chucknorris_desc" xml:space="preserve">
 | 
			
		||||
    <value>Shows a random Chuck Norris joke from <http://tambal.azurewebsites.net/joke/random></value>
 | 
			
		||||
    <value>Shows a random Chuck Norris joke from <http://api.icndb.com/jokes/random/></value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="chucknorris_usage" xml:space="preserve">
 | 
			
		||||
    <value>`{0}cn`</value>
 | 
			
		||||
@@ -3388,7 +3388,7 @@
 | 
			
		||||
    <value>shoprem shoprm</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="shopremove_desc" xml:space="preserve">
 | 
			
		||||
    <value>Removes an item from the shop by its color.</value>
 | 
			
		||||
    <value>Removes an item from the shop by its ID.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="shop_cmd" xml:space="preserve">
 | 
			
		||||
    <value>shop</value>
 | 
			
		||||
@@ -3406,7 +3406,7 @@
 | 
			
		||||
    <value>Toggles whether this role is displayed in the sidebar or not.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="rolehoist_usage" xml:space="preserve">
 | 
			
		||||
    <value>`{0}rh Guests` or `{0}rh "Space Wizards"</value>
 | 
			
		||||
    <value>`{0}rh Guests` or `{0}rh "Space Wizards"`</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="buy_cmd" xml:space="preserve">
 | 
			
		||||
    <value>buy</value>
 | 
			
		||||
@@ -3442,19 +3442,19 @@
 | 
			
		||||
    <value>globalcommand gcmd</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="gcmd_desc" xml:space="preserve">
 | 
			
		||||
    <value>Enables or disables a command from use on all servers.</value>
 | 
			
		||||
    <value>Toggles whether a command can be used on any server.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="gcmd_usage" xml:space="preserve">
 | 
			
		||||
    <value>`{0}gcmd  `</value>
 | 
			
		||||
    <value>`{0}gcmd .stats`</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="gmod_cmd" xml:space="preserve">
 | 
			
		||||
    <value>globalmodule gmod</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="gmod_desc" xml:space="preserve">
 | 
			
		||||
    <value>Enable or disable a module from use on all servers.</value>
 | 
			
		||||
    <value>Toggles whether a module can be used on any server.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="gmod_usage" xml:space="preserve">
 | 
			
		||||
    <value>`{0}gmod nsfw disable`</value>
 | 
			
		||||
    <value>`{0}gmod nsfw`</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="lgp_cmd" xml:space="preserve">
 | 
			
		||||
    <value>listglobalperms lgp</value>
 | 
			
		||||
 
 | 
			
		||||
@@ -772,7 +772,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Antigua and Barbuda",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/antigua-and-barbuda.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/antigua_and_barbuda.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Argentina",
 | 
			
		||||
@@ -836,7 +836,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Bosnia and Herzegovina",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/bosnia-and-herzegovina.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/bosnia_and_herzegovina.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Botswana",
 | 
			
		||||
@@ -856,7 +856,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Burkina Faso",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/burkina-faso.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/burkina_faso.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Burma",
 | 
			
		||||
@@ -880,11 +880,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Cape Verde",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/cape-verde.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/cape_verde.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Central African Republic",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/central-african-republic.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/central_african_republic.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Chad",
 | 
			
		||||
@@ -912,7 +912,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Costa Rica",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/costa-rica.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/costa_rica.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Croatia",
 | 
			
		||||
@@ -928,7 +928,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Czech Republic",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/czech-republic.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/czech_republic.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Denmark",
 | 
			
		||||
@@ -944,11 +944,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Dominican Republic",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/dominican-republic.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/dominican_republic.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "East Timor",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/east-timor.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/east_timor.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Ecuador",
 | 
			
		||||
@@ -960,7 +960,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "El Salvador",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/el-salvador.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/el_salvador.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "England",
 | 
			
		||||
@@ -968,7 +968,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Equatorial Guinea",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/equatorial-guinea.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/equatorial_guinea.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Eritrea",
 | 
			
		||||
@@ -1032,7 +1032,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Guinea-Bissau",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/guinea-bissau.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/guinea_bissau.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Guyana",
 | 
			
		||||
@@ -1048,7 +1048,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Hong Kong",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/hong-kong.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/hong_kong.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Hungary",
 | 
			
		||||
@@ -1080,7 +1080,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Isle of Man",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/isle-of-man.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/isle_of_man.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Israel",
 | 
			
		||||
@@ -1116,11 +1116,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "North Korea",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/korea-north.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/korea_north.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "South Korea",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/korea-south.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/korea_south.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Kosovo",
 | 
			
		||||
@@ -1204,7 +1204,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Marshall Islands",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/marshall-islands.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/marshall_islands.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Mauritania",
 | 
			
		||||
@@ -1264,7 +1264,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "New Zealand",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/new-zealand.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/new_zealand.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Nicaragua",
 | 
			
		||||
@@ -1300,7 +1300,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Papua New Guinea",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/papua-new-guinea.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/papua_new_guinea.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Paraguay",
 | 
			
		||||
@@ -1324,7 +1324,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Puerto Rico",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/puerto-rico.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/puerto_rico.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Qatar",
 | 
			
		||||
@@ -1344,15 +1344,15 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Saint Kitts and Nevis",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saint-kitts-and-nevis.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saint_kitts_and_nevis.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Saint Lucia",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saint-lucia.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saint_lucia.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Saint Vincent and the Grenadines",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saint-vincent-and-the-grenadines.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saint_vincent_and_the_grenadines.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Samoa",
 | 
			
		||||
@@ -1360,11 +1360,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "San Marino",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/san-marino.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/san_marino.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Saudi Arabia",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saudi-arabia.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/saudi_arabia.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Scotland",
 | 
			
		||||
@@ -1384,7 +1384,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Sierra Leone",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/sierra-leone.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/sierra_leone.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Singapore",
 | 
			
		||||
@@ -1400,7 +1400,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Solomon Islands",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/solomon-islands.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/solomon_islands.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Somalia",
 | 
			
		||||
@@ -1408,7 +1408,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "South Africa",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/south-africa.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/south_africa.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Spain",
 | 
			
		||||
@@ -1416,7 +1416,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Sri Lanka",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/sri-lanka.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/sri_lanka.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Sudan",
 | 
			
		||||
@@ -1468,7 +1468,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Trinidad and Tobago",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/trinidad-and-tobago.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/trinidad_and_tobago.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Tunisia",
 | 
			
		||||
@@ -1496,15 +1496,15 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "United Arab Emirates",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/united-arab-emirates.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/united_arab_emirates.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "United Kingdom",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/united-kingdom.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/united_kingdom.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "United States of America",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/united-states-of-america.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/united_states_of_america.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Uruguay",
 | 
			
		||||
@@ -1524,7 +1524,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Vatican City",
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/vatican-city.gif"
 | 
			
		||||
      "ImageUrl": "https://www.randomlists.com/img/national-flags/vatican_city.gif"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Word": "Venezuela",
 | 
			
		||||
		Reference in New Issue
	
	Block a user