public async Task GetEuroRatesAsync()
        {
            try
            {
                using (Context.Channel.EnterTypingState())
                {
                    VzlaResponse result = await VzlaService.GetEuroRates();

                    if (result != null)
                    {
                        EmbedBuilder embed = await VzlaService.CreateVzlaEmbedAsync(result);

                        embed.AddCommandDeprecationNotice(Configuration);
                        await ReplyAsync(embed : embed.Build());
                    }
                    else
                    {
                        await ReplyAsync(REQUEST_ERROR_MESSAGE);
                    }
                }
            }
            catch (Exception ex)
            {
                await SendErrorReply(ex);
            }
        }
        public async Task HandleCalculatorModalInput(string currencyCode, VzlaCalculatorModal 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;
                    }

                    Currencies currency = Enum.Parse <Currencies>(currencyCode);
                    VzlaResponse result = currency switch
                    {
                        Currencies.Dolar => await VzlaService.GetDollarRates(),
                        Currencies.Euro => await VzlaService.GetEuroRates(),
                        _ => throw new NotImplementedException(),
                    };
                    if (result != null)
                    {
                        EmbedBuilder embed = await VzlaService.CreateVzlaEmbedAsync(result, amount);
                        await SendDeferredEmbedAsync(embed.Build());
                    }
                    else
                    {
                        await SendDeferredApiErrorResponseAsync();
                    }
                }
                catch (Exception ex)
                {
                    await SendDeferredErrorResponseAsync(ex);
                }
            });
        }
        /// <summary>
        /// Queries the API endpoint asynchronously and returns a <see cref="VzlaResponse"/> object.
        /// </summary>
        /// <returns>A task that contains a normalized <see cref="VzlaResponse"/> object.</returns>
        public async Task <VzlaResponse> GetVzlaRates(VenezuelaEndpoints type)
        {
            VzlaResponse cachedResponse = Cache.GetObject <VzlaResponse>(type);

            if (cachedResponse != null)
            {
                return(cachedResponse);
            }
            else
            {
                string      endpoint = type.GetDescription();
                RestRequest request  = new(endpoint);
                RestResponse <VzlaResponse> response = await Client.ExecuteGetAsync <VzlaResponse>(request);

                if (response.IsSuccessful)
                {
                    VzlaResponse vzlaResponse = response.Data;
                    vzlaResponse.Type = type;
                    Cache.SaveObject(type, vzlaResponse);

                    return(vzlaResponse);
                }
                else
                {
                    OnError(response);
                    return(null);
                }
            }
        }
        /// <summary>
        /// Creates an <see cref="EmbedBuilder"/> object for a <see cref="VzlaResponse"/>.
        /// </summary>
        /// <param name="vzlaResponse">The Venezuela response.</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> CreateVzlaEmbedAsync(VzlaResponse vzlaResponse, decimal amount = 1)
        {
            var   emojis        = Configuration.GetSection("customEmojis");
            Emoji currencyEmoji = GetEmoji(vzlaResponse.Type);
            Emoji bankEmoji     = new(":bank:");
            Emoji moneyEmoji    = new(":money_with_wings:");
            Emoji whatsappEmoji = new(emojis["whatsapp"]);
            Emoji amountEmoji   = Emoji.Parse(":moneybag:");

            string       blankSpace    = GlobalConfiguration.Constants.BLANK_SPACE;
            TimeZoneInfo localTimeZone = GlobalConfiguration.GetLocalTimeZoneInfo();
            int          utcOffset     = localTimeZone.GetUtcOffset(DateTime.UtcNow).Hours;

            string thumbnailUrl   = Configuration.GetSection("images").GetSection("venezuela")["64"];
            string footerImageUrl = Configuration.GetSection("images").GetSection("clock")["32"];
            string currencyCode   = vzlaResponse.Type switch
            {
                VenezuelaEndpoints.Dollar => "USD",
                VenezuelaEndpoints.Euro => "EUR",
                _ => throw new NotImplementedException(),
            };

            decimal?bancosValue       = decimal.TryParse(vzlaResponse?.Bancos, NumberStyles.Any, DolarBotApiService.GetApiCulture(), out decimal b) ? b * amount : null;
            decimal?paraleloValue     = decimal.TryParse(vzlaResponse?.Paralelo, NumberStyles.Any, DolarBotApiService.GetApiCulture(), out decimal p) ? p * amount : null;
            string  bancosValueText   = bancosValue.HasValue ? Format.Bold($"B$ {bancosValue.Value.ToString("N2", GlobalConfiguration.GetLocalCultureInfo())}") : "No informado";
            string  paraleloValueText = paraleloValue.HasValue ? Format.Bold($"B$ {paraleloValue.Value.ToString("N2", GlobalConfiguration.GetLocalCultureInfo())}") : "No informado";

            string title       = $"{GetName(vzlaResponse.Type).Capitalize()} Venezuela";
            string description = new StringBuilder()
                                 .AppendLine($"Cotizaciones disponibles del {Format.Bold(GetName(vzlaResponse.Type))} expresadas en {Format.Bold("bolívares venezolanos")}.")
                                 .AppendLineBreak()
                                 .AppendLine($"{bankEmoji} {Format.Bold("Bancos")}: {Format.Italics("Promedio de las cotizaciones bancarias")}.")
                                 .Append($"{moneyEmoji} {Format.Bold("Paralelo")}: {Format.Italics($"Cotización del {GetName(vzlaResponse.Type).ToLower()} paralelo")}.")
                                 .ToString();
            string lastUpdated = vzlaResponse.Fecha.ToString(vzlaResponse.Fecha.Date == TimeZoneInfo.ConvertTime(DateTime.UtcNow, localTimeZone).Date ? "HH:mm" : "dd/MM/yyyy - HH:mm");

            string amountField = Format.Bold($"{amountEmoji} {blankSpace} {amount} {currencyCode}").AppendLineBreak();
            string shareText   = $"*{title}*{Environment.NewLine}{Environment.NewLine}*{amount} {currencyCode}*{Environment.NewLine}Bancos: \t\tB$ *{bancosValue.GetValueOrDefault().ToString("N2", GlobalConfiguration.GetLocalCultureInfo())}*{Environment.NewLine}Paralelo: \t\tB$ *{paraleloValue.GetValueOrDefault().ToString("N2", GlobalConfiguration.GetLocalCultureInfo())}*{Environment.NewLine}Hora: \t\t{lastUpdated} (UTC {utcOffset})";

            EmbedBuilder embed = new EmbedBuilder().WithColor(GlobalConfiguration.Colors.Venezuela)
                                 .WithTitle(title)
                                 .WithDescription(description.ToString().AppendLineBreak())
                                 .WithThumbnailUrl(thumbnailUrl)
                                 .WithFooter(new EmbedFooterBuilder()
            {
                Text    = $"Ultima actualización: {lastUpdated} (UTC {utcOffset})",
                IconUrl = footerImageUrl
            })
                                 .AddField("Monto", amountField)
                                 .AddInlineField($"{bankEmoji} Bancos", $"{currencyEmoji} {blankSpace} {bancosValueText} {blankSpace}")
                                 .AddInlineField($"{moneyEmoji} Paralelo", $"{currencyEmoji} {blankSpace} {paraleloValueText} {blankSpace}".AppendLineBreak());

            await embed.AddFieldWhatsAppShare(whatsappEmoji, shareText, Api.Cuttly.ShortenUrl);

            return(embed.AddPlayStoreLink(Configuration));
        }
 public async Task GetDollarRatesAsync()
 {
     await DeferAsync().ContinueWith(async(task) =>
     {
         try
         {
             VzlaResponse result = await VzlaService.GetDollarRates();
             if (result != null)
             {
                 EmbedBuilder embed = await VzlaService.CreateVzlaEmbedAsync(result);
                 await SendDeferredEmbedAsync(embed.Build(), components: new CalculatorComponentBuilder(Currencies.Dolar.ToString(), CalculatorTypes.Venezuela, Configuration).Build());
             }
             else
             {
                 await SendDeferredApiErrorResponseAsync();
             }
         }
         catch (Exception ex)
         {
             await SendDeferredErrorResponseAsync(ex);
         }
     });
 }