mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 17:58:26 -04:00
Restructured the project structure back to the way it was, there's no reasonable way to split the modules
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Modules.Utility.Common;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NadekoBot.Modules.Utility.Services;
|
||||
|
||||
public class ConverterService : INService, IReadyExecutor
|
||||
{
|
||||
private static readonly TypedKey<List<ConvertUnit>> _convertKey =
|
||||
new("convert:units");
|
||||
|
||||
private readonly TimeSpan _updateInterval = new(12, 0, 0);
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly IBotCache _cache;
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
|
||||
public ConverterService(
|
||||
DiscordSocketClient client,
|
||||
IBotCache cache,
|
||||
IHttpClientFactory factory)
|
||||
{
|
||||
_client = client;
|
||||
_cache = cache;
|
||||
_httpFactory = factory;
|
||||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
if (_client.ShardId != 0)
|
||||
return;
|
||||
|
||||
using var timer = new PeriodicTimer(_updateInterval);
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdateCurrency();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
} while (await timer.WaitForNextTickAsync());
|
||||
}
|
||||
|
||||
private async Task<Rates> GetCurrencyRates()
|
||||
{
|
||||
using var http = _httpFactory.CreateClient();
|
||||
var res = await http.GetStringAsync("https://convertapi.nadeko.bot/latest");
|
||||
return JsonSerializer.Deserialize<Rates>(res);
|
||||
}
|
||||
|
||||
private async Task UpdateCurrency()
|
||||
{
|
||||
var unitTypeString = "currency";
|
||||
var currencyRates = await GetCurrencyRates();
|
||||
var baseType = new ConvertUnit
|
||||
{
|
||||
Triggers = new[] { currencyRates.Base },
|
||||
Modifier = decimal.One,
|
||||
UnitType = unitTypeString
|
||||
};
|
||||
var units = currencyRates.ConversionRates.Select(u => new ConvertUnit
|
||||
{
|
||||
Triggers = new[] { u.Key },
|
||||
Modifier = u.Value,
|
||||
UnitType = unitTypeString
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var stream = File.OpenRead("data/units.json");
|
||||
var defaultUnits = await JsonSerializer.DeserializeAsync<ConvertUnit[]>(stream);
|
||||
if(defaultUnits is not null)
|
||||
units.AddRange(defaultUnits);
|
||||
|
||||
units.Add(baseType);
|
||||
|
||||
await _cache.AddAsync(_convertKey, units);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<ConvertUnit>> GetUnitsAsync()
|
||||
=> (await _cache.GetAsync(_convertKey)).TryGetValue(out var list)
|
||||
? list
|
||||
: Array.Empty<ConvertUnit>();
|
||||
}
|
||||
|
||||
public class Rates
|
||||
{
|
||||
[JsonPropertyName("base")]
|
||||
public string Base { get; set; }
|
||||
|
||||
[JsonPropertyName("date")]
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
[JsonPropertyName("rates")]
|
||||
public Dictionary<string, decimal> ConversionRates { get; set; }
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Modules.Utility.Services;
|
||||
|
||||
namespace NadekoBot.Modules.Utility;
|
||||
|
||||
public partial class Utility
|
||||
{
|
||||
[Group]
|
||||
public partial class UnitConverterCommands : NadekoModule<ConverterService>
|
||||
{
|
||||
[Cmd]
|
||||
public async Task ConvertList()
|
||||
{
|
||||
var units = await _service.GetUnitsAsync();
|
||||
|
||||
var embed = _eb.Create().WithTitle(GetText(strs.convertlist)).WithOkColor();
|
||||
|
||||
|
||||
foreach (var g in units.GroupBy(x => x.UnitType))
|
||||
{
|
||||
embed.AddField(g.Key.ToTitleCase(),
|
||||
string.Join(", ", g.Select(x => x.Triggers.FirstOrDefault()).OrderBy(x => x)));
|
||||
}
|
||||
|
||||
await ctx.Channel.EmbedAsync(embed);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[Priority(0)]
|
||||
public async Task Convert(string origin, string target, decimal value)
|
||||
{
|
||||
var units = await _service.GetUnitsAsync();
|
||||
var originUnit = units.FirstOrDefault(x
|
||||
=> x.Triggers.Select(y => y.ToUpperInvariant()).Contains(origin.ToUpperInvariant()));
|
||||
var targetUnit = units.FirstOrDefault(x
|
||||
=> x.Triggers.Select(y => y.ToUpperInvariant()).Contains(target.ToUpperInvariant()));
|
||||
if (originUnit is null || targetUnit is null)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.convert_not_found(Format.Bold(origin), Format.Bold(target)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (originUnit.UnitType != targetUnit.UnitType)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.convert_type_error(Format.Bold(originUnit.Triggers.First()),
|
||||
Format.Bold(targetUnit.Triggers.First())));
|
||||
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 -= 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 SendConfirmAsync(GetText(strs.convert(value,
|
||||
originUnit.Triggers.Last(),
|
||||
res,
|
||||
targetUnit.Triggers.Last())));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user