almost done
This commit is contained in:
		@@ -144,7 +144,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (roleToEdit.Position > (await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false)).Roles.Max(r => r.Position))
 | 
			
		||||
                if (roleToEdit.Position > (await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false)).GetRoles().Max(r => r.Position))
 | 
			
		||||
                {
 | 
			
		||||
                    await Context.Channel.SendErrorAsync("🚫 You can't edit roles higher than your highest role.").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
@@ -165,7 +165,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await user.RemoveRolesAsync(user.Roles).ConfigureAwait(false);
 | 
			
		||||
                await user.RemoveRolesAsync(user.GetRoles()).ConfigureAwait(false);
 | 
			
		||||
                await Context.Channel.SendConfirmAsync($"🗑 Successfully removed **all** roles from user **{user.Username}**").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
@@ -237,7 +237,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            {
 | 
			
		||||
                msg = "❗️No reason provided.";
 | 
			
		||||
            }
 | 
			
		||||
            if (Context.User.Id != user.Guild.OwnerId && Context.User.Roles.Select(r=>r.Position).Max() >= ((IGuildUser)Context.User).Roles.Select(r => r.Position).Max())
 | 
			
		||||
            if (Context.User.Id != user.Guild.OwnerId && ((IGuildUser)Context.User).GetRoles().Select(r=>r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
 | 
			
		||||
            {
 | 
			
		||||
                await Context.Channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -271,7 +271,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            {
 | 
			
		||||
                msg = "❗️No reason provided.";
 | 
			
		||||
            }
 | 
			
		||||
            if (Context.User.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)Context.User).Roles.Select(r => r.Position).Max())
 | 
			
		||||
            if (Context.User.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
 | 
			
		||||
            {
 | 
			
		||||
                await Context.Channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
 | 
			
		||||
                return;
 | 
			
		||||
@@ -308,7 +308,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (Context.Message.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)Context.User).Roles.Select(r => r.Position).Max())
 | 
			
		||||
            if (Context.Message.Author.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
 | 
			
		||||
            {
 | 
			
		||||
                await Context.Channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
 | 
			
		||||
                return;
 | 
			
		||||
@@ -564,7 +564,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            else if (ids[1].ToUpperInvariant().StartsWith("U:"))
 | 
			
		||||
            {
 | 
			
		||||
                var uid = ulong.Parse(ids[1].Substring(2));
 | 
			
		||||
                var user = (await server.GetUsersAsync()).Where(u => u.Id == uid).FirstOrDefault();
 | 
			
		||||
                var user = server.Users.Where(u => u.Id == uid).FirstOrDefault();
 | 
			
		||||
                if (user == null)
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
@@ -631,7 +631,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            foreach (var role in roles)
 | 
			
		||||
            { 
 | 
			
		||||
                send += $"\n**{role.Name}**\n";
 | 
			
		||||
                send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.Roles.Contains(role)).Distinct().Select(u=>u.Mention));
 | 
			
		||||
                send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.GetRoles().Contains(role)).Distinct().Select(u=>u.Mention));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            while (send.Length > 2000)
 | 
			
		||||
 
 | 
			
		||||
@@ -158,7 +158,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                        case PunishmentAction.Mute:
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                await MuteCommands.Mute(gu).ConfigureAwait(false);
 | 
			
		||||
                                await MuteCommands.MuteUser(gu).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); }
 | 
			
		||||
                            break;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
