Fixed some crashes in response strings source generator, reorganized more submodules into their folders

This commit is contained in:
Kwoth
2022-01-02 03:49:54 +01:00
parent 9c590668df
commit 4b6af0e4ef
191 changed files with 120 additions and 80 deletions

View File

@@ -0,0 +1,62 @@
#nullable disable
using NadekoBot.Modules.Searches.Services;
namespace NadekoBot.Modules.Searches;
public partial class Searches
{
public partial class CryptoCommands : NadekoSubmodule<CryptoService>
{
[Cmd]
public async partial Task Crypto(string name)
{
name = name?.ToUpperInvariant();
if (string.IsNullOrWhiteSpace(name))
return;
var (crypto, nearest) = await _service.GetCryptoData(name);
if (nearest is not null)
{
var embed = _eb.Create()
.WithTitle(GetText(strs.crypto_not_found))
.WithDescription(
GetText(strs.did_you_mean(Format.Bold($"{nearest.Name} ({nearest.Symbol})"))));
if (await PromptUserConfirmAsync(embed)) crypto = nearest;
}
if (crypto is null)
{
await ReplyErrorLocalizedAsync(strs.crypto_not_found);
return;
}
var sevenDay = decimal.TryParse(crypto.Quote.Usd.Percent_Change_7d, out var sd)
? sd.ToString("F2")
: crypto.Quote.Usd.Percent_Change_7d;
var lastDay = decimal.TryParse(crypto.Quote.Usd.Percent_Change_24h, out var ld)
? ld.ToString("F2")
: crypto.Quote.Usd.Percent_Change_24h;
await ctx.Channel.EmbedAsync(_eb.Create()
.WithOkColor()
.WithTitle($"{crypto.Name} ({crypto.Symbol})")
.WithUrl($"https://coinmarketcap.com/currencies/{crypto.Slug}/")
.WithThumbnailUrl(
$"https://s3.coinmarketcap.com/static/img/coins/128x128/{crypto.Id}.png")
.AddField(GetText(strs.market_cap),
$"${crypto.Quote.Usd.Market_Cap:n0}",
true)
.AddField(GetText(strs.price), $"${crypto.Quote.Usd.Price}", true)
.AddField(GetText(strs.volume_24h),
$"${crypto.Quote.Usd.Volume_24h:n0}",
true)
.AddField(GetText(strs.change_7d_24h), $"{sevenDay}% / {lastDay}%", true)
.WithImageUrl(
$"https://s3.coinmarketcap.com/generated/sparklines/web/7d/usd/{crypto.Id}.png"));
}
}
}

View File

@@ -0,0 +1,96 @@
#nullable disable
using NadekoBot.Modules.Searches.Common;
using Newtonsoft.Json;
namespace NadekoBot.Modules.Searches.Services;
public class CryptoService : INService
{
private readonly IDataCache _cache;
private readonly IHttpClientFactory _httpFactory;
private readonly IBotCredentials _creds;
private readonly SemaphoreSlim getCryptoLock = new(1, 1);
public CryptoService(IDataCache cache, IHttpClientFactory httpFactory, IBotCredentials creds)
{
_cache = cache;
_httpFactory = httpFactory;
_creds = creds;
}
public async Task<(CryptoResponseData Data, CryptoResponseData Nearest)> GetCryptoData(string name)
{
if (string.IsNullOrWhiteSpace(name)) return (null, null);
name = name.ToUpperInvariant();
var cryptos = await CryptoData();
if (cryptos is null)
return (null, null);
var crypto = cryptos?.FirstOrDefault(x
=> x.Id.ToUpperInvariant() == name
|| x.Name.ToUpperInvariant() == name
|| x.Symbol.ToUpperInvariant() == name);
(CryptoResponseData Elem, int Distance)? nearest = null;
if (crypto is null)
{
nearest = cryptos.Select(x => (x, Distance: x.Name.ToUpperInvariant().LevenshteinDistance(name)))
.OrderBy(x => x.Distance)
.Where(x => x.Distance <= 2)
.FirstOrDefault();
crypto = nearest?.Elem;
}
if (nearest is not null) return (null, crypto);
return (crypto, null);
}
public async Task<List<CryptoResponseData>> CryptoData()
{
await getCryptoLock.WaitAsync();
try
{
var fullStrData = await _cache.GetOrAddCachedDataAsync("nadeko:crypto_data",
async _ =>
{
try
{
using var _http = _httpFactory.CreateClient();
var strData = await _http.GetStringAsync(
"https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?"
+ $"CMC_PRO_API_KEY={_creds.CoinmarketcapApiKey}"
+ "&start=1"
+ "&limit=5000"
+ "&convert=USD");
JsonConvert.DeserializeObject<CryptoResponse>(strData); // just to see if its' valid
return strData;
}
catch (Exception ex)
{
Log.Error(ex, "Error getting crypto data: {Message}", ex.Message);
return default;
}
},
"",
TimeSpan.FromHours(1));
return JsonConvert.DeserializeObject<CryptoResponse>(fullStrData).Data;
}
catch (Exception ex)
{
Log.Error(ex, "Error retreiving crypto data: {Message}", ex.Message);
return default;
}
finally
{
getCryptoLock.Release();
}
}
}