Updated Searches module

This commit is contained in:
Toastie (DCS Team) 2024-07-15 15:44:58 +12:00
parent ca64765c34
commit 6b6f822ec8
Signed by: toastie_t0ast
GPG key ID: 27F3B6855AFD40A4
2 changed files with 146 additions and 46 deletions

View file

@ -18,7 +18,7 @@ public partial class Searches
}
[Cmd]
public async Task Stock([Leftover]string query)
public async Task Stock([Leftover] string query)
{
using var typing = ctx.Channel.EnterTypingState();
@ -36,8 +36,8 @@ public partial class Searches
var symbol = symbols.First();
var promptEmbed = _sender.CreateEmbed()
.WithDescription(symbol.Description)
.WithTitle(GetText(strs.did_you_mean(symbol.Symbol)));
.WithDescription(symbol.Description)
.WithTitle(GetText(strs.did_you_mean(symbol.Symbol)));
if (!await PromptUserConfirmAsync(promptEmbed))
return;
@ -80,17 +80,17 @@ public partial class Searches
var price = stock.Price.ToString("C2", localCulture);
var eb = _sender.CreateEmbed()
.WithOkColor()
.WithAuthor(stock.Symbol)
.WithUrl($"https://www.tradingview.com/chart/?symbol={stock.Symbol}")
.WithTitle(stock.Name)
.AddField(GetText(strs.price), $"{sign} **{price}**", true)
.AddField(GetText(strs.market_cap), stock.MarketCap, true)
.AddField(GetText(strs.volume_24h), stock.DailyVolume.ToString("C0", localCulture), true)
.AddField("Change", $"{change} ({changePercent})", true)
// .AddField("Change 50d", $"{sign50}{change50}", true)
// .AddField("Change 200d", $"{sign200}{change200}", true)
.WithFooter(stock.Exchange);
.WithOkColor()
.WithAuthor(stock.Symbol)
.WithUrl($"https://www.tradingview.com/chart/?symbol={stock.Symbol}")
.WithTitle(stock.Name)
.AddField(GetText(strs.price), $"{sign} **{price}**", true)
.AddField(GetText(strs.market_cap), stock.MarketCap, true)
.AddField(GetText(strs.volume_24h), stock.DailyVolume.ToString("C0", localCulture), true)
.AddField("Change", $"{change} ({changePercent})", true)
// .AddField("Change 50d", $"{sign50}{change50}", true)
// .AddField("Change 200d", $"{sign200}{change200}", true)
.WithFooter(stock.Exchange);
var message = await Response().Embed(eb).SendAsync();
await using var imageData = await stockImageTask;
@ -105,10 +105,7 @@ public partial class Searches
await message.ModifyAsync(mp =>
{
mp.Attachments =
new(new[]
{
attachment
});
new(new[] { attachment });
mp.Embed = eb.WithImageUrl($"attachment://{fileName}").Build();
});
@ -128,9 +125,9 @@ public partial class Searches
if (nearest is not null)
{
var embed = _sender.CreateEmbed()
.WithTitle(GetText(strs.crypto_not_found))
.WithDescription(
GetText(strs.did_you_mean(Format.Bold($"{nearest.Name} ({nearest.Symbol})"))));
.WithTitle(GetText(strs.crypto_not_found))
.WithDescription(
GetText(strs.did_you_mean(Format.Bold($"{nearest.Name} ({nearest.Symbol})"))));
if (await PromptUserConfirmAsync(embed))
crypto = nearest;
@ -161,17 +158,18 @@ public partial class Searches
var fileName = $"{crypto.Slug}_7d.png";
var toSend = _sender.CreateEmbed()
.WithOkColor()
.WithAuthor($"#{crypto.CmcRank}")
.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), marketCap, true)
.AddField(GetText(strs.price), price, true)
.AddField(GetText(strs.volume_24h), volume, true)
.AddField(GetText(strs.change_7d_24h), $"{sevenDay} / {lastDay}", true)
.AddField(GetText(strs.market_cap_dominance), dominance, true)
.WithImageUrl($"attachment://{fileName}");
.WithOkColor()
.WithAuthor($"#{crypto.CmcRank}")
.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), marketCap, true)
.AddField(GetText(strs.price), price, true)
.AddField(GetText(strs.volume_24h), volume, true)
.AddField(GetText(strs.change_7d_24h), $"{sevenDay} / {lastDay}", true)
.AddField(GetText(strs.market_cap_dominance), dominance, true)
.WithImageUrl($"attachment://{fileName}");
if (crypto.CirculatingSupply is double cs)
{
@ -192,5 +190,54 @@ public partial class Searches
await ctx.Channel.SendFileAsync(sparkline, fileName, embed: toSend.Build());
}
[Cmd]
public async Task Coins(int page = 1)
{
if (--page < 0)
return;
if (page > 25)
page = 25;
await Response()
.Paginated()
.PageItems(async (page) =>
{
var coins = await _service.GetTopCoins(page);
return coins;
})
.PageSize(10)
.Page((items, _) =>
{
var embed = _sender.CreateEmbed()
.WithOkColor();
if (items.Count > 0)
{
foreach (var coin in items)
{
embed.AddField($"#{coin.MarketCapRank} {coin.Symbol} - {coin.Name}",
$"""
`Price:` {GetArrowEmoji(coin.PercentChange24h)} {coin.CurrentPrice.ToShortString()}$ ({GetSign(coin.PercentChange24h)}{Math.Round(coin.PercentChange24h, 2)}%)
`MarketCap:` {coin.MarketCap.ToShortString()}$
`Supply:` {(coin.CirculatingSupply?.ToShortString() ?? "?")} / {(coin.TotalSupply?.ToShortString() ?? "?")}
""",
inline: false);
}
}
return embed;
})
.CurrentPage(page)
.AddFooter(false)
.SendAsync();
}
private static string GetArrowEmoji(decimal value)
=> value > 0 ? "▲" : "▼";
private static string GetSign(decimal value)
=> value >= 0 ? "+" : "-";
}
}

