a LOT More work
This commit is contained in:
		@@ -1,53 +0,0 @@
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes
 | 
			
		||||
{
 | 
			
		||||
    internal static class FlowersHandler
 | 
			
		||||
    {
 | 
			
		||||
        public static async Task AddFlowersAsync(Discord.User u, string reason, int amount, bool silent = false)
 | 
			
		||||
        {
 | 
			
		||||
            if (amount <= 0)
 | 
			
		||||
                return;
 | 
			
		||||
            await Task.Run(() =>
 | 
			
		||||
            {
 | 
			
		||||
                DbHandler.Instance.Connection.Insert(new DataModels.CurrencyTransaction
 | 
			
		||||
                {
 | 
			
		||||
                    Reason = reason,
 | 
			
		||||
                    UserId = (long)u.Id,
 | 
			
		||||
                    Value = amount,
 | 
			
		||||
                });
 | 
			
		||||
            }).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            if (silent)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var flows = amount + " " + NadekoBot.Config.CurrencySign;
 | 
			
		||||
 | 
			
		||||
            await u.SendMessageAsync("👑Congratulations!👑\nYou received: " + flows).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<bool> RemoveFlowers(Discord.User u, string reason, int amount, bool silent=false, string message="👎`Bot owner has taken {0}{1} from you.`")
 | 
			
		||||
        {
 | 
			
		||||
            if (amount <= 0)
 | 
			
		||||
                return false;
 | 
			
		||||
            var uid = (long)u.Id;
 | 
			
		||||
            var state = DbHandler.Instance.FindOne<DataModels.CurrencyState>(cs => cs.UserId == uid);
 | 
			
		||||
 | 
			
		||||
            if (state.Value < amount)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            DbHandler.Instance.Connection.Insert(new DataModels.CurrencyTransaction
 | 
			
		||||
            {
 | 
			
		||||
                Reason = reason,
 | 
			
		||||
                UserId = (long)u.Id,
 | 
			
		||||
                Value = -amount,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            if (silent)
 | 
			
		||||
                return true;
 | 
			
		||||
 | 
			
		||||
            await u.SendMessageAsync(string.Format(message,amount,NadekoBot.Config.CurrencySign)).ConfigureAwait(false);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
using NadekoBot.DataModels;
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes
 | 
			
		||||
{
 | 
			
		||||
    internal static class IncidentsHandler
 | 
			
		||||
    {
 | 
			
		||||
        public static void Add(ulong serverId, ulong channelId, string text)
 | 
			
		||||
        {
 | 
			
		||||
            var def = Console.ForegroundColor;
 | 
			
		||||
            Console.ForegroundColor = ConsoleColor.Red;
 | 
			
		||||
            Console.WriteLine($"INCIDENT: {text}");
 | 
			
		||||
            Console.ForegroundColor = def;
 | 
			
		||||
            var incident = new Incident
 | 
			
		||||
            {
 | 
			
		||||
                ChannelId = (long)channelId,
 | 
			
		||||
                ServerId = (long)serverId,
 | 
			
		||||
                Text = text,
 | 
			
		||||
                Read = false
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            DbHandler.Instance.Connection.Insert(incident, typeof(Incident));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,284 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Modules.Administration.Commands;
 | 
			
		||||
using NadekoBot.Modules.Music;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Timers;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot
 | 
			
		||||
{
 | 
			
		||||
    public class NadekoStats
 | 
			
		||||
    {
 | 
			
		||||
        public static NadekoStats Instance { get; } = new NadekoStats();
 | 
			
		||||
 | 
			
		||||
        public string BotVersion => $"{Assembly.GetExecutingAssembly().GetName().Name} v{Assembly.GetExecutingAssembly().GetName().Version}";
 | 
			
		||||
 | 
			
		||||
        private int commandsRan = 0;
 | 
			
		||||
        private string statsCache = "";
 | 
			
		||||
        private readonly Stopwatch statsStopwatch = new Stopwatch();
 | 
			
		||||
 | 
			
		||||
        public int ServerCount { get; private set; } = 0;
 | 
			
		||||
        public int TextChannelsCount { get; private set; } = 0;
 | 
			
		||||
        public int VoiceChannelsCount { get; private set; } = 0;
 | 
			
		||||
 | 
			
		||||
        private readonly Timer commandLogTimer = new Timer() { Interval = 10000 };
 | 
			
		||||
        private readonly Timer carbonStatusTimer = new Timer() { Interval = 3600000 };
 | 
			
		||||
 | 
			
		||||
        private static ulong messageCounter = 0;
 | 
			
		||||
        public static ulong MessageCounter => messageCounter;
 | 
			
		||||
 | 
			
		||||
        static NadekoStats() { }
 | 
			
		||||
 | 
			
		||||
        private NadekoStats()
 | 
			
		||||
        {
 | 
			
		||||
            var commandService = NadekoBot.Client.GetService<CommandService>();
 | 
			
		||||
 | 
			
		||||
            statsStopwatch.Start();
 | 
			
		||||
 | 
			
		||||
            commandService.CommandExecuted += StatsCollector_RanCommand;
 | 
			
		||||
            commandService.CommandFinished += CommandService_CommandFinished;
 | 
			
		||||
            commandService.CommandErrored += CommandService_CommandFinished;
 | 
			
		||||
 | 
			
		||||
            Task.Run(StartCollecting);
 | 
			
		||||
 | 
			
		||||
            commandLogTimer.Start();
 | 
			
		||||
 | 
			
		||||
            ServerCount = NadekoBot.Client.Servers.Count();
 | 
			
		||||
            var channels = NadekoBot.Client.Servers.SelectMany(s => s.AllChannels);
 | 
			
		||||
            var channelsArray = channels as Channel[] ?? channels.ToArray();
 | 
			
		||||
            TextChannelsCount = channelsArray.Count(c => c.Type == ChannelType.Text);
 | 
			
		||||
            VoiceChannelsCount = channelsArray.Count() - TextChannelsCount;
 | 
			
		||||
 | 
			
		||||
            NadekoBot.Client.MessageReceived += (s, e) => messageCounter++;
 | 
			
		||||
 | 
			
		||||
            NadekoBot.Client.JoinedServer += (s, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    ServerCount++;
 | 
			
		||||
                    TextChannelsCount += e.Server.TextChannels.Count();
 | 
			
		||||
                    VoiceChannelsCount += e.Server.VoiceChannels.Count();
 | 
			
		||||
                    //await SendUpdateToCarbon().ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                catch { }
 | 
			
		||||
            };
 | 
			
		||||
            NadekoBot.Client.LeftServer += (s, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    ServerCount--;
 | 
			
		||||
                    TextChannelsCount -= e.Server.TextChannels.Count();
 | 
			
		||||
                    VoiceChannelsCount -= e.Server.VoiceChannels.Count();
 | 
			
		||||
                    //await SendUpdateToCarbon().ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                catch { }
 | 
			
		||||
            };
 | 
			
		||||
            NadekoBot.Client.ChannelCreated += (s, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if (e.Channel.IsPrivate)
 | 
			
		||||
                        return;
 | 
			
		||||
                    if (e.Channel.Type == ChannelType.Text)
 | 
			
		||||
                        TextChannelsCount++;
 | 
			
		||||
                    else if (e.Channel.Type == ChannelType.Voice)
 | 
			
		||||
                        VoiceChannelsCount++;
 | 
			
		||||
                }
 | 
			
		||||
                catch { }
 | 
			
		||||
            };
 | 
			
		||||
            NadekoBot.Client.ChannelDestroyed += (s, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    if (e.Channel.IsPrivate)
 | 
			
		||||
                        return;
 | 
			
		||||
                    if (e.Channel.Type == ChannelType.Text)
 | 
			
		||||
                        TextChannelsCount--;
 | 
			
		||||
                    else if (e.Channel.Type == ChannelType.Voice)
 | 
			
		||||
                        VoiceChannelsCount--;
 | 
			
		||||
                }
 | 
			
		||||
                catch { }
 | 
			
		||||
            };
 | 
			
		||||
            carbonStatusTimer.Elapsed += async (s, e) => await SendUpdateToCarbon().ConfigureAwait(false);
 | 
			
		||||
            carbonStatusTimer.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        HttpClient carbonClient = new HttpClient();
 | 
			
		||||
        private async Task SendUpdateToCarbon()
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.CarbonKey))
 | 
			
		||||
                return;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var content = new FormUrlEncodedContent(new Dictionary<string, string> {
 | 
			
		||||
                                { "servercount", NadekoBot.Client.Servers.Count().ToString() },
 | 
			
		||||
                                { "key", NadekoBot.Credentials.CarbonKey }
 | 
			
		||||
                    }))
 | 
			
		||||
                {
 | 
			
		||||
                    content.Headers.Clear();
 | 
			
		||||
                    content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
 | 
			
		||||
 | 
			
		||||
                    var res = await carbonClient.PostAsync("https://www.carbonitex.net/discord/data/botdata.php", content).ConfigureAwait(false);
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine("Failed sending status update to carbon.");
 | 
			
		||||
                Console.WriteLine(ex);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public TimeSpan GetUptime() =>
 | 
			
		||||
            DateTime.Now - Process.GetCurrentProcess().StartTime;
 | 
			
		||||
 | 
			
		||||
        public string GetUptimeString()
 | 
			
		||||
        {
 | 
			
		||||
            var time = GetUptime();
 | 
			
		||||
            return time.Days + " days, " + time.Hours + " hours, and " + time.Minutes + " minutes.";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task LoadStats() =>
 | 
			
		||||
            Task.Run(() =>
 | 
			
		||||
            {
 | 
			
		||||
                var songs = MusicModule.MusicPlayers.Count(mp => mp.Value.CurrentSong != null);
 | 
			
		||||
                var sb = new System.Text.StringBuilder();
 | 
			
		||||
                sb.AppendLine("`Author: Kwoth` `Library: Discord.Net`");
 | 
			
		||||
                sb.AppendLine($"`Bot Version: {BotVersion}`");
 | 
			
		||||
                sb.AppendLine($"`Bot id: {NadekoBot.Client.CurrentUser.Id}`");
 | 
			
		||||
                sb.Append("`Owners' Ids:` ");
 | 
			
		||||
                sb.AppendLine("`" + String.Join(", ", NadekoBot.Credentials.OwnerIds) + "`");
 | 
			
		||||
                sb.AppendLine($"`Uptime: {GetUptimeString()}`");
 | 
			
		||||
                sb.Append($"`Servers: {ServerCount}");
 | 
			
		||||
                sb.Append($" | TextChannels: {TextChannelsCount}");
 | 
			
		||||
                sb.AppendLine($" | VoiceChannels: {VoiceChannelsCount}`");
 | 
			
		||||
                sb.AppendLine($"`Commands Ran this session: {commandsRan}`");
 | 
			
		||||
                sb.AppendLine($"`Message queue size: {NadekoBot.Client.MessageQueue.Count}`");
 | 
			
		||||
                sb.Append($"`Greeted {ServerGreetCommand.Greeted} times.`");
 | 
			
		||||
                sb.AppendLine($" `| Playing {songs} songs, ".SnPl(songs) +
 | 
			
		||||
                              $"{MusicModule.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count)} queued.`");
 | 
			
		||||
                sb.AppendLine($"`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)`  `Heap: {Heap(false)}`");
 | 
			
		||||
                statsCache = sb.ToString();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        public string Heap(bool pass = true) => Math.Round((double)GC.GetTotalMemory(pass) / 1.MiB(), 2).ToString();
 | 
			
		||||
 | 
			
		||||
        public async Task<string> GetStats()
 | 
			
		||||
        {
 | 
			
		||||
            if (statsStopwatch.Elapsed.Seconds < 4 &&
 | 
			
		||||
                !string.IsNullOrWhiteSpace(statsCache)) return statsCache;
 | 
			
		||||
            await LoadStats().ConfigureAwait(false);
 | 
			
		||||
            statsStopwatch.Restart();
 | 
			
		||||
            return statsCache;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task StartCollecting()
 | 
			
		||||
        {
 | 
			
		||||
            var statsSw = new Stopwatch();
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(new TimeSpan(0, 30, 0)).ConfigureAwait(false);
 | 
			
		||||
                statsSw.Start();
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    var onlineUsers = await Task.Run(() => NadekoBot.Client.Servers.Sum(x => x.Users.Count())).ConfigureAwait(false);
 | 
			
		||||
                    var realOnlineUsers = await Task.Run(() => NadekoBot.Client.Servers
 | 
			
		||||
                                                                        .Sum(x => x.Users.Count(u => u.Status == UserStatus.Online)))
 | 
			
		||||
                                                                        .ConfigureAwait(false);
 | 
			
		||||
                    var connectedServers = NadekoBot.Client.Servers.Count();
 | 
			
		||||
 | 
			
		||||
                    Classes.DbHandler.Instance.Connection.Insert(new DataModels.Stats
 | 
			
		||||
                    {
 | 
			
		||||
                        OnlineUsers = onlineUsers,
 | 
			
		||||
                        RealOnlineUsers = realOnlineUsers,
 | 
			
		||||
                        Uptime = GetUptime(),
 | 
			
		||||
                        ConnectedServers = connectedServers,
 | 
			
		||||
                        DateAdded = DateTime.Now
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    statsSw.Stop();
 | 
			
		||||
                    var clr = Console.ForegroundColor;
 | 
			
		||||
                    Console.ForegroundColor = ConsoleColor.Blue;
 | 
			
		||||
                    Console.WriteLine($"--------------\nCollecting stats finished in {statsSw.Elapsed.TotalSeconds}s\n-------------");
 | 
			
		||||
                    Console.ForegroundColor = clr;
 | 
			
		||||
                    statsSw.Reset();
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    Console.WriteLine("DB Exception in stats collecting.");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static ConcurrentDictionary<ulong, DateTime> commandTracker = new ConcurrentDictionary<ulong, DateTime>();
 | 
			
		||||
 | 
			
		||||
        private void CommandService_CommandFinished(object sender, CommandEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            DateTime dt;
 | 
			
		||||
            if (!commandTracker.TryGetValue(e.Message.Id, out dt))
 | 
			
		||||
                return;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (e is CommandErrorEventArgs)
 | 
			
		||||
                {
 | 
			
		||||
                    var er = e as CommandErrorEventArgs;
 | 
			
		||||
                    if (er.ErrorType == CommandErrorType.Exception)
 | 
			
		||||
                    {
 | 
			
		||||
                        File.AppendAllText("errors.txt", $@"Command: {er.Command}
 | 
			
		||||
{er.Exception}
 | 
			
		||||
-------------------------------------
 | 
			
		||||
");
 | 
			
		||||
                        Console.WriteLine($">>COMMAND ERRORED after *{(DateTime.UtcNow - dt).TotalSeconds}s*\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {imsg.Author.Username} [{imsg.Author.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----");
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    Console.WriteLine($">>COMMAND ENDED after *{(DateTime.UtcNow - dt).TotalSeconds}s*\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {imsg.Author.Username} [{imsg.Author.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void StatsCollector_RanCommand(object sender, CommandEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            commandTracker.TryAdd(e.Message.Id, DateTime.UtcNow);
 | 
			
		||||
            Console.WriteLine($">>COMMAND STARTED\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {imsg.Author.Username} [{imsg.Author.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----");
 | 
			
		||||
#if !NADEKO_RELEASE
 | 
			
		||||
            await Task.Run(() =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    commandsRan++;
 | 
			
		||||
                    Classes.DbHandler.Instance.Connection.Insert(new DataModels.Command
 | 
			
		||||
                    {
 | 
			
		||||
                        ServerId = (long)(e.Server?.Id ?? 0),
 | 
			
		||||
                        ServerName = e.Server?.Name ?? "--Direct Message--",
 | 
			
		||||
                        ChannelId = (long)e.Channel.Id,
 | 
			
		||||
                        ChannelName = e.Channel.IsPrivate ? "--Direct Message" : e.Channel.Name,
 | 
			
		||||
                        UserId = (long)imsg.Author.Id,
 | 
			
		||||
                        UserName = imsg.Author.Username,
 | 
			
		||||
                        CommandName = e.Command.Text,
 | 
			
		||||
                        DateAdded = DateTime.Now
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    Console.WriteLine("Probably unimportant error in ran command DB write.");
 | 
			
		||||
                    Console.WriteLine(ex);
 | 
			
		||||
                }
 | 
			
		||||
            }).ConfigureAwait(false);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -11,6 +11,8 @@ using NadekoBot.Services;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
 | 
			
		||||
//todo fix delmsgoncmd
 | 
			
		||||
//todo DB
 | 
			
		||||
@@ -35,24 +37,27 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //    System.Diagnostics.Process.Start(System.Reflection.Assembly.GetEntryAssembly().Location);
 | 
			
		||||
        //    Environment.Exit(0);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo DB
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //[RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
        //public async Task Delmsgoncmd(IMessage imsg)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
        //    var conf = SpecificConfigurations.Default.Of(channel.Guild.Id);
 | 
			
		||||
        //    conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand;
 | 
			
		||||
        //    await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
 | 
			
		||||
        //    if (conf.AutoDeleteMessagesOnCommand)
 | 
			
		||||
        //        await channel.SendMessageAsync("❗`Now automatically deleting successfull command invokations.`");
 | 
			
		||||
        //    else
 | 
			
		||||
        //        await channel.SendMessageAsync("❗`Stopped automatic deletion of successfull command invokations.`");
 | 
			
		||||
        //}
 | 
			
		||||
        
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.Administrator)]
 | 
			
		||||
        public async Task Delmsgoncmd(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
            Config conf;
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                conf = uow.Configs.For(channel.Guild.Id);
 | 
			
		||||
                conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand;
 | 
			
		||||
                uow.Configs.Update(conf);
 | 
			
		||||
                await uow.CompleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
            if (conf.DeleteMessageOnCommand)
 | 
			
		||||
                await channel.SendMessageAsync("❗`Now automatically deleting successfull command invokations.`");
 | 
			
		||||
            else
 | 
			
		||||
                await channel.SendMessageAsync("❗`Stopped automatic deletion of successfull command invokations.`");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
@@ -563,30 +568,6 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        ////todo DB
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Donadd(IMessage imsg, IUser donator, int amount)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
        //    var donator = channel.Guild.FindUsers(donator).FirstOrDefault();
 | 
			
		||||
        //    var amount = int.Parse(amount);
 | 
			
		||||
        //    if (donator == null) return;
 | 
			
		||||
        //    try
 | 
			
		||||
        //    {
 | 
			
		||||
        //        DbHandler.Instance.Connection.Insert(new Donator
 | 
			
		||||
        //        {
 | 
			
		||||
        //            Amount = amount,
 | 
			
		||||
        //            UserName = donator.Name,
 | 
			
		||||
        //            UserId = (long)donator.Id
 | 
			
		||||
        //        });
 | 
			
		||||
        //        channel.SendMessageAsync("Successfuly added a new donator. 👑").ConfigureAwait(false);
 | 
			
		||||
        //    }
 | 
			
		||||
        //    catch { }
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -660,18 +641,36 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await channel.SendMessageAsync(send).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //todo DB
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Donators(IMessage imsg)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Donators(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
            IEnumerable<Donator> donatorsOrdered;
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                donatorsOrdered = uow.Donators.GetDonatorsOrdered();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        //    var rows = DbHandler.Instance.GetAllRows<Donator>();
 | 
			
		||||
        //    var donatorsOrdered = rows.OrderByDescending(d => d.Amount);
 | 
			
		||||
        //    string str = $"**Thanks to the people listed below for making this project happen!**\n";
 | 
			
		||||
            string str = $"**Thanks to the people listed below for making this project happen!**\n";
 | 
			
		||||
            await channel.SendMessageAsync(str + string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //    await channel.SendMessageAsync(str + string.Join("⭐", donatorsOrdered.Select(d => d.UserName))).ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Donadd(IMessage imsg, IUser donator, int amount)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
            Donator don;
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                don = uow.Donators.AddOrUpdateDonator(donator.Id, donator.Username, amount);
 | 
			
		||||
                await uow.CompleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await channel.SendMessageAsync($"Successfuly added a new donator. Total donated amount from this user: {don.Amount} 👑").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Utility.Commands
 | 
			
		||||
namespace NadekoBot.Modules.Utility
 | 
			
		||||
{
 | 
			
		||||
    public partial class Utility
 | 
			
		||||
    {
 | 
			
		||||
@@ -103,7 +103,7 @@ namespace NadekoBot.Modules.Utility.Commands
 | 
			
		||||
            {
 | 
			
		||||
                var quotes = uow.Quotes.GetAllQuotesByKeyword(keyword);
 | 
			
		||||
 | 
			
		||||
                uow.Quotes.RemoveRange(quotes.Select(q => q.Id).ToArray());//wtf?!
 | 
			
		||||
                uow.Quotes.RemoveRange(quotes.ToArray());//wtf?!
 | 
			
		||||
 | 
			
		||||
                await uow.CompleteAsync();
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
    public interface IUnitOfWork : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        IQuoteRepository Quotes { get; }
 | 
			
		||||
        IConfigRepository Configs { get; }
 | 
			
		||||
        IDonatorsRepository Donators { get; }
 | 
			
		||||
        int Complete();
 | 
			
		||||
        Task<int> CompleteAsync();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								src/NadekoBot/Services/Database/Models/Config.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/NadekoBot/Services/Database/Models/Config.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Models
 | 
			
		||||
{
 | 
			
		||||
    public class Config : DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public ulong GuildId { get; set; }
 | 
			
		||||
        public bool DeleteMessageOnCommand { get; set; } = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								src/NadekoBot/Services/Database/Models/Donator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/NadekoBot/Services/Database/Models/Donator.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Models
 | 
			
		||||
{
 | 
			
		||||
    public class Donator : DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public ulong UserId { get; set; }
 | 
			
		||||
        public string Name { get; set; }
 | 
			
		||||
        public int Amount { get; set; } = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -15,24 +15,28 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        protected override void OnModelCreating(ModelBuilder modelBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            #region QUOTES
 | 
			
		||||
            //// guildid and keyword are unique pair
 | 
			
		||||
            var quoteEntity = modelBuilder.Entity<Quote>();
 | 
			
		||||
            //quoteEntity
 | 
			
		||||
            //    .HasAlternateKey(q => q.GuildId)
 | 
			
		||||
            //    .HasName("AK_GuildId_Keyword");
 | 
			
		||||
 | 
			
		||||
            //quoteEntity
 | 
			
		||||
            //    .HasAlternateKey(q => q.Keyword)
 | 
			
		||||
            //    .HasName("AK_GuildId_Keyword");
 | 
			
		||||
 | 
			
		||||
            quoteEntity
 | 
			
		||||
                .HasIndex(q => new { q.GuildId, q.Keyword })
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
            
 | 
			
		||||
            var quoteEntity = modelBuilder.Entity<Quote>();
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
 | 
			
		||||
            #region 
 | 
			
		||||
 | 
			
		||||
            #region Donators
 | 
			
		||||
 | 
			
		||||
            var donatorEntity = modelBuilder.Entity<Donator>();
 | 
			
		||||
            donatorEntity
 | 
			
		||||
                .HasIndex(d => d.UserId)
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
 | 
			
		||||
            #region Config
 | 
			
		||||
 | 
			
		||||
            var configEntity = modelBuilder.Entity<Config>();
 | 
			
		||||
            configEntity
 | 
			
		||||
                .HasIndex(c => c.GuildId)
 | 
			
		||||
                .IsUnique();
 | 
			
		||||
 | 
			
		||||
            #endregion
 | 
			
		||||
        }
 | 
			
		||||
        protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using NadekoBot.Services.Database.Repositories.Impl;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
{
 | 
			
		||||
    public interface IConfigRepository : IRepository<Config>
 | 
			
		||||
    {
 | 
			
		||||
        Config For(ulong guildId);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
{
 | 
			
		||||
    public interface IDonatorsRepository : IRepository<Donator>
 | 
			
		||||
    {
 | 
			
		||||
        IEnumerable<Donator> GetDonatorsOrdered();
 | 
			
		||||
        Donator AddOrUpdateDonator(ulong userId, string name, int amount);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -18,7 +18,7 @@ namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
 | 
			
		||||
        void Remove(int id);
 | 
			
		||||
        void Remove(T obj);
 | 
			
		||||
        void RemoveRange(params int[] ids);
 | 
			
		||||
        void RemoveRange(params T[] objs);
 | 
			
		||||
 | 
			
		||||
        void Update(T obj);
 | 
			
		||||
        void UpdateRange(params T[] objs);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
{
 | 
			
		||||
    public class ConfigRepository : Repository<Config>, IConfigRepository
 | 
			
		||||
    {
 | 
			
		||||
        public ConfigRepository(DbContext context) : base(context)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets and creates if it doesn't exist a config for a guild.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="guildId"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public Config For(ulong guildId)
 | 
			
		||||
        {
 | 
			
		||||
            var config = _set.Where(c => c.GuildId == guildId).FirstOrDefault();
 | 
			
		||||
 | 
			
		||||
            if (config == null)
 | 
			
		||||
            {
 | 
			
		||||
                _set.Add((config = new Config
 | 
			
		||||
                {
 | 
			
		||||
                    GuildId = guildId
 | 
			
		||||
                }));
 | 
			
		||||
            }
 | 
			
		||||
            return config;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,41 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
{
 | 
			
		||||
    public class DonatorsRepository : Repository<Donator>, IDonatorsRepository
 | 
			
		||||
    {
 | 
			
		||||
        public DonatorsRepository(DbContext context) : base(context)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Donator AddOrUpdateDonator(ulong userId, string name, int amount)
 | 
			
		||||
        {
 | 
			
		||||
            var donator = _set.Find(userId);
 | 
			
		||||
 | 
			
		||||
            if (donator == null)
 | 
			
		||||
            {
 | 
			
		||||
                _set.Add(donator = new Donator
 | 
			
		||||
                {
 | 
			
		||||
                    Amount = amount,
 | 
			
		||||
                    UserId = userId
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                donator.Amount += amount;
 | 
			
		||||
                _set.Update(donator);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return donator;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<Donator> GetDonatorsOrdered() => 
 | 
			
		||||
            _set.OrderByDescending(d => d.Amount).ToList();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -15,6 +15,11 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        private IQuoteRepository _quotes;
 | 
			
		||||
        public IQuoteRepository Quotes => _quotes ?? (_quotes = new QuoteRepository(_context));
 | 
			
		||||
 | 
			
		||||
        private IConfigRepository _configs;
 | 
			
		||||
        public IConfigRepository Configs => _configs ?? (_configs = new ConfigRepository(_context));
 | 
			
		||||
 | 
			
		||||
        private IDonatorsRepository _donators;
 | 
			
		||||
        public IDonatorsRepository Donators => _donators ?? (_donators = new DonatorsRepository(_context));
 | 
			
		||||
 | 
			
		||||
        public UnitOfWork(NadekoContext context)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,10 @@ namespace NadekoBot.Services.Impl
 | 
			
		||||
                MashapeKey = cm.MashapeKey;
 | 
			
		||||
                OsuApiKey = cm.OsuApiKey;
 | 
			
		||||
                SoundCloudClientId = cm.SoundCloudClientId;
 | 
			
		||||
                Db = new DB(string.IsNullOrWhiteSpace(cm.Db.Type) ? cm.Db.Type : "sqlite", cm.Db.ConnectionString);
 | 
			
		||||
                if (cm.Db == null)
 | 
			
		||||
                    Db = new DB("sqlite", "");
 | 
			
		||||
                else
 | 
			
		||||
                    Db = new DB(cm.Db.Type, cm.Db.ConnectionString);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                _log.Fatal("credentials.json is missing. Failed to start.");
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    "emitEntryPoint": true,
 | 
			
		||||
    "allowUnsafe": true,
 | 
			
		||||
    "compile": {
 | 
			
		||||
      "exclude": [ "_Models", "Classes", "_Modules" ]
 | 
			
		||||
      "exclude": [ "_Models", "_Classes", "_Modules" ]
 | 
			
		||||
    },
 | 
			
		||||
    "define": []
 | 
			
		||||
  },
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
    "System.Resources.ResourceWriter": "4.0.0-beta-22816",
 | 
			
		||||
    "Google.Apis.YouTube.v3": "1.15.0.582",
 | 
			
		||||
    "Google.Apis.Urlshortener.v1": "1.15.0.138",
 | 
			
		||||
    "Google.Apis.Customsearch.v1": "1.16.0.466",
 | 
			
		||||
    "System.Diagnostics.Contracts": "4.0.1",
 | 
			
		||||
    "NLog": "4.4.0-betaV15",
 | 
			
		||||
    "VideoLibrary": "1.3.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -23,10 +23,10 @@
 | 
			
		||||
          "lib/netstandard1.3/NCalc.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "Google.Apis/1.15.0": {
 | 
			
		||||
      "Google.Apis/1.16.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "Google.Apis.Core": "1.15.0",
 | 
			
		||||
          "Google.Apis.Core": "1.16.0",
 | 
			
		||||
          "System.Collections": "4.0.11",
 | 
			
		||||
          "System.Diagnostics.Debug": "4.0.11",
 | 
			
		||||
          "System.IO": "4.1.0",
 | 
			
		||||
@@ -81,7 +81,7 @@
 | 
			
		||||
          "lib/netstandard1.3/Google.Apis.Auth.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "Google.Apis.Core/1.15.0": {
 | 
			
		||||
      "Google.Apis.Core/1.16.0": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "Newtonsoft.Json": "9.0.1",
 | 
			
		||||
@@ -108,6 +108,18 @@
 | 
			
		||||
          "lib/netstandard1.3/Google.Apis.Core.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "Google.Apis.Customsearch.v1/1.16.0.466": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
          "Google.Apis": "1.16.0"
 | 
			
		||||
        },
 | 
			
		||||
        "compile": {
 | 
			
		||||
          "lib/netstandard1.3/Google.Apis.Customsearch.v1.dll": {}
 | 
			
		||||
        },
 | 
			
		||||
        "runtime": {
 | 
			
		||||
          "lib/netstandard1.3/Google.Apis.Customsearch.v1.dll": {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      "Google.Apis.Urlshortener.v1/1.15.0.138": {
 | 
			
		||||
        "type": "package",
 | 
			
		||||
        "dependencies": {
 | 
			
		||||
@@ -3203,12 +3215,12 @@
 | 
			
		||||
        "lib/netstandard1.3/NCalc.dll"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "Google.Apis/1.15.0": {
 | 
			
		||||
      "sha512": "B//vbZgUsR0jdJztCJ0ORmVcAzhoiisIsxwc1libVjoZzu+kxUKNJKUl5Wlkj7V28kauS56y3hJUj3FMsgaJZQ==",
 | 
			
		||||
    "Google.Apis/1.16.0": {
 | 
			
		||||
      "sha512": "/p657K7J7p9aRl6QxUjQfNK0AobxnLHwDWdSqAr/17lZeQR+XMuEbIy7No80+zDeS39kKrRVWFlu1vHiws7gRQ==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "Google.Apis/1.15.0",
 | 
			
		||||
      "path": "Google.Apis/1.16.0",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "Google.Apis.1.15.0.nupkg.sha512",
 | 
			
		||||
        "Google.Apis.1.16.0.nupkg.sha512",
 | 
			
		||||
        "Google.Apis.nuspec",
 | 
			
		||||
        "License.txt",
 | 
			
		||||
        "lib/net45/Google.Apis.PlatformServices.dll",
 | 
			
		||||
@@ -3286,12 +3298,12 @@
 | 
			
		||||
        "lib/wpa81/Google.Apis.Auth.xml"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "Google.Apis.Core/1.15.0": {
 | 
			
		||||
      "sha512": "izmsmat5RRL0bmJ2tr3SvlqEiGf40wDeOTHv0PJOVUvHoZBdAaVbbZFxtevOWOyo878mwpYGXfzMs5Zfoyfrfw==",
 | 
			
		||||
    "Google.Apis.Core/1.16.0": {
 | 
			
		||||
      "sha512": "uATqVAsPHlpOf+3VV51xFEIghAMSLJyh1hqoVpnPOlkXBx7fkOcs0qP3tKXtmsaeuyC/7BYM1Tt42lyIyhY2lQ==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "Google.Apis.Core/1.15.0",
 | 
			
		||||
      "path": "Google.Apis.Core/1.16.0",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "Google.Apis.Core.1.15.0.nupkg.sha512",
 | 
			
		||||
        "Google.Apis.Core.1.16.0.nupkg.sha512",
 | 
			
		||||
        "Google.Apis.Core.nuspec",
 | 
			
		||||
        "License.txt",
 | 
			
		||||
        "lib/net45/Google.Apis.Core.dll",
 | 
			
		||||
@@ -3305,6 +3317,24 @@
 | 
			
		||||
        "lib/portable-net45+sl50+netcore45+wpa81+wp8/Google.Apis.Core.xml"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "Google.Apis.Customsearch.v1/1.16.0.466": {
 | 
			
		||||
      "sha512": "uZ5VP/xKgTZCMJXgEfwHYEIR/7FsbtvL+bncm08a07RhWLFZTdRpCAkNL4b5wADHkblpkBe1VWKv43W77I4tJw==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
      "path": "Google.Apis.Customsearch.v1/1.16.0.466",
 | 
			
		||||
      "files": [
 | 
			
		||||
        "Google.Apis.Customsearch.v1.1.16.0.466.nupkg.sha512",
 | 
			
		||||
        "Google.Apis.Customsearch.v1.nuspec",
 | 
			
		||||
        "lib/netstandard1.3/Google.Apis.Customsearch.v1.dll",
 | 
			
		||||
        "lib/netstandard1.3/Google.Apis.Customsearch.v1.pdb",
 | 
			
		||||
        "lib/netstandard1.3/Google.Apis.Customsearch.v1.xml",
 | 
			
		||||
        "lib/portable-net40+sl50+netcore45+wpa81+wp8/Google.Apis.Customsearch.v1.dll",
 | 
			
		||||
        "lib/portable-net40+sl50+netcore45+wpa81+wp8/Google.Apis.Customsearch.v1.pdb",
 | 
			
		||||
        "lib/portable-net40+sl50+netcore45+wpa81+wp8/Google.Apis.Customsearch.v1.xml",
 | 
			
		||||
        "lib/portable-net45+netcore45+wpa81+wp8/Google.Apis.Customsearch.v1.dll",
 | 
			
		||||
        "lib/portable-net45+netcore45+wpa81+wp8/Google.Apis.Customsearch.v1.pdb",
 | 
			
		||||
        "lib/portable-net45+netcore45+wpa81+wp8/Google.Apis.Customsearch.v1.xml"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "Google.Apis.Urlshortener.v1/1.15.0.138": {
 | 
			
		||||
      "sha512": "67USnpqrk8tWO3LAgaK9qDQT6h8A7i7eUIOKm+OISThZoQuHiLCn6dbg46FVb597LUh57AxClSSbhnweYcYC3Q==",
 | 
			
		||||
      "type": "package",
 | 
			
		||||
@@ -9004,6 +9034,7 @@
 | 
			
		||||
    "": [
 | 
			
		||||
      "CoreCLR-NCalc >= 2.1.0",
 | 
			
		||||
      "Discord.Net.Commands >= 1.0.0-dev",
 | 
			
		||||
      "Google.Apis.Customsearch.v1 >= 1.16.0.466",
 | 
			
		||||
      "Google.Apis.Urlshortener.v1 >= 1.15.0.138",
 | 
			
		||||
      "Google.Apis.YouTube.v3 >= 1.15.0.582",
 | 
			
		||||
      "Microsoft.EntityFrameworkCore >= 1.0.0",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user