Some cleanup
This commit is contained in:
		@@ -24,7 +24,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void DelMsgOnCmd_Handler(object sender, CommandExecutedEventArgs e)
 | 
			
		||||
        private async void DelMsgOnCmd_Handler(object sender, CommandExecutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (shouldDelete)
 | 
			
		||||
                    e.Message.DeleteAsync();
 | 
			
		||||
                    await e.Message.DeleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,22 +19,26 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            public AutoAssignRoleCommands()
 | 
			
		||||
            {
 | 
			
		||||
                var _client = NadekoBot.Client;
 | 
			
		||||
                _client.UserJoined += async (user) =>
 | 
			
		||||
                _client.UserJoined += (user) =>
 | 
			
		||||
                {
 | 
			
		||||
                    GuildConfig conf;
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    var t = Task.Run(async () =>
 | 
			
		||||
                    {
 | 
			
		||||
                        conf = uow.GuildConfigs.For(user.Guild.Id);
 | 
			
		||||
                    }
 | 
			
		||||
                    var aarType = conf.AutoAssignRoleId.GetType();
 | 
			
		||||
                        GuildConfig conf;
 | 
			
		||||
                        using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                        {
 | 
			
		||||
                            conf = uow.GuildConfigs.For(user.Guild.Id);
 | 
			
		||||
                        }
 | 
			
		||||
                        var aarType = conf.AutoAssignRoleId.GetType();
 | 
			
		||||
 | 
			
		||||
                    if (conf.AutoAssignRoleId == 0)
 | 
			
		||||
                        return;
 | 
			
		||||
                        if (conf.AutoAssignRoleId == 0)
 | 
			
		||||
                            return;
 | 
			
		||||
 | 
			
		||||
                    var role = user.Guild.Roles.FirstOrDefault(r => r.Id == conf.AutoAssignRoleId);
 | 
			
		||||
                        var role = user.Guild.Roles.FirstOrDefault(r => r.Id == conf.AutoAssignRoleId);
 | 
			
		||||
 | 
			
		||||
                    if (role != null)
 | 
			
		||||
                        await user.AddRolesAsync(role);
 | 
			
		||||
                        if (role != null)
 | 
			
		||||
                            await user.AddRolesAsync(role);
 | 
			
		||||
                    });
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                        }
 | 
			
		||||
                        catch { }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,13 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                _client.MessageReceived += _client_MessageReceived;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_MessageReceived(IMessage arg)
 | 
			
		||||
            private Task _client_MessageReceived(IMessage imsg)
 | 
			
		||||
            {
 | 
			
		||||
                throw new NotImplementedException();
 | 
			
		||||
                var msg = imsg as IUserMessage;
 | 
			
		||||
                if (msg == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
 | 
			
		||||
            private Task UserUpdatedEventHandler(IGuildUser before, IGuildUser after)
 | 
			
		||||
            {
 | 
			
		||||
                Task.Run(async () =>
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    var guild = before.Guild ?? after.Guild;
 | 
			
		||||
                    var botUserPerms = guild.GetCurrentUser().GuildPermissions;
 | 
			
		||||
 
 | 
			
		||||
@@ -143,7 +143,6 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                            //update the state
 | 
			
		||||
                            participants.ForEach(p =>
 | 
			
		||||
                            {
 | 
			
		||||
 | 
			
		||||
                                p.Total += 1 + rng.Next(0, 10);
 | 
			
		||||
                                if (p.Total > 60)
 | 
			
		||||
                                {
 | 
			
		||||
 
 | 
			
		||||
@@ -107,26 +107,36 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task Vote(IMessage imsg)
 | 
			
		||||
        private Task Vote(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var msg = imsg as ISystemMessage;
 | 
			
		||||
            // has to be a user message
 | 
			
		||||
            var msg = imsg as IUserMessage;
 | 
			
		||||
            if (msg == null)
 | 
			
		||||
                return;
 | 
			
		||||
            try
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            // channel must be private
 | 
			
		||||
            IPrivateChannel ch;
 | 
			
		||||
            if ((ch = msg.Channel as IPrivateChannel) == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
            // has to be an integer
 | 
			
		||||
            int vote;
 | 
			
		||||
            if (!int.TryParse(msg.Content, out vote)) return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
            var t = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                IPrivateChannel ch;
 | 
			
		||||
                if ((ch = msg.Channel as IPrivateChannel) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
                int vote;
 | 
			
		||||
                if (!int.TryParse(msg.Content, out vote)) return;
 | 
			
		||||
                if (vote < 1 || vote > answers.Length)
 | 
			
		||||
                    return;
 | 
			
		||||
                if (participants.TryAdd(msg.Author, vote))
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await (ch as ITextChannel).SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
 | 
			
		||||
                    
 | 
			
		||||
                    if (vote < 1 || vote > answers.Length)
 | 
			
		||||
                        return;
 | 
			
		||||
                    if (participants.TryAdd(msg.Author, vote))
 | 
			
		||||
                    {
 | 
			
		||||
                        await (ch as ITextChannel).SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
                catch { }
 | 
			
		||||
            });
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -92,30 +92,34 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
            NadekoBot.Client.MessageReceived += AnswerReceived;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task AnswerReceived(IMessage imsg)
 | 
			
		||||
        private Task AnswerReceived(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var msg = imsg as IUserMessage;
 | 
			
		||||
            if (msg == null)
 | 
			
		||||
                return;
 | 
			
		||||
            try
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            var t = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                if (channel== null || channel.Id != channel.Id || msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
 | 
			
		||||
 | 
			
		||||
                var guess = msg.Content;
 | 
			
		||||
 | 
			
		||||
                var distance = CurrentSentence.LevenshteinDistance(guess);
 | 
			
		||||
                var decision = Judge(distance, guess.Length);
 | 
			
		||||
                if (decision && !finishedUserIds.Contains(msg.Author.Id))
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    finishedUserIds.Add(msg.Author.Id);
 | 
			
		||||
                    await channel.SendMessageAsync($"{msg.Author.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!").ConfigureAwait(false);
 | 
			
		||||
                    if (finishedUserIds.Count % 2 == 0)
 | 
			
		||||
                    if (channel == null || channel.Id != channel.Id || msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
 | 
			
		||||
 | 
			
		||||
                    var guess = msg.Content;
 | 
			
		||||
 | 
			
		||||
                    var distance = CurrentSentence.LevenshteinDistance(guess);
 | 
			
		||||
                    var decision = Judge(distance, guess.Length);
 | 
			
		||||
                    if (decision && !finishedUserIds.Contains(msg.Author.Id))
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{CurrentSentence}**:book:").ConfigureAwait(false);
 | 
			
		||||
                        finishedUserIds.Add(msg.Author.Id);
 | 
			
		||||
                        await channel.SendMessageAsync($"{msg.Author.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!").ConfigureAwait(false);
 | 
			
		||||
                        if (finishedUserIds.Count % 2 == 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{CurrentSentence}**:book:").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
                catch { }
 | 
			
		||||
            });
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool Judge(int errors, int textLength) => errors <= textLength / 25;
 | 
			
		||||
 
 | 
			
		||||
@@ -105,34 +105,36 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
            var umsg = imsg as IUserMessage;
 | 
			
		||||
            if (umsg == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            var t = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                if (!(umsg.Channel is IGuildChannel && umsg.Channel is ITextChannel)) return;
 | 
			
		||||
                if ((umsg.Channel as ITextChannel).Guild != guild) return;
 | 
			
		||||
                if (umsg.Author.Id == (await NadekoBot.Client.GetCurrentUserAsync()).Id) return;
 | 
			
		||||
 | 
			
		||||
                var guildUser = umsg.Author as IGuildUser;
 | 
			
		||||
 | 
			
		||||
                var guess = false;
 | 
			
		||||
                await _guessLock.WaitAsync().ConfigureAwait(false);
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if (GameActive && CurrentQuestion.IsAnswerCorrect(umsg.Content) && !triviaCancelSource.IsCancellationRequested)
 | 
			
		||||
                    if (!(umsg.Channel is IGuildChannel && umsg.Channel is ITextChannel)) return;
 | 
			
		||||
                    if ((umsg.Channel as ITextChannel).Guild != guild) return;
 | 
			
		||||
                    if (umsg.Author.Id == (await NadekoBot.Client.GetCurrentUserAsync()).Id) return;
 | 
			
		||||
 | 
			
		||||
                    var guildUser = umsg.Author as IGuildUser;
 | 
			
		||||
 | 
			
		||||
                    var guess = false;
 | 
			
		||||
                    await _guessLock.WaitAsync().ConfigureAwait(false);
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        Users.AddOrUpdate(guildUser, 0, (gu, old) => old++);
 | 
			
		||||
                        guess = true;
 | 
			
		||||
                        if (GameActive && CurrentQuestion.IsAnswerCorrect(umsg.Content) && !triviaCancelSource.IsCancellationRequested)
 | 
			
		||||
                        {
 | 
			
		||||
                            Users.AddOrUpdate(guildUser, 0, (gu, old) => old++);
 | 
			
		||||
                            guess = true;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    finally { _guessLock.Release(); }
 | 
			
		||||
                    if (!guess) return;
 | 
			
		||||
                    triviaCancelSource.Cancel();
 | 
			
		||||
                    await channel.SendMessageAsync($"☑️ {guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
 | 
			
		||||
                    if (Users[guildUser] != WinRequirement) return;
 | 
			
		||||
                    ShouldStopGame = true;
 | 
			
		||||
                    await channel.SendMessageAsync($":exclamation: We have a winner! It's {guildUser.Mention}.").ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                finally { _guessLock.Release(); }
 | 
			
		||||
                if (!guess) return;
 | 
			
		||||
                triviaCancelSource.Cancel();
 | 
			
		||||
                await channel.SendMessageAsync($"☑️ {guildUser.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
 | 
			
		||||
                if (Users[guildUser] != WinRequirement) return;
 | 
			
		||||
                ShouldStopGame = true;
 | 
			
		||||
                await channel.SendMessageAsync($":exclamation: We have a winner! It's {guildUser.Mention}.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
                catch { }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string GetLeaderboard()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,204 +0,0 @@
 | 
			
		||||
//--------------------------------------------------------------------------
 | 
			
		||||
// 
 | 
			
		||||
//  Copyright (c) Microsoft Corporation.  All rights reserved. 
 | 
			
		||||
// 
 | 
			
		||||
//  File: ObservableConcurrentDictionary.cs
 | 
			
		||||
//
 | 
			
		||||
//--------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.Specialized;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
 | 
			
		||||
namespace System.Collections.Concurrent
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Provides a thread-safe dictionary for use with data binding.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <typeparam name="TKey">Specifies the type of the keys in this collection.</typeparam>
 | 
			
		||||
    /// <typeparam name="TValue">Specifies the type of the values in this collection.</typeparam>
 | 
			
		||||
    [DebuggerDisplay("Count={Count}")]
 | 
			
		||||
    public class ObservableConcurrentDictionary<TKey, TValue> :
 | 
			
		||||
        ICollection<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>,
 | 
			
		||||
        INotifyCollectionChanged, INotifyPropertyChanged
 | 
			
		||||
    {
 | 
			
		||||
        private readonly SynchronizationContext _context;
 | 
			
		||||
        private readonly ConcurrentDictionary<TKey, TValue> _dictionary;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes an instance of the ObservableConcurrentDictionary class.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ObservableConcurrentDictionary()
 | 
			
		||||
        {
 | 
			
		||||
            _context = AsyncOperationManager.SynchronizationContext;
 | 
			
		||||
            _dictionary = new ConcurrentDictionary<TKey, TValue>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>Event raised when the collection changes.</summary>
 | 
			
		||||
        public event NotifyCollectionChangedEventHandler CollectionChanged;
 | 
			
		||||
        /// <summary>Event raised when a property on the collection changes.</summary>
 | 
			
		||||
        public event PropertyChangedEventHandler PropertyChanged;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Notifies observers of CollectionChanged or PropertyChanged of an update to the dictionary.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void NotifyObserversOfChange()
 | 
			
		||||
        {
 | 
			
		||||
            var collectionHandler = CollectionChanged;
 | 
			
		||||
            var propertyHandler = PropertyChanged;
 | 
			
		||||
            if (collectionHandler != null || propertyHandler != null)
 | 
			
		||||
            {
 | 
			
		||||
                _context.Post(s =>
 | 
			
		||||
                {
 | 
			
		||||
                    if (collectionHandler != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        collectionHandler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
 | 
			
		||||
                    }
 | 
			
		||||
                    if (propertyHandler != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        propertyHandler(this, new PropertyChangedEventArgs("Count"));
 | 
			
		||||
                        propertyHandler(this, new PropertyChangedEventArgs("Keys"));
 | 
			
		||||
                        propertyHandler(this, new PropertyChangedEventArgs("Values"));
 | 
			
		||||
                    }
 | 
			
		||||
                }, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
 | 
			
		||||
        /// <param name="item">The item to be added.</param>
 | 
			
		||||
        /// <returns>Whether the add was successful.</returns>
 | 
			
		||||
        private bool TryAddWithNotification(KeyValuePair<TKey, TValue> item)
 | 
			
		||||
        {
 | 
			
		||||
            return TryAddWithNotification(item.Key, item.Value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
 | 
			
		||||
        /// <param name="key">The key of the item to be added.</param>
 | 
			
		||||
        /// <param name="value">The value of the item to be added.</param>
 | 
			
		||||
        /// <returns>Whether the add was successful.</returns>
 | 
			
		||||
        private bool TryAddWithNotification(TKey key, TValue value)
 | 
			
		||||
        {
 | 
			
		||||
            bool result = _dictionary.TryAdd(key, value);
 | 
			
		||||
            if (result) NotifyObserversOfChange();
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>Attempts to remove an item from the dictionary, notifying observers of any changes.</summary>
 | 
			
		||||
        /// <param name="key">The key of the item to be removed.</param>
 | 
			
		||||
        /// <param name="value">The value of the item removed.</param>
 | 
			
		||||
        /// <returns>Whether the removal was successful.</returns>
 | 
			
		||||
        private bool TryRemoveWithNotification(TKey key, out TValue value)
 | 
			
		||||
        {
 | 
			
		||||
            bool result = _dictionary.TryRemove(key, out value);
 | 
			
		||||
            if (result) NotifyObserversOfChange();
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>Attempts to add or update an item in the dictionary, notifying observers of any changes.</summary>
 | 
			
		||||
        /// <param name="key">The key of the item to be updated.</param>
 | 
			
		||||
        /// <param name="value">The new value to set for the item.</param>
 | 
			
		||||
        /// <returns>Whether the update was successful.</returns>
 | 
			
		||||
        private void UpdateWithNotification(TKey key, TValue value)
 | 
			
		||||
        {
 | 
			
		||||
            _dictionary[key] = value;
 | 
			
		||||
            NotifyObserversOfChange();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region ICollection<KeyValuePair<TKey,TValue>> Members
 | 
			
		||||
        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
 | 
			
		||||
        {
 | 
			
		||||
            TryAddWithNotification(item);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void ICollection<KeyValuePair<TKey, TValue>>.Clear()
 | 
			
		||||
        {
 | 
			
		||||
            ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Clear();
 | 
			
		||||
            NotifyObserversOfChange();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
 | 
			
		||||
        {
 | 
			
		||||
            return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Contains(item);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
 | 
			
		||||
        {
 | 
			
		||||
            ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).CopyTo(array, arrayIndex);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int ICollection<KeyValuePair<TKey, TValue>>.Count {
 | 
			
		||||
            get { return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Count; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
 | 
			
		||||
            get { return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).IsReadOnly; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
 | 
			
		||||
        {
 | 
			
		||||
            TValue temp;
 | 
			
		||||
            return TryRemoveWithNotification(item.Key, out temp);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IEnumerable<KeyValuePair<TKey,TValue>> Members
 | 
			
		||||
        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IEnumerator IEnumerable.GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IDictionary<TKey,TValue> Members
 | 
			
		||||
        public void Add(TKey key, TValue value)
 | 
			
		||||
        {
 | 
			
		||||
            TryAddWithNotification(key, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool ContainsKey(TKey key)
 | 
			
		||||
        {
 | 
			
		||||
            return _dictionary.ContainsKey(key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ICollection<TKey> Keys {
 | 
			
		||||
            get { return _dictionary.Keys; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Remove(TKey key)
 | 
			
		||||
        {
 | 
			
		||||
            TValue temp;
 | 
			
		||||
            return TryRemoveWithNotification(key, out temp);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool TryGetValue(TKey key, out TValue value)
 | 
			
		||||
        {
 | 
			
		||||
            return _dictionary.TryGetValue(key, out value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool TryAdd(TKey key, TValue value)
 | 
			
		||||
        {
 | 
			
		||||
            return TryAddWithNotification(key, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ICollection<TValue> Values {
 | 
			
		||||
            get { return _dictionary.Values; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public TValue this[TKey key] {
 | 
			
		||||
            get { return _dictionary[key]; }
 | 
			
		||||
            set { UpdateWithNotification(key, value); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool TryRemove(TKey key, out TValue value)
 | 
			
		||||
        {
 | 
			
		||||
            return TryRemoveWithNotification(key, out value);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,287 +0,0 @@
 | 
			
		||||
using NadekoBot.Classes.JSONModels;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Security.Authentication;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Xml.Linq;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes
 | 
			
		||||
{
 | 
			
		||||
    public enum RequestHttpMethod
 | 
			
		||||
    {
 | 
			
		||||
        Get,
 | 
			
		||||
        Post
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class SearchHelper
 | 
			
		||||
    {
 | 
			
		||||
        private static DateTime lastRefreshed = DateTime.MinValue;
 | 
			
		||||
        private static string token { get; set; } = "";
 | 
			
		||||
 | 
			
		||||
        public static async Task<Stream> GetResponseStreamAsync(string url,
 | 
			
		||||
            IEnumerable<KeyValuePair<string, string>> headers = null, RequestHttpMethod method = RequestHttpMethod.Get)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(url))
 | 
			
		||||
                throw new ArgumentNullException(nameof(url));
 | 
			
		||||
            var cl = new HttpClient();
 | 
			
		||||
            cl.DefaultRequestHeaders.Clear();
 | 
			
		||||
            switch (method)
 | 
			
		||||
            {
 | 
			
		||||
                case RequestHttpMethod.Get:
 | 
			
		||||
                    if (headers != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        foreach (var header in headers)
 | 
			
		||||
                        {
 | 
			
		||||
                            cl.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    return await cl.GetStreamAsync(url).ConfigureAwait(false);
 | 
			
		||||
                case RequestHttpMethod.Post:
 | 
			
		||||
                    FormUrlEncodedContent formContent = null;
 | 
			
		||||
                    if (headers != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        formContent = new FormUrlEncodedContent(headers);
 | 
			
		||||
                    }
 | 
			
		||||
                    var message = await cl.PostAsync(url, formContent).ConfigureAwait(false);
 | 
			
		||||
                    return await message.Content.ReadAsStreamAsync().ConfigureAwait(false);
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new NotImplementedException("That type of request is unsupported.");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<string> GetResponseStringAsync(string url,
 | 
			
		||||
            IEnumerable<KeyValuePair<string, string>> headers = null,
 | 
			
		||||
            RequestHttpMethod method = RequestHttpMethod.Get)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            using (var streamReader = new StreamReader(await GetResponseStreamAsync(url, headers, method).ConfigureAwait(false)))
 | 
			
		||||
            {
 | 
			
		||||
                return await streamReader.ReadToEndAsync().ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<AnimeResult> GetAnimeData(string query)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
                throw new ArgumentNullException(nameof(query));
 | 
			
		||||
 | 
			
		||||
            await RefreshAnilistToken().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
 | 
			
		||||
            var smallContent = "";
 | 
			
		||||
            var cl = new RestSharp.RestClient("http://anilist.co/api");
 | 
			
		||||
            var rq = new RestSharp.RestRequest("/anime/search/" + Uri.EscapeUriString(query));
 | 
			
		||||
            rq.AddParameter("access_token", token);
 | 
			
		||||
            smallContent = cl.Execute(rq).Content;
 | 
			
		||||
            var smallObj = JArray.Parse(smallContent)[0];
 | 
			
		||||
 | 
			
		||||
            rq = new RestSharp.RestRequest("/anime/" + smallObj["id"]);
 | 
			
		||||
            rq.AddParameter("access_token", token);
 | 
			
		||||
            var content = cl.Execute(rq).Content;
 | 
			
		||||
 | 
			
		||||
            return await Task.Run(() => JsonConvert.DeserializeObject<AnimeResult>(content)).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<MangaResult> GetMangaData(string query)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
                throw new ArgumentNullException(nameof(query));
 | 
			
		||||
 | 
			
		||||
            await RefreshAnilistToken().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
 | 
			
		||||
            var smallContent = "";
 | 
			
		||||
            var cl = new RestSharp.RestClient("http://anilist.co/api");
 | 
			
		||||
            var rq = new RestSharp.RestRequest("/manga/search/" + Uri.EscapeUriString(query));
 | 
			
		||||
            rq.AddParameter("access_token", token);
 | 
			
		||||
            smallContent = cl.Execute(rq).Content;
 | 
			
		||||
            var smallObj = JArray.Parse(smallContent)[0];
 | 
			
		||||
 | 
			
		||||
            rq = new RestSharp.RestRequest("/manga/" + smallObj["id"]);
 | 
			
		||||
            rq.AddParameter("access_token", token);
 | 
			
		||||
            var content = cl.Execute(rq).Content;
 | 
			
		||||
 | 
			
		||||
            return await Task.Run(() => JsonConvert.DeserializeObject<MangaResult>(content)).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static async Task RefreshAnilistToken()
 | 
			
		||||
        {
 | 
			
		||||
            if (DateTime.Now - lastRefreshed > TimeSpan.FromMinutes(29))
 | 
			
		||||
                lastRefreshed = DateTime.Now;
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var headers = new Dictionary<string, string> {
 | 
			
		||||
                {"grant_type", "client_credentials"},
 | 
			
		||||
                {"client_id", "kwoth-w0ki9"},
 | 
			
		||||
                {"client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z"},
 | 
			
		||||
            };
 | 
			
		||||
            var content = await GetResponseStringAsync(
 | 
			
		||||
                            "http://anilist.co/api/auth/access_token",
 | 
			
		||||
                            headers,
 | 
			
		||||
                            RequestHttpMethod.Post).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            token = JObject.Parse(content)["access_token"].ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<string> FindYoutubeUrlByKeywords(string keywords)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(keywords))
 | 
			
		||||
                throw new ArgumentNullException(nameof(keywords), "Query not specified.");
 | 
			
		||||
            if (keywords.Length > 150)
 | 
			
		||||
                throw new ArgumentException("Query is too long.");
 | 
			
		||||
 | 
			
		||||
            //maybe it is already a youtube url, in which case we will just extract the id and prepend it with youtube.com?v=
 | 
			
		||||
            var match = new Regex("(?:youtu\\.be\\/|v=)(?<id>[\\da-zA-Z\\-_]*)").Match(keywords);
 | 
			
		||||
            if (match.Length > 1)
 | 
			
		||||
            {
 | 
			
		||||
                return $"https://www.youtube.com/watch?v={match.Groups["id"].Value}";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey))
 | 
			
		||||
                throw new InvalidCredentialException("Google API Key is missing.");
 | 
			
		||||
 | 
			
		||||
            var response = await GetResponseStringAsync(
 | 
			
		||||
                                    $"https://www.googleapis.com/youtube/v3/search?" +
 | 
			
		||||
                                    $"part=snippet&maxResults=1" +
 | 
			
		||||
                                    $"&q={Uri.EscapeDataString(keywords)}" +
 | 
			
		||||
                                    $"&key={NadekoBot.Credentials.GoogleAPIKey}").ConfigureAwait(false);
 | 
			
		||||
            JObject obj = JObject.Parse(response);
 | 
			
		||||
 | 
			
		||||
            var data = JsonConvert.DeserializeObject<YoutubeVideoSearch>(response);
 | 
			
		||||
 | 
			
		||||
            if (data.items.Length > 0)
 | 
			
		||||
            {
 | 
			
		||||
                var toReturn = "http://www.youtube.com/watch?v=" + data.items[0].id.videoId.ToString();
 | 
			
		||||
                return toReturn;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<IEnumerable<string>> GetRelatedVideoIds(string id, int count = 1)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(id))
 | 
			
		||||
                throw new ArgumentNullException(nameof(id));
 | 
			
		||||
            var match = new Regex("(?:youtu\\.be\\/|v=)(?<id>[\\da-zA-Z\\-_]*)").Match(id);
 | 
			
		||||
            if (match.Length > 1)
 | 
			
		||||
            {
 | 
			
		||||
                id = match.Groups["id"].Value;
 | 
			
		||||
            }
 | 
			
		||||
            var response = await GetResponseStringAsync(
 | 
			
		||||
                                    $"https://www.googleapis.com/youtube/v3/search?" +
 | 
			
		||||
                                    $"part=snippet&maxResults={count}&type=video" +
 | 
			
		||||
                                    $"&relatedToVideoId={id}" +
 | 
			
		||||
                                    $"&key={NadekoBot.Credentials.GoogleAPIKey}").ConfigureAwait(false);
 | 
			
		||||
            JObject obj = JObject.Parse(response);
 | 
			
		||||
 | 
			
		||||
            var data = JsonConvert.DeserializeObject<YoutubeVideoSearch>(response);
 | 
			
		||||
 | 
			
		||||
            return data.items.Select(v => "http://www.youtube.com/watch?v=" + v.id.videoId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<string> GetPlaylistIdByKeyword(string query)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey))
 | 
			
		||||
                throw new ArgumentNullException(nameof(query));
 | 
			
		||||
            var match = new Regex("(?:youtu\\.be\\/|list=)(?<id>[\\da-zA-Z\\-_]*)").Match(query);
 | 
			
		||||
            if (match.Length > 1)
 | 
			
		||||
            {
 | 
			
		||||
                return match.Groups["id"].Value.ToString();
 | 
			
		||||
            }
 | 
			
		||||
            var link = "https://www.googleapis.com/youtube/v3/search?part=snippet" +
 | 
			
		||||
                        "&maxResults=1&type=playlist" +
 | 
			
		||||
                       $"&q={Uri.EscapeDataString(query)}" +
 | 
			
		||||
                       $"&key={NadekoBot.Credentials.GoogleAPIKey}";
 | 
			
		||||
 | 
			
		||||
            var response = await GetResponseStringAsync(link).ConfigureAwait(false);
 | 
			
		||||
            var data = JsonConvert.DeserializeObject<YoutubePlaylistSearch>(response);
 | 
			
		||||
            JObject obj = JObject.Parse(response);
 | 
			
		||||
 | 
			
		||||
            return data.items.Length > 0 ? data.items[0].id.playlistId.ToString() : null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<IList<string>> GetVideoIDs(string playlist, int number = 50)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey))
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(playlist));
 | 
			
		||||
            }
 | 
			
		||||
            if (number < 1)
 | 
			
		||||
                throw new ArgumentOutOfRangeException();
 | 
			
		||||
 | 
			
		||||
            string nextPageToken = null;
 | 
			
		||||
 | 
			
		||||
            List<string> toReturn = new List<string>();
 | 
			
		||||
 | 
			
		||||
            do
 | 
			
		||||
            {
 | 
			
		||||
                var toGet = number > 50 ? 50 : number;
 | 
			
		||||
                number -= toGet;
 | 
			
		||||
                var link =
 | 
			
		||||
                    $"https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails" +
 | 
			
		||||
                    $"&maxResults={toGet}" +
 | 
			
		||||
                    $"&playlistId={playlist}" +
 | 
			
		||||
                    $"&key={NadekoBot.Credentials.GoogleAPIKey}";
 | 
			
		||||
                if (!string.IsNullOrWhiteSpace(nextPageToken))
 | 
			
		||||
                    link += $"&pageToken={nextPageToken}";
 | 
			
		||||
                var response = await GetResponseStringAsync(link).ConfigureAwait(false);
 | 
			
		||||
                var data = await Task.Run(() => JsonConvert.DeserializeObject<PlaylistItemsSearch>(response)).ConfigureAwait(false);
 | 
			
		||||
                nextPageToken = data.nextPageToken;
 | 
			
		||||
                toReturn.AddRange(data.items.Select(i => i.contentDetails.videoId));
 | 
			
		||||
            } while (number > 0 && !string.IsNullOrWhiteSpace(nextPageToken));
 | 
			
		||||
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static async Task<string> ShortenUrl(string url)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleAPIKey)) return url;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var httpWebRequest =
 | 
			
		||||
                    (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/urlshortener/v1/url?key=" +
 | 
			
		||||
                                                       NadekoBot.Credentials.GoogleAPIKey);
 | 
			
		||||
                httpWebRequest.ContentType = "application/json";
 | 
			
		||||
                httpWebRequest.Method = "POST";
 | 
			
		||||
 | 
			
		||||
                using (var streamWriter = new StreamWriter(await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)))
 | 
			
		||||
                {
 | 
			
		||||
                    var json = "{\"longUrl\":\"" + Uri.EscapeDataString(url) + "\"}";
 | 
			
		||||
                    streamWriter.Write(json);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var httpResponse = (await httpWebRequest.GetResponseAsync().ConfigureAwait(false)) as HttpWebResponse;
 | 
			
		||||
                var responseStream = httpResponse.GetResponseStream();
 | 
			
		||||
                using (var streamReader = new StreamReader(responseStream))
 | 
			
		||||
                {
 | 
			
		||||
                    var responseText = await streamReader.ReadToEndAsync().ConfigureAwait(false);
 | 
			
		||||
                    return Regex.Match(responseText, @"""id"": ?""(?<id>.+)""").Groups["id"].Value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine("Shortening of this url failed: " + url);
 | 
			
		||||
                Console.WriteLine(ex.ToString());
 | 
			
		||||
                return url;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static string ShowInPrettyCode<T>(IEnumerable<T> items, Func<T, string> howToPrint, int cols = 3)
 | 
			
		||||
        {
 | 
			
		||||
            var i = 0;
 | 
			
		||||
            return "```xl\n" + string.Join("\n", items.GroupBy(item => (i++) / cols)
 | 
			
		||||
                                      .Select(ig => string.Concat(ig.Select(el => howToPrint(el)))))
 | 
			
		||||
                                      + $"\n```";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,292 +0,0 @@
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes
 | 
			
		||||
{
 | 
			
		||||
    public class SpecificConfigurations
 | 
			
		||||
    {
 | 
			
		||||
        public static SpecificConfigurations Default { get; } = new SpecificConfigurations();
 | 
			
		||||
        public static bool Instantiated { get; private set; }
 | 
			
		||||
 | 
			
		||||
        private const string filePath = "data/ServerSpecificConfigs.json";
 | 
			
		||||
 | 
			
		||||
        static SpecificConfigurations() { }
 | 
			
		||||
 | 
			
		||||
        private SpecificConfigurations()
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            if (File.Exists(filePath))
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    configs = JsonConvert
 | 
			
		||||
                        .DeserializeObject<ConcurrentDictionary<ulong, ServerSpecificConfig>>(
 | 
			
		||||
                            File.ReadAllText(filePath), new JsonSerializerSettings()
 | 
			
		||||
                            {
 | 
			
		||||
                                Error = (s, e) =>
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels")
 | 
			
		||||
                                    {
 | 
			
		||||
                                        e.ErrorContext.Handled = true;
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    Console.WriteLine($"Deserialization failing: {ex}");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (configs == null)
 | 
			
		||||
                configs = new ConcurrentDictionary<ulong, ServerSpecificConfig>();
 | 
			
		||||
            Instantiated = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private readonly ConcurrentDictionary<ulong, ServerSpecificConfig> configs;
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<ServerSpecificConfig> AllConfigs => configs.Values;
 | 
			
		||||
 | 
			
		||||
        public ServerSpecificConfig Of(ulong id) =>
 | 
			
		||||
            configs.GetOrAdd(id, _ => new ServerSpecificConfig());
 | 
			
		||||
 | 
			
		||||
        private readonly SemaphoreSlim saveLock = new SemaphoreSlim(1, 1);
 | 
			
		||||
 | 
			
		||||
        public async Task Save()
 | 
			
		||||
        {
 | 
			
		||||
            await saveLock.WaitAsync();
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented));
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                saveLock.Release();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ServerSpecificConfig : INotifyPropertyChanged
 | 
			
		||||
    {
 | 
			
		||||
        [JsonProperty("VoicePlusTextEnabled")]
 | 
			
		||||
        private bool voicePlusTextEnabled;
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public bool VoicePlusTextEnabled {
 | 
			
		||||
            get { return voicePlusTextEnabled; }
 | 
			
		||||
            set {
 | 
			
		||||
                voicePlusTextEnabled = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        [JsonProperty("SendPrivateMessageOnMention")]
 | 
			
		||||
        private bool sendPrivateMessageOnMention;
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public bool SendPrivateMessageOnMention {
 | 
			
		||||
            get { return sendPrivateMessageOnMention; }
 | 
			
		||||
            set {
 | 
			
		||||
                sendPrivateMessageOnMention = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonProperty("LogChannel")]
 | 
			
		||||
        private ulong? logServerChannel = null;
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public ulong? LogServerChannel {
 | 
			
		||||
            get { return logServerChannel; }
 | 
			
		||||
            set {
 | 
			
		||||
                logServerChannel = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private ObservableCollection<ulong> logserverIgnoreChannels;
 | 
			
		||||
        public ObservableCollection<ulong> LogserverIgnoreChannels {
 | 
			
		||||
            get { return logserverIgnoreChannels; }
 | 
			
		||||
            set {
 | 
			
		||||
                logserverIgnoreChannels = value;
 | 
			
		||||
                if (value != null)
 | 
			
		||||
                    logserverIgnoreChannels.CollectionChanged += (s, e) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                        OnPropertyChanged();
 | 
			
		||||
                    };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonProperty("LogPresenceChannel")]
 | 
			
		||||
        private ulong? logPresenceChannel = null;
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public ulong? LogPresenceChannel {
 | 
			
		||||
            get { return logPresenceChannel; }
 | 
			
		||||
            set {
 | 
			
		||||
                logPresenceChannel = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private ObservableConcurrentDictionary<ulong, ulong> voiceChannelLog;
 | 
			
		||||
        public ObservableConcurrentDictionary<ulong, ulong> VoiceChannelLog {
 | 
			
		||||
            get { return voiceChannelLog; }
 | 
			
		||||
            set {
 | 
			
		||||
                voiceChannelLog = value;
 | 
			
		||||
                if (value != null)
 | 
			
		||||
                    voiceChannelLog.CollectionChanged += (s, e) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                        OnPropertyChanged();
 | 
			
		||||
                    };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private ObservableCollection<ulong> listOfSelfAssignableRoles;
 | 
			
		||||
        public ObservableCollection<ulong> ListOfSelfAssignableRoles {
 | 
			
		||||
            get { return listOfSelfAssignableRoles; }
 | 
			
		||||
            set {
 | 
			
		||||
                listOfSelfAssignableRoles = value;
 | 
			
		||||
                if (value != null)
 | 
			
		||||
                    listOfSelfAssignableRoles.CollectionChanged += (s, e) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                        OnPropertyChanged();
 | 
			
		||||
                    };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private ulong autoAssignedRole = 0;
 | 
			
		||||
        public ulong AutoAssignedRole {
 | 
			
		||||
            get { return autoAssignedRole; }
 | 
			
		||||
            set {
 | 
			
		||||
                autoAssignedRole = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private ObservableConcurrentDictionary<ulong, int> generateCurrencyChannels;
 | 
			
		||||
        public ObservableConcurrentDictionary<ulong, int> GenerateCurrencyChannels {
 | 
			
		||||
            get { return generateCurrencyChannels; }
 | 
			
		||||
            set {
 | 
			
		||||
                generateCurrencyChannels = value;
 | 
			
		||||
                if (value != null)
 | 
			
		||||
                    generateCurrencyChannels.CollectionChanged += (s, e) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                        OnPropertyChanged();
 | 
			
		||||
                    };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private bool autoDeleteMessagesOnCommand = false;
 | 
			
		||||
        public bool AutoDeleteMessagesOnCommand {
 | 
			
		||||
            get { return autoDeleteMessagesOnCommand; }
 | 
			
		||||
            set {
 | 
			
		||||
                autoDeleteMessagesOnCommand = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private bool exclusiveSelfAssignedRoles = false;
 | 
			
		||||
        public bool ExclusiveSelfAssignedRoles
 | 
			
		||||
        {
 | 
			
		||||
            get { return exclusiveSelfAssignedRoles; }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                exclusiveSelfAssignedRoles = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private ObservableCollection<StreamNotificationConfig> observingStreams;
 | 
			
		||||
        public ObservableCollection<StreamNotificationConfig> ObservingStreams {
 | 
			
		||||
            get { return observingStreams; }
 | 
			
		||||
            set {
 | 
			
		||||
                observingStreams = value;
 | 
			
		||||
                if (value != null)
 | 
			
		||||
                    observingStreams.CollectionChanged += (s, e) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                        OnPropertyChanged();
 | 
			
		||||
                    };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        private float defaultMusicVolume = 1f;
 | 
			
		||||
        public float DefaultMusicVolume {
 | 
			
		||||
            get { return defaultMusicVolume; }
 | 
			
		||||
            set {
 | 
			
		||||
                defaultMusicVolume = value;
 | 
			
		||||
                if (!SpecificConfigurations.Instantiated) return;
 | 
			
		||||
                OnPropertyChanged();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ServerSpecificConfig()
 | 
			
		||||
        {
 | 
			
		||||
            ListOfSelfAssignableRoles = new ObservableCollection<ulong>();
 | 
			
		||||
            ObservingStreams = new ObservableCollection<StreamNotificationConfig>();
 | 
			
		||||
            GenerateCurrencyChannels = new ObservableConcurrentDictionary<ulong, int>();
 | 
			
		||||
            VoiceChannelLog = new ObservableConcurrentDictionary<ulong, ulong>();
 | 
			
		||||
            LogserverIgnoreChannels = new ObservableCollection<ulong>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public event PropertyChangedEventHandler PropertyChanged = async delegate { await SpecificConfigurations.Default.Save().ConfigureAwait(false); };
 | 
			
		||||
 | 
			
		||||
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
 | 
			
		||||
        {
 | 
			
		||||
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class StreamNotificationConfig : IEquatable<StreamNotificationConfig>
 | 
			
		||||
    {
 | 
			
		||||
        public string Username { get; set; }
 | 
			
		||||
        public StreamType Type { get; set; }
 | 
			
		||||
        public ulong ServerId { get; set; }
 | 
			
		||||
        public ulong ChannelId { get; set; }
 | 
			
		||||
        public bool LastStatus { get; set; }
 | 
			
		||||
 | 
			
		||||
        public enum StreamType
 | 
			
		||||
        {
 | 
			
		||||
            Twitch,
 | 
			
		||||
            Beam,
 | 
			
		||||
            Hitbox,
 | 
			
		||||
            YoutubeGaming
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Equals(StreamNotificationConfig other) =>
 | 
			
		||||
            this.Username.ToLower().Trim() == other.Username.ToLower().Trim() &&
 | 
			
		||||
            this.Type == other.Type &&
 | 
			
		||||
            this.ServerId == other.ServerId;
 | 
			
		||||
 | 
			
		||||
        public override int GetHashCode()
 | 
			
		||||
        {
 | 
			
		||||
            return (int)ServerId + Username.Length + (int)Type;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,67 +0,0 @@
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.Modules;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.CustomReactions
 | 
			
		||||
{
 | 
			
		||||
    public class CustomReactionsModule : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public override string Prefix { get; } = "";
 | 
			
		||||
 | 
			
		||||
        private Random rng = new Random();
 | 
			
		||||
 | 
			
		||||
        private Dictionary<Regex, Func<CommandEventArgs, Match, string>> commandFuncs;
 | 
			
		||||
 | 
			
		||||
        public CustomReactionsModule()
 | 
			
		||||
        {
 | 
			
		||||
            commandFuncs = new Dictionary<Regex, Func<CommandEventArgs, Match, string>>
 | 
			
		||||
                 {
 | 
			
		||||
                    {new Regex(@"(?:%rng%|%rng:(\d{1,9})-(\d{1,9})%)"), (e,m) => {
 | 
			
		||||
                        int start, end;
 | 
			
		||||
                        if (m.Groups[1].Success)
 | 
			
		||||
                        {
 | 
			
		||||
                            start = int.Parse(m.Groups[1].Value);
 | 
			
		||||
                            end = int.Parse(m.Groups[2].Value);
 | 
			
		||||
                            return rng.Next(start, end).ToString();
 | 
			
		||||
                        }else return rng.Next().ToString();
 | 
			
		||||
                        } },
 | 
			
		||||
                    {new Regex("%mention%"), (e,m) => NadekoBot.BotMention },
 | 
			
		||||
                    {new Regex("%user%"), (e,m) => umsg.Author.Mention },
 | 
			
		||||
                    {new Regex("%target%"), (e,m) => args?.Trim() ?? "" },
 | 
			
		||||
 | 
			
		||||
                 };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Install(ModuleManager manager)
 | 
			
		||||
        {
 | 
			
		||||
            manager.CreateCommands("", cgb =>
 | 
			
		||||
             {
 | 
			
		||||
                 cgb.AddCheck(PermissionChecker.Instance);
 | 
			
		||||
 | 
			
		||||
                 foreach (var command in NadekoBot.Config.CustomReactions)
 | 
			
		||||
                 {
 | 
			
		||||
                     var commandName = command.Key.Replace("%mention%", NadekoBot.BotMention);
 | 
			
		||||
 | 
			
		||||
                     var c = cgb.CreateCommand(commandName);
 | 
			
		||||
                     if (commandName.Contains(NadekoBot.BotMention))
 | 
			
		||||
                         c.Alias(commandName.Replace("<@", "<@!"));
 | 
			
		||||
                     c.Description($"Custom reaction. | `{command.Key}`")
 | 
			
		||||
                         .Parameter("args", ParameterType.Unparsed)
 | 
			
		||||
                         .Do(async e =>
 | 
			
		||||
                          {
 | 
			
		||||
                              string str = command.Value[rng.Next(0, command.Value.Count())];
 | 
			
		||||
                              commandFuncs.Keys.ForEach(key => str = key.Replace(str, m => commandFuncs[key](e, m)));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                              await channel.SendMessageAsync(str).ConfigureAwait(false);
 | 
			
		||||
                          });
 | 
			
		||||
                 }
 | 
			
		||||
             });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Modules;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Base DiscordCommand Class.
 | 
			
		||||
    /// Inherit this class to create your own command.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract class DiscordCommand
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Parent module
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected DiscordModule Module { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Parent module's prefix
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected string Prefix => Module.Prefix;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new instance of discord command,
 | 
			
		||||
        /// use ": base(module)" in the derived class'
 | 
			
		||||
        /// constructor to make sure module is assigned
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="module">Module this command resides in</param>
 | 
			
		||||
        protected DiscordCommand(DiscordModule module)
 | 
			
		||||
        {
 | 
			
		||||
            this.Module = module;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes the CommandBuilder with values using CommandGroupBuilder
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public abstract void Init(CommandGroupBuilder cgb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,13 +0,0 @@
 | 
			
		||||
using Discord.Modules;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using NadekoBot.Classes;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules {
 | 
			
		||||
    public abstract class DiscordModule : IModule {
 | 
			
		||||
        protected readonly HashSet<DiscordCommand> commands = new HashSet<DiscordCommand>();
 | 
			
		||||
 | 
			
		||||
        public abstract string Prefix { get; }
 | 
			
		||||
 | 
			
		||||
        public abstract void Install(ModuleManager manager);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,175 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.Commands.Permissions;
 | 
			
		||||
using NadekoBot.Classes.JSONModels;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    public class PermissionChecker : IPermissionChecker
 | 
			
		||||
    {
 | 
			
		||||
        public static PermissionChecker Instance { get; } = new PermissionChecker();
 | 
			
		||||
 | 
			
		||||
        //key - sid:command
 | 
			
		||||
        //value - userid
 | 
			
		||||
        private ConcurrentDictionary<string, ulong> commandCooldowns = new ConcurrentDictionary<string, ulong>();
 | 
			
		||||
        private HashSet<ulong> timeBlackList { get; } = new HashSet<ulong>();
 | 
			
		||||
 | 
			
		||||
        static PermissionChecker() { }
 | 
			
		||||
        private PermissionChecker()
 | 
			
		||||
        {
 | 
			
		||||
            Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    //blacklist is cleared every 1.00 seconds. That is the most time anyone will be blocked
 | 
			
		||||
                    await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
                    timeBlackList.Clear();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool CanRun(Command command, User user, Channel channel, out string error)
 | 
			
		||||
        {
 | 
			
		||||
            error = String.Empty;
 | 
			
		||||
 | 
			
		||||
            if (!NadekoBot.Ready)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            if (channel.IsPrivate || channel.Server == null)
 | 
			
		||||
                return command.Category == "Help";
 | 
			
		||||
 | 
			
		||||
            if (ConfigHandler.IsUserBlacklisted(user.Id) ||
 | 
			
		||||
                (!channel.IsPrivate &&
 | 
			
		||||
                 (ConfigHandler.IsServerBlacklisted(channel.Server.Id) || ConfigHandler.IsChannelBlacklisted(channel.Id))))
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            if (timeBlackList.Contains(user.Id))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            if (!channel.IsPrivate && !channel.Server.CurrentUser.GetPermissions(channel).SendMessages)
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            timeBlackList.Add(user.Id);
 | 
			
		||||
 | 
			
		||||
            ServerPermissions perms;
 | 
			
		||||
            PermissionsHandler.PermissionsDict.TryGetValue(user.Server.Id, out perms);
 | 
			
		||||
 | 
			
		||||
            AddUserCooldown(user.Server.Id, user.Id, command.Text.ToLower());
 | 
			
		||||
            if (commandCooldowns.Keys.Contains(user.Server.Id + ":" + command.Text.ToLower()))
 | 
			
		||||
            {
 | 
			
		||||
                if (perms?.Verbose == true)
 | 
			
		||||
                    error = $"{user.Mention} You have a cooldown on that command.";
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                //is it a permission command?
 | 
			
		||||
                // if it is, check if the user has the correct role
 | 
			
		||||
                // if yes return true, if no return false
 | 
			
		||||
                if (command.Category == "Permissions")
 | 
			
		||||
                {
 | 
			
		||||
                    Discord.Role role = null;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        role = PermissionHelper.ValidateRole(user.Server,
 | 
			
		||||
                            PermissionsHandler.GetServerPermissionsRoleName(user.Server));
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
                    if (user.Server.Owner.Id == user.Id || (role != null && user.HasRole(role)))
 | 
			
		||||
                        return true;
 | 
			
		||||
                    throw new Exception($"You don't have the necessary role (**{(perms?.PermissionsControllerRole ?? "Nadeko")}**) to change permissions.");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var permissionType = PermissionsHandler.GetPermissionBanType(command, user, channel);
 | 
			
		||||
 | 
			
		||||
                string msg;
 | 
			
		||||
 | 
			
		||||
                if (permissionType == PermissionsHandler.PermissionBanType.ServerBanModule &&
 | 
			
		||||
                    command.Category.ToLower() == "nsfw")
 | 
			
		||||
                    msg = $"**{command.Category}** module has been banned from use on this **server**.\nNSFW module is disabled by default. Server owner can type `;sm nsfw enable` to enable it.";
 | 
			
		||||
                else
 | 
			
		||||
                    switch (permissionType)
 | 
			
		||||
                    {
 | 
			
		||||
                        case PermissionsHandler.PermissionBanType.None:
 | 
			
		||||
                            return true;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanType.ServerBanCommand:
 | 
			
		||||
                            msg = $"**{command.Text}** command has been banned from use on this **server**.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanType.ServerBanModule:
 | 
			
		||||
                            msg = $"**{command.Category}** module has been banned from use on this **server**.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanType.ChannelBanCommand:
 | 
			
		||||
                            msg = $"**{command.Text}** command has been banned from use on this **channel**.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanType.ChannelBanModule:
 | 
			
		||||
                            msg = $"**{command.Category}** module has been banned from use on this **channel**.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanType.RoleBanCommand:
 | 
			
		||||
                            msg = $"You do not have a **role** which permits you the usage of **{command.Text}** command.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanType.RoleBanModule:
 | 
			
		||||
                            msg = $"You do not have a **role** which permits you the usage of **{command.Category}** module.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanTypumsg.AuthorBanCommand:
 | 
			
		||||
                            msg = $"{user.Mention}, You have been banned from using **{command.Text}** command.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        case PermissionsHandler.PermissionBanTypumsg.AuthorBanModule:
 | 
			
		||||
                            msg = $"{user.Mention}, You have been banned from using **{command.Category}** module.";
 | 
			
		||||
                            break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            return true;
 | 
			
		||||
                    }
 | 
			
		||||
                if (PermissionsHandler.PermissionsDict[user.Server.Id].Verbose) //if verbose - print errors
 | 
			
		||||
                    error = msg;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine($"Exception in canrun: {ex}");
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if (perms != null && perms.Verbose)
 | 
			
		||||
                        //if verbose - print errors
 | 
			
		||||
                        error = ex.Message;
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex2)
 | 
			
		||||
                {
 | 
			
		||||
                    Console.WriteLine($"SERIOUS PERMISSION ERROR {ex2}\n\nUser:{user} Server: {user?.Server?.Name}/{user?.Server?.Id}");
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void AddUserCooldown(ulong serverId, ulong userId, string commandName)
 | 
			
		||||
        {
 | 
			
		||||
            commandCooldowns.TryAdd(commandName, userId);
 | 
			
		||||
            var tosave = serverId + ":" + commandName;
 | 
			
		||||
            Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                ServerPermissions perms;
 | 
			
		||||
                PermissionsHandler.PermissionsDict.TryGetValue(serverId, out perms);
 | 
			
		||||
                int cd;
 | 
			
		||||
                if (!perms.CommandCooldowns.TryGetValue(commandName, out cd))
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                if (commandCooldowns.TryAdd(tosave, userId))
 | 
			
		||||
                {
 | 
			
		||||
                    await Task.Delay(cd * 1000);
 | 
			
		||||
                    ulong throwaway;
 | 
			
		||||
                    commandCooldowns.TryRemove(tosave, out throwaway);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,101 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.Modules;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
{
 | 
			
		||||
    public static class PermissionHelper
 | 
			
		||||
    {
 | 
			
		||||
        public static bool ValidateBool(string passedArg)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(passedArg))
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException("No value supplied! Missing argument");
 | 
			
		||||
            }
 | 
			
		||||
            switch (passedArg.ToLower())
 | 
			
		||||
            {
 | 
			
		||||
                case "1":
 | 
			
		||||
                case "t":
 | 
			
		||||
                case "true":
 | 
			
		||||
                case "enable":
 | 
			
		||||
                case "enabled":
 | 
			
		||||
                case "allow":
 | 
			
		||||
                case "unban":
 | 
			
		||||
                    return true;
 | 
			
		||||
                case "0":
 | 
			
		||||
                case "f":
 | 
			
		||||
                case "false":
 | 
			
		||||
                case "disable":
 | 
			
		||||
                case "disabled":
 | 
			
		||||
                case "disallow":
 | 
			
		||||
                case "ban":
 | 
			
		||||
                    return false;
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new ArgumentException("Did not receive a valid boolean value");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static string ValidateModule(string mod)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(mod))
 | 
			
		||||
                throw new ArgumentNullException(nameof(mod));
 | 
			
		||||
 | 
			
		||||
            foreach (var m in NadekoBot.Client.GetService<ModuleService>().Modules)
 | 
			
		||||
            {
 | 
			
		||||
                if (m.Name.ToLower().Equals(mod.Trim().ToLower()))
 | 
			
		||||
                    return m.Name;
 | 
			
		||||
            }
 | 
			
		||||
            throw new ArgumentException("That module does not exist.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static string ValidateCommand(string commandText)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(commandText))
 | 
			
		||||
                throw new ArgumentNullException(nameof(commandText));
 | 
			
		||||
 | 
			
		||||
            var normalizedCmdTxt = commandText.Trim().ToUpperInvariant();
 | 
			
		||||
 | 
			
		||||
            foreach (var com in NadekoBot.Client.GetService<CommandService>().AllCommands)
 | 
			
		||||
            {
 | 
			
		||||
                if (com.Text.ToUpperInvariant().Equals(normalizedCmdTxt) || com.Aliases.Select(c=>c.ToUpperInvariant()).Contains(normalizedCmdTxt))
 | 
			
		||||
                    return com.Text;
 | 
			
		||||
            }
 | 
			
		||||
            throw new NullReferenceException("That command does not exist.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Role ValidateRole(Server server, string roleName)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(roleName))
 | 
			
		||||
                throw new ArgumentNullException(nameof(roleName));
 | 
			
		||||
 | 
			
		||||
            if (roleName.Trim() == "everyone")
 | 
			
		||||
                roleName = "@everyone";
 | 
			
		||||
            var role = server.FindRoles(roleName.Trim()).FirstOrDefault();
 | 
			
		||||
            if (role == null)
 | 
			
		||||
                throw new NullReferenceException("That role does not exist.");
 | 
			
		||||
            return role;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Channel ValidateChannel(Server server, string channelName)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(channelName))
 | 
			
		||||
                throw new ArgumentNullException(nameof(channelName));
 | 
			
		||||
            var channel = server.FindChannels(channelName.Trim(), ChannelType.Text).FirstOrDefault();
 | 
			
		||||
            if (channel == null)
 | 
			
		||||
                throw new NullReferenceException("That channel does not exist.");
 | 
			
		||||
            return channel;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static User ValidateUser(Server server, string userName)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(userName))
 | 
			
		||||
                throw new ArgumentNullException(nameof(userName));
 | 
			
		||||
            var user = server.FindUsers(userName.Trim()).FirstOrDefault();
 | 
			
		||||
            if (user == null)
 | 
			
		||||
                throw new NullReferenceException("That user does not exist.");
 | 
			
		||||
            return user;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,575 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
{
 | 
			
		||||
    public static class PermissionsHandler
 | 
			
		||||
    {
 | 
			
		||||
        public static ConcurrentDictionary<ulong, ServerPermissions> PermissionsDict =
 | 
			
		||||
            new ConcurrentDictionary<ulong, ServerPermissions>();
 | 
			
		||||
 | 
			
		||||
        public enum PermissionBanType
 | 
			
		||||
        {
 | 
			
		||||
            None, ServerBanCommand, ServerBanModule,
 | 
			
		||||
            ChannelBanCommand, ChannelBanModule, RoleBanCommand,
 | 
			
		||||
            RoleBanModule, UserBanCommand, UserBanModule
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public static void Initialize()
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("Reading from the permission files.");
 | 
			
		||||
            Directory.CreateDirectory("data/permissions");
 | 
			
		||||
            foreach (var file in Directory.EnumerateFiles("data/permissions/"))
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    var strippedFileName = Path.GetFileNameWithoutExtension(file);
 | 
			
		||||
                    if (string.IsNullOrWhiteSpace(strippedFileName)) continue;
 | 
			
		||||
                    var id = ulong.Parse(strippedFileName);
 | 
			
		||||
                    var data = Newtonsoft.Json.JsonConvert.DeserializeObject<ServerPermissions>(File.ReadAllText(file));
 | 
			
		||||
                    PermissionsDict.TryAdd(id, data);
 | 
			
		||||
                }
 | 
			
		||||
                catch { }
 | 
			
		||||
            }
 | 
			
		||||
            Console.WriteLine("Permission initialization complete.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Permissions GetRolePermissionsById(Server server, ulong id)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            if (!PermissionsDict.TryGetValue(server.Id, out serverPerms))
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            Permissions toReturn;
 | 
			
		||||
            serverPerms.RolePermissions.TryGetValue(id, out toReturn);
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Permissions GetUserPermissionsById(Server server, ulong id)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            if (!PermissionsDict.TryGetValue(server.Id, out serverPerms))
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            Permissions toReturn;
 | 
			
		||||
            serverPerms.UserPermissions.TryGetValue(id, out toReturn);
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Permissions GetChannelPermissionsById(Server server, ulong id)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            if (!PermissionsDict.TryGetValue(server.Id, out serverPerms))
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            Permissions toReturn;
 | 
			
		||||
            serverPerms.ChannelPermissions.TryGetValue(id, out toReturn);
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Permissions GetServerPermissions(Server server)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            return !PermissionsDict.TryGetValue(server.Id, out serverPerms) ? null : serverPerms.Permissions;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static PermissionBanType GetPermissionBanType(Command command, User user, Channel channel)
 | 
			
		||||
        {
 | 
			
		||||
            var server = user.Server;
 | 
			
		||||
            ServerPermissions serverPerms = PermissionsDict.GetOrAdd(server.Id, id => new ServerPermissions(id, server.Name));
 | 
			
		||||
            bool val;
 | 
			
		||||
            Permissions perm;
 | 
			
		||||
            //server
 | 
			
		||||
            if (serverPerms.Permissions.Modules.TryGetValue(command.Category, out val) && val == false)
 | 
			
		||||
                return PermissionBanType.ServerBanModule;
 | 
			
		||||
            if (serverPerms.Permissions.Commands.TryGetValue(command.Text, out val) && val == false)
 | 
			
		||||
                return PermissionBanType.ServerBanCommand;
 | 
			
		||||
            //channel
 | 
			
		||||
            if (serverPerms.ChannelPermissions.TryGetValue(channel.Id, out perm) &&
 | 
			
		||||
                perm.Modules.TryGetValue(command.Category, out val) && val == false)
 | 
			
		||||
                return PermissionBanType.ChannelBanModule;
 | 
			
		||||
            if (serverPerms.ChannelPermissions.TryGetValue(channel.Id, out perm) &&
 | 
			
		||||
                perm.Commands.TryGetValue(command.Text, out val) && val == false)
 | 
			
		||||
                return PermissionBanType.ChannelBanCommand;
 | 
			
		||||
 | 
			
		||||
            //ROLE PART - TWO CASES
 | 
			
		||||
            // FIRST CASE:
 | 
			
		||||
            // IF EVERY ROLE USER HAS IS BANNED FROM THE MODULE,
 | 
			
		||||
            // THAT MEANS USER CANNOT RUN THIS COMMAND
 | 
			
		||||
            // IF AT LEAST ONE ROLE EXIST THAT IS NOT BANNED,
 | 
			
		||||
            // USER CAN RUN THE COMMAND
 | 
			
		||||
            var foundNotBannedRole = false;
 | 
			
		||||
            foreach (var role in user.Roles)
 | 
			
		||||
            {
 | 
			
		||||
                //if every role is banned from using the module -> rolebanmodule
 | 
			
		||||
                if (serverPerms.RolePermissions.TryGetValue(role.Id, out perm) &&
 | 
			
		||||
                perm.Modules.TryGetValue(command.Category, out val) && val == false)
 | 
			
		||||
                    continue;
 | 
			
		||||
                foundNotBannedRole = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (!foundNotBannedRole)
 | 
			
		||||
                return PermissionBanType.RoleBanModule;
 | 
			
		||||
 | 
			
		||||
            // SECOND CASE:
 | 
			
		||||
            // IF EVERY ROLE USER HAS IS BANNED FROM THE COMMAND,
 | 
			
		||||
            // THAT MEANS USER CANNOT RUN THAT COMMAND
 | 
			
		||||
            // IF AT LEAST ONE ROLE EXISTS THAT IS NOT BANNED,
 | 
			
		||||
            // USER CAN RUN THE COMMAND
 | 
			
		||||
            foundNotBannedRole = false;
 | 
			
		||||
            foreach (var role in user.Roles)
 | 
			
		||||
            {
 | 
			
		||||
                //if every role is banned from using the module -> rolebanmodule
 | 
			
		||||
                if (serverPerms.RolePermissions.TryGetValue(role.Id, out perm) &&
 | 
			
		||||
                perm.Commands.TryGetValue(command.Text, out val) && val == false)
 | 
			
		||||
                    continue;
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    foundNotBannedRole = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!foundNotBannedRole)
 | 
			
		||||
                return PermissionBanType.RoleBanCommand;
 | 
			
		||||
 | 
			
		||||
            //user
 | 
			
		||||
            if (serverPerms.UserPermissions.TryGetValue(user.Id, out perm) &&
 | 
			
		||||
                perm.Modules.TryGetValue(command.Category, out val) && val == false)
 | 
			
		||||
                return PermissionBanTypumsg.AuthorBanModule;
 | 
			
		||||
            if (serverPerms.UserPermissions.TryGetValue(user.Id, out perm) &&
 | 
			
		||||
                perm.Commands.TryGetValue(command.Text, out val) && val == false)
 | 
			
		||||
                return PermissionBanTypumsg.AuthorBanCommand;
 | 
			
		||||
 | 
			
		||||
            return PermissionBanType.None;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Task WriteServerToJson(ServerPermissions serverPerms) => Task.Run(() =>
 | 
			
		||||
        {
 | 
			
		||||
            string pathToFile = $"data/permissions/{serverPerms.Id}.json";
 | 
			
		||||
            File.WriteAllText(pathToFile,
 | 
			
		||||
                Newtonsoft.Json.JsonConvert.SerializeObject(serverPerms, Newtonsoft.Json.Formatting.Indented));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        public static Task WriteToJson() => Task.Run(() => 
 | 
			
		||||
        {
 | 
			
		||||
            Directory.CreateDirectory("data/permissions/");
 | 
			
		||||
            foreach (var kvp in PermissionsDict)
 | 
			
		||||
            {
 | 
			
		||||
                WriteServerToJson(kvp.Value);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        public static string GetServerPermissionsRoleName(Server server)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            return serverPerms.PermissionsControllerRole;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetPermissionsRole(Server server, string roleName)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            serverPerms.PermissionsControllerRole = roleName;
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetVerbosity(Server server, bool val)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            serverPerms.Verbose = val;
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task CopyRolePermissions(Role fromRole, Role toRole)
 | 
			
		||||
        {
 | 
			
		||||
            var server = fromRole.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            var from = GetRolePermissionsById(server, fromRole.Id);
 | 
			
		||||
            if (from == null)
 | 
			
		||||
                serverPerms.RolePermissions.Add(fromRole.Id, from = new Permissions(fromRole.Name));
 | 
			
		||||
            var to = GetRolePermissionsById(server, toRole.Id);
 | 
			
		||||
            if (to == null)
 | 
			
		||||
                serverPerms.RolePermissions.Add(toRole.Id, to = new Permissions(toRole.Name));
 | 
			
		||||
 | 
			
		||||
            to.CopyFrom(from);
 | 
			
		||||
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task CopyChannelPermissions(Channel fromChannel, Channel toChannel)
 | 
			
		||||
        {
 | 
			
		||||
            var server = fromChannel.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            var from = GetChannelPermissionsById(server, fromChannel.Id);
 | 
			
		||||
            if (from == null)
 | 
			
		||||
                serverPerms.ChannelPermissions.Add(fromChannel.Id, from = new Permissions(fromChannel.Name));
 | 
			
		||||
            var to = GetChannelPermissionsById(server, toChannel.Id);
 | 
			
		||||
            if (to == null)
 | 
			
		||||
                serverPerms.ChannelPermissions.Add(toChannel.Id, to = new Permissions(toChannel.Name));
 | 
			
		||||
 | 
			
		||||
            to.CopyFrom(from);
 | 
			
		||||
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task CopyUserPermissions(User fromUser, User toUser)
 | 
			
		||||
        {
 | 
			
		||||
            var server = fromUser.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            var from = GetUserPermissionsById(server, fromUser.Id);
 | 
			
		||||
            if (from == null)
 | 
			
		||||
                serverPerms.UserPermissions.Add(fromUser.Id, from = new Permissions(fromUser.Name));
 | 
			
		||||
            var to = GetUserPermissionsById(server, toUser.Id);
 | 
			
		||||
            if (to == null)
 | 
			
		||||
                serverPerms.UserPermissions.Add(toUser.Id, to = new Permissions(toUser.Name));
 | 
			
		||||
 | 
			
		||||
            to.CopyFrom(from);
 | 
			
		||||
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetServerModulePermission(Server server, string moduleName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            var modules = serverPerms.Permissions.Modules;
 | 
			
		||||
            if (modules.ContainsKey(moduleName))
 | 
			
		||||
                modules[moduleName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                modules.TryAdd(moduleName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetServerCommandPermission(Server server, string commandName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            var commands = serverPerms.Permissions.Commands;
 | 
			
		||||
            if (commands.ContainsKey(commandName))
 | 
			
		||||
                commands[commandName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                commands.TryAdd(commandName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetChannelModulePermission(Channel channel, string moduleName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = channel.Server;
 | 
			
		||||
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            if (!serverPerms.ChannelPermissions.ContainsKey(channel.Id))
 | 
			
		||||
                serverPerms.ChannelPermissions.Add(channel.Id, new Permissions(channel.Name));
 | 
			
		||||
 | 
			
		||||
            var modules = serverPerms.ChannelPermissions[channel.Id].Modules;
 | 
			
		||||
 | 
			
		||||
            if (modules.ContainsKey(moduleName))
 | 
			
		||||
                modules[moduleName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                modules.TryAdd(moduleName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetChannelCommandPermission(Channel channel, string commandName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = channel.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            if (!serverPerms.ChannelPermissions.ContainsKey(channel.Id))
 | 
			
		||||
                serverPerms.ChannelPermissions.Add(channel.Id, new Permissions(channel.Name));
 | 
			
		||||
 | 
			
		||||
            var commands = serverPerms.ChannelPermissions[channel.Id].Commands;
 | 
			
		||||
 | 
			
		||||
            if (commands.ContainsKey(commandName))
 | 
			
		||||
                commands[commandName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                commands.TryAdd(commandName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetRoleModulePermission(Role role, string moduleName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = role.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            if (!serverPerms.RolePermissions.ContainsKey(role.Id))
 | 
			
		||||
                serverPerms.RolePermissions.Add(role.Id, new Permissions(role.Name));
 | 
			
		||||
 | 
			
		||||
            var modules = serverPerms.RolePermissions[role.Id].Modules;
 | 
			
		||||
 | 
			
		||||
            if (modules.ContainsKey(moduleName))
 | 
			
		||||
                modules[moduleName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                modules.TryAdd(moduleName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetRoleCommandPermission(Role role, string commandName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = role.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            if (!serverPerms.RolePermissions.ContainsKey(role.Id))
 | 
			
		||||
                serverPerms.RolePermissions.Add(role.Id, new Permissions(role.Name));
 | 
			
		||||
 | 
			
		||||
            var commands = serverPerms.RolePermissions[role.Id].Commands;
 | 
			
		||||
 | 
			
		||||
            if (commands.ContainsKey(commandName))
 | 
			
		||||
                commands[commandName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                commands.TryAdd(commandName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetUserModulePermission(User user, string moduleName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = user.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            if (!serverPerms.UserPermissions.ContainsKey(user.Id))
 | 
			
		||||
                serverPerms.UserPermissions.Add(user.Id, new Permissions(user.Name));
 | 
			
		||||
 | 
			
		||||
            var modules = serverPerms.UserPermissions[user.Id].Modules;
 | 
			
		||||
 | 
			
		||||
            if (modules.ContainsKey(moduleName))
 | 
			
		||||
                modules[moduleName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                modules.TryAdd(moduleName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetUserCommandPermission(User user, string commandName, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = user.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
            if (!serverPerms.UserPermissions.ContainsKey(user.Id))
 | 
			
		||||
                serverPerms.UserPermissions.Add(user.Id, new Permissions(user.Name));
 | 
			
		||||
 | 
			
		||||
            var commands = serverPerms.UserPermissions[user.Id].Commands;
 | 
			
		||||
 | 
			
		||||
            if (commands.ContainsKey(commandName))
 | 
			
		||||
                commands[commandName] = value;
 | 
			
		||||
            else
 | 
			
		||||
                commands.TryAdd(commandName, value);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetServerWordPermission(Server server, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            serverPerms.Permissions.FilterWords = value;
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetChannelWordPermission(Channel channel, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = channel.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            if (!serverPerms.ChannelPermissions.ContainsKey(channel.Id))
 | 
			
		||||
                serverPerms.ChannelPermissions.Add(channel.Id, new Permissions(channel.Name));
 | 
			
		||||
 | 
			
		||||
            serverPerms.ChannelPermissions[channel.Id].FilterWords = value;
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetServerFilterInvitesPermission(Server server, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            serverPerms.Permissions.FilterInvites = value;
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetChannelFilterInvitesPermission(Channel channel, bool value)
 | 
			
		||||
        {
 | 
			
		||||
            var server = channel.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
 | 
			
		||||
            if (!serverPerms.ChannelPermissions.ContainsKey(channel.Id))
 | 
			
		||||
                serverPerms.ChannelPermissions.Add(channel.Id, new Permissions(channel.Name));
 | 
			
		||||
 | 
			
		||||
            serverPerms.ChannelPermissions[channel.Id].FilterInvites = value;
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task SetCommandCooldown(Server server, string commandName, int value)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
            if (value == 0) {
 | 
			
		||||
                int throwaway;
 | 
			
		||||
                serverPerms.CommandCooldowns.TryRemove(commandName, out throwaway);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                serverPerms.CommandCooldowns.AddOrUpdate(commandName, value, (str, v) => value);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task AddFilteredWord(Server server, string word)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
            if (serverPerms.Words.Contains(word))
 | 
			
		||||
                throw new InvalidOperationException("That word is already banned.");
 | 
			
		||||
            serverPerms.Words.Add(word);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        public static async Task RemoveFilteredWord(Server server, string word)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
            if (!serverPerms.Words.Contains(word))
 | 
			
		||||
                throw new InvalidOperationException("That word is not banned.");
 | 
			
		||||
            serverPerms.Words.Remove(word);
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Holds a permission list
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class Permissions
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Name of the parent object whose permissions these are
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Name { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Module name with allowed/disallowed
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ConcurrentDictionary<string, bool> Modules { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Command name with allowed/disallowed
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ConcurrentDictionary<string, bool> Commands { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Should the bot filter invites to other discord servers (and ref links in the future)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool FilterInvites { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Should the bot filter words which are specified in the Words hashset
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool FilterWords { get; set; }
 | 
			
		||||
 | 
			
		||||
        public Permissions(string name)
 | 
			
		||||
        {
 | 
			
		||||
            Name = name;
 | 
			
		||||
            Modules = new ConcurrentDictionary<string, bool>();
 | 
			
		||||
            Commands = new ConcurrentDictionary<string, bool>();
 | 
			
		||||
            FilterInvites = false;
 | 
			
		||||
            FilterWords = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void CopyFrom(Permissions other)
 | 
			
		||||
        {
 | 
			
		||||
            Modules.Clear();
 | 
			
		||||
            foreach (var mp in other.Modules)
 | 
			
		||||
                Modules.AddOrUpdate(mp.Key, mp.Value, (s, b) => mp.Value);
 | 
			
		||||
            Commands.Clear();
 | 
			
		||||
            foreach (var cp in other.Commands)
 | 
			
		||||
                Commands.AddOrUpdate(cp.Key, cp.Value, (s, b) => cp.Value);
 | 
			
		||||
            FilterInvites = other.FilterInvites;
 | 
			
		||||
            FilterWords = other.FilterWords;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            var toReturn = "";
 | 
			
		||||
            var bannedModules = Modules.Where(kvp => kvp.Value == false);
 | 
			
		||||
            var bannedModulesArray = bannedModules as KeyValuePair<string, bool>[] ?? bannedModules.ToArray();
 | 
			
		||||
            if (bannedModulesArray.Any())
 | 
			
		||||
            {
 | 
			
		||||
                toReturn += "`Banned Modules:`\n";
 | 
			
		||||
                toReturn = bannedModulesArray.Aggregate(toReturn, (current, m) => current + $"\t`[x]  {m.Key}`\n");
 | 
			
		||||
            }
 | 
			
		||||
            var bannedCommands = Commands.Where(kvp => kvp.Value == false);
 | 
			
		||||
            var bannedCommandsArr = bannedCommands as KeyValuePair<string, bool>[] ?? bannedCommands.ToArray();
 | 
			
		||||
            if (bannedCommandsArr.Any())
 | 
			
		||||
            {
 | 
			
		||||
                toReturn += "`Banned Commands:`\n";
 | 
			
		||||
                toReturn = bannedCommandsArr.Aggregate(toReturn, (current, c) => current + $"\t`[x]  {c.Key}`\n");
 | 
			
		||||
            }
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class ServerPermissions
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The guy who can edit the permissions
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string PermissionsControllerRole { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Does it print the error when a restriction occurs
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool Verbose { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The id of the thing (user/server/channel)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ulong Id { get; set; } //a string because of the role name.
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Permission object bound to the id of something/role name
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Permissions Permissions { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Banned words, usually profanities, like word "java"
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public HashSet<string> Words { get; set; }
 | 
			
		||||
 | 
			
		||||
        public Dictionary<ulong, Permissions> UserPermissions { get; set; }
 | 
			
		||||
        public Dictionary<ulong, Permissions> ChannelPermissions { get; set; }
 | 
			
		||||
        public Dictionary<ulong, Permissions> RolePermissions { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Dictionary of command names with their respective cooldowns
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ConcurrentDictionary<string, int> CommandCooldowns { get; set; }
 | 
			
		||||
 | 
			
		||||
        public ServerPermissions(ulong id, string name)
 | 
			
		||||
        {
 | 
			
		||||
            Id = id;
 | 
			
		||||
            PermissionsControllerRole = "Nadeko";
 | 
			
		||||
            Verbose = true;
 | 
			
		||||
 | 
			
		||||
            Permissions = new Permissions(name);
 | 
			
		||||
            Permissions.Modules.TryAdd("NSFW", false);
 | 
			
		||||
            UserPermissions = new Dictionary<ulong, Permissions>();
 | 
			
		||||
            ChannelPermissions = new Dictionary<ulong, Permissions>();
 | 
			
		||||
            RolePermissions = new Dictionary<ulong, Permissions>();
 | 
			
		||||
            CommandCooldowns = new ConcurrentDictionary<string, int>();
 | 
			
		||||
            Words = new HashSet<string>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,36 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.Commands.Permissions;
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
{
 | 
			
		||||
    public static class SimpleCheckers
 | 
			
		||||
    {
 | 
			
		||||
        public static ManageRoles CanManageRoles { get; } = new ManageRoles();
 | 
			
		||||
 | 
			
		||||
        public static Func<Command, User, Channel, bool> OwnerOnly() =>
 | 
			
		||||
            (com, user, ch) => NadekoBot.IsOwner(user.Id);
 | 
			
		||||
 | 
			
		||||
        public static Func<Command, User, Channel, bool> ManageMessages() =>
 | 
			
		||||
            (com, user, ch) => user.ServerPermissions.ManageMessages;
 | 
			
		||||
 | 
			
		||||
        public static Func<Command, User, Channel, bool> ManageChannels() =>
 | 
			
		||||
            (com, user, ch) => user.ServerPermissions.ManageChannels;
 | 
			
		||||
 | 
			
		||||
        public static Func<Command, User, Channel, bool> ManageServer() =>
 | 
			
		||||
            (com, user, ch) => user.ServerPermissions.ManageServer;
 | 
			
		||||
 | 
			
		||||
        public class ManageRoles : IPermissionChecker
 | 
			
		||||
        {
 | 
			
		||||
            public bool CanRun(Command command, User user, Channel channel, out string error)
 | 
			
		||||
            {
 | 
			
		||||
                error = string.Empty;
 | 
			
		||||
                if (user.ServerPermissions.ManageRoles)
 | 
			
		||||
                    return true;
 | 
			
		||||
                error = "You do not have a permission to manage roles.";
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,117 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Classes;
 | 
			
		||||
using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions
 | 
			
		||||
{
 | 
			
		||||
    public class FilterInvitesCommand : DiscordCommand
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Regex filterRegex = new Regex(@"(?:discord(?:\.gg|app\.com\/invite)\/(?<id>([\w]{16}|(?:[\w]+-?){3})))");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public FilterInvitesCommand(DiscordModule module) : base(module)
 | 
			
		||||
        {
 | 
			
		||||
            NadekoBot.Client.MessageReceived += async (sender, args) =>
 | 
			
		||||
            {
 | 
			
		||||
                if (args.Channel.IsPrivate || args.User.Id == NadekoBot.Client.CurrentUser.Id) return;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    Classes.ServerPermissions serverPerms;
 | 
			
		||||
                    if (!IsChannelOrServerFiltering(args.Channel, out serverPerms)) return;
 | 
			
		||||
 | 
			
		||||
                    if (filterRegex.IsMatch(args.Message.RawText))
 | 
			
		||||
                    {
 | 
			
		||||
                        await args.Message.Delete().ConfigureAwait(false);
 | 
			
		||||
                        IncidentsHandler.Add(args.Server.Id, args.Channel.Id, $"User [{args.User.Name}/{args.User.Id}] posted " +
 | 
			
		||||
                                                             $"INVITE LINK in [{args.Channel.Name}/{args.Channel.Id}] channel.\n" +
 | 
			
		||||
                                                             $"`Full message:` {args.Message.Text}");
 | 
			
		||||
                        if (serverPerms.Verbose)
 | 
			
		||||
                            await args.Channel.SendMessageAsync($"{args.User.Mention} Invite links are not " +
 | 
			
		||||
                                                           $"allowed on this channel.")
 | 
			
		||||
                                                           .ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch { }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool IsChannelOrServerFiltering(Channel channel, out Classes.ServerPermissions serverPerms)
 | 
			
		||||
        {
 | 
			
		||||
            if (!PermissionsHandler.PermissionsDict.TryGetValue(channel.Server.Id, out serverPerms)) return false;
 | 
			
		||||
 | 
			
		||||
            if (serverPerms.Permissions.FilterInvites)
 | 
			
		||||
                return true;
 | 
			
		||||
 | 
			
		||||
            Classes.Permissions perms;
 | 
			
		||||
            return serverPerms.ChannelPermissions.TryGetValue(channel.Id, out perms) && perms.FilterInvites;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
        {
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "chnlfilterinv")
 | 
			
		||||
                .Alias(Module.Prefix + "cfi")
 | 
			
		||||
                .Description("Enables or disables automatic deleting of invites on the channel." +
 | 
			
		||||
                             "If no channel supplied, it will default to current one. Use ALL to apply to all existing channels at once." +
 | 
			
		||||
                             $" | `{Prefix}cfi enable #general-chat`")
 | 
			
		||||
                .Parameter("bool")
 | 
			
		||||
                .Parameter("channel", ParameterType.Optional)
 | 
			
		||||
                .Do(async e =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                        var chanStr = channel;
 | 
			
		||||
 | 
			
		||||
                        if (chanStr?.ToLowerInvariant().Trim() != "all")
 | 
			
		||||
                        {
 | 
			
		||||
 | 
			
		||||
                            var chan = string.IsNullOrWhiteSpace(chanStr)
 | 
			
		||||
                                ? e.Channel
 | 
			
		||||
                                : PermissionHelper.ValidateChannel(e.Server, chanStr);
 | 
			
		||||
                            await PermissionsHandler.SetChannelFilterInvitesPermission(chan, state).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Invite Filter has been **{(state ? "enabled" : "disabled")}** for **{chan.Name}** channel.")
 | 
			
		||||
                                            .ConfigureAwait(false);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        //all channels
 | 
			
		||||
 | 
			
		||||
                        foreach (var curChannel in e.Server.TextChannels)
 | 
			
		||||
                        {
 | 
			
		||||
                            await PermissionsHandler.SetChannelFilterInvitesPermission(curChannel, state).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        await channel.SendMessageAsync($"Invite Filter has been **{(state ? "enabled" : "disabled")}** for **ALL** channels.")
 | 
			
		||||
                                       .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync($"💢 Error: {ex.Message}")
 | 
			
		||||
                                       .ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "srvrfilterinv")
 | 
			
		||||
                .Alias(Module.Prefix + "sfi")
 | 
			
		||||
                .Description($"Enables or disables automatic deleting of invites on the server. | `{Prefix}sfi disable`")
 | 
			
		||||
                .Parameter("bool")
 | 
			
		||||
                .Do(async e =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                        await PermissionsHandler.SetServerFilterInvitesPermission(e.Server, state).ConfigureAwait(false);
 | 
			
		||||
                        await channel.SendMessageAsync($"Invite Filter has been **{(state ? "enabled" : "disabled")}** for this server.")
 | 
			
		||||
                                       .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync($"💢 Error: {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,174 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Classes;
 | 
			
		||||
using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions
 | 
			
		||||
{
 | 
			
		||||
    public class FilterWords : DiscordCommand
 | 
			
		||||
    {
 | 
			
		||||
        public FilterWords(DiscordModule module) : base(module)
 | 
			
		||||
        {
 | 
			
		||||
            NadekoBot.Client.MessageReceived += async (sender, args) =>
 | 
			
		||||
            {
 | 
			
		||||
                if (args.Channel.IsPrivate || args.User.Id == NadekoBot.Client.CurrentUser.Id) return;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    Classes.ServerPermissions serverPerms;
 | 
			
		||||
                    if (!IsChannelOrServerFiltering(args.Channel, out serverPerms)) return;
 | 
			
		||||
 | 
			
		||||
                    var wordsInMessage = args.Message.RawText.ToLowerInvariant().Split(' ');
 | 
			
		||||
                    if (serverPerms.Words.Any(w => wordsInMessage.Contains(w)))
 | 
			
		||||
                    {
 | 
			
		||||
                        await args.Message.Delete().ConfigureAwait(false);
 | 
			
		||||
                        IncidentsHandler.Add(args.Server.Id, args.Channel.Id, $"User [{args.User.Name}/{args.User.Id}] posted " +
 | 
			
		||||
                                                             $"BANNED WORD in [{args.Channel.Name}/{args.Channel.Id}] channel.\n" +
 | 
			
		||||
                                                             $"`Full message:` {args.Message.Text}");
 | 
			
		||||
                        if (serverPerms.Verbose)
 | 
			
		||||
                            await args.Channel.SendMessageAsync($"{args.User.Mention} One or more of the words you used " +
 | 
			
		||||
                                                           $"in that sentence are not allowed here.")
 | 
			
		||||
                                                           .ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch { }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool IsChannelOrServerFiltering(Channel channel, out Classes.ServerPermissions serverPerms)
 | 
			
		||||
        {
 | 
			
		||||
            if (!PermissionsHandler.PermissionsDict.TryGetValue(channel.Server.Id, out serverPerms)) return false;
 | 
			
		||||
 | 
			
		||||
            if (serverPerms.Permissions.FilterWords)
 | 
			
		||||
                return true;
 | 
			
		||||
 | 
			
		||||
            Classes.Permissions perms;
 | 
			
		||||
            return serverPerms.ChannelPermissions.TryGetValue(channel.Id, out perms) && perms.FilterWords;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
        {
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "chnlfilterwords")
 | 
			
		||||
                .Alias(Module.Prefix + "cfw")
 | 
			
		||||
                .Description("Enables or disables automatic deleting of messages containing banned words on the channel." +
 | 
			
		||||
                             "If no channel supplied, it will default to current one. Use ALL to apply to all existing channels at once." +
 | 
			
		||||
                             $" | `{Prefix}cfw enable #general-chat`")
 | 
			
		||||
                .Parameter("bool")
 | 
			
		||||
                .Parameter("channel", ParameterType.Optional)
 | 
			
		||||
                .Do(async e =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                        var chanStr = channel?.ToLowerInvariant().Trim();
 | 
			
		||||
 | 
			
		||||
                        if (chanStr != "all")
 | 
			
		||||
                        {
 | 
			
		||||
                            var chan = string.IsNullOrWhiteSpace(chanStr)
 | 
			
		||||
                                ? e.Channel
 | 
			
		||||
                                : PermissionHelper.ValidateChannel(e.Server, chanStr);
 | 
			
		||||
                            await PermissionsHandler.SetChannelWordPermission(chan, state).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Word filtering has been **{(state ? "enabled" : "disabled")}** for **{chan.Name}** channel.").ConfigureAwait(false);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        //all channels
 | 
			
		||||
 | 
			
		||||
                        foreach (var curChannel in e.Server.TextChannels)
 | 
			
		||||
                        {
 | 
			
		||||
                            await PermissionsHandler.SetChannelWordPermission(curChannel, state).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        await channel.SendMessageAsync($"Word filtering has been **{(state ? "enabled" : "disabled")}** for **ALL** channels.").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync($"💢 Error: {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "addfilterword")
 | 
			
		||||
               .Alias(Module.Prefix + "afw")
 | 
			
		||||
               .Description("Adds a new word to the list of filtered words" +
 | 
			
		||||
                            $" | `{Prefix}afw poop`")
 | 
			
		||||
               .Parameter("word", ParameterType.Unparsed)
 | 
			
		||||
               .Do(async e =>
 | 
			
		||||
               {
 | 
			
		||||
                   try
 | 
			
		||||
                   {
 | 
			
		||||
                       var word = word;
 | 
			
		||||
                       if (string.IsNullOrWhiteSpace(word))
 | 
			
		||||
                           return;
 | 
			
		||||
                       await PermissionsHandler.AddFilteredWord(e.Server, word.ToLowerInvariant().Trim()).ConfigureAwait(false);
 | 
			
		||||
                       await channel.SendMessageAsync($"Successfully added new filtered word.").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                   }
 | 
			
		||||
                   catch (Exception ex)
 | 
			
		||||
                   {
 | 
			
		||||
                       await channel.SendMessageAsync($"💢 Error: {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
                   }
 | 
			
		||||
               });
 | 
			
		||||
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "rmvfilterword")
 | 
			
		||||
               .Alias(Module.Prefix + "rfw")
 | 
			
		||||
               .Description("Removes the word from the list of filtered words" +
 | 
			
		||||
                            $" | `{Prefix}rw poop`")
 | 
			
		||||
               .Parameter("word", ParameterType.Unparsed)
 | 
			
		||||
               .Do(async e =>
 | 
			
		||||
               {
 | 
			
		||||
                   try
 | 
			
		||||
                   {
 | 
			
		||||
                       var word = word;
 | 
			
		||||
                       if (string.IsNullOrWhiteSpace(word))
 | 
			
		||||
                           return;
 | 
			
		||||
                       await PermissionsHandler.RemoveFilteredWord(e.Server, word.ToLowerInvariant().Trim()).ConfigureAwait(false);
 | 
			
		||||
                       await channel.SendMessageAsync($"Successfully removed filtered word.").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                   }
 | 
			
		||||
                   catch (Exception ex)
 | 
			
		||||
                   {
 | 
			
		||||
                       await channel.SendMessageAsync($"💢 Error: {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
                   }
 | 
			
		||||
               });
 | 
			
		||||
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "lstfilterwords")
 | 
			
		||||
               .Alias(Module.Prefix + "lfw")
 | 
			
		||||
               .Description("Shows a list of filtered words" +
 | 
			
		||||
                            $" | `{Prefix}lfw`")
 | 
			
		||||
               .Do(async e =>
 | 
			
		||||
               {
 | 
			
		||||
                   try
 | 
			
		||||
                   {
 | 
			
		||||
                       Classes.ServerPermissions serverPerms;
 | 
			
		||||
                       if (!PermissionsHandler.PermissionsDict.TryGetValue(e.Server.Id, out serverPerms))
 | 
			
		||||
                           return;
 | 
			
		||||
                       await channel.SendMessageAsync($"There are `{serverPerms.Words.Count}` filtered words.\n" +
 | 
			
		||||
                           string.Join("\n", serverPerms.Words)).ConfigureAwait(false);
 | 
			
		||||
                   }
 | 
			
		||||
                   catch (Exception ex)
 | 
			
		||||
                   {
 | 
			
		||||
                       await channel.SendMessageAsync($"💢 Error: {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
                   }
 | 
			
		||||
               });
 | 
			
		||||
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "srvrfilterwords")
 | 
			
		||||
                .Alias(Module.Prefix + "sfw")
 | 
			
		||||
                .Description($"Enables or disables automatic deleting of messages containing forbidden words on the server. | `{Prefix}sfw disable`")
 | 
			
		||||
                .Parameter("bool")
 | 
			
		||||
                .Do(async e =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                        await PermissionsHandler.SetServerWordPermission(e.Server, state).ConfigureAwait(false);
 | 
			
		||||
                        await channel.SendMessageAsync($"Word filtering has been **{(state ? "enabled" : "disabled")}** on this server.")
 | 
			
		||||
                                       .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync($"💢 Error: {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,834 +0,0 @@
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.Modules;
 | 
			
		||||
using NadekoBot.Classes;
 | 
			
		||||
using NadekoBot.Classes.JSONModels;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Modules.Games.Commands;
 | 
			
		||||
using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
using NadekoBot.Modules.Permissions.Commands;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions
 | 
			
		||||
{
 | 
			
		||||
    public class PermissionModule : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Permissions;
 | 
			
		||||
 | 
			
		||||
        public PermissionModule()
 | 
			
		||||
        {
 | 
			
		||||
            commands.Add(new FilterInvitesCommand(this));
 | 
			
		||||
            commands.Add(new FilterWords(this));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Install(ModuleManager manager)
 | 
			
		||||
        {
 | 
			
		||||
            manager.CreateCommands("", cgb =>
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                cgb.AddCheck(PermissionChecker.Instance);
 | 
			
		||||
 | 
			
		||||
                commands.ForEach(cmd => cmd.Init(cgb));
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "permrole")
 | 
			
		||||
                    .Alias(Prefix + "pr")
 | 
			
		||||
                    .Description($"Sets a role which can change permissions. Or supply no parameters to find out the current one. Default one is 'Nadeko'. | `{Prefix}pr role`")
 | 
			
		||||
                    .Parameter("role", ParameterType.Unparsed)
 | 
			
		||||
                     .Do(async e =>
 | 
			
		||||
                     {
 | 
			
		||||
                         if (string.IsNullOrWhiteSpace(role))
 | 
			
		||||
                         {
 | 
			
		||||
                             await channel.SendMessageAsync($"Current permissions role is `{PermissionsHandler.GetServerPermissionsRoleName(e.Server)}`").ConfigureAwait(false);
 | 
			
		||||
                             return;
 | 
			
		||||
                         }
 | 
			
		||||
 | 
			
		||||
                         var arg = role;
 | 
			
		||||
                         Discord.Role role = null;
 | 
			
		||||
                         try
 | 
			
		||||
                         {
 | 
			
		||||
                             role = PermissionHelper.ValidateRole(e.Server, arg);
 | 
			
		||||
                         }
 | 
			
		||||
                         catch (Exception ex)
 | 
			
		||||
                         {
 | 
			
		||||
                             Console.WriteLine(ex.Message);
 | 
			
		||||
                             await channel.SendMessageAsync($"Role `{arg}` probably doesn't exist. Create the role with that name first.").ConfigureAwait(false);
 | 
			
		||||
                             return;
 | 
			
		||||
                         }
 | 
			
		||||
                         await PermissionsHandler.SetPermissionsRole(e.Server, role.Name).ConfigureAwait(false);
 | 
			
		||||
                         await channel.SendMessageAsync($"Role `{role.Name}` is now required in order to change permissions.").ConfigureAwait(false);
 | 
			
		||||
                     });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "rolepermscopy")
 | 
			
		||||
                    .Alias(Prefix + "rpc")
 | 
			
		||||
                    .Description($"Copies BOT PERMISSIONS (not discord permissions) from one role to another. |`{Prefix}rpc Some Role ~ Some other role`")
 | 
			
		||||
                    .Parameter("from_to", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var arg = from_to?.Trim();
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(arg) || !arg.Contains('~'))
 | 
			
		||||
                            return;
 | 
			
		||||
                        var args = arg.Split('~').Select(a => a.Trim()).ToArray();
 | 
			
		||||
                        if (args.Length > 2)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("💢Invalid number of '~'s in the argument.").ConfigureAwait(false);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var fromRole = PermissionHelper.ValidateRole(e.Server, args[0]);
 | 
			
		||||
                            var toRole = PermissionHelper.ValidateRole(e.Server, args[1]);
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.CopyRolePermissions(fromRole, toRole).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Copied permission settings from **{fromRole.Name}** to **{toRole.Name}**.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync($"💢{ex.Message}").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                cgb.CreateCommand(Prefix + "chnlpermscopy")
 | 
			
		||||
                    .Alias(Prefix + "cpc")
 | 
			
		||||
                    .Description($"Copies BOT PERMISSIONS (not discord permissions) from one channel to another. |`{Prefix}cpc Some Channel ~ Some other channel`")
 | 
			
		||||
                    .Parameter("from_to", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var arg = from_to?.Trim();
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(arg) || !arg.Contains('~'))
 | 
			
		||||
                            return;
 | 
			
		||||
                        var args = arg.Split('~').Select(a => a.Trim()).ToArray();
 | 
			
		||||
                        if (args.Length > 2)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("💢Invalid number of '~'s in the argument.");
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var fromChannel = PermissionHelper.ValidateChannel(e.Server, args[0]);
 | 
			
		||||
                            var toChannel = PermissionHelper.ValidateChannel(e.Server, args[1]);
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.CopyChannelPermissions(fromChannel, toChannel).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Copied permission settings from **{fromChannel.Name}** to **{toChannel.Name}**.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync($"💢{ex.Message}");
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                cgb.CreateCommand(Prefix + "usrpermscopy")
 | 
			
		||||
                    .Alias(Prefix + "upc")
 | 
			
		||||
                    .Description($"Copies BOT PERMISSIONS (not discord permissions) from one role to another. |`{Prefix}upc @SomeUser ~ @SomeOtherUser`")
 | 
			
		||||
                    .Parameter("from_to", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var arg = from_to?.Trim();
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(arg) || !arg.Contains('~'))
 | 
			
		||||
                            return;
 | 
			
		||||
                        var args = arg.Split('~').Select(a => a.Trim()).ToArray();
 | 
			
		||||
                        if (args.Length > 2)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("💢Invalid number of '~'s in the argument.").ConfigureAwait(false);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var fromUser = PermissionHelper.ValidateUser(e.Server, args[0]);
 | 
			
		||||
                            var toUser = PermissionHelper.ValidateUser(e.Server, args[1]);
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.CopyUserPermissions(fromUser, toUser).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Copied permission settings from **{fromUser.ToString()}**to * *{toUser.ToString()}**.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync($"💢{ex.Message}");
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "verbose")
 | 
			
		||||
                    .Alias(Prefix + "v")
 | 
			
		||||
                    .Description($"Sets whether to show when a command/module is blocked. | `{Prefix}verbose true`")
 | 
			
		||||
                    .Parameter("arg", ParameterType.Required)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var arg = arg;
 | 
			
		||||
                        var val = PermissionHelper.ValidateBool(arg);
 | 
			
		||||
                        await PermissionsHandler.SetVerbosity(e.Server, val).ConfigureAwait(false);
 | 
			
		||||
                        await channel.SendMessageAsync($"Verbosity set to {val}.").ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "srvrperms")
 | 
			
		||||
                    .Alias(Prefix + "sp")
 | 
			
		||||
                    .Description($"Shows banned permissions for this server. | `{Prefix}sp`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var perms = PermissionsHandler.GetServerPermissions(e.Server);
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(perms?.ToString()))
 | 
			
		||||
                            await channel.SendMessageAsync("No permissions set for this server.").ConfigureAwait(false);
 | 
			
		||||
                        await channel.SendMessageAsync(perms.ToString()).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "roleperms")
 | 
			
		||||
                    .Alias(Prefix + "rp")
 | 
			
		||||
                    .Description($"Shows banned permissions for a certain role. No argument means for everyone. | `{Prefix}rp AwesomeRole`")
 | 
			
		||||
                    .Parameter("role", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var arg = role;
 | 
			
		||||
                        var role = e.Server.EveryoneRole;
 | 
			
		||||
                        if (!string.IsNullOrWhiteSpace(arg))
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                role = PermissionHelper.ValidateRole(e.Server, arg);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (Exception ex)
 | 
			
		||||
                            {
 | 
			
		||||
                                await channel.SendMessageAsync("💢 Error: " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                        var perms = PermissionsHandler.GetRolePermissionsById(e.Server, role.Id);
 | 
			
		||||
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(perms?.ToString()))
 | 
			
		||||
                            await channel.SendMessageAsync($"No permissions set for **{role.Name}** role.").ConfigureAwait(false);
 | 
			
		||||
                        await channel.SendMessageAsync(perms.ToString()).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "chnlperms")
 | 
			
		||||
                    .Alias(Prefix + "cp")
 | 
			
		||||
                    .Description($"Shows banned permissions for a certain channel. No argument means for this channel. | `{Prefix}cp #dev`")
 | 
			
		||||
                    .Parameter("channel", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var arg = channel;
 | 
			
		||||
                        var channel = e.Channel;
 | 
			
		||||
                        if (!string.IsNullOrWhiteSpace(arg))
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                channel = PermissionHelper.ValidateChannel(e.Server, arg);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (Exception ex)
 | 
			
		||||
                            {
 | 
			
		||||
                                await channel.SendMessageAsync("💢 Error: " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                        var perms = PermissionsHandler.GetChannelPermissionsById(e.Server, channel.Id);
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(perms?.ToString()))
 | 
			
		||||
                            await channel.SendMessageAsync($"No permissions set for **{channel.Name}** channel.").ConfigureAwait(false);
 | 
			
		||||
                        await channel.SendMessageAsync(perms.ToString()).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "userperms")
 | 
			
		||||
                    .Alias(Prefix + "up")
 | 
			
		||||
                    .Description($"Shows banned permissions for a certain user. No argument means for yourself. | `{Prefix}up Kwoth`")
 | 
			
		||||
                    .Parameter("user", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var user = umsg.Author;
 | 
			
		||||
                        if (!string.IsNullOrWhiteSpace(user))
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                user = PermissionHelper.ValidateUser(e.Server, user);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (Exception ex)
 | 
			
		||||
                            {
 | 
			
		||||
                                await channel.SendMessageAsync("💢 Error: " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                        var perms = PermissionsHandler.GetUserPermissionsById(e.Server, user.Id);
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(perms?.ToString()))
 | 
			
		||||
                            await channel.SendMessageAsync($"No permissions set for user **{user.Name}**.").ConfigureAwait(false);
 | 
			
		||||
                        await channel.SendMessageAsync(perms.ToString()).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "srvrmdl")
 | 
			
		||||
                    .Alias(Prefix + "sm")
 | 
			
		||||
                    .Parameter("module", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Description($"Sets a module's permission at the server level. | `{Prefix}sm \"module name\" enable`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var module = PermissionHelper.ValidateModule(module);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.SetServerModulePermission(e.Server, module, state).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "srvrcmd").Alias(Prefix + "sc")
 | 
			
		||||
                    .Parameter("command", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Description($"Sets a command's permission at the server level. | `{Prefix}sc \"command name\" disable`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var command = PermissionHelper.ValidateCommand(command);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.SetServerCommandPermission(e.Server, command, state).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "rolemdl").Alias(Prefix + "rm")
 | 
			
		||||
                    .Parameter("module", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("role", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets a module's permission at the role level. | `{Prefix}rm \"module name\" enable MyRole`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var module = PermissionHelper.ValidateModule(module);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
 | 
			
		||||
                            if (role?.ToLower() == "all")
 | 
			
		||||
                            {
 | 
			
		||||
                                foreach (var role in e.Server.Roles)
 | 
			
		||||
                                {
 | 
			
		||||
                                    await PermissionsHandler.SetRoleModulePermission(role, module, state).ConfigureAwait(false);
 | 
			
		||||
                                }
 | 
			
		||||
                                await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **ALL** roles.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                var role = PermissionHelper.ValidateRole(e.Server, role);
 | 
			
		||||
 | 
			
		||||
                                await PermissionsHandler.SetRoleModulePermission(role, module, state).ConfigureAwait(false);
 | 
			
		||||
                                await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "rolecmd").Alias(Prefix + "rc")
 | 
			
		||||
                    .Parameter("command", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("role", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets a command's permission at the role level. | `{Prefix}rc \"command name\" disable MyRole`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var command = PermissionHelper.ValidateCommand(command);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
 | 
			
		||||
                            if (role?.ToLower() == "all")
 | 
			
		||||
                            {
 | 
			
		||||
                                foreach (var role in e.Server.Roles)
 | 
			
		||||
                                {
 | 
			
		||||
                                    await PermissionsHandler.SetRoleCommandPermission(role, command, state).ConfigureAwait(false);
 | 
			
		||||
                                }
 | 
			
		||||
                                await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **ALL** roles.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                var role = PermissionHelper.ValidateRole(e.Server, role);
 | 
			
		||||
 | 
			
		||||
                                await PermissionsHandler.SetRoleCommandPermission(role, command, state).ConfigureAwait(false);
 | 
			
		||||
                                await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "chnlmdl").Alias(Prefix + "cm")
 | 
			
		||||
                    .Parameter("module", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("channel", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets a module's permission at the channel level. | `{Prefix}cm \"module name\" enable SomeChannel`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var module = PermissionHelper.ValidateModule(module);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var channelArg = channel;
 | 
			
		||||
                            if (channelArg?.ToLower() == "all")
 | 
			
		||||
                            {
 | 
			
		||||
                                foreach (var channel in e.Server.TextChannels)
 | 
			
		||||
                                {
 | 
			
		||||
                                    await PermissionsHandler.SetChannelModulePermission(channel, module, state).ConfigureAwait(false);
 | 
			
		||||
                                }
 | 
			
		||||
                                await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** on **ALL** channels.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (string.IsNullOrWhiteSpace(channelArg))
 | 
			
		||||
                            {
 | 
			
		||||
                                await PermissionsHandler.SetChannelModulePermission(e.Channel, module, state).ConfigureAwait(false);
 | 
			
		||||
                                await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{e.Channel.Name}** channel.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                var channel = PermissionHelper.ValidateChannel(e.Server, channelArg);
 | 
			
		||||
 | 
			
		||||
                                await PermissionsHandler.SetChannelModulePermission(channel, module, state).ConfigureAwait(false);
 | 
			
		||||
                                await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "chnlcmd").Alias(Prefix + "cc")
 | 
			
		||||
                    .Parameter("command", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("channel", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets a command's permission at the channel level. | `{Prefix}cc \"command name\" enable SomeChannel`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var command = PermissionHelper.ValidateCommand(command);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
 | 
			
		||||
                            if (channel?.ToLower() == "all")
 | 
			
		||||
                            {
 | 
			
		||||
                                foreach (var channel in e.Server.TextChannels)
 | 
			
		||||
                                {
 | 
			
		||||
                                    await PermissionsHandler.SetChannelCommandPermission(channel, command, state).ConfigureAwait(false);
 | 
			
		||||
                                }
 | 
			
		||||
                                await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** on **ALL** channels.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                var channel = PermissionHelper.ValidateChannel(e.Server, channel);
 | 
			
		||||
 | 
			
		||||
                                await PermissionsHandler.SetChannelCommandPermission(channel, command, state).ConfigureAwait(false);
 | 
			
		||||
                                await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "usrmdl").Alias(Prefix + "um")
 | 
			
		||||
                    .Parameter("module", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("user", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets a module's permission at the user level. | `{Prefix}um \"module name\" enable SomeUsername`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var module = PermissionHelper.ValidateModule(module);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var user = PermissionHelper.ValidateUser(e.Server, user);
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.SetUserModulePermission(user, module, state).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "usrcmd").Alias(Prefix + "uc")
 | 
			
		||||
                    .Parameter("command", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("user", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets a command's permission at the user level. | `{Prefix}uc \"command name\" enable SomeUsername`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var command = PermissionHelper.ValidateCommand(command);
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var user = PermissionHelper.ValidateUser(e.Server, user);
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.SetUserCommandPermission(user, command, state).ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "allsrvrmdls").Alias(Prefix + "asm")
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Description($"Sets permissions for all modules at the server level. | `{Prefix}asm [enable/disable]`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
 | 
			
		||||
                            foreach (var module in NadekoBot.Client.GetService<ModuleService>().Modules)
 | 
			
		||||
                            {
 | 
			
		||||
                                await PermissionsHandler.SetServerModulePermission(e.Server, module.Name, state).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            await channel.SendMessageAsync($"All modules have been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "allsrvrcmds").Alias(Prefix + "asc")
 | 
			
		||||
                    .Parameter("module", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Description($"Sets permissions for all commands from a certain module at the server level. | `{Prefix}asc \"module name\" [enable/disable]`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var module = PermissionHelper.ValidateModule(module);
 | 
			
		||||
 | 
			
		||||
                            foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
 | 
			
		||||
                            {
 | 
			
		||||
                                await PermissionsHandler.SetServerCommandPermission(e.Server, command.Text, state).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            await channel.SendMessageAsync($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "allchnlmdls").Alias(Prefix + "acm")
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("channel", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets permissions for all modules at the channel level. | `{Prefix}acm [enable/disable] SomeChannel`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var chArg = channel;
 | 
			
		||||
                            var channel = string.IsNullOrWhiteSpace(chArg) ? e.Channel : PermissionHelper.ValidateChannel(e.Server, chArg);
 | 
			
		||||
                            foreach (var module in NadekoBot.Client.GetService<ModuleService>().Modules)
 | 
			
		||||
                            {
 | 
			
		||||
                                await PermissionsHandler.SetChannelModulePermission(channel, module.Name, state).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            await channel.SendMessageAsync($"All modules have been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "allchnlcmds").Alias(Prefix + "acc")
 | 
			
		||||
                    .Parameter("module", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("channel", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets permissions for all commands from a certain module at the channel level. | `{Prefix}acc \"module name\" [enable/disable] SomeChannel`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var module = PermissionHelper.ValidateModule(module);
 | 
			
		||||
                            var channel = PermissionHelper.ValidateChannel(e.Server, channel);
 | 
			
		||||
                            foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
 | 
			
		||||
                            {
 | 
			
		||||
                                await PermissionsHandler.SetChannelCommandPermission(channel, command.Text, state).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            await channel.SendMessageAsync($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "allrolemdls").Alias(Prefix + "arm")
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("role", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets permissions for all modules at the role level. | `{Prefix}arm [enable/disable] MyRole`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var role = PermissionHelper.ValidateRole(e.Server, role);
 | 
			
		||||
                            foreach (var module in NadekoBot.Client.GetService<ModuleService>().Modules)
 | 
			
		||||
                            {
 | 
			
		||||
                                await PermissionsHandler.SetRoleModulePermission(role, module.Name, state).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            await channel.SendMessageAsync($"All modules have been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "allrolecmds").Alias(Prefix + "arc")
 | 
			
		||||
                    .Parameter("module", ParameterType.Required)
 | 
			
		||||
                    .Parameter("bool", ParameterType.Required)
 | 
			
		||||
                    .Parameter("role", ParameterType.Unparsed)
 | 
			
		||||
                    .Description($"Sets permissions for all commands from a certain module at the role level. | `{Prefix}arc \"module name\" [enable/disable] MyRole`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var state = PermissionHelper.ValidateBool(bool);
 | 
			
		||||
                            var module = PermissionHelper.ValidateModule(module);
 | 
			
		||||
                            if (role?.ToLower() == "all")
 | 
			
		||||
                            {
 | 
			
		||||
                                foreach (var role in e.Server.Roles)
 | 
			
		||||
                                {
 | 
			
		||||
                                    foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
 | 
			
		||||
                                    {
 | 
			
		||||
                                        await PermissionsHandler.SetRoleCommandPermission(role, command.Text, state).ConfigureAwait(false);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                await channel.SendMessageAsync($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **all roles** role.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                var role = PermissionHelper.ValidateRole(e.Server, role);
 | 
			
		||||
 | 
			
		||||
                                foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
 | 
			
		||||
                                {
 | 
			
		||||
                                    await PermissionsHandler.SetRoleCommandPermission(role, command.Text, state).ConfigureAwait(false);
 | 
			
		||||
                                }
 | 
			
		||||
                                await channel.SendMessageAsync($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "ubl")
 | 
			
		||||
                    .Description($"Blacklists a mentioned user. | `{Prefix}ubl [user_mention]`")
 | 
			
		||||
                    .Parameter("user", ParameterType.Unparsed)
 | 
			
		||||
                    .AddCheck(SimpleCheckers.OwnerOnly())
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        await Task.Run(async () =>
 | 
			
		||||
                        {
 | 
			
		||||
                            if (!e.Message.MentionedUsers.Any()) return;
 | 
			
		||||
                            var usr = e.Message.MentionedUsers.First();
 | 
			
		||||
                            NadekoBot.Config.UserBlacklist.Add(usr.Id);
 | 
			
		||||
                            await ConfigHandler.SaveConfig().ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"`Sucessfully blacklisted user {usr.Name}`").ConfigureAwait(false);
 | 
			
		||||
                        }).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "uubl")
 | 
			
		||||
                   .Description($"Unblacklists a mentioned user. | `{Prefix}uubl [user_mention]`")
 | 
			
		||||
                   .Parameter("user", ParameterType.Unparsed)
 | 
			
		||||
                   .AddCheck(SimpleCheckers.OwnerOnly())
 | 
			
		||||
                   .Do(async e =>
 | 
			
		||||
                   {
 | 
			
		||||
                       await Task.Run(async () =>
 | 
			
		||||
                       {
 | 
			
		||||
                           if (!e.Message.MentionedUsers.Any()) return;
 | 
			
		||||
                           var usr = e.Message.MentionedUsers.First();
 | 
			
		||||
                           if (NadekoBot.Config.UserBlacklist.Contains(usr.Id))
 | 
			
		||||
                           {
 | 
			
		||||
                               NadekoBot.Config.UserBlacklist.Remove(usr.Id);
 | 
			
		||||
                               await ConfigHandler.SaveConfig().ConfigureAwait(false);
 | 
			
		||||
                               await channel.SendMessageAsync($"`Sucessfully unblacklisted user {usr.Name}`").ConfigureAwait(false);
 | 
			
		||||
                           }
 | 
			
		||||
                           else
 | 
			
		||||
                           {
 | 
			
		||||
                               await channel.SendMessageAsync($"`{usr.Name} was not in blacklist`").ConfigureAwait(false);
 | 
			
		||||
                           }
 | 
			
		||||
                       }).ConfigureAwait(false);
 | 
			
		||||
                   });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "cbl")
 | 
			
		||||
                    .Description($"Blacklists a mentioned channel (#general for example). | `{Prefix}cbl #some_channel`")
 | 
			
		||||
                    .Parameter("channel", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        await Task.Run(async () =>
 | 
			
		||||
                        {
 | 
			
		||||
                            if (!e.Message.MentionedChannels.Any()) return;
 | 
			
		||||
                            var ch = e.Message.MentionedChannels.First();
 | 
			
		||||
                            NadekoBot.Config.UserBlacklist.Add(ch.Id);
 | 
			
		||||
                            await ConfigHandler.SaveConfig().ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false);
 | 
			
		||||
                        }).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "cubl")
 | 
			
		||||
                    .Description($"Unblacklists a mentioned channel (#general for example). | `{Prefix}cubl #some_channel`")
 | 
			
		||||
                    .Parameter("channel", ParameterType.Unparsed)
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        await Task.Run(async () =>
 | 
			
		||||
                        {
 | 
			
		||||
                            if (!e.Message.MentionedChannels.Any()) return;
 | 
			
		||||
                            var ch = e.Message.MentionedChannels.First();
 | 
			
		||||
                            NadekoBot.Config.UserBlacklist.Remove(ch.Id);
 | 
			
		||||
                            await ConfigHandler.SaveConfig().ConfigureAwait(false);
 | 
			
		||||
                            await channel.SendMessageAsync($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false);
 | 
			
		||||
                        }).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "sbl")
 | 
			
		||||
                    .Description($"Blacklists a server by a name or id (#general for example). **BOT OWNER ONLY** | `{Prefix}sbl [servername/serverid]`")
 | 
			
		||||
                    .Parameter("server", ParameterType.Unparsed)
 | 
			
		||||
                    .AddCheck(SimpleCheckers.OwnerOnly())
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        await Task.Run(async () =>
 | 
			
		||||
                        {
 | 
			
		||||
                            var arg = server?.Trim();
 | 
			
		||||
                            if (string.IsNullOrWhiteSpace(arg))
 | 
			
		||||
                                return;
 | 
			
		||||
                            var server = NadekoBot.Client.Servers.FirstOrDefault(s => s.Id.ToString() == arg) ??
 | 
			
		||||
                                         NadekoBot.Client.FindServers(arg.Trim()).FirstOrDefault();
 | 
			
		||||
                            if (server == null)
 | 
			
		||||
                            {
 | 
			
		||||
                                await channel.SendMessageAsync("Cannot find that server").ConfigureAwait(false);
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
                            var serverId = server.Id;
 | 
			
		||||
                            NadekoBot.Config.ServerBlacklist.Add(serverId);
 | 
			
		||||
                            await ConfigHandler.SaveConfig().ConfigureAwait(false);
 | 
			
		||||
                            //cleanup trivias and typeracing
 | 
			
		||||
                            Modules.Games.Commands.Trivia.TriviaGame trivia;
 | 
			
		||||
                            TriviaCommands.RunningTrivias.TryRemove(serverId, out trivia);
 | 
			
		||||
                            TypingGame typeracer;
 | 
			
		||||
                            SpeedTyping.RunningContests.TryRemove(serverId, out typeracer);
 | 
			
		||||
 | 
			
		||||
                            await channel.SendMessageAsync($"`Sucessfully blacklisted server {server.Name}`").ConfigureAwait(false);
 | 
			
		||||
                        }).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "cmdcooldown")
 | 
			
		||||
                    .Alias(Prefix+ "cmdcd")
 | 
			
		||||
                    .Description($"Sets a cooldown per user for a command. Set 0 to clear. | `{Prefix}cmdcd \"some cmd\" 5`")
 | 
			
		||||
                    .Parameter("command", ParameterType.Required)
 | 
			
		||||
                    .Parameter("secs",ParameterType.Required)
 | 
			
		||||
                    .AddCheck(SimpleCheckers.ManageMessages())
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            var command = PermissionHelper.ValidateCommand(command);
 | 
			
		||||
                            var secsStr = secs.Trim();
 | 
			
		||||
                            int secs;
 | 
			
		||||
                            if (!int.TryParse(secsStr, out secs) || secs < 0 || secs > 3600)
 | 
			
		||||
                                throw new ArgumentOutOfRangeException("secs", "Invalid second parameter. (Must be a number between 0 and 3600)");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                            await PermissionsHandler.SetCommandCooldown(e.Server, command, secs).ConfigureAwait(false);
 | 
			
		||||
                            if(secs == 0)
 | 
			
		||||
                                await channel.SendMessageAsync($"Command **{command}** has no coooldown now.").ConfigureAwait(false);
 | 
			
		||||
                            else
 | 
			
		||||
                                await channel.SendMessageAsync($"Command **{command}** now has a **{secs} {(secs==1 ? "second" : "seconds")}** cooldown.").ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (ArgumentException exArg)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync(exArg.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("Something went terribly wrong - " + ex.Message).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                cgb.CreateCommand(Prefix + "allcmdcooldowns")
 | 
			
		||||
                    .Alias(Prefix + "acmdcds")
 | 
			
		||||
                    .Description("Shows a list of all commands and their respective cooldowns. | `{Prefix}acmdcds`")
 | 
			
		||||
                    .Do(async e =>
 | 
			
		||||
                    {
 | 
			
		||||
                        ServerPermissions perms;
 | 
			
		||||
                        PermissionsHandler.PermissionsDict.TryGetValue(e.Server.Id, out perms);
 | 
			
		||||
                        if (perms == null)
 | 
			
		||||
                            return;
 | 
			
		||||
 | 
			
		||||
                        if (!perms.CommandCooldowns.Any())
 | 
			
		||||
                        {
 | 
			
		||||
                            await channel.SendMessageAsync("`No command cooldowns set.`").ConfigureAwait(false);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        await channel.SendMessageAsync(SearchHelper.ShowInPrettyCode(perms.CommandCooldowns.Select(c=>c.Key+ ": "+c.Value+" secs"),s=>$"{s,-30}",2)).ConfigureAwait(false);
 | 
			
		||||
                    });
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user