View file

@ -4,8 +4,10 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using System.Xml;
using Color = SixLabors.ImageSharp.Color;
using StringExtensions = EllieBot.Extensions.StringExtensions;
@ -212,4 +214,55 @@ public class CryptoService : IEService
var points = GetSparklinePointsFromSvgText(str);
return points;
}
private static TypedKey<IReadOnlyCollection<GeckoCoinsResult>> GetTopCoinsKey()
=> new($"crypto:top_coins");
public async Task<IReadOnlyCollection<GeckoCoinsResult>?> GetTopCoins(int page)
{
if (page >= 25)
page = 24;
using var http = _httpFactory.CreateClient();
http.AddFakeHeaders();
var result = await _cache.GetOrAddAsync<IReadOnlyCollection<GeckoCoinsResult>>(GetTopCoinsKey(),
async () => await http.GetFromJsonAsync<List<GeckoCoinsResult>>(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250")
?? [],
expiry: TimeSpan.FromHours(1));
return result!.Skip(page * 10).Take(10).ToList();
}
}
public sealed class GeckoCoinsResult
{
[JsonPropertyName("id")]
public required string Id { get; init; }
[JsonPropertyName("name")]
public required string Name { get; init; }
[JsonPropertyName("symbol")]
public required string Symbol { get; init; }
[JsonPropertyName("current_price")]
public required decimal CurrentPrice { get; init; }
[JsonPropertyName("price_change_percentage_24h")]
public required decimal PercentChange24h { get; init; }
[JsonPropertyName("market_cap")]
public required decimal MarketCap { get; init; }
[JsonPropertyName("circulating_supply")]
public required decimal? CirculatingSupply { get; init; }
[JsonPropertyName("total_supply")]
public required decimal? TotalSupply { get; init; }
[JsonPropertyName("market_cap_rank")]
public required int MarketCapRank { get; init; }
}