Fixes, more stuff, .stats added?
This commit is contained in:
		@@ -16,10 +16,11 @@ using System.Text.RegularExpressions;
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    [Module(".", AppendSpace = false)]
 | 
			
		||||
    public partial class AdministrationModule : DiscordModule
 | 
			
		||||
    public partial class Administration : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public AdministrationModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        public Administration(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
@@ -188,10 +189,12 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.BanMembers)]
 | 
			
		||||
        public async Task Ban(IMessage imsg, IGuildUser user, [Remainder] string msg = null)
 | 
			
		||||
        public async Task Ban(IMessage imsg, IGuildUser user)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            var msg = "";
 | 
			
		||||
 | 
			
		||||
            if (!string.IsNullOrWhiteSpace(msg))
 | 
			
		||||
            {
 | 
			
		||||
                await (await user.CreateDMChannelAsync()).SendMessageAsync($"**You have been BANNED from `{channel.Guild.Name}` server.**\n" +
 | 
			
		||||
@@ -217,15 +220,10 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            if (user == null)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("User not found.").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (!string.IsNullOrWhiteSpace(msg))
 | 
			
		||||
            {
 | 
			
		||||
                await user.SendMessageAsync($"**You have been SOFT-BANNED from `{channel.Guild.Name}` server.**\n" +
 | 
			
		||||
                                        $"Reason: {msg}").ConfigureAwait(false);
 | 
			
		||||
                    $"Reason: {msg}").ConfigureAwait(false);
 | 
			
		||||
                await Task.Delay(2000).ConfigureAwait(false); // temp solution; give time for a message to be send, fu volt
 | 
			
		||||
            }
 | 
			
		||||
            try
 | 
			
		||||
@@ -492,7 +490,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //todo owner only
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Die(IMessage imsg)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,184 +1,285 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Classes.ClashOfClans;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes.ClashOfClans
 | 
			
		||||
//todo DB
 | 
			
		||||
namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
{
 | 
			
		||||
    public enum DestroyStars
 | 
			
		||||
    [Module(",",AppendSpace = false)]
 | 
			
		||||
    internal class ClashOfClans : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        One, Two, Three
 | 
			
		||||
    }
 | 
			
		||||
    public enum WarState
 | 
			
		||||
    {
 | 
			
		||||
        Started, Ended, Created
 | 
			
		||||
    }
 | 
			
		||||
        public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
 | 
			
		||||
 | 
			
		||||
    internal class Caller
 | 
			
		||||
    {
 | 
			
		||||
        public string CallUser { get; set; }
 | 
			
		||||
 | 
			
		||||
        public DateTime TimeAdded { get; set; }
 | 
			
		||||
 | 
			
		||||
        public bool BaseDestroyed { get; set; }
 | 
			
		||||
 | 
			
		||||
        public int Stars { get; set; } = 3;
 | 
			
		||||
 | 
			
		||||
        public Caller() { }
 | 
			
		||||
 | 
			
		||||
        public Caller(string callUser, DateTime timeAdded, bool baseDestroyed)
 | 
			
		||||
        public ClashOfClans(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
            CallUser = callUser;
 | 
			
		||||
            TimeAdded = timeAdded;
 | 
			
		||||
            BaseDestroyed = baseDestroyed;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ResetTime()
 | 
			
		||||
        private static async Task CheckWar(TimeSpan callExpire, ClashWar war)
 | 
			
		||||
        {
 | 
			
		||||
            TimeAdded = DateTime.UtcNow;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Destroy()
 | 
			
		||||
        {
 | 
			
		||||
            BaseDestroyed = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal class ClashWar
 | 
			
		||||
    {
 | 
			
		||||
        private static TimeSpan callExpire => new TimeSpan(2, 0, 0);
 | 
			
		||||
 | 
			
		||||
        public string EnemyClan { get; set; }
 | 
			
		||||
        public int Size { get; set; }
 | 
			
		||||
 | 
			
		||||
        public Caller[] Bases { get; set; }
 | 
			
		||||
        public WarState WarState { get; set; } = WarState.Created;
 | 
			
		||||
        //public bool Started { get; set; } = false;
 | 
			
		||||
        public DateTime StartedAt { get; set; }
 | 
			
		||||
        //public bool Ended { get; private set; } = false;
 | 
			
		||||
 | 
			
		||||
        public ulong ServerId { get; set; }
 | 
			
		||||
        public ulong ChannelId { get; set; }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public ITextChannel Channel { get; internal set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This init is purely for the deserialization
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ClashWar() { }
 | 
			
		||||
 | 
			
		||||
        public ClashWar(string enemyClan, int size, ulong serverId, ulong channelId)
 | 
			
		||||
        {
 | 
			
		||||
            this.EnemyClan = enemyClan;
 | 
			
		||||
            this.Size = size;
 | 
			
		||||
            this.Bases = new Caller[size];
 | 
			
		||||
            this.ServerId = serverId;
 | 
			
		||||
            this.ChannelId = channelId;
 | 
			
		||||
            this.Channel = NadekoBot.Client.GetGuildsAsync() //nice api you got here volt, 
 | 
			
		||||
                                    .GetAwaiter() //especially like how getguildsasync isn't async at all internally. 
 | 
			
		||||
                                    .GetResult() //But hey, lib has to be async kek
 | 
			
		||||
                                    .FirstOrDefault(s => s.Id == serverId)? // srsly
 | 
			
		||||
                                    .GetChannelsAsync() //wtf is this
 | 
			
		||||
                                    .GetAwaiter() // oh i know, its the implementation detail
 | 
			
		||||
                                    .GetResult() // and makes library look consistent
 | 
			
		||||
                                    .FirstOrDefault(c => c.Id == channelId) // its not common sense to make library work like this.
 | 
			
		||||
                                        as ITextChannel; // oh and don't forget to cast it to this arbitrary bullshit 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void End()
 | 
			
		||||
        {
 | 
			
		||||
            //Ended = true;
 | 
			
		||||
            WarState = WarState.Ended;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void Call(string u, int baseNumber)
 | 
			
		||||
        {
 | 
			
		||||
            if (baseNumber < 0 || baseNumber >= Bases.Length)
 | 
			
		||||
                throw new ArgumentException("Invalid base number");
 | 
			
		||||
            if (Bases[baseNumber] != null)
 | 
			
		||||
                throw new ArgumentException("That base is already claimed.");
 | 
			
		||||
            var Bases = war.Bases;
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i]?.BaseDestroyed == false && Bases[i]?.CallUser == u)
 | 
			
		||||
                    throw new ArgumentException($"@{u} You already claimed base #{i + 1}. You can't claim a new one.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Bases[baseNumber] = new Caller(u.Trim(), DateTime.UtcNow, false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void Start()
 | 
			
		||||
        {
 | 
			
		||||
            if (WarState == WarState.Started)
 | 
			
		||||
                throw new InvalidOperationException("War already started");
 | 
			
		||||
            //if (Started)
 | 
			
		||||
            //    throw new InvalidOperationException();
 | 
			
		||||
            //Started = true;
 | 
			
		||||
            WarState = WarState.Started;
 | 
			
		||||
            StartedAt = DateTime.UtcNow;
 | 
			
		||||
            foreach (var b in Bases.Where(b => b != null))
 | 
			
		||||
            {
 | 
			
		||||
                b.ResetTime();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal int Uncall(string user)
 | 
			
		||||
        {
 | 
			
		||||
            user = user.Trim();
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i]?.CallUser != user) continue;
 | 
			
		||||
                Bases[i] = null;
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
            throw new InvalidOperationException("You are not participating in that war.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string ShortPrint() =>
 | 
			
		||||
            $"`{EnemyClan}` ({Size} v {Size})";
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            var sb = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
            sb.AppendLine($"🔰**WAR AGAINST `{EnemyClan}` ({Size} v {Size}) INFO:**");
 | 
			
		||||
            if (WarState == WarState.Created)
 | 
			
		||||
                sb.AppendLine("`not started`");
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i] == null)
 | 
			
		||||
                if (Bases[i] == null) continue;
 | 
			
		||||
                if (!Bases[i].BaseDestroyed && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire)
 | 
			
		||||
                {
 | 
			
		||||
                    sb.AppendLine($"`{i + 1}.` ❌*unclaimed*");
 | 
			
		||||
                    await war.Channel.SendMessageAsync($"❗🔰**Claim from @{Bases[i].CallUser} for a war against {war.ShortPrint()} has expired.**").ConfigureAwait(false);
 | 
			
		||||
                    Bases[i] = null;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task CreateWar(IMessage imsg, int size, [Remainder] string enemyClan = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            if (!(imsg.Author as IGuildUser).GuildPermissions.ManageChannels)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(enemyClan))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (size < 10 || size > 50 || size % 5 != 0)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 Not a Valid war size").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            List<ClashWar> wars;
 | 
			
		||||
            if (!ClashWars.TryGetValue(channel.Guild.Id, out wars))
 | 
			
		||||
            {
 | 
			
		||||
                wars = new List<ClashWar>();
 | 
			
		||||
                if (!ClashWars.TryAdd(channel.Guild.Id, wars))
 | 
			
		||||
                    return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            var cw = new ClashWar(enemyClan, size, channel.Guild.Id, imsg.Channel.Id);
 | 
			
		||||
            //cw.Start();
 | 
			
		||||
 | 
			
		||||
            wars.Add(cw);
 | 
			
		||||
            await imsg.Channel.SendMessageAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task StartWar(IMessage imsg, [Remainder] string number = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            int num = 0;
 | 
			
		||||
            int.TryParse(number, out num);
 | 
			
		||||
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, num);
 | 
			
		||||
            if (warsInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var war = warsInfo.Item1[warsInfo.Item2];
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                war.Start();
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ListWar(IMessage imsg, [Remainder] string number = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            // if number is null, print all wars in a short way
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(number))
 | 
			
		||||
            {
 | 
			
		||||
                //check if there are any wars
 | 
			
		||||
                List<ClashWar> wars = null;
 | 
			
		||||
                ClashWars.TryGetValue(channel.Guild.Id, out wars);
 | 
			
		||||
                if (wars == null || wars.Count == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    if (Bases[i].BaseDestroyed)
 | 
			
		||||
                    {
 | 
			
		||||
                        sb.AppendLine($"`{i + 1}.` ✅ `{Bases[i].CallUser}` {new string('⭐', Bases[i].Stars)}");
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        var left = (WarState == WarState.Started) ? callExpire - (DateTime.UtcNow - Bases[i].TimeAdded) : callExpire;
 | 
			
		||||
                        sb.AppendLine($"`{i + 1}.` ✅ `{Bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
 | 
			
		||||
                    }
 | 
			
		||||
                    await imsg.Channel.SendMessageAsync("🔰 **No active wars.**").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var sb = new StringBuilder();
 | 
			
		||||
                sb.AppendLine("🔰 **LIST OF ACTIVE WARS**");
 | 
			
		||||
                sb.AppendLine("**-------------------------**");
 | 
			
		||||
                for (var i = 0; i < wars.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    sb.AppendLine($"**#{i + 1}.**  `Enemy:` **{wars[i].EnemyClan}**");
 | 
			
		||||
                    sb.AppendLine($"\t\t`Size:` **{wars[i].Size} v {wars[i].Size}**");
 | 
			
		||||
                    sb.AppendLine("**-------------------------**");
 | 
			
		||||
                }
 | 
			
		||||
                await imsg.Channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            return sb.ToString();
 | 
			
		||||
            var num = 0;
 | 
			
		||||
            int.TryParse(number, out num);
 | 
			
		||||
            //if number is not null, print the war needed
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, num);
 | 
			
		||||
            if (warsInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await imsg.Channel.SendMessageAsync(warsInfo.Item1[warsInfo.Item2].ToString()).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal int FinishClaim(string user, int stars = 3)
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Claim(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            user = user.Trim();
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, number);
 | 
			
		||||
            if (warsInfo == null || warsInfo.Item1.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i]?.BaseDestroyed != false || Bases[i]?.CallUser != user) continue;
 | 
			
		||||
                Bases[i].BaseDestroyed = true;
 | 
			
		||||
                Bases[i].Stars = stars;
 | 
			
		||||
                return i;
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            throw new InvalidOperationException($"@{user} You are either not participating in that war, or you already destroyed a base.");
 | 
			
		||||
            var usr =
 | 
			
		||||
                string.IsNullOrWhiteSpace(other_name) ?
 | 
			
		||||
                imsg.Author.Username :
 | 
			
		||||
                other_name;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var war = warsInfo.Item1[warsInfo.Item2];
 | 
			
		||||
                war.Call(usr, baseNumber - 1);
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰**{usr}** claimed a base #{baseNumber} for a war against {war.ShortPrint()}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish1(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            await FinishClaim(imsg, number, baseNumber, other_name, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish2(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            await FinishClaim(imsg, number, baseNumber, other_name, 2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            await FinishClaim(imsg, number, baseNumber, other_name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task EndWar(IMessage imsg, int number)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg,number);
 | 
			
		||||
            if (warsInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 That war does not exist.").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            warsInfo.Item1[warsInfo.Item2].End();
 | 
			
		||||
            await imsg.Channel.SendMessageAsync($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            var size = warsInfo.Item1[warsInfo.Item2].Size;
 | 
			
		||||
            warsInfo.Item1.RemoveAt(warsInfo.Item2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Unclaim(IMessage imsg, int number, [Remainder] string otherName = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, number);
 | 
			
		||||
            if (warsInfo == null || warsInfo.Item1.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var usr =
 | 
			
		||||
                string.IsNullOrWhiteSpace(otherName) ?
 | 
			
		||||
                imsg.Author.Username :
 | 
			
		||||
                otherName;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var war = warsInfo.Item1[warsInfo.Item2];
 | 
			
		||||
                var baseNumber = war.Uncall(usr);
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task FinishClaim(IMessage imsg, int number, int baseNumber, [Remainder] string other_name, int stars = 3)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            var warInfo = GetWarInfo(imsg, number);
 | 
			
		||||
            if (warInfo == null || warInfo.Item1.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var usr =
 | 
			
		||||
                string.IsNullOrWhiteSpace(other_name) ?
 | 
			
		||||
                imsg.Author.Username :
 | 
			
		||||
                other_name;
 | 
			
		||||
 | 
			
		||||
            var war = warInfo.Item1[warInfo.Item2];
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var baseNum = war.FinishClaim(usr, stars);
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"❗🔰{imsg.Author.Mention} **DESTROYED** a base #{baseNum + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Tuple<List<ClashWar>, int> GetWarInfo(IMessage imsg, int num)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            //check if there are any wars
 | 
			
		||||
            List<ClashWar> wars = null;
 | 
			
		||||
            ClashWars.TryGetValue(channel.Guild.Id, out wars);
 | 
			
		||||
            if (wars == null || wars.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            // get the number of the war
 | 
			
		||||
            else if (num < 1 || num > wars.Count)
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            num -= 1;
 | 
			
		||||
            //get the actual war
 | 
			
		||||
            return new Tuple<List<ClashWar>, int>(wars, num);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,285 +0,0 @@
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Classes.ClashOfClans;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
 | 
			
		||||
//todo DB
 | 
			
		||||
namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
{
 | 
			
		||||
    [Module(",",AppendSpace = false)]
 | 
			
		||||
    internal class ClashOfClansModule : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
 | 
			
		||||
 | 
			
		||||
        public ClashOfClansModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static async Task CheckWar(TimeSpan callExpire, ClashWar war)
 | 
			
		||||
        {
 | 
			
		||||
            var Bases = war.Bases;
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i] == null) continue;
 | 
			
		||||
                if (!Bases[i].BaseDestroyed && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire)
 | 
			
		||||
                {
 | 
			
		||||
                    await war.Channel.SendMessageAsync($"❗🔰**Claim from @{Bases[i].CallUser} for a war against {war.ShortPrint()} has expired.**").ConfigureAwait(false);
 | 
			
		||||
                    Bases[i] = null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task CreateWar(IMessage imsg, int size, [Remainder] string enemyClan = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            if (!(imsg.Author as IGuildUser).GuildPermissions.ManageChannels)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(enemyClan))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (size < 10 || size > 50 || size % 5 != 0)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 Not a Valid war size").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            List<ClashWar> wars;
 | 
			
		||||
            if (!ClashWars.TryGetValue(channel.Guild.Id, out wars))
 | 
			
		||||
            {
 | 
			
		||||
                wars = new List<ClashWar>();
 | 
			
		||||
                if (!ClashWars.TryAdd(channel.Guild.Id, wars))
 | 
			
		||||
                    return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            var cw = new ClashWar(enemyClan, size, channel.Guild.Id, imsg.Channel.Id);
 | 
			
		||||
            //cw.Start();
 | 
			
		||||
 | 
			
		||||
            wars.Add(cw);
 | 
			
		||||
            await imsg.Channel.SendMessageAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task StartWar(IMessage imsg, [Remainder] string number = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            int num = 0;
 | 
			
		||||
            int.TryParse(number, out num);
 | 
			
		||||
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, num);
 | 
			
		||||
            if (warsInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var war = warsInfo.Item1[warsInfo.Item2];
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                war.Start();
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ListWar(IMessage imsg, [Remainder] string number = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            // if number is null, print all wars in a short way
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(number))
 | 
			
		||||
            {
 | 
			
		||||
                //check if there are any wars
 | 
			
		||||
                List<ClashWar> wars = null;
 | 
			
		||||
                ClashWars.TryGetValue(channel.Guild.Id, out wars);
 | 
			
		||||
                if (wars == null || wars.Count == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    await imsg.Channel.SendMessageAsync("🔰 **No active wars.**").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var sb = new StringBuilder();
 | 
			
		||||
                sb.AppendLine("🔰 **LIST OF ACTIVE WARS**");
 | 
			
		||||
                sb.AppendLine("**-------------------------**");
 | 
			
		||||
                for (var i = 0; i < wars.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    sb.AppendLine($"**#{i + 1}.**  `Enemy:` **{wars[i].EnemyClan}**");
 | 
			
		||||
                    sb.AppendLine($"\t\t`Size:` **{wars[i].Size} v {wars[i].Size}**");
 | 
			
		||||
                    sb.AppendLine("**-------------------------**");
 | 
			
		||||
                }
 | 
			
		||||
                await imsg.Channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            var num = 0;
 | 
			
		||||
            int.TryParse(number, out num);
 | 
			
		||||
            //if number is not null, print the war needed
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, num);
 | 
			
		||||
            if (warsInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await imsg.Channel.SendMessageAsync(warsInfo.Item1[warsInfo.Item2].ToString()).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Claim(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, number);
 | 
			
		||||
            if (warsInfo == null || warsInfo.Item1.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var usr =
 | 
			
		||||
                string.IsNullOrWhiteSpace(other_name) ?
 | 
			
		||||
                imsg.Author.Username :
 | 
			
		||||
                other_name;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var war = warsInfo.Item1[warsInfo.Item2];
 | 
			
		||||
                war.Call(usr, baseNumber - 1);
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰**{usr}** claimed a base #{baseNumber} for a war against {war.ShortPrint()}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish1(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            await FinishClaim(imsg, number, baseNumber, other_name, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish2(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            await FinishClaim(imsg, number, baseNumber, other_name, 2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish(IMessage imsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            await FinishClaim(imsg, number, baseNumber, other_name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task EndWar(IMessage imsg, int number)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg,number);
 | 
			
		||||
            if (warsInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 That war does not exist.").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            warsInfo.Item1[warsInfo.Item2].End();
 | 
			
		||||
            await imsg.Channel.SendMessageAsync($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            var size = warsInfo.Item1[warsInfo.Item2].Size;
 | 
			
		||||
            warsInfo.Item1.RemoveAt(warsInfo.Item2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Unclaim(IMessage imsg, int number, [Remainder] string otherName = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            var warsInfo = GetWarInfo(imsg, number);
 | 
			
		||||
            if (warsInfo == null || warsInfo.Item1.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var usr =
 | 
			
		||||
                string.IsNullOrWhiteSpace(otherName) ?
 | 
			
		||||
                imsg.Author.Username :
 | 
			
		||||
                otherName;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var war = warsInfo.Item1[warsInfo.Item2];
 | 
			
		||||
                var baseNumber = war.Uncall(usr);
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task FinishClaim(IMessage imsg, int number, int baseNumber, [Remainder] string other_name, int stars = 3)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            var warInfo = GetWarInfo(imsg, number);
 | 
			
		||||
            if (warInfo == null || warInfo.Item1.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var usr =
 | 
			
		||||
                string.IsNullOrWhiteSpace(other_name) ?
 | 
			
		||||
                imsg.Author.Username :
 | 
			
		||||
                other_name;
 | 
			
		||||
 | 
			
		||||
            var war = warInfo.Item1[warInfo.Item2];
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var baseNum = war.FinishClaim(usr, stars);
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"❗🔰{imsg.Author.Mention} **DESTROYED** a base #{baseNum + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await imsg.Channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Tuple<List<ClashWar>, int> GetWarInfo(IMessage imsg, int num)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
            //check if there are any wars
 | 
			
		||||
            List<ClashWar> wars = null;
 | 
			
		||||
            ClashWars.TryGetValue(channel.Guild.Id, out wars);
 | 
			
		||||
            if (wars == null || wars.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            // get the number of the war
 | 
			
		||||
            else if (num < 1 || num > wars.Count)
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            num -= 1;
 | 
			
		||||
            //get the actual war
 | 
			
		||||
            return new Tuple<List<ClashWar>, int>(wars, num);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										183
									
								
								src/NadekoBot/Modules/ClashOfClans/ClashWar.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/NadekoBot/Modules/ClashOfClans/ClashWar.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,183 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes.ClashOfClans
 | 
			
		||||
{
 | 
			
		||||
    internal class ClashWar
 | 
			
		||||
    {
 | 
			
		||||
        public enum DestroyStars
 | 
			
		||||
        {
 | 
			
		||||
            One, Two, Three
 | 
			
		||||
        }
 | 
			
		||||
        public enum StateOfWar
 | 
			
		||||
        {
 | 
			
		||||
            Started, Ended, Created
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal class Caller
 | 
			
		||||
        {
 | 
			
		||||
            public string CallUser { get; set; }
 | 
			
		||||
 | 
			
		||||
            public DateTime TimeAdded { get; set; }
 | 
			
		||||
 | 
			
		||||
            public bool BaseDestroyed { get; set; }
 | 
			
		||||
 | 
			
		||||
            public int Stars { get; set; } = 3;
 | 
			
		||||
 | 
			
		||||
            public Caller() { }
 | 
			
		||||
 | 
			
		||||
            public Caller(string callUser, DateTime timeAdded, bool baseDestroyed)
 | 
			
		||||
            {
 | 
			
		||||
                CallUser = callUser;
 | 
			
		||||
                TimeAdded = timeAdded;
 | 
			
		||||
                BaseDestroyed = baseDestroyed;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public void ResetTime()
 | 
			
		||||
            {
 | 
			
		||||
                TimeAdded = DateTime.UtcNow;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public void Destroy()
 | 
			
		||||
            {
 | 
			
		||||
                BaseDestroyed = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private static TimeSpan callExpire => new TimeSpan(2, 0, 0);
 | 
			
		||||
 | 
			
		||||
        public string EnemyClan { get; set; }
 | 
			
		||||
        public int Size { get; set; }
 | 
			
		||||
 | 
			
		||||
        public Caller[] Bases { get; set; }
 | 
			
		||||
        public StateOfWar WarState { get; set; } = StateOfWar.Created;
 | 
			
		||||
        //public bool Started { get; set; } = false;
 | 
			
		||||
        public DateTime StartedAt { get; set; }
 | 
			
		||||
        //public bool Ended { get; private set; } = false;
 | 
			
		||||
 | 
			
		||||
        public ulong ServerId { get; set; }
 | 
			
		||||
        public ulong ChannelId { get; set; }
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public ITextChannel Channel { get; internal set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This init is purely for the deserialization
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public ClashWar() { }
 | 
			
		||||
 | 
			
		||||
        public ClashWar(string enemyClan, int size, ulong serverId, ulong channelId)
 | 
			
		||||
        {
 | 
			
		||||
            this.EnemyClan = enemyClan;
 | 
			
		||||
            this.Size = size;
 | 
			
		||||
            this.Bases = new Caller[size];
 | 
			
		||||
            this.ServerId = serverId;
 | 
			
		||||
            this.ChannelId = channelId;
 | 
			
		||||
            this.Channel = NadekoBot.Client.GetGuildsAsync() //nice api you got here volt, 
 | 
			
		||||
                                    .GetAwaiter() //especially like how getguildsasync isn't async at all internally. 
 | 
			
		||||
                                    .GetResult() //But hey, lib has to be async kek
 | 
			
		||||
                                    .FirstOrDefault(s => s.Id == serverId)? // srsly
 | 
			
		||||
                                    .GetChannelsAsync() //wtf is this
 | 
			
		||||
                                    .GetAwaiter() // oh i know, its the implementation detail
 | 
			
		||||
                                    .GetResult() // and makes library look consistent
 | 
			
		||||
                                    .FirstOrDefault(c => c.Id == channelId) // its not common sense to make library work like this.
 | 
			
		||||
                                        as ITextChannel; // oh and don't forget to cast it to this arbitrary bullshit 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void End()
 | 
			
		||||
        {
 | 
			
		||||
            //Ended = true;
 | 
			
		||||
            WarState = StateOfWar.Ended;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void Call(string u, int baseNumber)
 | 
			
		||||
        {
 | 
			
		||||
            if (baseNumber < 0 || baseNumber >= Bases.Length)
 | 
			
		||||
                throw new ArgumentException("Invalid base number");
 | 
			
		||||
            if (Bases[baseNumber] != null)
 | 
			
		||||
                throw new ArgumentException("That base is already claimed.");
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i]?.BaseDestroyed == false && Bases[i]?.CallUser == u)
 | 
			
		||||
                    throw new ArgumentException($"@{u} You already claimed base #{i + 1}. You can't claim a new one.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Bases[baseNumber] = new Caller(u.Trim(), DateTime.UtcNow, false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void Start()
 | 
			
		||||
        {
 | 
			
		||||
            if (WarState == StateOfWar.Started)
 | 
			
		||||
                throw new InvalidOperationException("War already started");
 | 
			
		||||
            //if (Started)
 | 
			
		||||
            //    throw new InvalidOperationException();
 | 
			
		||||
            //Started = true;
 | 
			
		||||
            WarState = StateOfWar.Started;
 | 
			
		||||
            StartedAt = DateTime.UtcNow;
 | 
			
		||||
            foreach (var b in Bases.Where(b => b != null))
 | 
			
		||||
            {
 | 
			
		||||
                b.ResetTime();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal int Uncall(string user)
 | 
			
		||||
        {
 | 
			
		||||
            user = user.Trim();
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i]?.CallUser != user) continue;
 | 
			
		||||
                Bases[i] = null;
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
            throw new InvalidOperationException("You are not participating in that war.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string ShortPrint() =>
 | 
			
		||||
            $"`{EnemyClan}` ({Size} v {Size})";
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            var sb = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
            sb.AppendLine($"🔰**WAR AGAINST `{EnemyClan}` ({Size} v {Size}) INFO:**");
 | 
			
		||||
            if (WarState == StateOfWar.Created)
 | 
			
		||||
                sb.AppendLine("`not started`");
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i] == null)
 | 
			
		||||
                {
 | 
			
		||||
                    sb.AppendLine($"`{i + 1}.` ❌*unclaimed*");
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if (Bases[i].BaseDestroyed)
 | 
			
		||||
                    {
 | 
			
		||||
                        sb.AppendLine($"`{i + 1}.` ✅ `{Bases[i].CallUser}` {new string('⭐', Bases[i].Stars)}");
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        var left = (WarState == StateOfWar.Started) ? callExpire - (DateTime.UtcNow - Bases[i].TimeAdded) : callExpire;
 | 
			
		||||
                        sb.AppendLine($"`{i + 1}.` ✅ `{Bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            return sb.ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal int FinishClaim(string user, int stars = 3)
 | 
			
		||||
        {
 | 
			
		||||
            user = user.Trim();
 | 
			
		||||
            for (var i = 0; i < Bases.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (Bases[i]?.BaseDestroyed != false || Bases[i]?.CallUser != user) continue;
 | 
			
		||||
                Bases[i].BaseDestroyed = true;
 | 
			
		||||
                Bases[i].Stars = stars;
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
            throw new InvalidOperationException($"@{user} You are either not participating in that war, or you already destroyed a base.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using NLog;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules
 | 
			
		||||
{
 | 
			
		||||
@@ -10,6 +11,7 @@ namespace NadekoBot.Modules
 | 
			
		||||
        protected CommandService _commands;
 | 
			
		||||
        protected IBotConfiguration _config;
 | 
			
		||||
        protected IDiscordClient _client;
 | 
			
		||||
        protected Logger _log;
 | 
			
		||||
 | 
			
		||||
        public DiscordModule(ILocalization loc, CommandService cmds, IBotConfiguration config,IDiscordClient client)
 | 
			
		||||
        {
 | 
			
		||||
@@ -17,6 +19,7 @@ namespace NadekoBot.Modules
 | 
			
		||||
            _commands = cmds;
 | 
			
		||||
            _config = config;
 | 
			
		||||
            _client = client;
 | 
			
		||||
            _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,11 +11,11 @@ using NadekoBot.Extensions;
 | 
			
		||||
namespace NadekoBot.Modules.Games
 | 
			
		||||
{
 | 
			
		||||
    [Module(">", AppendSpace = false)]
 | 
			
		||||
    public partial class GamesModule : DiscordModule
 | 
			
		||||
    public partial class Games : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        //todo DB
 | 
			
		||||
        private IEnumerable<string> _8BallResponses;
 | 
			
		||||
        public GamesModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        public Games(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -12,7 +12,7 @@ using System.Text;
 | 
			
		||||
namespace NadekoBot.Modules.Help
 | 
			
		||||
{
 | 
			
		||||
    [Module("-", AppendSpace = false)]
 | 
			
		||||
    public partial class HelpModule : DiscordModule
 | 
			
		||||
    public partial class Help : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public string HelpString {
 | 
			
		||||
            get {
 | 
			
		||||
@@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
                return str + String.Format(str, NadekoBot.Credentials.ClientId);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public HelpModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        public Help(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -66,7 +66,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Help(IMessage imsg, [Remainder] string comToFind = null)
 | 
			
		||||
        public async Task H(IMessage imsg, [Remainder] string comToFind = null)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
            }
 | 
			
		||||
            helpstr = helpstr.Replace((await NadekoBot.Client.GetCurrentUserAsync()).Username , "@BotName");
 | 
			
		||||
#if DEBUG
 | 
			
		||||
            File.WriteAllText("../../../docs/Commands List.md", helpstr.ToString());
 | 
			
		||||
            File.WriteAllText("../../../../../docs/Commands List.md", helpstr.ToString());
 | 
			
		||||
#else
 | 
			
		||||
            File.WriteAllText("commandlist.md", helpstr.ToString());
 | 
			
		||||
#endif
 | 
			
		||||
@@ -9,13 +9,14 @@ using NadekoBot.Services;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Xml.Linq;
 | 
			
		||||
using System.Net;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.NSFW
 | 
			
		||||
{
 | 
			
		||||
    [Module("~", AppendSpace = false)]
 | 
			
		||||
    public class NSFWModule : DiscordModule
 | 
			
		||||
    public class NSFW : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public NSFWModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        public NSFW(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -212,7 +213,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
                    http.DefaultRequestHeaders.Clear();
 | 
			
		||||
                    http.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1");
 | 
			
		||||
                    http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
 | 
			
		||||
                    var data = await http.GetStringAsync("http://e621.net/post/index.xml?tags=" + Uri.EscapeUriString(tags) + "%20order:random&limit=1");
 | 
			
		||||
                    var data = await http.GetStreamAsync("http://e621.net/post/index.xml?tags=" + Uri.EscapeUriString(tags) + "%20order:random&limit=1");
 | 
			
		||||
                    var doc = XDocument.Load(data);
 | 
			
		||||
                    return doc.Descendants("file_url").FirstOrDefault().Value;
 | 
			
		||||
                }
 | 
			
		||||
@@ -7,9 +7,9 @@ using NadekoBot.Services;
 | 
			
		||||
namespace NadekoBot.Modules.Games.Commands
 | 
			
		||||
{
 | 
			
		||||
    [Module(">", AppendSpace = false)]
 | 
			
		||||
    public partial class PokemonModule : DiscordModule
 | 
			
		||||
    public partial class Pokemon : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public PokemonModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        public Pokemon(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -76,7 +76,7 @@
 | 
			
		||||
//                        var reqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&{mapId}";
 | 
			
		||||
//                        var obj = JArray.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false))[0];
 | 
			
		||||
//                        var sb = new System.Text.StringBuilder();
 | 
			
		||||
//                        var starRating = Math.Round(Double.Parse($"{obj["difficultyrating"]}"), 2);
 | 
			
		||||
//                        var starRating = Math.Round(Double.Parse($"{obj["difficultyrating"]}", CultureInfo.InvariantCulture), 2);
 | 
			
		||||
//                        var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss");
 | 
			
		||||
//                        sb.AppendLine($"{obj["artist"]} - {obj["title"]}, mapped by {obj["creator"]}. https://osu.ppy.sh/s/{obj["beatmapset_id"]}");
 | 
			
		||||
//                        sb.AppendLine($"{starRating} stars, {obj["bpm"]} BPM | AR{obj["diff_approach"]}, CS{obj["diff_size"]}, OD{obj["diff_overall"]} | Length: {time}");
 | 
			
		||||
@@ -121,7 +121,7 @@
 | 
			
		||||
//                        {
 | 
			
		||||
//                            var mapReqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&b={item["beatmap_id"]}";
 | 
			
		||||
//                            var map = JArray.Parse(await http.GetStringAsync(mapReqString).ConfigureAwait(false))[0];
 | 
			
		||||
//                            var pp = Math.Round(Double.Parse($"{item["pp"]}"), 2);
 | 
			
		||||
//                            var pp = Math.Round(Double.Parse($"{item["pp"]}", CultureInfo.InvariantCulture), 2);
 | 
			
		||||
//                            var acc = CalculateAcc(item, m);
 | 
			
		||||
//                            var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}"));
 | 
			
		||||
//                            if (mods != "+")
 | 
			
		||||
 
 | 
			
		||||
@@ -17,13 +17,13 @@ using NadekoBot.Modules.Searches.Commands.Models;
 | 
			
		||||
namespace NadekoBot.Modules.Searches
 | 
			
		||||
{
 | 
			
		||||
    [Module("~", AppendSpace = false)]
 | 
			
		||||
    public class SearchesModule : DiscordModule
 | 
			
		||||
    public class Searches : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Random rng;
 | 
			
		||||
 | 
			
		||||
        private IYoutubeService _yt { get; }
 | 
			
		||||
 | 
			
		||||
        public SearchesModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client, IYoutubeService youtube) : base(loc, cmds, config, client)
 | 
			
		||||
        public Searches(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client, IYoutubeService youtube) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
            rng = new Random();
 | 
			
		||||
            _yt = youtube;
 | 
			
		||||
@@ -94,6 +94,7 @@ namespace NadekoBot.Modules.Translator
 | 
			
		||||
                    { "bn", "bn"},
 | 
			
		||||
                    { "bg", "bg"},
 | 
			
		||||
                    { "ca", "ca"},
 | 
			
		||||
                    { "zh-TW", "zh-TW"},
 | 
			
		||||
                    { "zh-CN", "zh-CN"},
 | 
			
		||||
                    { "hr", "hr"},
 | 
			
		||||
                    { "cs", "cs"},
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,9 @@ using NadekoBot.Services;
 | 
			
		||||
namespace NadekoBot.Modules.Translator
 | 
			
		||||
{
 | 
			
		||||
    [Module("~", AppendSpace = false)]
 | 
			
		||||
    public class TranslatorModule : DiscordModule
 | 
			
		||||
    public class Translator : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public TranslatorModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        public Translator(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
////todo rewrite
 | 
			
		||||
//namespace NadekoBot.Modules.Trello
 | 
			
		||||
//{
 | 
			
		||||
//    internal class TrelloModule : DiscordModule
 | 
			
		||||
//    internal class Trello : DiscordModule
 | 
			
		||||
//    {
 | 
			
		||||
//        private readonly Timer t = new Timer { Interval = 2000 };
 | 
			
		||||
//        public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Trello;
 | 
			
		||||
@@ -9,7 +9,7 @@ using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Utility
 | 
			
		||||
{
 | 
			
		||||
    partial class UtilityModule : DiscordModule
 | 
			
		||||
    partial class Utility : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,9 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    [Module(".", AppendSpace = false)]
 | 
			
		||||
    public partial class UtilityModule : DiscordModule
 | 
			
		||||
    public partial class Utility : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public UtilityModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        public Utility(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
@@ -127,6 +127,15 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                await msg.Reply("`List of roles:` \n• " + string.Join("\n• ", (msg.Channel as ITextChannel).Guild.Roles.Except(new[] { guild.EveryoneRole })));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Stats(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
            await channel.SendMessageAsync(await NadekoBot.Stats.Print());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3,6 +3,9 @@ using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using NadekoBot.Services.Impl;
 | 
			
		||||
using NLog;
 | 
			
		||||
using NLog.Config;
 | 
			
		||||
using NLog.Targets;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
@@ -12,6 +15,8 @@ namespace NadekoBot
 | 
			
		||||
{
 | 
			
		||||
    public class NadekoBot
 | 
			
		||||
    {
 | 
			
		||||
        private Logger _log;
 | 
			
		||||
 | 
			
		||||
        public static CommandService Commands { get; private set; }
 | 
			
		||||
        public static DiscordSocketClient Client { get; private set; }
 | 
			
		||||
        public static BotConfiguration Config { get; private set; }
 | 
			
		||||
@@ -19,9 +24,12 @@ namespace NadekoBot
 | 
			
		||||
        public static BotCredentials Credentials { get; private set; }
 | 
			
		||||
 | 
			
		||||
        private static YoutubeService Youtube { get; set; }
 | 
			
		||||
        public static StatsService Stats { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public async Task RunAsync(string[] args)
 | 
			
		||||
        {
 | 
			
		||||
            SetupLogger();
 | 
			
		||||
 | 
			
		||||
            //create client
 | 
			
		||||
            Client = new DiscordSocketClient(new DiscordSocketConfig
 | 
			
		||||
            {
 | 
			
		||||
@@ -37,7 +45,9 @@ namespace NadekoBot
 | 
			
		||||
            Config = new BotConfiguration();
 | 
			
		||||
            Localizer = new Localization();
 | 
			
		||||
            Youtube = new YoutubeService();
 | 
			
		||||
                        
 | 
			
		||||
            Stats = new StatsService(Client);
 | 
			
		||||
            _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
 | 
			
		||||
            //setup DI
 | 
			
		||||
            var depMap = new DependencyMap();
 | 
			
		||||
            depMap.Add<ILocalization>(Localizer);
 | 
			
		||||
@@ -47,23 +57,56 @@ namespace NadekoBot
 | 
			
		||||
            depMap.Add<IYoutubeService>(Youtube);
 | 
			
		||||
 | 
			
		||||
            //connect
 | 
			
		||||
            await Client.LoginAsync(TokenType.Bot, "MTE5Nzc3MDIxMzE5NTc3NjEw.CpGoCA.yQBJbLWurrjSk7IlGpGzBm-tPTg");
 | 
			
		||||
            await Client.LoginAsync(TokenType.Bot, "MTE5Nzc3MDIxMzE5NTc3NjEw.CpdrFA.0rex01uCrn9dBTJOV2tXwMLo0wE");
 | 
			
		||||
            await Client.ConnectAsync();
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            _log.Info("Connected");
 | 
			
		||||
 | 
			
		||||
            //load commands
 | 
			
		||||
            await Commands.LoadAssembly(Assembly.GetEntryAssembly(), depMap);
 | 
			
		||||
            Client.MessageReceived += Client_MessageReceived;
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine(Commands.Commands.Count());
 | 
			
		||||
            Console.WriteLine(await Stats.Print());
 | 
			
		||||
 | 
			
		||||
            await Task.Delay(-1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task Client_MessageReceived(IMessage arg)
 | 
			
		||||
        private void SetupLogger()
 | 
			
		||||
        {
 | 
			
		||||
                var t = await Commands.Execute(arg, 0);
 | 
			
		||||
                if(!t.IsSuccess && t.Error != CommandError.UnknownCommand)
 | 
			
		||||
                    Console.WriteLine(t.ErrorReason);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var logConfig = new LoggingConfiguration();
 | 
			
		||||
                var consoleTarget = new ColoredConsoleTarget();
 | 
			
		||||
 | 
			
		||||
                consoleTarget.Layout = @"${date:format=HH\:mm\:ss} ${logger} | ${message}";
 | 
			
		||||
 | 
			
		||||
                logConfig.AddTarget("Console", consoleTarget);
 | 
			
		||||
 | 
			
		||||
                logConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
 | 
			
		||||
 | 
			
		||||
                LogManager.Configuration = logConfig;
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex) {
 | 
			
		||||
                Console.WriteLine(ex);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Task Client_MessageReceived(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var throwaway = Task.Run(async () =>
 | 
			
		||||
            {
 | 
			
		||||
                var t = await Commands.Execute(imsg, imsg.Content);
 | 
			
		||||
                if (t.IsSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    _log.Info("Command Executed\n\tFull Message: {0}",imsg.Content);
 | 
			
		||||
                }
 | 
			
		||||
                else if (!t.IsSuccess && t.Error != CommandError.UnknownCommand)
 | 
			
		||||
                {
 | 
			
		||||
                    _log.Warn("Command errored!\n\tFull Message: {0}\n\tError:{1}", imsg.Content, t.Error);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								src/NadekoBot/Services/IStatsService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/NadekoBot/Services/IStatsService.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services
 | 
			
		||||
{
 | 
			
		||||
    public interface IStatsService
 | 
			
		||||
    {
 | 
			
		||||
        Task<string> Print();
 | 
			
		||||
        Task Reset();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										58
									
								
								src/NadekoBot/Services/Impl/StatsService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/NadekoBot/Services/Impl/StatsService.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Impl
 | 
			
		||||
{
 | 
			
		||||
    public class StatsService : IStatsService
 | 
			
		||||
    {
 | 
			
		||||
        private int messageCounter;
 | 
			
		||||
        private DiscordSocketClient client;
 | 
			
		||||
        private DateTime started;
 | 
			
		||||
 | 
			
		||||
        public string BotVersion => "1.0-alpha";
 | 
			
		||||
 | 
			
		||||
        public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public StatsService(DiscordSocketClient client)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            this.client = client;
 | 
			
		||||
 | 
			
		||||
            Reset();
 | 
			
		||||
            this.client.MessageReceived += _ => Task.FromResult(messageCounter++);
 | 
			
		||||
 | 
			
		||||
            this.client.Disconnected += _ => Reset();
 | 
			
		||||
        }
 | 
			
		||||
        public Task<string> Print() => Task.FromResult($@"`Author: Kwoth` `Library: Discord.Net`
 | 
			
		||||
`Bot Version: {BotVersion}`
 | 
			
		||||
`Bot id: {(client.GetCurrentUser()).Id}`
 | 
			
		||||
`Owners' Ids:`
 | 
			
		||||
`Uptime: {GetUptimeString()}`
 | 
			
		||||
`Servers: {client.GetGuilds().Count} | TextChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count()} | VoiceChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count()}`
 | 
			
		||||
`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`");
 | 
			
		||||
 | 
			
		||||
        public Task Reset()
 | 
			
		||||
        {
 | 
			
		||||
            messageCounter = 0;
 | 
			
		||||
            started = DateTime.Now;
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public TimeSpan GetUptime() =>
 | 
			
		||||
            DateTime.Now - started;
 | 
			
		||||
 | 
			
		||||
        public string GetUptimeString()
 | 
			
		||||
        {
 | 
			
		||||
            var time = GetUptime();
 | 
			
		||||
            return time.Days + " days, " + time.Hours + " hours, and " + time.Minutes + " minutes.";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -19,7 +19,8 @@
 | 
			
		||||
    "Discord.Net.Commands": "1.0.0-dev",
 | 
			
		||||
    "System.Resources.ResourceWriter": "4.0.0-beta-22816",
 | 
			
		||||
    "Google.Apis.YouTube.v3": "1.15.0.582",
 | 
			
		||||
    "System.Diagnostics.Contracts": "4.0.1"
 | 
			
		||||
    "System.Diagnostics.Contracts": "4.0.1",
 | 
			
		||||
    "NLog": "4.4.0-betaV15"
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "frameworks": {
 | 
			
		||||
 
 | 
			
		||||
@@ -339,7 +339,7 @@
 | 
			
		||||
      "Microsoft.NETCore.Jit/1.0.2": {
 | 
			
		||||
        "type": "package"
 | 
			
		||||
      },
 | 
			
		||||
      "Microsoft.NETCore.Platforms/1.0.1": {
 | 
			
		||||
      "Microsoft.NETCore.Platforms/1.0.2-beta-24410-01": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "lib/netstandard1.0/_._": {}
 | 
			
		||||
@@ -513,6 +513,33 @@
 | 
			
		||||
          "lib/netstandard1.0/Newtonsoft.Json.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "NLog/4.4.0-betav15": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "Microsoft.Extensions.PlatformAbstractions": "1.0.0",
 | 
			
		||||
          "NETStandard.Library": "1.6.0",
 | 
			
		||||
          "System.Collections.NonGeneric": "4.0.1",
 | 
			
		||||
          "System.ComponentModel.TypeConverter": "4.1.0",
 | 
			
		||||
          "System.Data.Common": "4.1.0",
 | 
			
		||||
          "System.Diagnostics.Contracts": "4.0.1",
 | 
			
		||||
          "System.Diagnostics.StackTrace": "4.0.1",
 | 
			
		||||
          "System.Diagnostics.TraceSource": "4.0.0",
 | 
			
		||||
          "System.IO.FileSystem.Watcher": "4.0.0",
 | 
			
		||||
          "System.Net.NameResolution": "4.0.0",
 | 
			
		||||
          "System.Net.Requests": "4.0.11",
 | 
			
		||||
          "System.Reflection.TypeExtensions": "4.1.0",
 | 
			
		||||
          "System.Runtime.Serialization.Primitives": "4.1.1",
 | 
			
		||||
          "System.Threading.Thread": "4.0.0",
 | 
			
		||||
          "System.Threading.ThreadPool": "4.0.10",
 | 
			
		||||
          "System.Xml.XmlDocument": "4.0.1"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "lib/netstandard1.5/NLog.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.5/NLog.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "Portable.BouncyCastle/1.8.1.1": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
@@ -628,7 +655,7 @@
 | 
			
		||||
          "lib/netstandard1.1/System.Buffers.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.1/_._": {}
 | 
			
		||||
          "lib/netstandard1.1/System.Buffers.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Collections/4.0.11": {
 | 
			
		||||
@@ -682,6 +709,41 @@
 | 
			
		||||
          "lib/netstandard1.0/System.Collections.Immutable.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Collections.NonGeneric/4.0.1": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "System.Diagnostics.Debug": "4.0.11",
 | 
			
		||||
          "System.Globalization": "4.0.11",
 | 
			
		||||
          "System.Resources.ResourceManager": "4.0.1",
 | 
			
		||||
          "System.Runtime": "4.1.0",
 | 
			
		||||
          "System.Runtime.Extensions": "4.1.0",
 | 
			
		||||
          "System.Threading": "4.0.11"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.3/System.Collections.NonGeneric.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.3/System.Collections.NonGeneric.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Collections.Specialized/4.0.1": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "System.Collections.NonGeneric": "4.0.1",
 | 
			
		||||
          "System.Globalization": "4.0.11",
 | 
			
		||||
          "System.Globalization.Extensions": "4.0.1",
 | 
			
		||||
          "System.Resources.ResourceManager": "4.0.1",
 | 
			
		||||
          "System.Runtime": "4.1.0",
 | 
			
		||||
          "System.Runtime.Extensions": "4.1.0",
 | 
			
		||||
          "System.Threading": "4.0.11"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.3/_._": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.3/System.Collections.Specialized.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.ComponentModel/4.0.1": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
@@ -716,6 +778,46 @@
 | 
			
		||||
          "lib/netstandard1.4/_._": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.ComponentModel.Primitives/4.1.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "System.ComponentModel": "4.0.1",
 | 
			
		||||
          "System.Resources.ResourceManager": "4.0.1",
 | 
			
		||||
          "System.Runtime": "4.1.0"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.0/System.ComponentModel.Primitives.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.0/System.ComponentModel.Primitives.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.ComponentModel.TypeConverter/4.1.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "System.Collections": "4.0.11",
 | 
			
		||||
          "System.Collections.NonGeneric": "4.0.1",
 | 
			
		||||
          "System.Collections.Specialized": "4.0.1",
 | 
			
		||||
          "System.ComponentModel": "4.0.1",
 | 
			
		||||
          "System.ComponentModel.Primitives": "4.1.0",
 | 
			
		||||
          "System.Globalization": "4.0.11",
 | 
			
		||||
          "System.Linq": "4.1.0",
 | 
			
		||||
          "System.Reflection": "4.1.0",
 | 
			
		||||
          "System.Reflection.Extensions": "4.0.1",
 | 
			
		||||
          "System.Reflection.Primitives": "4.0.1",
 | 
			
		||||
          "System.Reflection.TypeExtensions": "4.1.0",
 | 
			
		||||
          "System.Resources.ResourceManager": "4.0.1",
 | 
			
		||||
          "System.Runtime": "4.1.0",
 | 
			
		||||
          "System.Runtime.Extensions": "4.1.0",
 | 
			
		||||
          "System.Threading": "4.0.11"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.5/System.ComponentModel.TypeConverter.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.5/System.ComponentModel.TypeConverter.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Console/4.0.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
@@ -729,6 +831,25 @@
 | 
			
		||||
          "ref/netstandard1.3/System.Console.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Data.Common/4.1.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "System.Collections": "4.0.11",
 | 
			
		||||
          "System.Globalization": "4.0.11",
 | 
			
		||||
          "System.IO": "4.1.0",
 | 
			
		||||
          "System.Resources.ResourceManager": "4.0.1",
 | 
			
		||||
          "System.Runtime": "4.1.0",
 | 
			
		||||
          "System.Runtime.Extensions": "4.1.0",
 | 
			
		||||
          "System.Text.RegularExpressions": "4.1.0",
 | 
			
		||||
          "System.Threading.Tasks": "4.0.11"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.2/System.Data.Common.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.2/System.Data.Common.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Diagnostics.Contracts/4.0.1": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
@@ -845,10 +966,10 @@
 | 
			
		||||
          "System.Runtime.Extensions": "4.1.0"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.3/_._": {}
 | 
			
		||||
          "ref/netstandard1.3/System.Diagnostics.StackTrace.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.3/_._": {}
 | 
			
		||||
          "lib/netstandard1.3/System.Diagnostics.StackTrace.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Diagnostics.Tools/4.0.1": {
 | 
			
		||||
@@ -862,6 +983,33 @@
 | 
			
		||||
          "ref/netstandard1.0/System.Diagnostics.Tools.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Diagnostics.TraceSource/4.0.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "Microsoft.NETCore.Platforms": "1.0.1",
 | 
			
		||||
          "System.Collections": "4.0.11",
 | 
			
		||||
          "System.Diagnostics.Debug": "4.0.11",
 | 
			
		||||
          "System.Globalization": "4.0.11",
 | 
			
		||||
          "System.Resources.ResourceManager": "4.0.1",
 | 
			
		||||
          "System.Runtime": "4.1.0",
 | 
			
		||||
          "System.Runtime.Extensions": "4.1.0",
 | 
			
		||||
          "System.Threading": "4.0.11",
 | 
			
		||||
          "runtime.native.System": "4.0.0"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.3/System.Diagnostics.TraceSource.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtimeTargets": {
 | 
			
		||||
          "runtimes/unix/lib/netstandard1.3/System.Diagnostics.TraceSource.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "unix"
 | 
			
		||||
          },
 | 
			
		||||
          "runtimes/win/lib/netstandard1.3/System.Diagnostics.TraceSource.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "win"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Diagnostics.Tracing/4.1.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
@@ -1008,7 +1156,7 @@
 | 
			
		||||
          "ref/netstandard1.3/System.IO.Compression.ZipFile.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.3/_._": {}
 | 
			
		||||
          "lib/netstandard1.3/System.IO.Compression.ZipFile.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.IO.FileSystem/4.0.1": {
 | 
			
		||||
@@ -1063,9 +1211,17 @@
 | 
			
		||||
          "ref/netstandard1.3/System.IO.FileSystem.Watcher.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtimeTargets": {
 | 
			
		||||
          "runtimes/osx/lib/netstandard1.3/_._": {
 | 
			
		||||
          "runtimes/linux/lib/netstandard1.3/System.IO.FileSystem.Watcher.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "linux"
 | 
			
		||||
          },
 | 
			
		||||
          "runtimes/osx/lib/netstandard1.3/System.IO.FileSystem.Watcher.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "osx"
 | 
			
		||||
          },
 | 
			
		||||
          "runtimes/win/lib/netstandard1.3/System.IO.FileSystem.Watcher.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "win"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
@@ -1353,7 +1509,11 @@
 | 
			
		||||
          "ref/netstandard1.3/System.Net.Security.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtimeTargets": {
 | 
			
		||||
          "runtimes/win/lib/netstandard1.3/_._": {
 | 
			
		||||
          "runtimes/unix/lib/netstandard1.6/System.Net.Security.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "unix"
 | 
			
		||||
          },
 | 
			
		||||
          "runtimes/win/lib/netstandard1.3/System.Net.Security.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "win"
 | 
			
		||||
          }
 | 
			
		||||
@@ -1403,16 +1563,20 @@
 | 
			
		||||
          "lib/netstandard1.3/System.Net.WebSockets.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Net.WebSockets.Client/4.0.0": {
 | 
			
		||||
      "System.Net.WebSockets.Client/4.0.1-beta-24410-01": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "Microsoft.NETCore.Platforms": "1.0.1",
 | 
			
		||||
          "Microsoft.NETCore.Platforms": "1.0.2-beta-24410-01",
 | 
			
		||||
          "Microsoft.Win32.Primitives": "4.0.1",
 | 
			
		||||
          "System.Collections": "4.0.11",
 | 
			
		||||
          "System.Diagnostics.Debug": "4.0.11",
 | 
			
		||||
          "System.Diagnostics.Tracing": "4.1.0",
 | 
			
		||||
          "System.Globalization": "4.0.11",
 | 
			
		||||
          "System.IO": "4.1.0",
 | 
			
		||||
          "System.Net.NameResolution": "4.0.0",
 | 
			
		||||
          "System.Net.Primitives": "4.0.11",
 | 
			
		||||
          "System.Net.Security": "4.0.0",
 | 
			
		||||
          "System.Net.Sockets": "4.1.0",
 | 
			
		||||
          "System.Net.WebHeaderCollection": "4.0.1",
 | 
			
		||||
          "System.Net.WebSockets": "4.0.0",
 | 
			
		||||
          "System.Resources.ResourceManager": "4.0.1",
 | 
			
		||||
@@ -1420,10 +1584,14 @@
 | 
			
		||||
          "System.Runtime.Extensions": "4.1.0",
 | 
			
		||||
          "System.Runtime.Handles": "4.0.1",
 | 
			
		||||
          "System.Runtime.InteropServices": "4.1.0",
 | 
			
		||||
          "System.Security.Cryptography.Algorithms": "4.2.0",
 | 
			
		||||
          "System.Security.Cryptography.Primitives": "4.0.0",
 | 
			
		||||
          "System.Security.Cryptography.X509Certificates": "4.1.0",
 | 
			
		||||
          "System.Text.Encoding": "4.0.11",
 | 
			
		||||
          "System.Text.Encoding.Extensions": "4.0.11",
 | 
			
		||||
          "System.Threading": "4.0.11",
 | 
			
		||||
          "System.Threading.Tasks": "4.0.11"
 | 
			
		||||
          "System.Threading.Tasks": "4.0.11",
 | 
			
		||||
          "System.Threading.Timer": "4.0.1"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.3/System.Net.WebSockets.Client.dll": {}
 | 
			
		||||
@@ -1584,7 +1752,7 @@
 | 
			
		||||
          "lib/netstandard1.1/System.Reflection.Metadata.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.1/_._": {}
 | 
			
		||||
          "lib/netstandard1.1/System.Reflection.Metadata.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Reflection.Primitives/4.0.1": {
 | 
			
		||||
@@ -2131,7 +2299,11 @@
 | 
			
		||||
          "ref/netstandard1.3/_._": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtimeTargets": {
 | 
			
		||||
          "runtimes/win/lib/netstandard1.3/_._": {
 | 
			
		||||
          "runtimes/unix/lib/netstandard1.3/System.Threading.Overlapped.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "unix"
 | 
			
		||||
          },
 | 
			
		||||
          "runtimes/win/lib/netstandard1.3/System.Threading.Overlapped.dll": {
 | 
			
		||||
            "assetType": "runtime",
 | 
			
		||||
            "rid": "win"
 | 
			
		||||
          }
 | 
			
		||||
@@ -2303,10 +2475,10 @@
 | 
			
		||||
          "System.Xml.ReaderWriter": "4.0.11"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "ref/netstandard1.3/_._": {}
 | 
			
		||||
          "ref/netstandard1.3/System.Xml.XmlDocument.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.3/_._": {}
 | 
			
		||||
          "lib/netstandard1.3/System.Xml.XmlDocument.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "System.Xml.XPath/4.0.1": {
 | 
			
		||||
@@ -2362,7 +2534,7 @@
 | 
			
		||||
          "System.Net.Http": "4.1.0",
 | 
			
		||||
          "System.Net.NameResolution": "4.0.0",
 | 
			
		||||
          "System.Net.Sockets": "4.1.0",
 | 
			
		||||
          "System.Net.WebSockets.Client": "4.0.0",
 | 
			
		||||
          "System.Net.WebSockets.Client": "4.0.1-beta-24410-01",
 | 
			
		||||
          "System.Reflection.Extensions": "4.0.1",
 | 
			
		||||
          "System.Runtime.InteropServices": "4.1.0",
 | 
			
		||||
          "System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
 | 
			
		||||
@@ -2746,12 +2918,12 @@
 | 
			
		||||
        "runtime.json"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "Microsoft.NETCore.Platforms/1.0.1": {
 | 
			
		||||
      "sha512": "2G6OjjJzwBfNOO8myRV/nFrbTw5iA+DEm0N+qUqhrOmaVtn4pC77h38I1jsXGw5VH55+dPfQsqHD0We9sCl9FQ==",
 | 
			
		||||
    "Microsoft.NETCore.Platforms/1.0.2-beta-24410-01": {
 | 
			
		||||
      "sha512": "uc/pGYdE4sVy3OovFF8hg79MvCxptzICxn0jdA6WusGWZa7VieqFoZYc+a6bHUVhMI0s/7SfBriux0RUq+PpbA==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "Microsoft.NETCore.Platforms/1.0.1",
 | 
			
		||||
      "path": "Microsoft.NETCore.Platforms/1.0.2-beta-24410-01",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "Microsoft.NETCore.Platforms.1.0.1.nupkg.sha512",
 | 
			
		||||
        "Microsoft.NETCore.Platforms.1.0.2-beta-24410-01.nupkg.sha512",
 | 
			
		||||
        "Microsoft.NETCore.Platforms.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
@@ -2938,6 +3110,35 @@
 | 
			
		||||
        "tools/install.ps1"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "NLog/4.4.0-betav15": {
 | 
			
		||||
      "sha512": "LDRcdjv5VG9EWz+mnFqdSolUci+j+DBPIPjm7Xdam3xa1F9Rt7o0UpYoCnNRulqHzpKbU704o7Ad4ck9WxDhnw==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "NLog/4.4.0-betav15",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "NLog.4.4.0-betav15.nupkg.sha512",
 | 
			
		||||
        "NLog.nuspec",
 | 
			
		||||
        "lib/monoandroid23/NLog.dll",
 | 
			
		||||
        "lib/monoandroid23/NLog.xml",
 | 
			
		||||
        "lib/net35/NLog.dll",
 | 
			
		||||
        "lib/net35/NLog.xml",
 | 
			
		||||
        "lib/net40/NLog.dll",
 | 
			
		||||
        "lib/net40/NLog.xml",
 | 
			
		||||
        "lib/net45/NLog.dll",
 | 
			
		||||
        "lib/net45/NLog.xml",
 | 
			
		||||
        "lib/netstandard1.3/NLog.dll",
 | 
			
		||||
        "lib/netstandard1.3/NLog.xml",
 | 
			
		||||
        "lib/netstandard1.5/NLog.dll",
 | 
			
		||||
        "lib/netstandard1.5/NLog.xml",
 | 
			
		||||
        "lib/sl40/NLog.dll",
 | 
			
		||||
        "lib/sl40/NLog.xml",
 | 
			
		||||
        "lib/sl50/NLog.dll",
 | 
			
		||||
        "lib/sl50/NLog.xml",
 | 
			
		||||
        "lib/wp80/NLog.dll",
 | 
			
		||||
        "lib/wp80/NLog.xml",
 | 
			
		||||
        "lib/xamarinios10/NLog.dll",
 | 
			
		||||
        "lib/xamarinios10/NLog.xml"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "Portable.BouncyCastle/1.8.1.1": {
 | 
			
		||||
      "sha512": "bKqC2Me9ukybNYTBhlYd2sJ6j2kRV7SgB+JfiP2GueYq6QdM4Ym6PYV5eyrqb6KViOyd3zqQfJp0o6UW5ZG+GQ==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
@@ -3230,6 +3431,80 @@
 | 
			
		||||
        "lib/portable-net45+win8+wp8+wpa81/System.Collections.Immutable.xml"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Collections.NonGeneric/4.0.1": {
 | 
			
		||||
      "sha512": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "System.Collections.NonGeneric/4.0.1",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "System.Collections.NonGeneric.4.0.1.nupkg.sha512",
 | 
			
		||||
        "System.Collections.NonGeneric.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
        "lib/MonoAndroid10/_._",
 | 
			
		||||
        "lib/MonoTouch10/_._",
 | 
			
		||||
        "lib/net46/System.Collections.NonGeneric.dll",
 | 
			
		||||
        "lib/netstandard1.3/System.Collections.NonGeneric.dll",
 | 
			
		||||
        "lib/xamarinios10/_._",
 | 
			
		||||
        "lib/xamarinmac20/_._",
 | 
			
		||||
        "lib/xamarintvos10/_._",
 | 
			
		||||
        "lib/xamarinwatchos10/_._",
 | 
			
		||||
        "ref/MonoAndroid10/_._",
 | 
			
		||||
        "ref/MonoTouch10/_._",
 | 
			
		||||
        "ref/net46/System.Collections.NonGeneric.dll",
 | 
			
		||||
        "ref/netstandard1.3/System.Collections.NonGeneric.dll",
 | 
			
		||||
        "ref/netstandard1.3/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/de/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/es/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/fr/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/it/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/ja/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/ko/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/ru/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/zh-hans/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/netstandard1.3/zh-hant/System.Collections.NonGeneric.xml",
 | 
			
		||||
        "ref/xamarinios10/_._",
 | 
			
		||||
        "ref/xamarinmac20/_._",
 | 
			
		||||
        "ref/xamarintvos10/_._",
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Collections.Specialized/4.0.1": {
 | 
			
		||||
      "sha512": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "System.Collections.Specialized/4.0.1",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "System.Collections.Specialized.4.0.1.nupkg.sha512",
 | 
			
		||||
        "System.Collections.Specialized.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
        "lib/MonoAndroid10/_._",
 | 
			
		||||
        "lib/MonoTouch10/_._",
 | 
			
		||||
        "lib/net46/System.Collections.Specialized.dll",
 | 
			
		||||
        "lib/netstandard1.3/System.Collections.Specialized.dll",
 | 
			
		||||
        "lib/xamarinios10/_._",
 | 
			
		||||
        "lib/xamarinmac20/_._",
 | 
			
		||||
        "lib/xamarintvos10/_._",
 | 
			
		||||
        "lib/xamarinwatchos10/_._",
 | 
			
		||||
        "ref/MonoAndroid10/_._",
 | 
			
		||||
        "ref/MonoTouch10/_._",
 | 
			
		||||
        "ref/net46/System.Collections.Specialized.dll",
 | 
			
		||||
        "ref/netstandard1.3/System.Collections.Specialized.dll",
 | 
			
		||||
        "ref/netstandard1.3/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/de/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/es/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/fr/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/it/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/ja/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/ko/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/ru/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/zh-hans/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/netstandard1.3/zh-hant/System.Collections.Specialized.xml",
 | 
			
		||||
        "ref/xamarinios10/_._",
 | 
			
		||||
        "ref/xamarinmac20/_._",
 | 
			
		||||
        "ref/xamarintvos10/_._",
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.ComponentModel/4.0.1": {
 | 
			
		||||
      "sha512": "oBZFnm7seFiVfugsIyOvQCWobNZs7FzqDV/B7tx20Ep/l3UUFCPDkdTnCNaJZTU27zjeODmy2C/cP60u3D4c9w==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
@@ -3364,6 +3639,94 @@
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.ComponentModel.Primitives/4.1.0": {
 | 
			
		||||
      "sha512": "sc/7eVCdxPrp3ljpgTKVaQGUXiW05phNWvtv/m2kocXqrUQvTVWKou1Edas2aDjTThLPZOxPYIGNb/HN0QjURg==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "System.ComponentModel.Primitives/4.1.0",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "System.ComponentModel.Primitives.4.1.0.nupkg.sha512",
 | 
			
		||||
        "System.ComponentModel.Primitives.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
        "lib/MonoAndroid10/_._",
 | 
			
		||||
        "lib/MonoTouch10/_._",
 | 
			
		||||
        "lib/net45/System.ComponentModel.Primitives.dll",
 | 
			
		||||
        "lib/netstandard1.0/System.ComponentModel.Primitives.dll",
 | 
			
		||||
        "lib/xamarinios10/_._",
 | 
			
		||||
        "lib/xamarinmac20/_._",
 | 
			
		||||
        "lib/xamarintvos10/_._",
 | 
			
		||||
        "lib/xamarinwatchos10/_._",
 | 
			
		||||
        "ref/MonoAndroid10/_._",
 | 
			
		||||
        "ref/MonoTouch10/_._",
 | 
			
		||||
        "ref/net45/System.ComponentModel.Primitives.dll",
 | 
			
		||||
        "ref/netstandard1.0/System.ComponentModel.Primitives.dll",
 | 
			
		||||
        "ref/netstandard1.0/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/de/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/es/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/fr/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/it/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/ja/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/ko/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/ru/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/zh-hans/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/netstandard1.0/zh-hant/System.ComponentModel.Primitives.xml",
 | 
			
		||||
        "ref/xamarinios10/_._",
 | 
			
		||||
        "ref/xamarinmac20/_._",
 | 
			
		||||
        "ref/xamarintvos10/_._",
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.ComponentModel.TypeConverter/4.1.0": {
 | 
			
		||||
      "sha512": "MnDAlaeJZy9pdB5ZdOlwdxfpI+LJQ6e0hmH7d2+y2LkiD8DRJynyDYl4Xxf3fWFm7SbEwBZh4elcfzONQLOoQw==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "System.ComponentModel.TypeConverter/4.1.0",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "System.ComponentModel.TypeConverter.4.1.0.nupkg.sha512",
 | 
			
		||||
        "System.ComponentModel.TypeConverter.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
        "lib/MonoAndroid10/_._",
 | 
			
		||||
        "lib/MonoTouch10/_._",
 | 
			
		||||
        "lib/net45/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "lib/net462/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "lib/netstandard1.0/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "lib/netstandard1.5/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "lib/xamarinios10/_._",
 | 
			
		||||
        "lib/xamarinmac20/_._",
 | 
			
		||||
        "lib/xamarintvos10/_._",
 | 
			
		||||
        "lib/xamarinwatchos10/_._",
 | 
			
		||||
        "ref/MonoAndroid10/_._",
 | 
			
		||||
        "ref/MonoTouch10/_._",
 | 
			
		||||
        "ref/net45/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "ref/net462/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "ref/netstandard1.0/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "ref/netstandard1.0/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/de/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/es/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/fr/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/it/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/ja/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/ko/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/ru/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/zh-hans/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.0/zh-hant/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/System.ComponentModel.TypeConverter.dll",
 | 
			
		||||
        "ref/netstandard1.5/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/de/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/es/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/fr/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/it/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/ja/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/ko/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/ru/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/zh-hans/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/netstandard1.5/zh-hant/System.ComponentModel.TypeConverter.xml",
 | 
			
		||||
        "ref/xamarinios10/_._",
 | 
			
		||||
        "ref/xamarinmac20/_._",
 | 
			
		||||
        "ref/xamarintvos10/_._",
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Console/4.0.0": {
 | 
			
		||||
      "sha512": "qSKUSOIiYA/a0g5XXdxFcUFmv1hNICBD7QZ0QhGYVipPIhvpiydY8VZqr1thmCXvmn8aipMg64zuanB4eotK9A==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
@@ -3400,6 +3763,55 @@
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Data.Common/4.1.0": {
 | 
			
		||||
      "sha512": "epU8jeTe7aE7RqGHq9rZ8b0Q4Ah7DgubzHQblgZMSqgW1saW868WmooSyC5ywf8upLBkcVLDu93W9GPWUYsU2Q==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "System.Data.Common/4.1.0",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "System.Data.Common.4.1.0.nupkg.sha512",
 | 
			
		||||
        "System.Data.Common.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
        "lib/MonoAndroid10/_._",
 | 
			
		||||
        "lib/MonoTouch10/_._",
 | 
			
		||||
        "lib/net451/System.Data.Common.dll",
 | 
			
		||||
        "lib/netstandard1.2/System.Data.Common.dll",
 | 
			
		||||
        "lib/portable-net451+win8+wp8+wpa81/System.Data.Common.dll",
 | 
			
		||||
        "lib/xamarinios10/_._",
 | 
			
		||||
        "lib/xamarinmac20/_._",
 | 
			
		||||
        "lib/xamarintvos10/_._",
 | 
			
		||||
        "lib/xamarinwatchos10/_._",
 | 
			
		||||
        "ref/MonoAndroid10/_._",
 | 
			
		||||
        "ref/MonoTouch10/_._",
 | 
			
		||||
        "ref/net451/System.Data.Common.dll",
 | 
			
		||||
        "ref/netstandard1.2/System.Data.Common.dll",
 | 
			
		||||
        "ref/netstandard1.2/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/de/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/es/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/fr/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/it/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/ja/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/ko/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/ru/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/zh-hans/System.Data.Common.xml",
 | 
			
		||||
        "ref/netstandard1.2/zh-hant/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/System.Data.Common.dll",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/de/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/es/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/fr/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/it/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/ja/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/ko/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/ru/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/zh-hans/System.Data.Common.xml",
 | 
			
		||||
        "ref/portable-net451+win8+wp8+wpa81/zh-hant/System.Data.Common.xml",
 | 
			
		||||
        "ref/xamarinios10/_._",
 | 
			
		||||
        "ref/xamarinmac20/_._",
 | 
			
		||||
        "ref/xamarintvos10/_._",
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Diagnostics.Contracts/4.0.1": {
 | 
			
		||||
      "sha512": "HvQQjy712vnlpPxaloZYkuE78Gn353L0SJLJVeLcNASeg9c4qla2a1Xq8I7B3jZoDzKPtHTkyVO7AZ5tpeQGuA==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
@@ -3731,6 +4143,45 @@
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Diagnostics.TraceSource/4.0.0": {
 | 
			
		||||
      "sha512": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "System.Diagnostics.TraceSource/4.0.0",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "System.Diagnostics.TraceSource.4.0.0.nupkg.sha512",
 | 
			
		||||
        "System.Diagnostics.TraceSource.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
        "lib/MonoAndroid10/_._",
 | 
			
		||||
        "lib/MonoTouch10/_._",
 | 
			
		||||
        "lib/net46/System.Diagnostics.TraceSource.dll",
 | 
			
		||||
        "lib/xamarinios10/_._",
 | 
			
		||||
        "lib/xamarinmac20/_._",
 | 
			
		||||
        "lib/xamarintvos10/_._",
 | 
			
		||||
        "lib/xamarinwatchos10/_._",
 | 
			
		||||
        "ref/MonoAndroid10/_._",
 | 
			
		||||
        "ref/MonoTouch10/_._",
 | 
			
		||||
        "ref/net46/System.Diagnostics.TraceSource.dll",
 | 
			
		||||
        "ref/netstandard1.3/System.Diagnostics.TraceSource.dll",
 | 
			
		||||
        "ref/netstandard1.3/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/de/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/es/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/fr/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/it/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/ja/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/ko/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/ru/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/zh-hans/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/netstandard1.3/zh-hant/System.Diagnostics.TraceSource.xml",
 | 
			
		||||
        "ref/xamarinios10/_._",
 | 
			
		||||
        "ref/xamarinmac20/_._",
 | 
			
		||||
        "ref/xamarintvos10/_._",
 | 
			
		||||
        "ref/xamarinwatchos10/_._",
 | 
			
		||||
        "runtimes/unix/lib/netstandard1.3/System.Diagnostics.TraceSource.dll",
 | 
			
		||||
        "runtimes/win/lib/net46/System.Diagnostics.TraceSource.dll",
 | 
			
		||||
        "runtimes/win/lib/netstandard1.3/System.Diagnostics.TraceSource.dll"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Diagnostics.Tracing/4.1.0": {
 | 
			
		||||
      "sha512": "vDN1PoMZCkkdNjvZLql592oYJZgS7URcJzJ7bxeBgGtx5UtR5leNm49VmfHGqIffX4FKacHbI3H6UyNSHQknBg==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
@@ -5097,12 +5548,12 @@
 | 
			
		||||
        "ref/xamarinwatchos10/_._"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "System.Net.WebSockets.Client/4.0.0": {
 | 
			
		||||
      "sha512": "GY5h9cn0ZVsG4ORQqMytTldrqxet2RC2CSEsgWGf4XNW5jhL5SxzcUZph03xbZsgn7K3qMr+Rq+gkbJNI+FEXg==",
 | 
			
		||||
    "System.Net.WebSockets.Client/4.0.1-beta-24410-01": {
 | 
			
		||||
      "sha512": "IOqAcR7k+3LwNI6aL7qN61HcCOA9X4MM9LbrZhDeNbeB/IeWTk7zpeb7kh3d7H678s7ndIqN6a7okO8dAAfcYQ==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "System.Net.WebSockets.Client/4.0.0",
 | 
			
		||||
      "path": "System.Net.WebSockets.Client/4.0.1-beta-24410-01",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "System.Net.WebSockets.Client.4.0.0.nupkg.sha512",
 | 
			
		||||
        "System.Net.WebSockets.Client.4.0.1-beta-24410-01.nupkg.sha512",
 | 
			
		||||
        "System.Net.WebSockets.Client.nuspec",
 | 
			
		||||
        "ThirdPartyNotices.txt",
 | 
			
		||||
        "dotnet_library_license.txt",
 | 
			
		||||
@@ -7421,6 +7872,7 @@
 | 
			
		||||
      "Microsoft.Extensions.DependencyInjection.Abstractions >= 1.0.0",
 | 
			
		||||
      "Microsoft.Extensions.PlatformAbstractions >= 1.0.0",
 | 
			
		||||
      "Microsoft.NETCore.App >= 1.0.0",
 | 
			
		||||
      "NLog >= 4.4.0-betaV15",
 | 
			
		||||
      "Newtonsoft.Json >= 9.0.1",
 | 
			
		||||
      "System.Diagnostics.Contracts >= 4.0.1",
 | 
			
		||||
      "System.Resources.ResourceWriter >= 4.0.0-beta-22816"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user