a LOT More work
This commit is contained in:
parent
cb7fb76b91
commit
acd1480cb1
1
.gitignore
vendored
1
.gitignore
vendored
@ -32,3 +32,4 @@ NadekoBot.sln.iml
|
|||||||
.idea/vcs.xml
|
.idea/vcs.xml
|
||||||
.idea/modules.xml
|
.idea/modules.xml
|
||||||
NadekoBot/bin/Debug/data/config_xnaas.json
|
NadekoBot/bin/Debug/data/config_xnaas.json
|
||||||
|
src/NadekoBot/project.lock.json
|
@ -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 NadekoBot.Attributes;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
//todo fix delmsgoncmd
|
//todo fix delmsgoncmd
|
||||||
//todo DB
|
//todo DB
|
||||||
@ -36,22 +38,25 @@ namespace NadekoBot.Modules.Administration
|
|||||||
// Environment.Exit(0);
|
// Environment.Exit(0);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
////todo DB
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||||
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
[RequireContext(ContextType.Guild)]
|
||||||
//[RequireContext(ContextType.Guild)]
|
[RequirePermission(GuildPermission.Administrator)]
|
||||||
//[RequirePermission(GuildPermission.ManageGuild)]
|
public async Task Delmsgoncmd(IMessage imsg)
|
||||||
//public async Task Delmsgoncmd(IMessage imsg)
|
{
|
||||||
//{
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
// var channel = (ITextChannel)imsg.Channel;
|
Config conf;
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
// var conf = SpecificConfigurations.Default.Of(channel.Guild.Id);
|
{
|
||||||
// conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand;
|
conf = uow.Configs.For(channel.Guild.Id);
|
||||||
// await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
|
conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand;
|
||||||
// if (conf.AutoDeleteMessagesOnCommand)
|
uow.Configs.Update(conf);
|
||||||
// await channel.SendMessageAsync("❗`Now automatically deleting successfull command invokations.`");
|
await uow.CompleteAsync();
|
||||||
// else
|
}
|
||||||
// await channel.SendMessageAsync("❗`Stopped automatic deletion of successfull command invokations.`");
|
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]
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@ -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
|
////todo owner only
|
||||||
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||||
//[RequireContext(ContextType.Guild)]
|
//[RequireContext(ContextType.Guild)]
|
||||||
@ -660,18 +641,36 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await channel.SendMessageAsync(send).ConfigureAwait(false);
|
await channel.SendMessageAsync(send).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo DB
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||||
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
[RequireContext(ContextType.Guild)]
|
||||||
//[RequireContext(ContextType.Guild)]
|
public async Task Donators(IMessage imsg)
|
||||||
//public async Task Donators(IMessage imsg)
|
{
|
||||||
//{
|
var channel = (ITextChannel)imsg.Channel;
|
||||||
// var channel = (ITextChannel)imsg.Channel;
|
IEnumerable<Donator> donatorsOrdered;
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
donatorsOrdered = uow.Donators.GetDonatorsOrdered();
|
||||||
|
}
|
||||||
|
|
||||||
// var rows = DbHandler.Instance.GetAllRows<Donator>();
|
string str = $"**Thanks to the people listed below for making this project happen!**\n";
|
||||||
// var donatorsOrdered = rows.OrderByDescending(d => d.Amount);
|
await channel.SendMessageAsync(str + string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false);
|
||||||
// string str = $"**Thanks to the people listed below for making this project happen!**\n";
|
}
|
||||||
|
|
||||||
// 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.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Utility.Commands
|
namespace NadekoBot.Modules.Utility
|
||||||
{
|
{
|
||||||
public partial class Utility
|
public partial class Utility
|
||||||
{
|
{
|
||||||
@ -103,7 +103,7 @@ namespace NadekoBot.Modules.Utility.Commands
|
|||||||
{
|
{
|
||||||
var quotes = uow.Quotes.GetAllQuotesByKeyword(keyword);
|
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();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ namespace NadekoBot.Services.Database
|
|||||||
public interface IUnitOfWork : IDisposable
|
public interface IUnitOfWork : IDisposable
|
||||||
{
|
{
|
||||||
IQuoteRepository Quotes { get; }
|
IQuoteRepository Quotes { get; }
|
||||||
|
IConfigRepository Configs { get; }
|
||||||
|
IDonatorsRepository Donators { get; }
|
||||||
int Complete();
|
int Complete();
|
||||||
Task<int> CompleteAsync();
|
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)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
#region QUOTES
|
#region QUOTES
|
||||||
//// guildid and keyword are unique pair
|
|
||||||
var quoteEntity = modelBuilder.Entity<Quote>();
|
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();
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#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
|
#endregion
|
||||||
}
|
}
|
||||||
protected abstract override void OnConfiguring(DbContextOptionsBuilder optionsBuilder);
|
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(int id);
|
||||||
void Remove(T obj);
|
void Remove(T obj);
|
||||||
void RemoveRange(params int[] ids);
|
void RemoveRange(params T[] objs);
|
||||||
|
|
||||||
void Update(T obj);
|
void Update(T obj);
|
||||||
void UpdateRange(params T[] objs);
|
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;
|
private IQuoteRepository _quotes;
|
||||||
public IQuoteRepository Quotes => _quotes ?? (_quotes = new QuoteRepository(_context));
|
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)
|
public UnitOfWork(NadekoContext context)
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,10 @@ namespace NadekoBot.Services.Impl
|
|||||||
MashapeKey = cm.MashapeKey;
|
MashapeKey = cm.MashapeKey;
|
||||||
OsuApiKey = cm.OsuApiKey;
|
OsuApiKey = cm.OsuApiKey;
|
||||||
SoundCloudClientId = cm.SoundCloudClientId;
|
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
|
else
|
||||||
_log.Fatal("credentials.json is missing. Failed to start.");
|
_log.Fatal("credentials.json is missing. Failed to start.");
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"emitEntryPoint": true,
|
"emitEntryPoint": true,
|
||||||
"allowUnsafe": true,
|
"allowUnsafe": true,
|
||||||
"compile": {
|
"compile": {
|
||||||
"exclude": [ "_Models", "Classes", "_Modules" ]
|
"exclude": [ "_Models", "_Classes", "_Modules" ]
|
||||||
},
|
},
|
||||||
"define": []
|
"define": []
|
||||||
},
|
},
|
||||||
@ -24,6 +24,7 @@
|
|||||||
"System.Resources.ResourceWriter": "4.0.0-beta-22816",
|
"System.Resources.ResourceWriter": "4.0.0-beta-22816",
|
||||||
"Google.Apis.YouTube.v3": "1.15.0.582",
|
"Google.Apis.YouTube.v3": "1.15.0.582",
|
||||||
"Google.Apis.Urlshortener.v1": "1.15.0.138",
|
"Google.Apis.Urlshortener.v1": "1.15.0.138",
|
||||||
|
"Google.Apis.Customsearch.v1": "1.16.0.466",
|
||||||
"System.Diagnostics.Contracts": "4.0.1",
|
"System.Diagnostics.Contracts": "4.0.1",
|
||||||
"NLog": "4.4.0-betaV15",
|
"NLog": "4.4.0-betaV15",
|
||||||
"VideoLibrary": "1.3.4",
|
"VideoLibrary": "1.3.4",
|
||||||
|
@ -23,10 +23,10 @@
|
|||||||
"lib/netstandard1.3/NCalc.dll": {}
|
"lib/netstandard1.3/NCalc.dll": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Google.Apis/1.15.0": {
|
"Google.Apis/1.16.0": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Google.Apis.Core": "1.15.0",
|
"Google.Apis.Core": "1.16.0",
|
||||||
"System.Collections": "4.0.11",
|
"System.Collections": "4.0.11",
|
||||||
"System.Diagnostics.Debug": "4.0.11",
|
"System.Diagnostics.Debug": "4.0.11",
|
||||||
"System.IO": "4.1.0",
|
"System.IO": "4.1.0",
|
||||||
@ -81,7 +81,7 @@
|
|||||||
"lib/netstandard1.3/Google.Apis.Auth.dll": {}
|
"lib/netstandard1.3/Google.Apis.Auth.dll": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Google.Apis.Core/1.15.0": {
|
"Google.Apis.Core/1.16.0": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Newtonsoft.Json": "9.0.1",
|
"Newtonsoft.Json": "9.0.1",
|
||||||
@ -108,6 +108,18 @@
|
|||||||
"lib/netstandard1.3/Google.Apis.Core.dll": {}
|
"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": {
|
"Google.Apis.Urlshortener.v1/1.15.0.138": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3203,12 +3215,12 @@
|
|||||||
"lib/netstandard1.3/NCalc.dll"
|
"lib/netstandard1.3/NCalc.dll"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Google.Apis/1.15.0": {
|
"Google.Apis/1.16.0": {
|
||||||
"sha512": "B//vbZgUsR0jdJztCJ0ORmVcAzhoiisIsxwc1libVjoZzu+kxUKNJKUl5Wlkj7V28kauS56y3hJUj3FMsgaJZQ==",
|
"sha512": "/p657K7J7p9aRl6QxUjQfNK0AobxnLHwDWdSqAr/17lZeQR+XMuEbIy7No80+zDeS39kKrRVWFlu1vHiws7gRQ==",
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"path": "Google.Apis/1.15.0",
|
"path": "Google.Apis/1.16.0",
|
||||||
"files": [
|
"files": [
|
||||||
"Google.Apis.1.15.0.nupkg.sha512",
|
"Google.Apis.1.16.0.nupkg.sha512",
|
||||||
"Google.Apis.nuspec",
|
"Google.Apis.nuspec",
|
||||||
"License.txt",
|
"License.txt",
|
||||||
"lib/net45/Google.Apis.PlatformServices.dll",
|
"lib/net45/Google.Apis.PlatformServices.dll",
|
||||||
@ -3286,12 +3298,12 @@
|
|||||||
"lib/wpa81/Google.Apis.Auth.xml"
|
"lib/wpa81/Google.Apis.Auth.xml"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Google.Apis.Core/1.15.0": {
|
"Google.Apis.Core/1.16.0": {
|
||||||
"sha512": "izmsmat5RRL0bmJ2tr3SvlqEiGf40wDeOTHv0PJOVUvHoZBdAaVbbZFxtevOWOyo878mwpYGXfzMs5Zfoyfrfw==",
|
"sha512": "uATqVAsPHlpOf+3VV51xFEIghAMSLJyh1hqoVpnPOlkXBx7fkOcs0qP3tKXtmsaeuyC/7BYM1Tt42lyIyhY2lQ==",
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"path": "Google.Apis.Core/1.15.0",
|
"path": "Google.Apis.Core/1.16.0",
|
||||||
"files": [
|
"files": [
|
||||||
"Google.Apis.Core.1.15.0.nupkg.sha512",
|
"Google.Apis.Core.1.16.0.nupkg.sha512",
|
||||||
"Google.Apis.Core.nuspec",
|
"Google.Apis.Core.nuspec",
|
||||||
"License.txt",
|
"License.txt",
|
||||||
"lib/net45/Google.Apis.Core.dll",
|
"lib/net45/Google.Apis.Core.dll",
|
||||||
@ -3305,6 +3317,24 @@
|
|||||||
"lib/portable-net45+sl50+netcore45+wpa81+wp8/Google.Apis.Core.xml"
|
"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": {
|
"Google.Apis.Urlshortener.v1/1.15.0.138": {
|
||||||
"sha512": "67USnpqrk8tWO3LAgaK9qDQT6h8A7i7eUIOKm+OISThZoQuHiLCn6dbg46FVb597LUh57AxClSSbhnweYcYC3Q==",
|
"sha512": "67USnpqrk8tWO3LAgaK9qDQT6h8A7i7eUIOKm+OISThZoQuHiLCn6dbg46FVb597LUh57AxClSSbhnweYcYC3Q==",
|
||||||
"type": "package",
|
"type": "package",
|
||||||
@ -9004,6 +9034,7 @@
|
|||||||
"": [
|
"": [
|
||||||
"CoreCLR-NCalc >= 2.1.0",
|
"CoreCLR-NCalc >= 2.1.0",
|
||||||
"Discord.Net.Commands >= 1.0.0-dev",
|
"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.Urlshortener.v1 >= 1.15.0.138",
|
||||||
"Google.Apis.YouTube.v3 >= 1.15.0.582",
|
"Google.Apis.YouTube.v3 >= 1.15.0.582",
|
||||||
"Microsoft.EntityFrameworkCore >= 1.0.0",
|
"Microsoft.EntityFrameworkCore >= 1.0.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user