@@ -18,7 +19,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
    public partial class Administration
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class LogCommands
 | 
			
		||||
        public class LogCommands : ModuleBase
 | 
			
		||||
        {
 | 
			
		||||
            private static ShardedDiscordClient _client { get; }
 | 
			
		||||
            private static Logger _log { get; }
 | 
			
		||||
@@ -29,7 +30,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
 | 
			
		||||
            private static ConcurrentDictionary<ITextChannel, List<string>> UserPresenceUpdates { get; } = new ConcurrentDictionary<ITextChannel, List<string>>();
 | 
			
		||||
            private static Timer timerReference { get; }
 | 
			
		||||
            private IGoogleApiService _google { get; }
 | 
			
		||||
 | 
			
		||||
            static LogCommands()
 | 
			
		||||
            {
 | 
			
		||||
@@ -60,10 +60,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                        _log.Warn(ex);
 | 
			
		||||
                    }
 | 
			
		||||
                }, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public LogCommands()
 | 
			
		||||
            {
 | 
			
		||||
                _client.MessageUpdated += _client_MessageUpdated;
 | 
			
		||||
                _client.MessageDeleted += _client_MessageDeleted;
 | 
			
		||||
                _client.UserBanned += _client_UserBanned;
 | 
			
		||||
@@ -72,7 +69,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                _client.UserLeft += _client_UserLeft;
 | 
			
		||||
                _client.UserPresenceUpdated += _client_UserPresenceUpdated;
 | 
			
		||||
                _client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
 | 
			
		||||
                _client.UserUpdated += _client_UserUpdated;
 | 
			
		||||
                //_client.UserUpdated += _client_UserUpdated;
 | 
			
		||||
 | 
			
		||||
                _client.ChannelCreated += _client_ChannelCreated;
 | 
			
		||||
                _client.ChannelDestroyed += _client_ChannelDestroyed;
 | 
			
		||||
@@ -82,16 +79,16 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                MuteCommands.UserUnmuted += MuteCommands_UserUnmuted;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task MuteCommands_UserMuted(IGuildUser usr, MuteCommands.MuteType muteType)
 | 
			
		||||
            private static async Task MuteCommands_UserMuted(IGuildUser usr, MuteCommands.MuteType muteType)
 | 
			
		||||
            {
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
@@ -111,19 +108,19 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🔇 **| User muted from the {mutes}. |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task MuteCommands_UserUnmuted(IGuildUser usr, MuteCommands.MuteType muteType)
 | 
			
		||||
            private static async Task MuteCommands_UserUnmuted(IGuildUser usr, MuteCommands.MuteType muteType)
 | 
			
		||||
            {
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
@@ -143,7 +140,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🔊 **| User unmuted from the {mutes}. |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public static async Task TriggeredAntiProtection(IGuildUser[] users, PunishmentAction action, ProtectionType protection)
 | 
			
		||||
@@ -156,7 +153,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    || !logSetting.IsLogging)
 | 
			
		||||
                    return;
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(users.First().Guild, logSetting)) == null)
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(users.First().Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var punishment = "";
 | 
			
		||||
@@ -179,63 +176,63 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                //await logChannel.SendMessageAsync(String.Join("\n",users.Select(user=>$"{Format.Bold(user.ToString())} was **{punishment}** due to `{protection}` protection on **{user.Guild.Name}** server.")))
 | 
			
		||||
                                .ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            //todo
 | 
			
		||||
            //private static async Task _client_UserUpdated(SocketUser before, SocketUser after)
 | 
			
		||||
            //{
 | 
			
		||||
            //    LogSetting logSetting;
 | 
			
		||||
            //    if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
 | 
			
		||||
            //        || !logSetting.IsLogging
 | 
			
		||||
            //        || !logSetting.UserUpdated)
 | 
			
		||||
            //        return;
 | 
			
		||||
 | 
			
		||||
            private Task _client_UserUpdated(IGuildUser before, IGuildUser after)
 | 
			
		||||
            {
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.UserUpdated)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
            //    ITextChannel logChannel;
 | 
			
		||||
            //    if ((logChannel = await TryGetLogChannel(before.Guild, logSetting)) == null)
 | 
			
		||||
            //        return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(before.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
            //    var task = Task.Run(async () =>
 | 
			
		||||
            //    {
 | 
			
		||||
            //        try
 | 
			
		||||
            //        {
 | 
			
		||||
            //            string str = $"🕔`{prettyCurrentTime}`";
 | 
			
		||||
            //            if (before.Username != after.Username)
 | 
			
		||||
            //                //str += $"**Name Changed**`{before.Username}#{before.Discriminator}`\n\t\t`New:`{after.ToString()}`";
 | 
			
		||||
            //                str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**";
 | 
			
		||||
            //            else if (before.Nickname != after.Nickname)
 | 
			
		||||
            //                str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**";
 | 
			
		||||
            //                //str += $"**Nickname Changed**`{before.Username}#{before.Discriminator}`\n\t\t`Old:` {before.Nickname}#{before.Discriminator}\n\t\t`New:` {after.Nickname}#{after.Discriminator}";
 | 
			
		||||
            //            else if (before.AvatarUrl != after.AvatarUrl)
 | 
			
		||||
            //                //str += $"**Avatar Changed**👤`{before.Username}#{before.Discriminator}`\n\t {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
 | 
			
		||||
            //                str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
 | 
			
		||||
            //            else if (!before.GetRoles().SequenceEqual(after.GetRoles()))
 | 
			
		||||
            //            {
 | 
			
		||||
            //                if (before.GetRoles().Count() < after.GetRoles().Count())
 | 
			
		||||
            //                {
 | 
			
		||||
            //                    var diffRoles = after.GetRoles().Where(r => !before.GetRoles().Contains(r)).Select(r => "**" + r.Name + "**");
 | 
			
		||||
            //                    //str += $"**User's Roles changed ⚔➕**👤`{before.ToString()}`\n\tNow has {string.Join(", ", diffRoles)} role.";
 | 
			
		||||
            //                    str += $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
 | 
			
		||||
            //                }
 | 
			
		||||
            //                else if (before.GetRoles().Count() > after.GetRoles().Count())
 | 
			
		||||
            //                {
 | 
			
		||||
            //                    var diffRoles = before.GetRoles().Where(r => !after.GetRoles().Contains(r)).Select(r => "**" + r.Name + "**");
 | 
			
		||||
            //                    //str += $"**User's Roles changed **`{before.ToString()}`\n\tNo longer has {string.Join(", ", diffRoles)} role.";
 | 
			
		||||
            //                    str += $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
 | 
			
		||||
            //                }
 | 
			
		||||
            //            }
 | 
			
		||||
            //            else
 | 
			
		||||
            //                return;
 | 
			
		||||
            //            try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
            //        }
 | 
			
		||||
            //        catch { }
 | 
			
		||||
            //    });
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        string str = $"🕔`{prettyCurrentTime}`";
 | 
			
		||||
                        if (before.Username != after.Username)
 | 
			
		||||
                            //str += $"**Name Changed**`{before.Username}#{before.Discriminator}`\n\t\t`New:`{after.ToString()}`";
 | 
			
		||||
                            str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**";
 | 
			
		||||
                        else if (before.Nickname != after.Nickname)
 | 
			
		||||
                            str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**";
 | 
			
		||||
                            //str += $"**Nickname Changed**`{before.Username}#{before.Discriminator}`\n\t\t`Old:` {before.Nickname}#{before.Discriminator}\n\t\t`New:` {after.Nickname}#{after.Discriminator}";
 | 
			
		||||
                        else if (before.AvatarUrl != after.AvatarUrl)
 | 
			
		||||
                            //str += $"**Avatar Changed**👤`{before.Username}#{before.Discriminator}`\n\t {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
 | 
			
		||||
                            str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}";
 | 
			
		||||
                        else if (!before.Roles.SequenceEqual(after.Roles))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (before.Roles.Count() < after.Roles.Count())
 | 
			
		||||
                            {
 | 
			
		||||
                                var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => "**" + r.Name + "**");
 | 
			
		||||
                                //str += $"**User's Roles changed ⚔➕**👤`{before.ToString()}`\n\tNow has {string.Join(", ", diffRoles)} role.";
 | 
			
		||||
                                str += $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (before.Roles.Count() > after.Roles.Count())
 | 
			
		||||
                            {
 | 
			
		||||
                                var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => "**" + r.Name + "**");
 | 
			
		||||
                                //str += $"**User's Roles changed **`{before.ToString()}`\n\tNo longer has {string.Join(", ", diffRoles)} role.";
 | 
			
		||||
                                str += $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                            return;
 | 
			
		||||
                        try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
                });
 | 
			
		||||
            //    return;
 | 
			
		||||
            //}
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
 | 
			
		||||
            private static async Task _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
 | 
			
		||||
            {
 | 
			
		||||
                var before = cbefore as IGuildChannel;
 | 
			
		||||
                if (before == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
                var after = (IGuildChannel)cafter;
 | 
			
		||||
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
@@ -243,11 +240,11 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.ChannelUpdated
 | 
			
		||||
                    || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == after.Id))
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(before.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(before.Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
@@ -267,78 +264,78 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    catch { }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_ChannelDestroyed(IChannel ich)
 | 
			
		||||
            private static async Task _client_ChannelDestroyed(IChannel ich)
 | 
			
		||||
            {
 | 
			
		||||
                var ch = ich as IGuildChannel;
 | 
			
		||||
                if (ch == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.ChannelDestroyed
 | 
			
		||||
                    || logSetting.IgnoredChannels.Any(ilc=>ilc.ChannelId == ch.Id))
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(ch.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($"🕕`{prettyCurrentTime}`🗑 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Deleted #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_ChannelCreated(IChannel ich)
 | 
			
		||||
            private static async Task _client_ChannelCreated(IChannel ich)
 | 
			
		||||
            {
 | 
			
		||||
                var ch = ich as IGuildChannel;
 | 
			
		||||
                if (ch == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.ChannelCreated)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(ch.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($"🕓`{prettyCurrentTime}`🆕 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Created: #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_UserVoiceStateUpdated(IUser iusr, IVoiceState before, IVoiceState after)
 | 
			
		||||
            private static async Task _client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
 | 
			
		||||
            {
 | 
			
		||||
                var usr = iusr as IGuildUser;
 | 
			
		||||
                var usr = iusr as SocketGuildUser;
 | 
			
		||||
                if (usr == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var beforeVch = before.VoiceChannel;
 | 
			
		||||
                var afterVch = after.VoiceChannel;
 | 
			
		||||
 | 
			
		||||
                if (beforeVch == afterVch)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.LogVoicePresence)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogChannelType.Voice)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogChannelType.Voice)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                    string str = null;
 | 
			
		||||
                    if (beforeVch?.Guild == afterVch?.Guild)
 | 
			
		||||
@@ -356,20 +353,24 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    if(str != null)
 | 
			
		||||
                        UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_UserPresenceUpdated(IGuildUser usr, IPresence before, IPresence after)
 | 
			
		||||
            private static async Task _client_UserPresenceUpdated(Optional<SocketGuild> oGuild, SocketUser usr, SocketPresence before, SocketPresence after)
 | 
			
		||||
            {
 | 
			
		||||
                if (!oGuild.IsSpecified)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var guild = oGuild.Value;
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.LogUserPresence
 | 
			
		||||
                    || before.Status == after.Status)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogChannelType.UserPresence)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(guild, logSetting, LogChannelType.UserPresence)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
                string str;
 | 
			
		||||
                if (before.Status != after.Status)
 | 
			
		||||
                    str = $"🔵`{prettyCurrentTime}`👤__**{usr.Username}**__ is now **{after.Status}**.";
 | 
			
		||||
@@ -378,116 +379,116 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
 | 
			
		||||
                UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_UserLeft(IGuildUser usr)
 | 
			
		||||
            private static async Task _client_UserLeft(IGuildUser usr)
 | 
			
		||||
            {
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.UserLeft)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($"❗️🕛`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__❌ **| USER LEFT |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_UserJoined(IGuildUser usr)
 | 
			
		||||
            private static async Task _client_UserJoined(IGuildUser usr)
 | 
			
		||||
            {
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.UserJoined)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($"❕🕓`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__✅ **| USER JOINED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_UserUnbanned(IUser usr, IGuild guild)
 | 
			
		||||
            private static async Task _client_UserUnbanned(IUser usr, IGuild guild)
 | 
			
		||||
            {
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.UserUnbanned)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                   try { await logChannel.SendMessageAsync($"❕🕘`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__♻️ **| USER UN-BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_UserBanned(IUser usr, IGuild guild)
 | 
			
		||||
            private static async Task _client_UserBanned(IUser usr, IGuild guild)
 | 
			
		||||
            {
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.UserBanned)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(guild, logSetting)) == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(guild, logSetting)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🚫 **| USER BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_MessageDeleted(ulong arg1, Optional<IMessage> imsg)
 | 
			
		||||
            private static async Task _client_MessageDeleted(ulong arg1, Optional<SocketMessage> imsg)
 | 
			
		||||
            {
 | 
			
		||||
                var msg = (imsg.IsSpecified ? imsg.Value : null) as IUserMessage;
 | 
			
		||||
                var msg = (imsg.IsSpecified ? imsg.Value : null) as SocketUserMessage;
 | 
			
		||||
                if (msg == null || msg.IsAuthor())
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                //var channel = Context.Channel as ITextChannel;
 | 
			
		||||
                var channel = msg.Channel as SocketTextChannel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(Context.Guild.Id, out logSetting)
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.MessageDeleted
 | 
			
		||||
                    || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id))
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(Context.Guild, logSetting)) == null || logChannel.Id == msg.Id)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting)) == null || logChannel.Id == msg.Id)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        var str = $@"🕔`{prettyCurrentTime}`👤__**{Context.User.Username}#{Context.User.Discriminator}**__ **| Deleted Message |** 🆔 `{Context.User.Id}` #⃣ `{channel.Name}`
 | 
			
		||||
🗑 {msg.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator)}";
 | 
			
		||||
                        var str = $@"🕔`{prettyCurrentTime}`👤__**{msg.Author.Username}#{msg.Author.Discriminator}**__ **| Deleted Message |** 🆔 `{msg.Author.Id}` #⃣ `{channel.Name}`
 | 
			
		||||
🗑 {msg.Resolve(userHandling: TagHandling.FullName)}";
 | 
			
		||||
                        if (msg.Attachments.Any())
 | 
			
		||||
                            str += $"{Environment.NewLine}📎 {string.Join(", ", msg.Attachments.Select(a => a.ProxyUrl))}";
 | 
			
		||||
                        await logChannel.SendMessageAsync(str.SanitizeMentions()).ConfigureAwait(false);
 | 
			
		||||
@@ -495,48 +496,48 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_MessageUpdated(Optional<IMessage> optmsg, IMessage imsg2)
 | 
			
		||||
            private static async Task _client_MessageUpdated(Optional<SocketMessage> optmsg, SocketMessage imsg2)
 | 
			
		||||
            {
 | 
			
		||||
                var after = imsg2 as IUserMessage;
 | 
			
		||||
                var after = imsg2 as SocketUserMessage;
 | 
			
		||||
                if (after == null || after.IsAuthor())
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return ;
 | 
			
		||||
 | 
			
		||||
                var before = (optmsg.IsSpecified ? optmsg.Value : null) as IUserMessage;
 | 
			
		||||
                var before = (optmsg.IsSpecified ? optmsg.Value : null) as SocketUserMessage;
 | 
			
		||||
                if (before == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                //var channel = after.Channel as ITextChannel;
 | 
			
		||||
                var channel = after.Channel as SocketTextChannel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return ;
 | 
			
		||||
 | 
			
		||||
                LogSetting logSetting;
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(Context.Guild.Id, out logSetting)
 | 
			
		||||
                if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting)
 | 
			
		||||
                    || !logSetting.IsLogging
 | 
			
		||||
                    || !logSetting.MessageUpdated
 | 
			
		||||
                    || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id))
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                ITextChannel logChannel;
 | 
			
		||||
                if ((logChannel = TryGetLogChannel(Context.Guild, logSetting)) == null || logChannel.Id == after.Channel.Id)
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting)) == null || logChannel.Id == after.Channel.Id)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var task = Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    //try { await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}` **Message** 📝 `#{channel.Name}`
 | 
			
		||||
