diff --git a/.gitignore b/.gitignore
index 0fa1ef5e..5169035d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
#Manually added files
+patreon_rewards.json
command_errors*.txt
src/NadekoBot/Command Errors*.txt
diff --git a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs
index f325c402..1e7f5d22 100644
--- a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs
+++ b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs
@@ -1,94 +1,93 @@
-//using Discord;
-//using Discord.Commands;
-//using NadekoBot.Attributes;
-//using NadekoBot.Extensions;
-//using NadekoBot.Services.Utility;
-//using System;
-//using System.Linq;
-//using System.Threading.Tasks;
-////todo Rewrite
-//namespace NadekoBot.Modules.Utility
-//{
-// public partial class Utility
-// {
-// [Group]
-// public class UnitConverterCommands : NadekoSubmodule
-// {
-// private readonly ConverterService _service;
+using Discord;
+using Discord.Commands;
+using NadekoBot.Attributes;
+using NadekoBot.Extensions;
+using NadekoBot.Services.Utility;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+namespace NadekoBot.Modules.Utility
+{
+ public partial class Utility
+ {
+ [Group]
+ public class UnitConverterCommands : NadekoSubmodule
+ {
+ private readonly ConverterService _service;
-// public UnitConverterCommands(ConverterService service)
-// {
-// _service = service;
-// }
+ public UnitConverterCommands(ConverterService service)
+ {
+ _service = service;
+ }
-// [NadekoCommand, Usage, Description, Aliases]
-// public async Task ConvertList()
-// {
-// var res = _service.Units.GroupBy(x => x.UnitType)
-// .Aggregate(new EmbedBuilder().WithTitle(GetText("convertlist"))
-// .WithColor(NadekoBot.OkColor),
-// (embed, g) => embed.AddField(efb =>
-// efb.WithName(g.Key.ToTitleCase())
-// .WithValue(String.Join(", ", g.Select(x => x.Triggers.FirstOrDefault())
-// .OrderBy(x => x)))));
-// await Context.Channel.EmbedAsync(res);
-// }
-// [NadekoCommand, Usage, Description, Aliases]
-// public async Task Convert(string origin, string target, decimal value)
-// {
-// var originUnit = _service.Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(origin.ToLowerInvariant()));
-// var targetUnit = _service.Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant()));
-// if (originUnit == null || targetUnit == null)
-// {
-// await ReplyErrorLocalized("convert_not_found", Format.Bold(origin), Format.Bold(target)).ConfigureAwait(false);
-// return;
-// }
-// if (originUnit.UnitType != targetUnit.UnitType)
-// {
-// await ReplyErrorLocalized("convert_type_error", Format.Bold(originUnit.Triggers.First()), Format.Bold(targetUnit.Triggers.First())).ConfigureAwait(false);
-// return;
-// }
-// decimal res;
-// if (originUnit.Triggers == targetUnit.Triggers) res = value;
-// else if (originUnit.UnitType == "temperature")
-// {
-// //don't really care too much about efficiency, so just convert to Kelvin, then to target
-// switch (originUnit.Triggers.First().ToUpperInvariant())
-// {
-// case "C":
-// res = value + 273.15m; //celcius!
-// break;
-// case "F":
-// res = (value + 459.67m) * (5m / 9m);
-// break;
-// default:
-// res = value;
-// break;
-// }
-// //from Kelvin to target
-// switch (targetUnit.Triggers.First().ToUpperInvariant())
-// {
-// case "C":
-// res = res - 273.15m; //celcius!
-// break;
-// case "F":
-// res = res * (9m / 5m) - 459.67m;
-// break;
-// }
-// }
-// else
-// {
-// if (originUnit.UnitType == "currency")
-// {
-// res = (value * targetUnit.Modifier) / originUnit.Modifier;
-// }
-// else
-// res = (value * originUnit.Modifier) / targetUnit.Modifier;
-// }
-// res = Math.Round(res, 4);
+ [NadekoCommand, Usage, Description, Aliases]
+ public async Task ConvertList()
+ {
+ var res = _service.Units.GroupBy(x => x.UnitType)
+ .Aggregate(new EmbedBuilder().WithTitle(GetText("convertlist"))
+ .WithColor(NadekoBot.OkColor),
+ (embed, g) => embed.AddField(efb =>
+ efb.WithName(g.Key.ToTitleCase())
+ .WithValue(String.Join(", ", g.Select(x => x.Triggers.FirstOrDefault())
+ .OrderBy(x => x)))));
+ await Context.Channel.EmbedAsync(res);
+ }
+ [NadekoCommand, Usage, Description, Aliases]
+ public async Task Convert(string origin, string target, decimal value)
+ {
+ var originUnit = _service.Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(origin.ToLowerInvariant()));
+ var targetUnit = _service.Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant()));
+ if (originUnit == null || targetUnit == null)
+ {
+ await ReplyErrorLocalized("convert_not_found", Format.Bold(origin), Format.Bold(target)).ConfigureAwait(false);
+ return;
+ }
+ if (originUnit.UnitType != targetUnit.UnitType)
+ {
+ await ReplyErrorLocalized("convert_type_error", Format.Bold(originUnit.Triggers.First()), Format.Bold(targetUnit.Triggers.First())).ConfigureAwait(false);
+ return;
+ }
+ decimal res;
+ if (originUnit.Triggers == targetUnit.Triggers) res = value;
+ else if (originUnit.UnitType == "temperature")
+ {
+ //don't really care too much about efficiency, so just convert to Kelvin, then to target
+ switch (originUnit.Triggers.First().ToUpperInvariant())
+ {
+ case "C":
+ res = value + 273.15m; //celcius!
+ break;
+ case "F":
+ res = (value + 459.67m) * (5m / 9m);
+ break;
+ default:
+ res = value;
+ break;
+ }
+ //from Kelvin to target
+ switch (targetUnit.Triggers.First().ToUpperInvariant())
+ {
+ case "C":
+ res = res - 273.15m; //celcius!
+ break;
+ case "F":
+ res = res * (9m / 5m) - 459.67m;
+ break;
+ }
+ }
+ else
+ {
+ if (originUnit.UnitType == "currency")
+ {
+ res = (value * targetUnit.Modifier) / originUnit.Modifier;
+ }
+ else
+ res = (value * originUnit.Modifier) / targetUnit.Modifier;
+ }
+ res = Math.Round(res, 4);
-// await Context.Channel.SendConfirmAsync(GetText("convert", value, (originUnit.Triggers.First()).SnPl(value.IsInteger() ? (int)value : 2), res, (targetUnit.Triggers.First() + "s").SnPl(res.IsInteger() ? (int)res : 2)));
-// }
-// }
-// }
-//}
\ No newline at end of file
+ await Context.Channel.SendConfirmAsync(GetText("convert", value, (originUnit.Triggers.First()).SnPl(value.IsInteger() ? (int)value : 2), res, (targetUnit.Triggers.First() + "s").SnPl(res.IsInteger() ? (int)res : 2)));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs
index 9025a0a3..2ee3d1b3 100644
--- a/src/NadekoBot/NadekoBot.cs
+++ b/src/NadekoBot/NadekoBot.cs
@@ -290,7 +290,10 @@ namespace NadekoBot
Task SetClientReady()
{
- clientReady.TrySetResult(true);
+ var _ = Task.Run(() =>
+ {
+ clientReady.TrySetResult(true);
+ });
return Task.CompletedTask;
}
diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj
index 0cc722bc..18ad4911 100644
--- a/src/NadekoBot/NadekoBot.csproj
+++ b/src/NadekoBot/NadekoBot.csproj
@@ -90,5 +90,6 @@
+
diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs
index 8cce6936..64507106 100644
--- a/src/NadekoBot/Services/Impl/StatsService.cs
+++ b/src/NadekoBot/Services/Impl/StatsService.cs
@@ -126,7 +126,6 @@ namespace NadekoBot.Services.Impl
return Task.CompletedTask;
};
- //todo carbonitex update
if (sc != null)
{
_carbonitexTimer = new Timer(async (state) =>
diff --git a/src/NadekoBot/Services/Utility/ConverterService.cs b/src/NadekoBot/Services/Utility/ConverterService.cs
index b7388335..1edb470a 100644
--- a/src/NadekoBot/Services/Utility/ConverterService.cs
+++ b/src/NadekoBot/Services/Utility/ConverterService.cs
@@ -1,4 +1,6 @@
-using NadekoBot.Services.Database.Models;
+using Discord.WebSocket;
+using NadekoBot.Services;
+using NadekoBot.Services.Database.Models;
using Newtonsoft.Json;
using NLog;
using System;
@@ -11,27 +13,29 @@ using System.Threading.Tasks;
namespace NadekoBot.Services.Utility
{
- //todo periodically load from the database, update only on shard 0
public class ConverterService
{
- public List Units { get; set; } = new List();
+ public List Units { get; } = new List();
private readonly Logger _log;
- private Timer _timer;
+ private readonly Timer _currencyUpdater;
+ private readonly Timer _currencyLoader;
private readonly TimeSpan _updateInterval = new TimeSpan(12, 0, 0);
private readonly DbService _db;
- public ConverterService(DbService db)
+ public ConverterService(DiscordSocketClient client, DbService db)
{
_log = LogManager.GetCurrentClassLogger();
_db = db;
try
{
- var data = JsonConvert.DeserializeObject>(File.ReadAllText("data/units.json")).Select(u => new ConvertUnit()
- {
- Modifier = u.Modifier,
- UnitType = u.UnitType,
- InternalTrigger = string.Join("|", u.Triggers)
- }).ToArray();
+ var data = JsonConvert.DeserializeObject>(
+ File.ReadAllText("data/units.json"))
+ .Select(u => new ConvertUnit()
+ {
+ Modifier = u.Modifier,
+ UnitType = u.UnitType,
+ InternalTrigger = string.Join("|", u.Triggers)
+ }).ToArray();
using (var uow = _db.UnitOfWork)
{
@@ -48,10 +52,10 @@ namespace NadekoBot.Services.Utility
_log.Warn("Could not load units: " + ex.Message);
}
- _timer = new Timer(async (obj) => await UpdateCurrency(), null, _updateInterval, _updateInterval);
+ _currencyUpdater = new Timer(async (shouldLoad) => await UpdateCurrency((bool)shouldLoad), client.ShardId == 0, _updateInterval, _updateInterval);
}
- public static async Task UpdateCurrencyRates()
+ private async Task GetCurrencyRates()
{
using (var http = new HttpClient())
{
@@ -60,38 +64,48 @@ namespace NadekoBot.Services.Utility
}
}
- public async Task UpdateCurrency()
+ private async Task UpdateCurrency(bool shouldLoad)
{
try
{
- var currencyRates = await UpdateCurrencyRates();
var unitTypeString = "currency";
- var range = currencyRates.ConversionRates.Select(u => new ConvertUnit()
+ if (shouldLoad)
{
- InternalTrigger = u.Key,
- Modifier = u.Value,
- UnitType = unitTypeString
- }).ToArray();
- var baseType = new ConvertUnit()
- {
- Triggers = new[] { currencyRates.Base },
- Modifier = decimal.One,
- UnitType = unitTypeString
- };
- var toRemove = Units.Where(u => u.UnitType == unitTypeString);
+ var currencyRates = await GetCurrencyRates();
+ var baseType = new ConvertUnit()
+ {
+ Triggers = new[] { currencyRates.Base },
+ Modifier = decimal.One,
+ UnitType = unitTypeString
+ };
+ var range = currencyRates.ConversionRates.Select(u => new ConvertUnit()
+ {
+ InternalTrigger = u.Key,
+ Modifier = u.Value,
+ UnitType = unitTypeString
+ }).ToArray();
+ var toRemove = Units.Where(u => u.UnitType == unitTypeString);
- using (var uow = _db.UnitOfWork)
- {
- uow.ConverterUnits.RemoveRange(toRemove.ToArray());
- uow.ConverterUnits.Add(baseType);
- uow.ConverterUnits.AddRange(range);
+ using (var uow = _db.UnitOfWork)
+ {
+ uow.ConverterUnits.RemoveRange(toRemove.ToArray());
+ uow.ConverterUnits.Add(baseType);
+ uow.ConverterUnits.AddRange(range);
- await uow.CompleteAsync().ConfigureAwait(false);
+ await uow.CompleteAsync().ConfigureAwait(false);
+ }
+ Units.RemoveAll(u => u.UnitType == unitTypeString);
+ Units.Add(baseType);
+ Units.AddRange(range);
+ }
+ else
+ {
+ using (var uow = _db.UnitOfWork)
+ {
+ Units.RemoveAll(u => u.UnitType == unitTypeString);
+ Units.AddRange(uow.ConverterUnits.GetAll().ToArray());
+ }
}
- Units.RemoveAll(u => u.UnitType == unitTypeString);
- Units.Add(baseType);
- Units.AddRange(range);
- _log.Info("Updated Currency");
}
catch
{
diff --git a/src/NadekoBot/Services/Utility/PatreonRewardsService.cs b/src/NadekoBot/Services/Utility/PatreonRewardsService.cs
index 0f7105b7..f3811c6d 100644
--- a/src/NadekoBot/Services/Utility/PatreonRewardsService.cs
+++ b/src/NadekoBot/Services/Utility/PatreonRewardsService.cs
@@ -1,12 +1,15 @@
-using NadekoBot.Services.Database.Models;
+using Discord.WebSocket;
+using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Utility.Patreon;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.IO;
using System.Linq;
using System.Net.Http;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -24,12 +27,13 @@ namespace NadekoBot.Services.Utility
private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
private readonly Logger _log;
- public readonly TimeSpan Interval = TimeSpan.FromMinutes(15);
- private IBotCredentials _creds;
+ public readonly TimeSpan Interval = TimeSpan.FromMinutes(3);
+ private readonly IBotCredentials _creds;
private readonly DbService _db;
private readonly CurrencyService _currency;
- public PatreonRewardsService(IBotCredentials creds, DbService db, CurrencyService currency)
+ public PatreonRewardsService(IBotCredentials creds, DbService db, CurrencyService currency,
+ DiscordSocketClient client)
{
_creds = creds;
_db = db;
@@ -37,58 +41,63 @@ namespace NadekoBot.Services.Utility
if (string.IsNullOrWhiteSpace(creds.PatreonAccessToken))
return;
_log = LogManager.GetCurrentClassLogger();
- Updater = new Timer(async (_) => await LoadPledges(), null, TimeSpan.Zero, Interval);
+ Updater = new Timer(async (load) => await RefreshPledges((bool)load), client.ShardId == 0, TimeSpan.Zero, Interval);
}
- public async Task LoadPledges()
+ public async Task RefreshPledges(bool shouldLoad)
{
- LastUpdate = DateTime.UtcNow;
- await getPledgesLocker.WaitAsync(1000).ConfigureAwait(false);
- try
+ if (shouldLoad)
{
- var rewards = new List();
- var users = new List();
- using (var http = new HttpClient())
+ LastUpdate = DateTime.UtcNow;
+ await getPledgesLocker.WaitAsync().ConfigureAwait(false);
+ try
{
- http.DefaultRequestHeaders.Clear();
- http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken);
- var data = new PatreonData()
+ var rewards = new List();
+ var users = new List();
+ using (var http = new HttpClient())
{
- Links = new PatreonDataLinks()
+ http.DefaultRequestHeaders.Clear();
+ http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken);
+ var data = new PatreonData()
{
- next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges"
- }
- };
- do
+ Links = new PatreonDataLinks()
+ {
+ next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges"
+ }
+ };
+ do
+ {
+ var res = await http.GetStringAsync(data.Links.next)
+ .ConfigureAwait(false);
+ data = JsonConvert.DeserializeObject(res);
+ var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge");
+ rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject(x.ToString()))
+ .Where(x => x.attributes.declined_since == null));
+ users.AddRange(data.Included
+ .Where(x => x["type"].ToString() == "user")
+ .Select(x => JsonConvert.DeserializeObject(x.ToString())));
+ } while (!string.IsNullOrWhiteSpace(data.Links.next));
+ }
+ Pledges = rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward()
{
- var res = await http.GetStringAsync(data.Links.next)
- .ConfigureAwait(false);
- data = JsonConvert.DeserializeObject(res);
- var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge");
- rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject(x.ToString()))
- .Where(x => x.attributes.declined_since == null));
- users.AddRange(data.Included
- .Where(x => x["type"].ToString() == "user")
- .Select(x => JsonConvert.DeserializeObject(x.ToString())));
- } while (!string.IsNullOrWhiteSpace(data.Links.next));
+ User = y,
+ Reward = x,
+ }).ToImmutableArray();
+ File.WriteAllText("./patreon_rewards.json", JsonConvert.SerializeObject(Pledges));
}
- Pledges = rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward()
+ catch (Exception ex)
{
- User = y,
- Reward = x,
- }).ToImmutableArray();
- }
- catch (Exception ex)
- {
- _log.Warn(ex);
- }
- finally
- {
- var _ = Task.Run(async () =>
+ _log.Warn(ex);
+ }
+ finally
{
- await Task.Delay(TimeSpan.FromMinutes(5)).ConfigureAwait(false);
getPledgesLocker.Release();
- });
+ }
+ }
+ else
+ {
+ Pledges = JsonConvert.DeserializeObject(File.ReadAllText("./patreon_rewards.json"))
+ .ToImmutableArray();
}
}