/// <summary> /// Queries the API and returns the value of a world currency by it's unique code. /// </summary> /// <param name="currencyCode">The currency 3-digit code.</param> /// <returns>A task that contains a normalized <see cref="WorldCurrencyResponse"/> object.</returns> public async Task <WorldCurrencyResponse> GetWorldCurrencyValue(string currencyCode) { string endpoint = $"{WorldCurrencyEndpoints.Base.GetDescription()}/{currencyCode.ToUpper()}"; WorldCurrencyResponse cachedResponse = Cache.GetObject <WorldCurrencyResponse>(endpoint); if (cachedResponse != null) { return(cachedResponse); } else { RestRequest request = new(endpoint); RestResponse <WorldCurrencyResponse> response = await Client.ExecuteGetAsync <WorldCurrencyResponse>(request); if (response.IsSuccessful) { WorldCurrencyResponse data = response.Data; data.Code = currencyCode.ToUpper().Trim(); Cache.SaveObject(endpoint, data); return(data); } else { OnError(response); return(null); } } }
/// <summary> /// Creates an <see cref="EmbedBuilder"/> object for a <see cref="WorldCurrencyResponse"/>. /// </summary> /// <param name="worldCurrencyResponse">The world currency response.</param> /// <param name="currencyName">The currency name.</param> /// <param name="amount">The amount to rate against.</param> /// <returns>An <see cref="EmbedBuilder"/> object ready to be built.</returns> public async Task <EmbedBuilder> CreateWorldCurrencyEmbedAsync(WorldCurrencyResponse worldCurrencyResponse, string currencyName, decimal amount = 1) { var emojis = Configuration.GetSection("customEmojis"); Emoji currencyEmoji = Emoji.Parse(":flag_ar:"); Emoji whatsappEmoji = new(emojis["whatsapp"]); Emoji amountEmoji = Emoji.Parse(":moneybag:"); string currencyImageUrl = Configuration.GetSection("images").GetSection("coins")["64"]; string footerImageUrl = Configuration.GetSection("images").GetSection("clock")["32"]; string blankSpace = GlobalConfiguration.Constants.BLANK_SPACE; TimeZoneInfo localTimeZone = GlobalConfiguration.GetLocalTimeZoneInfo(); int utcOffset = localTimeZone.GetUtcOffset(DateTime.UtcNow).Hours; string lastUpdated = worldCurrencyResponse.Fecha.ToString(worldCurrencyResponse.Fecha.Date == TimeZoneInfo.ConvertTime(DateTime.UtcNow, localTimeZone).Date ? "HH:mm" : "dd/MM/yyyy - HH:mm"); string amountField = Format.Bold($"{amountEmoji} {blankSpace} {amount} {worldCurrencyResponse.Code}"); decimal?valuePrice = decimal.TryParse(worldCurrencyResponse?.Valor, NumberStyles.Any, DolarBotApiService.GetApiCulture(), out decimal v) ? v * amount : null; string value = valuePrice.HasValue ? valuePrice.Value.ToString("N2", GlobalConfiguration.GetLocalCultureInfo()) : "?"; string shareText = $"*{currencyName} ({worldCurrencyResponse.Code})*{Environment.NewLine}{Environment.NewLine}*{amount} {worldCurrencyResponse.Code}*{Environment.NewLine}Valor: \t$ *{value}*{Environment.NewLine}Hora: \t{lastUpdated} (UTC {utcOffset})"; EmbedBuilder embed = new EmbedBuilder().WithColor(GlobalConfiguration.Colors.Currency) .WithTitle($"{currencyName} ({worldCurrencyResponse.Code})") .WithDescription($"Cotización de {Format.Bold($"{currencyName} ({worldCurrencyResponse.Code})")} expresada en {Format.Bold("pesos argentinos")}.".AppendLineBreak()) .WithThumbnailUrl(currencyImageUrl) .WithFooter(new EmbedFooterBuilder() { Text = $"Ultima actualización: {lastUpdated} (UTC {utcOffset})", IconUrl = footerImageUrl }) .AddInlineField("Monto", amountField) .AddInlineField($"Valor", $"{Format.Bold($"{currencyEmoji} ${blankSpace} {value.AppendLineBreak()}")}"); await embed.AddFieldWhatsAppShare(whatsappEmoji, shareText, Api.Cuttly.ShortenUrl); return(embed.AddPlayStoreLink(Configuration)); }
public async Task HandleCalculatorModalInput(string currencyCode, FiatCurrencyCalculatorModal calculatorModal) { await DeferAsync().ContinueWith(async(task) => { try { bool isNumeric = decimal.TryParse(calculatorModal.Value.Replace(",", "."), NumberStyles.Any, DolarBotApiService.GetApiCulture(), out decimal amount); if (!isNumeric || amount <= 0) { amount = 1; } List <WorldCurrencyCodeResponse> currenciesList = await FiatCurrencyService.GetWorldCurrenciesList(); WorldCurrencyCodeResponse worldCurrencyCode = currenciesList.FirstOrDefault(x => x.Code.Equals(currencyCode, StringComparison.OrdinalIgnoreCase)); if (worldCurrencyCode != null) { WorldCurrencyResponse currencyResponse = await FiatCurrencyService.GetCurrencyValue(currencyCode); EmbedBuilder embed = await FiatCurrencyService.CreateWorldCurrencyEmbedAsync(currencyResponse, worldCurrencyCode.Name, amount); await SendDeferredEmbedAsync(embed.Build()); } } catch (Exception ex) { await SendDeferredErrorResponseAsync(ex); } }); }
/// <summary> /// Replies with an embed message for a single currency value. /// </summary> /// <param name="currencyCode">The currency 3-digit code.</param> /// <param name="currenciesList">The collection of valid currency codes.</param> private async Task SendCurrencyValueAsync(string currencyCode, List <WorldCurrencyCodeResponse> currenciesList) { WorldCurrencyCodeResponse worldCurrencyCode = currenciesList.FirstOrDefault(x => x.Code.Equals(currencyCode, StringComparison.OrdinalIgnoreCase)); if (worldCurrencyCode != null) { WorldCurrencyResponse currencyResponse = await FiatCurrencyService.GetCurrencyValue(currencyCode); EmbedBuilder embed = await FiatCurrencyService.CreateWorldCurrencyEmbedAsync(currencyResponse, worldCurrencyCode.Name); embed.AddCommandDeprecationNotice(Configuration); await ReplyAsync(embed : embed.Build()); } else { await SendInvalidCurrencyCodeAsync(currencyCode); } }
public async Task GetCurrenciesAsync( [Summary("moneda", "Código de la moneda. Si no se especifica, mostrará todos los códigos de monedas disponibles.")] [Autocomplete(typeof(FiatCurrencyCodeAutocompleteHandler))] string codigo = null ) { await DeferAsync().ContinueWith(async(task) => { try { List <WorldCurrencyCodeResponse> currenciesList = await FiatCurrencyService.GetWorldCurrenciesList(); if (codigo != null) { string currencyCode = Format.Sanitize(codigo).ToUpper().Trim(); WorldCurrencyCodeResponse worldCurrencyCode = currenciesList.FirstOrDefault(x => x.Code.Equals(currencyCode, StringComparison.OrdinalIgnoreCase)); if (worldCurrencyCode != null) { WorldCurrencyResponse currencyResponse = await FiatCurrencyService.GetCurrencyValue(currencyCode); EmbedBuilder embed = await FiatCurrencyService.CreateWorldCurrencyEmbedAsync(currencyResponse, worldCurrencyCode.Name); await SendDeferredEmbedAsync(embed.Build(), components: new CalculatorComponentBuilder(currencyCode, CalculatorTypes.FiatCurrency, Configuration).Build()); } else { await SendInvalidCurrencyCodeAsync(currencyCode); } } else { string commandPrefix = Configuration["commandPrefix"]; int replyTimeout = Convert.ToInt32(Configuration["interactiveMessageReplyTimeout"]); string currencyCommand = GetType().GetMethod(nameof(GetCurrenciesAsync)).GetCustomAttributes(true).OfType <SlashCommandAttribute>().First().Name; EmbedBuilder[] embeds = FiatCurrencyService.CreateWorldCurrencyListEmbedAsync(currenciesList, currencyCommand, Context.User.Username).ToArray(); await SendDeferredPaginatedEmbedAsync(embeds); } } catch (Exception ex) { await SendDeferredErrorResponseAsync(ex); } }); }
/// <summary> /// Creates a collection of <see cref="EmbedBuilder"/> objects representing historical values. /// </summary> /// <param name="historicalCurrencyValues">A collection of <see cref="WorldCurrencyResponse"/> objects.</param> /// <param name="currencyName">The currency name.</param> /// <returns>A list of embeds ready to be built.</returns> public List <EmbedBuilder> CreateHistoricalValuesEmbedsAsync(List <WorldCurrencyResponse> historicalCurrencyValues, string currencyName, DateTime?startDate, DateTime?endDate) { var emojis = Configuration.GetSection("customEmojis"); Emoji upEmoji = new(emojis["arrowUpRed"]); Emoji downEmoji = new(emojis["arrowDownGreen"]); Emoji neutralEmoji = new(emojis["neutral"]); Emoji calendarEmoji = new(":calendar_spiral:"); string chartImageUrl = Configuration.GetSection("images").GetSection("chart")["64"]; int pageCount = 0; int totalPages = (int)Math.Ceiling(Convert.ToDecimal(historicalCurrencyValues.Count) / HISTORICAL_DATES_PER_PAGE); List <IEnumerable <WorldCurrencyResponse> > historicalCurrencyValuesPages = historicalCurrencyValues.ChunkBy(HISTORICAL_DATES_PER_PAGE); if (!startDate.HasValue) { startDate = historicalCurrencyValues.First().Fecha.Date; } if (!endDate.HasValue || endDate.Value.Date > DateTime.Now.Date) { endDate = DateTime.Now.Date; } bool isSingleDate = startDate.Value.Date == endDate.Value.Date; List <EmbedBuilder> embeds = new(); for (int i = 0; i < historicalCurrencyValuesPages.Count; i++) { IEnumerable <WorldCurrencyResponse> page = historicalCurrencyValuesPages.ElementAt(i); StringBuilder sbField = new(); for (int j = 0; j < page.Count(); j++) { WorldCurrencyResponse currencyValue = page.ElementAt(j); bool rateIsNumeric = decimal.TryParse(currencyValue.Valor, NumberStyles.Any, DolarBotApiService.GetApiCulture(), out decimal currencyRate); Emoji fieldEmoji = isSingleDate ? calendarEmoji : neutralEmoji; if (i > 0 || j > 0) { WorldCurrencyResponse previousCurrencyValue = j > 0 ? page.ElementAt(j - 1) : historicalCurrencyValuesPages.ElementAt(i - 1).Last(); bool previousValueIsNumeric = decimal.TryParse(previousCurrencyValue.Valor, NumberStyles.Any, DolarBotApiService.GetApiCulture(), out decimal previousRate); if (rateIsNumeric && previousValueIsNumeric) { if (currencyRate >= previousRate) { fieldEmoji = currencyRate > previousRate ? upEmoji : neutralEmoji; } else { fieldEmoji = downEmoji; } } } string fieldText = $"{fieldEmoji} {Format.Code(currencyValue.Fecha.ToString("dd/MM/yyyy"))}: {Format.Bold($"$ {currencyRate}")}"; sbField = sbField.AppendLine(fieldText); } string worldCurrencyCode = historicalCurrencyValues.First().Code; string embedTitle = isSingleDate ? "Cotización por fecha" : "Cotizaciones por Fecha"; string embedDescription = $"{(isSingleDate ? "Cotización oficial" : "Cotizaciones oficiales")} de {Format.Bold($"{currencyName} ({worldCurrencyCode})")} {(isSingleDate ? $"para el día {Format.Code(startDate.Value.Date.ToString("dd/MM/yyyy"))}" : $"entre el {Format.Code(startDate.Value.Date.ToString("dd/MM/yyyy"))} y el {Format.Code(endDate.Value.Date.ToString("dd/MM/yyyy"))}")}, expresada en {Format.Bold("pesos argentinos")}.".AppendLineBreak(); EmbedBuilder embed = new EmbedBuilder().WithColor(GlobalConfiguration.Colors.Currency) .WithTitle($"{currencyName} ({worldCurrencyCode})") .WithDescription(embedDescription) .WithThumbnailUrl(chartImageUrl) .WithFooter($"Página {++pageCount} de {totalPages}") .AddField(embedTitle, sbField.AppendLineBreak().ToString()); embeds.Add(embed); } return(embeds); }