//👤`{before.Author.Username}`
 | 
			
		||||
                    try { await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}`👤__**{before.Author.Username}#{before.Author.Discriminator}**__ **| 📝 Edited Message |** 🆔 `{before.Author.Id}` #⃣ `{channel.Name}`
 | 
			
		||||
        `Old:` {before.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}
 | 
			
		||||
        **`New:`** {after.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
        `Old:` {before.Resolve(userHandling: TagHandling.FullName).SanitizeMentions()}
 | 
			
		||||
        **`New:`** {after.Resolve(userHandling: TagHandling.FullName).SanitizeMentions()}").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private enum LogChannelType { Text, Voice, UserPresence };
 | 
			
		||||
            private static ITextChannel TryGetLogChannel(IGuild guild, LogSetting logSetting, LogChannelType logChannelType = LogChannelType.Text)
 | 
			
		||||
            private static async Task<ITextChannel> TryGetLogChannel(IGuild guild, LogSetting logSetting, LogChannelType logChannelType = LogChannelType.Text)
 | 
			
		||||
            {
 | 
			
		||||
                ulong id = 0;
 | 
			
		||||
                switch (logChannelType)
 | 
			
		||||
@@ -551,7 +552,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                        id = logSetting.UserPresenceChannelId;
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                //var channel = guild.GetTextChannel(id);
 | 
			
		||||
                var channel = await guild.GetTextChannelAsync(id);
 | 
			
		||||
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
@@ -591,7 +592,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    GuildLogSettings.AddOrUpdate(Context.Guild.Id, (id) => logSetting, (id, old) => logSetting);
 | 
			
		||||
                    logSetting.IsLogging = !logSetting.IsLogging;
 | 
			
		||||
                    if (logSetting.IsLogging)
 | 
			
		||||
                        logSetting.ChannelId = channel.Id;
 | 
			
		||||
                        logSetting.ChannelId = Context.Channel.Id;
 | 
			
		||||
                    await uow.CompleteAsync();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@@ -607,17 +608,16 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            [OwnerOnly]
 | 
			
		||||
            public async Task LogIgnore()
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                int removed;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    var config = uow.GuildConfigs.For(Context.Guild.Id);
 | 
			
		||||
                    LogSetting logSetting = GuildLogSettings.GetOrAdd(Context.Guild.Id, (id) => config.LogSetting);
 | 
			
		||||
                    removed = logSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
 | 
			
		||||
                    config.LogSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id);
 | 
			
		||||
                    removed = logSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == Context.Channel.Id);
 | 
			
		||||
                    config.LogSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == Context.Channel.Id);
 | 
			
		||||
                    if (removed == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        var toAdd = new IgnoredLogChannel { ChannelId = channel.Id };
 | 
			
		||||
                        var toAdd = new IgnoredLogChannel { ChannelId = Context.Channel.Id };
 | 
			
		||||
                        logSetting.IgnoredChannels.Add(toAdd);
 | 
			
		||||
                        config.LogSetting.IgnoredChannels.Add(toAdd);
 | 
			
		||||
                    }
 | 
			
		||||
@@ -625,9 +625,9 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (removed == 0)
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"🆗 Logging will **now ignore** #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"🆗 Logging will **now ignore** #⃣ `{Context.Channel.Name} ({Context.Channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"ℹ️ Logging will **no longer ignore** #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"ℹ️ Logging will **no longer ignore** #⃣ `{Context.Channel.Name} ({Context.Channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
@@ -705,7 +705,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            [RequireUserPermission(GuildPermission.Administrator)]
 | 
			
		||||
            public async Task UserPresence()
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                bool enabled;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
@@ -713,12 +712,12 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    GuildLogSettings.AddOrUpdate(Context.Guild.Id, (id) => logSetting, (id, old) => logSetting);
 | 
			
		||||
                    enabled = logSetting.LogUserPresence = !logSetting.LogUserPresence;
 | 
			
		||||
                    if(enabled)
 | 
			
		||||
                        logSetting.UserPresenceChannelId = channel.Id;
 | 
			
		||||
                        logSetting.UserPresenceChannelId = Context.Channel.Id;
 | 
			
		||||
                    await uow.CompleteAsync().ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (enabled)
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"✅ Logging **user presence** updates in #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"✅ Logging **user presence** updates in #⃣ `{Context.Channel.Name} ({Context.Channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"ℹ️ Stopped logging **user presence** updates.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
@@ -728,7 +727,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            [RequireUserPermission(GuildPermission.Administrator)]
 | 
			
		||||
            public async Task VoicePresence()
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                bool enabled;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
@@ -738,12 +736,12 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    GuildLogSettings.AddOrUpdate(Context.Guild.Id, (id) => logSetting, (id, old) => logSetting);
 | 
			
		||||
                    enabled = logSetting.LogVoicePresence = !logSetting.LogVoicePresence;
 | 
			
		||||
                    if (enabled)
 | 
			
		||||
                        logSetting.VoicePresenceChannelId = channel.Id;
 | 
			
		||||
                        logSetting.VoicePresenceChannelId = Context.Channel.Id;
 | 
			
		||||
                    await uow.CompleteAsync().ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (enabled)
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"✅ Logging **voice presence** updates in #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"✅ Logging **voice presence** updates in #⃣ `{Context.Channel.Name} ({Context.Channel.Id})`").ConfigureAwait(false);
 | 
			
		||||
                else
 | 
			
		||||
                    await Context.Channel.SendMessageAsync($"ℹ️ Stopped logging **voice presence** updates.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                {
 | 
			
		||||
                    _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
                    this.Repeater = repeater;
 | 
			
		||||
                    this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannel(repeater.ChannelId);
 | 
			
		||||
                    this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannelAsync(repeater.ChannelId).GetAwaiter().GetResult();
 | 
			
		||||
                    if (Channel == null)
 | 
			
		||||
                        return;
 | 
			
		||||
                    Task.Run(Run);
 | 
			
		||||
 
 | 
			
		||||
@@ -118,7 +118,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                            await guild.CreateRoleAsync(defaultMuteRoleName, GuildPermissions.None).ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    foreach (var toOverwrite in guild.GetTextChannels())
 | 
			
		||||
                    foreach (var toOverwrite in (await guild.GetTextChannelsAsync()))
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
 
 | 
			
		||||
@@ -170,9 +170,11 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
 | 
			
		||||
                if (conf.ExclusiveSelfAssignedRoles)
 | 
			
		||||
                {
 | 
			
		||||
                    if (guildUser.RoleIds.Contains(role.Id))
 | 
			
		||||
                    var sameRoleId = guildUser.RoleIds.Where(r => roles.Select(sar => sar.RoleId).Contains(r)).FirstOrDefault();
 | 
			
		||||
                    var sameRole = Context.Guild.GetRole(sameRoleId);
 | 
			
		||||
                    if (sameRoleId != default(ulong))
 | 
			
		||||
                    {
 | 
			
		||||
                        await Context.Channel.SendErrorAsync($"You already have **{sameRoles.FirstOrDefault().Name}** `exclusive self-assigned` role.").ConfigureAwait(false);
 | 
			
		||||
                        await Context.Channel.SendErrorAsync($"You already have **{sameRole?.Name}** `exclusive self-assigned` role.").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,9 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
                        .Select(cw =>
 | 
			
		||||
                        {
 | 
			
		||||
                            cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId)
 | 
			
		||||
                                                         ?.GetTextChannel(cw.ChannelId);
 | 
			
		||||
                                                         ?.GetTextChannelAsync(cw.ChannelId)
 | 
			
		||||
                                                         .GetAwaiter()
 | 
			
		||||
                                                         .GetResult();
 | 
			
		||||
                            return cw;
 | 
			
		||||
                        })
 | 
			
		||||
                        .Where(cw => cw?.Channel != null)
 | 
			
		||||
@@ -294,6 +296,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
 | 
			
		||||
        public static async Task<ClashWar> CreateWar(string enemyClan, int size, ulong serverId, ulong channelId)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = await NadekoBot.Client.GetGuild(serverId)?.GetTextChannelAsync(channelId);
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                var cw = new ClashWar
 | 
			
		||||
@@ -303,8 +306,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
                    Bases = new List<ClashCaller>(size),
 | 
			
		||||
                    GuildId = serverId,
 | 
			
		||||
                    ChannelId = channelId,
 | 
			
		||||
                    Channel = NadekoBot.Client.GetGuild(serverId)
 | 
			
		||||
                                       ?.GetTextChannel(channelId)
 | 
			
		||||
                    Channel = channel,
 | 
			
		||||
                };
 | 
			
		||||
                cw.Bases.Capacity = size;
 | 
			
		||||
                for (int i = 0; i < size; i++)
 | 
			
		||||
 
 | 
			
		||||
@@ -10,23 +10,20 @@ using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Image = ImageSharp.Image;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Gambling
 | 
			
		||||
{
 | 
			
		||||
    public partial class Gambling
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class DriceRollCommands
 | 
			
		||||
        public class DriceRollCommands : ModuleBase
 | 
			
		||||
        {
 | 
			
		||||
            private Regex dndRegex { get; } = new Regex(@"^(?<n1>\d+)d(?<n2>\d+)(?:\+(?<add>\d+))?(?:\-(?<sub>\d+))?$", RegexOptions.Compiled);
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Roll()
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return;
 | 
			
		||||
                var rng = new NadekoRandom();
 | 
			
		||||
                var gen = rng.Next(1, 101);
 | 
			
		||||
 | 
			
		||||
@@ -48,14 +45,9 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            }
 | 
			
		||||
            //todo merge into internallDndRoll and internalRoll
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [Priority(1)]
 | 
			
		||||
            public async Task Roll(IUserMessage umsg, string arg)
 | 
			
		||||
            public async Task Roll(string arg)
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var ordered = true;
 | 
			
		||||
                var rng = new NadekoRandom();
 | 
			
		||||
                Match match;
 | 
			
		||||
@@ -84,14 +76,9 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [Priority(0)]
 | 
			
		||||
            public async Task Roll(IUserMessage umsg, int num)
 | 
			
		||||
            public async Task Roll(int num)
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var ordered = true;
 | 
			
		||||
 | 
			
		||||
                if (num < 1 || num > 30)
 | 
			
		||||
@@ -138,13 +125,8 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Rolluo(IUserMessage umsg, string arg)
 | 
			
		||||
            public async Task Rolluo(string arg)
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var ordered = false;
 | 
			
		||||
                var rng = new NadekoRandom();
 | 
			
		||||
                Match match;
 | 
			
		||||
@@ -173,13 +155,8 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Rolluo(IUserMessage umsg, int num)
 | 
			
		||||
            public async Task Rolluo(int num)
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                if (channel == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                var ordered = false;
 | 
			
		||||
 | 
			
		||||
                if (num < 1 || num > 30)
 | 
			
		||||
@@ -226,11 +203,8 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task NRoll(IUserMessage umsg, [Remainder] string range)
 | 
			
		||||
            public async Task NRoll([Remainder] string range)
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    int rolled;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,13 +10,14 @@ using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Image = ImageSharp.Image;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Gambling
 | 
			
		||||
{
 | 
			
		||||
    public partial class Gambling
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class DrawCommands
 | 
			
		||||
        public class DrawCommands : ModuleBase
 | 
			
		||||
        {
 | 
			
		||||
            private static readonly ConcurrentDictionary<IGuild, Cards> AllDecks = new ConcurrentDictionary<IGuild, Cards>();
 | 
			
		||||
 | 
			
		||||
@@ -33,7 +34,6 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Draw(int num = 1)
 | 
			
		||||
            {
 | 
			
		||||
                //var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
                var cards = AllDecks.GetOrAdd(Context.Guild, (s) => new Cards());
 | 
			
		||||
                var images = new List<Image>();
 | 
			
		||||
                var cardObjects = new List<Cards.Card>();
 | 
			
		||||
 
 | 
			
		||||
@@ -7,13 +7,14 @@ using NadekoBot.Services;
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Image = ImageSharp.Image;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Gambling
 | 
			
		||||
{
 | 
			
		||||
    public partial class Gambling
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class FlipCoinCommands
 | 
			
		||||
        public class FlipCoinCommands : ModuleBase
 | 
			
		||||
        {
 | 
			
		||||
            private static NadekoRandom rng { get; } = new NadekoRandom();
 | 
			
		||||
            private const string headsPath = "data/images/coins/heads.png";
 | 
			
		||||
 
 | 
			
		||||
@@ -110,8 +110,8 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        public async Task Award(int amount, [Remainder] IRole role)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
            var users = Context.Guild.GetUsers()
 | 
			
		||||
                               .Where(u => u.Roles.Contains(role))
 | 
			
		||||
            var users = (await Context.Guild.GetUsersAsync())
 | 
			
		||||
                               .Where(u => u.GetRoles().Contains(role))
 | 
			
		||||
                               .ToList();
 | 
			
		||||
            await Task.WhenAll(users.Select(u => CurrencyHandler.AddCurrencyAsync(u.Id,
 | 
			
		||||
                                                      $"Awarded by bot owner to **{role.Name}** role. ({Context.User.Username}/{Context.User.Id})",
 | 
			
		||||
@@ -218,7 +218,7 @@ $@"```xl
 | 
			
		||||
┃        Id           ┃  $$$   ┃
 | 
			
		||||
"),
 | 
			
		||||
                (cur, cs) => cur.AppendLine($@"┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━┫
 | 
			
		||||
┃{(Context.Guild.GetUser(cs.UserId)?.Username?.TrimTo(18, true) ?? cs.UserId.ToString()),-20} ┃ {cs.Amount,6} ┃")
 | 
			
		||||
┃{(Context.Guild.GetUserAsync(cs.UserId).GetAwaiter().GetResult()?.Username?.TrimTo(18, true) ?? cs.UserId.ToString()),-20} ┃ {cs.Amount,6} ┃")
 | 
			
		||||
                        ).ToString() + "┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━┛```").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
 | 
			
		||||
            var embed = new EmbedBuilder().WithTitle("Hangman Game")
 | 
			
		||||
                                          .WithDescription(toSend)
 | 
			
		||||
                                          .AddField(efb => efb.WithName("It was").WithValue(Term.Word))
 | 
			
		||||
                                          .WithImage(eib => eib.WithUrl(Term.ImageUrl));
 | 
			
		||||
                                          .WithImageUrl(Term.ImageUrl);
 | 
			
		||||
            if (Errors >= MaxErrors)
 | 
			
		||||
                await GameChannel.EmbedAsync(embed.WithColor(NadekoBot.ErrorColor)).ConfigureAwait(false);
 | 
			
		||||
            else
 | 
			
		||||
@@ -124,7 +124,7 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
 | 
			
		||||
 | 
			
		||||
        private Task PotentialGuess(IMessage msg)
 | 
			
		||||
        {
 | 
			
		||||
            if (Context.Channel != GameChannel)
 | 
			
		||||
            if (msg.Channel != GameChannel)
 | 
			
		||||
                return Task.CompletedTask; // message's channel has to be the same as game's
 | 
			
		||||
            if (msg.Content.Length != 1) // message must be 1 char long
 | 
			
		||||
            {
 | 
			
		||||
@@ -154,7 +154,7 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
 | 
			
		||||
                    {
 | 
			
		||||
                        ++Errors;
 | 
			
		||||
                        if (Errors < MaxErrors)
 | 
			
		||||
                            await GameChannel.SendErrorAsync("Hangman Game", $"{Context.User.Mention} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false);
 | 
			
		||||
                            await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false);
 | 
			
		||||
                        else
 | 
			
		||||
                            await End().ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
@@ -166,19 +166,19 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
 | 
			
		||||
                    {
 | 
			
		||||
                        if (GuessedAll)
 | 
			
		||||
                        {
 | 
			
		||||
                            try { await GameChannel.SendConfirmAsync("Hangman Game", $"{Context.User.Mention} guessed a letter `{guess}`!").ConfigureAwait(false); } catch { }
 | 
			
		||||
                            try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!").ConfigureAwait(false); } catch { }
 | 
			
		||||
 | 
			
		||||
                          await End().ConfigureAwait(false);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        try { await GameChannel.SendConfirmAsync("Hangman Game", $"{Context.User.Mention} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false); } catch { }
 | 
			
		||||
                        try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false); } catch { }
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        ++Errors;
 | 
			
		||||
                        if (Errors < MaxErrors)
 | 
			
		||||
                            await GameChannel.SendErrorAsync("Hangman Game", $"{Context.User.Mention} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false);
 | 
			
		||||
                            await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false);
 | 
			
		||||
                        else
 | 
			
		||||
                            await End().ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
@@ -190,16 +190,12 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string GetHangman()
 | 
			
		||||
        {
 | 
			
		||||
            return
 | 
			
		||||
$@"\_\_\_\_\_\_\_\_\_
 | 
			
		||||
        public string GetHangman() => $@"\_\_\_\_\_\_\_\_\_
 | 
			
		||||
      |           |
 | 
			
		||||
      |           |
 | 
			
		||||
   {(Errors > 0 ? "😲" : "      ")}        |
 | 
			
		||||
   {(Errors > 1 ? "/" : "  ")} {(Errors > 2 ? "|" : "  ")} {(Errors > 3 ? "\\" : "  ")}       | 
 | 
			
		||||
    {(Errors > 4 ? "/" : "  ")} {(Errors > 5 ? "\\" : "  ")}        |
 | 
			
		||||
               /-\";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -128,7 +128,7 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
 | 
			
		||||
        private Task PotentialGuess(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            if (Context.User.IsBot)
 | 
			
		||||
            if (imsg.Author.IsBot)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            var umsg = imsg as IUserMessage;
 | 
			
		||||
            if (umsg == null)
 | 
			
		||||
@@ -137,11 +137,11 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if (!(Context.Channel is IGuildChannel && Context.Channel is ITextChannel)) return;
 | 
			
		||||
                    if ((Context.Channel as ITextChannel).Guild != guild) return;
 | 
			
		||||
                    if (Context.User.Id == NadekoBot.Client.CurrentUser().Id) return;
 | 
			
		||||
                    if (!(imsg.Channel is IGuildChannel && imsg.Channel is ITextChannel)) return;
 | 
			
		||||
                    if ((imsg.Channel as ITextChannel).Guild != guild) return;
 | 
			
		||||
                    if (imsg.Author.Id == NadekoBot.Client.CurrentUser().Id) return;
 | 
			
		||||
 | 
			
		||||
                    var guildUser = Context.User as IGuildUser;
 | 
			
		||||
                    var guildUser = imsg.Author as IGuildUser;
 | 
			
		||||
 | 
			
		||||
                    var guess = false;
 | 
			
		||||
                    await _guessLock.WaitAsync().ConfigureAwait(false);
 | 
			
		||||
 
 | 
			
		||||
@@ -102,21 +102,19 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
            await channel.EmbedAsync(embed).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string GetCommandRequirements(CommandInfo cmd)
 | 
			
		||||
        {
 | 
			
		||||
            return String.Join(" ", cmd.Preconditions
 | 
			
		||||
                      .Where(ca => ca is OwnerOnlyAttribute || ca is RequireUserPermissionAttribute)
 | 
			
		||||
                      .Select(ca =>
 | 
			
		||||
                      {
 | 
			
		||||
                          if (ca is OwnerOnlyAttribute)
 | 
			
		||||
                              return "**Bot Owner only.**";
 | 
			
		||||
                          var cau = (RequireUserPermissionAttribute)ca;
 | 
			
		||||
                          if (cau.GuildPermission != null)
 | 
			
		||||
                              return $"**Requires {cau.GuildPermission} server permission.**".Replace("Guild", "Server");
 | 
			
		||||
                          else
 | 
			
		||||
                              return $"**Requires {cau.ChannelPermission} channel permission.**".Replace("Guild", "Server");
 | 
			
		||||
                      }));
 | 
			
		||||
        }
 | 
			
		||||
        private string GetCommandRequirements(CommandInfo cmd) => 
 | 
			
		||||
            String.Join(" ", cmd.Preconditions
 | 
			
		||||
                  .Where(ca => ca is OwnerOnlyAttribute || ca is RequireUserPermissionAttribute)
 | 
			
		||||
                  .Select(ca =>
 | 
			
		||||
                  {
 | 
			
		||||
                      if (ca is OwnerOnlyAttribute)
 | 
			
		||||
                          return "**Bot Owner only.**";
 | 
			
		||||
                      var cau = (RequireUserPermissionAttribute)ca;
 | 
			
		||||
                      if (cau.GuildPermission != null)
 | 
			
		||||
                          return $"**Requires {cau.GuildPermission} server permission.**".Replace("Guild", "Server");
 | 
			
		||||
                      else
 | 
			
		||||
                          return $"**Requires {cau.ChannelPermission} channel permission.**".Replace("Guild", "Server");
 | 
			
		||||
                  }));
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
 
 | 
			
		||||
@@ -122,7 +122,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task Queue([Remainder] string query)
 | 
			
		||||
        {
 | 
			
		||||
            await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query).ConfigureAwait(false);
 | 
			
		||||
            if (Context.Guild.GetCurrentUser().GetPermissions(Context.Channel).ManageMessages)
 | 
			
		||||
            if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(10000).ConfigureAwait(false);
 | 
			
		||||
                await Context.Message.DeleteAsync().ConfigureAwait(false);
 | 
			
		||||
@@ -134,7 +134,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task SoundCloudQueue([Remainder] string query)
 | 
			
		||||
        {
 | 
			
		||||
            await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
 | 
			
		||||
            if (Context.Guild.GetCurrentUser().GetPermissions(Context.Channel).ManageMessages)
 | 
			
		||||
            if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(10000).ConfigureAwait(false);
 | 
			
		||||
                await Context.Message.DeleteAsync().ConfigureAwait(false);
 | 
			
		||||
@@ -389,7 +389,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false);
 | 
			
		||||
            if (Context.Guild.GetCurrentUser().GetPermissions(Context.Channel).ManageMessages)
 | 
			
		||||
            if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(10000).ConfigureAwait(false);
 | 
			
		||||
                await Context.Message.DeleteAsync().ConfigureAwait(false);
 | 
			
		||||
@@ -793,7 +793,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                            try { lastFinishedMessage = await textCh.SendConfirmAsync($"🎵 Finished {song.PrettyName}").ConfigureAwait(false); } catch { }
 | 
			
		||||
                            if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube")
 | 
			
		||||
                            {
 | 
			
		||||
                                await QueueSong(queuer.Guild.GetCurrentUser(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false);
 | 
			
		||||
                                await QueueSong(await queuer.Guild.GetCurrentUserAsync(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch { }
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class BlacklistCommands
 | 
			
		||||
        public class BlacklistCommands : ModuleBase
 | 
			
		||||
        {
 | 
			
		||||
            public static ConcurrentHashSet<BlacklistItem> BlacklistedItems { get; set; } = new ConcurrentHashSet<BlacklistItem>();
 | 
			
		||||
 | 
			
		||||
@@ -35,33 +35,31 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [OwnerOnly]
 | 
			
		||||
            public Task UserBlacklist(IUserMessage imsg, AddRemove action, ulong id)
 | 
			
		||||
                => Blacklist(imsg, action, id, BlacklistType.User);
 | 
			
		||||
            public Task UserBlacklist(AddRemove action, ulong id)
 | 
			
		||||
                => Blacklist(action, id, BlacklistType.User);
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [OwnerOnly]
 | 
			
		||||
            public Task UserBlacklist(IUserMessage imsg, AddRemove action, IUser usr)
 | 
			
		||||
                => Blacklist(imsg, action, usr.Id, BlacklistType.User);
 | 
			
		||||
            public Task UserBlacklist(AddRemove action, IUser usr)
 | 
			
		||||
                => Blacklist(action, usr.Id, BlacklistType.User);
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [OwnerOnly]
 | 
			
		||||
            public Task ChannelBlacklist(IUserMessage imsg, AddRemove action, ulong id)
 | 
			
		||||
                => Blacklist(imsg, action, id, BlacklistType.Channel);
 | 
			
		||||
            public Task ChannelBlacklist(AddRemove action, ulong id)
 | 
			
		||||
                => Blacklist(action, id, BlacklistType.Channel);
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [OwnerOnly]
 | 
			
		||||
            public Task ServerBlacklist(IUserMessage imsg, AddRemove action, ulong id)
 | 
			
		||||
                => Blacklist(imsg, action, id, BlacklistType.Server);
 | 
			
		||||
            public Task ServerBlacklist(AddRemove action, ulong id)
 | 
			
		||||
                => Blacklist(action, id, BlacklistType.Server);
 | 
			
		||||
 | 
			
		||||
            [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
            [OwnerOnly]
 | 
			
		||||
            public Task ServerBlacklist(IUserMessage imsg, AddRemove action, IGuild guild)
 | 
			
		||||
                => Blacklist(imsg, action, guild.Id, BlacklistType.Server);
 | 
			
		||||
            public Task ServerBlacklist(AddRemove action, IGuild guild)
 | 
			
		||||
                => Blacklist(action, guild.Id, BlacklistType.Server);
 | 
			
		||||
 | 
			
		||||
            private async Task Blacklist(IUserMessage imsg, AddRemove action, ulong id, BlacklistType type)
 | 
			
		||||
            private async Task Blacklist(AddRemove action, ulong id, BlacklistType type)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = Context.Channel;
 | 
			
		||||
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    if (action == AddRemove.Add)
 | 
			
		||||
@@ -105,7 +103,7 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await channel.SendConfirmAsync($"Blacklisted a `{type}` with id `{id}`").ConfigureAwait(false);
 | 
			
		||||
                await Context.Channel.SendConfirmAsync($"Blacklisted a `{type}` with id `{id}`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
    public partial class Permissions
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class FilterCommands
 | 
			
		||||
        public class FilterCommands : ModuleBase
 | 
			
		||||
        {
 | 
			
		||||
            public static ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
 | 
			
		||||
            public static ConcurrentHashSet<ulong> InviteFilteringServers { get; }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
@@ -85,7 +86,7 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static string GetCommand(this Permission perm, IGuild guild = null)
 | 
			
		||||
        public static string GetCommand(this Permission perm, SocketGuild guild = null)
 | 
			
		||||
        {
 | 
			
		||||
            var com = "";
 | 
			
		||||
            switch (perm.PrimaryTarget)
 | 
			
		||||
 
 | 
			
		||||
@@ -227,10 +227,11 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var text = string.Join("\n", streams.Select(snc =>
 | 
			
		||||
                var text = string.Join("\n", await Task.WhenAll(streams.Select(async snc =>
 | 
			
		||||
                {
 | 
			
		||||
                    return $"`{snc.Username}`'s stream on **{Context.Guild.GetTextChannel(snc.ChannelId)?.Name}** channel. 【`{snc.Type.ToString()}`】";
 | 
			
		||||
                }));
 | 
			
		||||
                    var ch = await Context.Guild.GetTextChannelAsync(snc.ChannelId);
 | 
			
		||||
                    return $"`{snc.Username}`'s stream on **{(ch)?.Name}** channel. 【`{snc.Type.ToString()}`】";
 | 
			
		||||
                })));
 | 
			
		||||
 | 
			
		||||
                await Context.Channel.SendConfirmAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -506,11 +506,11 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        public async Task Videocall([Remainder] string arg = null)
 | 
			
		||||
        public async Task Videocall([Remainder] params IUser[] users)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var allUsrs = Context.Message.MentionedUsers.Append(Context.User);
 | 
			
		||||
                var allUsrs = users.Append(Context.User);
 | 
			
		||||
                var allUsrsArray = allUsrs.ToArray();
 | 
			
		||||
                var str = allUsrsArray.Aggregate("http://appear.in/", (current, usr) => current + Uri.EscapeUriString(usr.Username[0].ToString()));
 | 
			
		||||
                str += new NadekoRandom().Next();
 | 
			
		||||
@@ -526,9 +526,8 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        public async Task Avatar([Remainder] string mention = null)
 | 
			
		||||
        public async Task Avatar([Remainder] IUser usr = null)
 | 
			
		||||
        {
 | 
			
		||||
            var usr = Context.Message.MentionedUsers().FirstOrDefault();
 | 
			
		||||
            if (usr == null)
 | 
			
		||||
            {
 | 
			
		||||
                await Context.Channel.SendErrorAsync("Invalid user specified.").ConfigureAwait(false);
 | 
			
		||||
 
 | 
			
		||||
@@ -93,8 +93,8 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                    .AddField(fb => fb.WithName("**Joined Server**").WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
 | 
			
		||||
                    .AddField(fb => fb.WithName("**Joined Discord**").WithValue($"{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
 | 
			
		||||
                    .AddField(fb => fb.WithName("**Current Game**").WithValue($"{(user.Game?.Name == null ? "-" : user.Game.Value.Name)}").WithIsInline(true))
 | 
			
		||||
                    .AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.RoleIds.Count})** - {string.Join(", ", user.Roles.Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
 | 
			
		||||
                    .WithThumbnail(tn => tn.WithUrl(user.AvatarUrl))
 | 
			
		||||
                    .AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.RoleIds.Count})** - {string.Join(", ", user.GetRoles().Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
 | 
			
		||||
                    .WithThumbnailUrl(user.AvatarUrl)
 | 
			
		||||
                    .WithColor(NadekoBot.OkColor);
 | 
			
		||||
                await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                var role = Context.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleStr).FirstOrDefault();
 | 
			
		||||
                if (role == null) continue;
 | 
			
		||||
                send += $"```css\n[{role.Name}]\n";
 | 
			
		||||
                send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.Roles.Contains(role)).Select(u => u.ToString()));
 | 
			
		||||
                send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.RoleIds.Contains(role.Id)).Select(u => u.ToString()));
 | 
			
		||||
                send += $"\n```";
 | 
			
		||||
            }
 | 
			
		||||
            var usr = Context.User as IGuildUser;
 | 
			
		||||
@@ -125,7 +125,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                return;
 | 
			
		||||
            if (target != null)
 | 
			
		||||
            {
 | 
			
		||||
                await channel.SendConfirmAsync($"⚔ **Page #{page} of roles for {target.Username}**", $"```css\n• " + string.Join("\n• ", target.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r => -r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage)).SanitizeMentions() + "\n```");
 | 
			
		||||
                await channel.SendConfirmAsync($"⚔ **Page #{page} of roles for {target.Username}**", $"```css\n• " + string.Join("\n• ", target.GetRoles().Except(new[] { guild.EveryoneRole }).OrderBy(r => -r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage)).SanitizeMentions() + "\n```");
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,15 +21,9 @@ namespace NadekoBot.Services
 | 
			
		||||
{
 | 
			
		||||
    public class IGuildUserComparer : IEqualityComparer<IGuildUser>
 | 
			
		||||
    {
 | 
			
		||||
        public bool Equals(IGuildUser x, IGuildUser y)
 | 
			
		||||
        {
 | 
			
		||||
            return x.Id == y.Id;
 | 
			
		||||
        }
 | 
			
		||||
        public bool Equals(IGuildUser x, IGuildUser y) => x.Id == y.Id;
 | 
			
		||||
 | 
			
		||||
        public int GetHashCode(IGuildUser obj)
 | 
			
		||||
        {
 | 
			
		||||
            return obj.Id.GetHashCode();
 | 
			
		||||
        }
 | 
			
		||||
        public int GetHashCode(IGuildUser obj) => obj.Id.GetHashCode();
 | 
			
		||||
    }
 | 
			
		||||
    public class CommandHandler
 | 
			
		||||
    {
 | 
			
		||||
@@ -49,7 +43,7 @@ namespace NadekoBot.Services
 | 
			
		||||
        }
 | 
			
		||||
        public async Task StartHandling()
 | 
			
		||||
        {
 | 
			
		||||
            ownerChannels = (await Task.WhenAll(_client.GetGuilds().SelectMany(g => g.GetUsersAsync().GetAwaiter().GetResult())
 | 
			
		||||
            ownerChannels = (await Task.WhenAll(_client.GetGuilds().SelectMany(g => g.Users)
 | 
			
		||||
                                  .Where(u => NadekoBot.Credentials.OwnerIds.Contains(u.Id))
 | 
			
		||||
                                  .Distinct(new IGuildUserComparer())
 | 
			
		||||
                                  .Select(async u => { try { return await u.CreateDMChannelAsync(); } catch { return null; } })))
 | 
			
		||||
@@ -70,14 +64,14 @@ namespace NadekoBot.Services
 | 
			
		||||
            if (usrMsg == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (usrContext.User.IsBot || !NadekoBot.Ready) //no bots
 | 
			
		||||
            if (msg.Author.IsBot || !NadekoBot.Ready) //no bots
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var guild = (Context.Channel as SocketTextChannel)?.Guild;
 | 
			
		||||
            var guild = (msg.Channel as SocketTextChannel)?.Guild;
 | 
			
		||||
 | 
			
		||||
            if (guild != null && guild.OwnerId != usrContext.User.Id)
 | 
			
		||||
            if (guild != null && guild.OwnerId != msg.Author.Id)
 | 
			
		||||
            {
 | 
			
		||||
                if (Permissions.FilterCommands.InviteFilteringChannels.Contains(usrContext.Channel.Id) ||
 | 
			
		||||
                if (Permissions.FilterCommands.InviteFilteringChannels.Contains(msg.Channel.Id) ||
 | 
			
		||||
                    Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id))
 | 
			
		||||
                {
 | 
			
		||||
                    if (usrMsg.Content.IsDiscordInvite())
 | 
			
		||||
@@ -89,12 +83,12 @@ namespace NadekoBot.Services
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (HttpException ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            _log.Warn("I do not have permission to filter invites in channel with id " + usrContext.Channel.Id, ex);
 | 
			
		||||
                            _log.Warn("I do not have permission to filter invites in channel with id " + msg.Channel.Id, ex);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var filteredWords = Permissions.FilterCommands.FilteredWordsForChannel(usrContext.Channel.Id, guild.Id).Concat(Permissions.FilterCommands.FilteredWordsForServer(guild.Id));
 | 
			
		||||
                var filteredWords = Permissions.FilterCommands.FilteredWordsForChannel(msg.Channel.Id, guild.Id).Concat(Permissions.FilterCommands.FilteredWordsForServer(guild.Id));
 | 
			
		||||
                var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
 | 
			
		||||
                if (filteredWords.Any(w => wordsInMessage.Contains(w)))
 | 
			
		||||
                {
 | 
			
		||||
@@ -105,7 +99,7 @@ namespace NadekoBot.Services
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (HttpException ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        _log.Warn("I do not have permission to filter words in channel with id " + usrContext.Channel.Id, ex);
 | 
			
		||||
                        _log.Warn("I do not have permission to filter words in channel with id " + msg.Channel.Id, ex);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -113,8 +107,8 @@ namespace NadekoBot.Services
 | 
			
		||||
            BlacklistItem blacklistedItem;
 | 
			
		||||
            if ((blacklistedItem = Permissions.BlacklistCommands.BlacklistedItems.FirstOrDefault(bi =>
 | 
			
		||||
                 (bi.Type == BlacklistItem.BlacklistType.Server && bi.ItemId == guild?.Id) ||
 | 
			
		||||
                 (bi.Type == BlacklistItem.BlacklistType.Channel && bi.ItemId == Context.Channel.Id) ||
 | 
			
		||||
                 (bi.Type == BlacklistItem.BlacklistType.User && bi.ItemId == usrContext.User.Id))) != null)
 | 
			
		||||
                 (bi.Type == BlacklistItem.BlacklistType.Channel && bi.ItemId == msg.Channel.Id) ||
 | 
			
		||||
                 (bi.Type == BlacklistItem.BlacklistType.User && bi.ItemId == msg.Author.Id))) != null)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -146,12 +140,12 @@ namespace NadekoBot.Services
 | 
			
		||||
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    var t = await ExecuteCommand(usrMsg, usrMsg.Content, guild, usrContext.User, MultiMatchHandling.Best);
 | 
			
		||||
                    var t = await ExecuteCommand(usrMsg, usrMsg.Content, guild, msg.Author, MultiMatchHandling.Best);
 | 
			
		||||
                    var command = t.Item1;
 | 
			
		||||
                    var permCache = t.Item2;
 | 
			
		||||
                    var result = t.Item3;
 | 
			
		||||
                    sw.Stop();
 | 
			
		||||
                    var channel = (usrContext.Channel as ITextChannel);
 | 
			
		||||
                    var channel = (msg.Channel as ITextChannel);
 | 
			
		||||
                    if (result.IsSuccess)
 | 
			
		||||
                    {
 | 
			
		||||
                        await CommandExecuted(usrMsg, command);
 | 
			
		||||
@@ -160,7 +154,7 @@ namespace NadekoBot.Services
 | 
			
		||||
                                    "Server: {1}\n\t" +
 | 
			
		||||
                                    "Channel: {2}\n\t" +
 | 
			
		||||
                                    "Message: {3}",
 | 
			
		||||
                                    usrContext.User + " [" + usrContext.User.Id + "]", // {0}
 | 
			
		||||
                                    msg.Author + " [" + msg.Author.Id + "]", // {0}
 | 
			
		||||
                                    (channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
 | 
			
		||||
                                    (channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
 | 
			
		||||
                                    usrMsg.Content, // {3}
 | 
			
		||||
@@ -175,7 +169,7 @@ namespace NadekoBot.Services
 | 
			
		||||
                                    "Channel: {2}\n\t" +
 | 
			
		||||
                                    "Message: {3}\n\t" +
 | 
			
		||||
                                    "Error: {4}",
 | 
			
		||||
                                    usrContext.User + " [" + usrContext.User.Id + "]", // {0}
 | 
			
		||||
                                    msg.Author + " [" + msg.Author.Id + "]", // {0}
 | 
			
		||||
                                    (channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
 | 
			
		||||
                                    (channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
 | 
			
		||||
                                    usrMsg.Content,// {3}
 | 
			
		||||
@@ -185,18 +179,18 @@ namespace NadekoBot.Services
 | 
			
		||||
                        if (guild != null && command != null && result.Error == CommandError.Exception)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (permCache != null && permCache.Verbose)
 | 
			
		||||
                                try { await Context.Channel.SendMessageAsync("⚠️ " + result.ErrorReason).ConfigureAwait(false); } catch { }
 | 
			
		||||
                                try { await msg.Channel.SendMessageAsync("⚠️ " + result.ErrorReason).ConfigureAwait(false); } catch { }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if (Context.Channel is IPrivateChannel)
 | 
			
		||||
                        if (msg.Channel is IPrivateChannel)
 | 
			
		||||
                        {
 | 
			
		||||
                            //rofl, gotta do this to prevent this message from occuring on polls
 | 
			
		||||
                            int vote;
 | 
			
		||||
                            if (int.TryParse(msg.Content, out vote)) return; 
 | 
			
		||||
 | 
			
		||||
                            await Context.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
 | 
			
		||||
                            await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                            await DMForwardCommands.HandleDMForwarding(msg, ownerChannels);
 | 
			
		||||
                        }
 | 
			
		||||
@@ -212,7 +206,7 @@ namespace NadekoBot.Services
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<Tuple<CommandInfo, PermissionCache, IResult>> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) {
 | 
			
		||||
        public async Task<Tuple<CommandInfo, PermissionCache, IResult>> ExecuteCommand(IUserMessage message, string input, SocketGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) {
 | 
			
		||||
            var searchResult = _commandService.Search(message, input);
 | 
			
		||||
            if (!searchResult.IsSuccess)
 | 
			
		||||
                return new Tuple<CommandInfo, PermissionCache, IResult>(null, null, searchResult);
 | 
			
		||||
@@ -273,16 +267,16 @@ namespace NadekoBot.Services
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                    int index;
 | 
			
		||||
                    if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(message, cmd.Text, cmd.Module.Name, out index))
 | 
			
		||||
                    if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(message, cmd.Aliases.First(), cmd.Module.Name, out index))
 | 
			
		||||
                    {
 | 
			
		||||
                        var returnMsg = $"Permission number #{index + 1} **{pc.RootPermission.GetAt(index).GetCommand(guild)}** is preventing this action.";
 | 
			
		||||
                        return new Tuple<CommandInfo, PermissionCache, IResult>(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    if (cmd.Module.Source.Name == typeof(Permissions).Name) //permissions, you must have special role
 | 
			
		||||
                    if (cmd.Module.Name == typeof(Permissions).Name)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!((IGuildUser)user).Roles.Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant()))
 | 
			
		||||
                        if (!((IGuildUser)user).GetRoles().Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant()))
 | 
			
		||||
                        {
 | 
			
		||||
                            return new Tuple<CommandInfo, PermissionCache, IResult>(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands."));
 | 
			
		||||
                        }
 | 
			
		||||
@@ -299,16 +293,4 @@ namespace NadekoBot.Services
 | 
			
		||||
            return new Tuple<CommandInfo, PermissionCache, IResult>(null, null, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload."));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class CommandExecutedEventArgs
 | 
			
		||||
    {
 | 
			
		||||
        public CommandInfo Command { get; }
 | 
			
		||||
        public IUserMessage Message { get; }
 | 
			
		||||
 | 
			
		||||
        public CommandExecutedEventArgs(CommandInfo cmd)
 | 
			
		||||
        {
 | 
			
		||||
            Message = msg;
 | 
			
		||||
            Command = cmd;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ namespace NadekoBot.Services.Impl
 | 
			
		||||
                configBuilder.AddJsonFile(credsFileName, true)
 | 
			
		||||
                    .AddEnvironmentVariables("NadekoBot_");
 | 
			
		||||
 | 
			
		||||
                var data = configBuilder;
 | 
			
		||||
                var data = configBuilder.Build();
 | 
			
		||||
 | 
			
		||||
                Token = data[nameof(Token)];
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(Token))
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,8 @@ namespace NadekoBot.Services.Impl
 | 
			
		||||
        public int CommandsRan { get; private set; } = 0;
 | 
			
		||||
        public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString();
 | 
			
		||||
        public double MessagesPerSecond => MessageCounter / (double)GetUptime().TotalSeconds;
 | 
			
		||||
        public int TextChannels => client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count();
 | 
			
		||||
        public int VoiceChannels => client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count();
 | 
			
		||||
        public int TextChannels => client.GetGuilds().SelectMany(g => g.Channels.Where(c => c is ITextChannel)).Count();
 | 
			
		||||
        public int VoiceChannels => client.GetGuilds().SelectMany(g => g.Channels.Where(c => c is IVoiceChannel)).Count();
 | 
			
		||||
        public string OwnerIds => string.Join(", ", NadekoBot.Credentials.OwnerIds);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -64,10 +64,10 @@ namespace NadekoBot.Services.Impl
 | 
			
		||||
                catch { }
 | 
			
		||||
            }, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
 | 
			
		||||
        }
 | 
			
		||||
        public async Task<string> Print()
 | 
			
		||||
        public Task<string> Print()
 | 
			
		||||
        {
 | 
			
		||||
            var curUser = await client.CurrentUser();
 | 
			
		||||
            return $@"
 | 
			
		||||
            var curUser = client.CurrentUser();
 | 
			
		||||
            return Task.FromResult($@"
 | 
			
		||||
Author: [{Author}] | Library: [{Library}]
 | 
			
		||||
Bot Version: [{BotVersion}]
 | 
			
		||||
Bot ID: {curUser.Id}
 | 
			
		||||
@@ -75,7 +75,7 @@ Owner ID(s): {OwnerIds}
 | 
			
		||||
Uptime: {GetUptimeString()}
 | 
			
		||||
Servers: {client.GetGuilds().Count} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels}
 | 
			
		||||
Commands Ran this session: {CommandsRan}
 | 
			
		||||
Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]";
 | 
			
		||||
Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task Reset()
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ namespace NadekoBot
 | 
			
		||||
        public IReadOnlyCollection<SocketGuild> GetGuilds() =>
 | 
			
		||||
            Clients.SelectMany(c => c.Guilds).ToList();
 | 
			
		||||
 | 
			
		||||
        public IGuild GetGuild(ulong id) =>
 | 
			
		||||
        public SocketGuild GetGuild(ulong id) =>
 | 
			
		||||
            Clients.Select(c => c.GetGuild(id)).FirstOrDefault(g => g != null);
 | 
			
		||||
 | 
			
		||||
        public Task<IDMChannel> GetDMChannelAsync(ulong channelId) =>
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,12 @@ namespace NadekoBot.Extensions
 | 
			
		||||
            return await ownerPrivate.SendMessageAsync(message).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //public static async Task<IEnumerable<IGuildUser>> MentionedUsers(this IUserMessage msg) =>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public static IEnumerable<IRole> GetRoles(this IGuildUser user) =>
 | 
			
		||||
            user.RoleIds.Select(r => user.Guild.GetRole(r)).Where(r => r != null);
 | 
			
		||||
 | 
			
		||||
        public static IEnumerable<T> ForEach<T>(this IEnumerable<T> elems, Action<T> exec)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var elem in elems)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user