mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 17:58:26 -04:00
5.1
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using AngleSharp;
|
||||
using CsvHelper;
|
||||
using CsvHelper.Configuration;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
|
||||
@@ -22,46 +23,32 @@ public sealed class DefaultStockDataService : IStockDataService, INService
|
||||
|
||||
using var http = _httpClientFactory.CreateClient();
|
||||
|
||||
|
||||
|
||||
var quoteHtmlPage = $"https://finance.yahoo.com/quote/{query.ToUpperInvariant()}";
|
||||
|
||||
var config = Configuration.Default.WithDefaultLoader();
|
||||
using var document = await BrowsingContext.New(config).OpenAsync(quoteHtmlPage);
|
||||
var divElem =
|
||||
document.QuerySelector(
|
||||
"#quote-header-info > div:nth-child(2) > div > div > h1");
|
||||
var tickerName = (divElem)?.TextContent;
|
||||
|
||||
var tickerName = document.QuerySelector("div.top > .left > .container > h1")
|
||||
?.TextContent;
|
||||
|
||||
if (tickerName is null)
|
||||
return default;
|
||||
|
||||
var marketcap = document
|
||||
.QuerySelectorAll("table")
|
||||
.Skip(1)
|
||||
.First()
|
||||
.QuerySelector("tbody > tr > td:nth-child(2)")
|
||||
.QuerySelector("li > span > fin-streamer[data-field='marketCap']")
|
||||
?.TextContent;
|
||||
|
||||
|
||||
var volume = document.QuerySelector("td[data-test='AVERAGE_VOLUME_3MONTH-value']")
|
||||
var volume = document.QuerySelector("li > span > fin-streamer[data-field='regularMarketVolume']")
|
||||
?.TextContent;
|
||||
|
||||
var close= document.QuerySelector("td[data-test='PREV_CLOSE-value']")
|
||||
?.TextContent ?? "0";
|
||||
|
||||
var price = document
|
||||
.QuerySelector("#quote-header-info")
|
||||
?.QuerySelector("fin-streamer[data-field='regularMarketPrice']")
|
||||
?.TextContent ?? close;
|
||||
|
||||
// var data = await http.GetFromJsonAsync<YahooQueryModel>(
|
||||
// $"https://query1.finance.yahoo.com/v7/finance/quote?symbols={query}");
|
||||
//
|
||||
// if (data is null)
|
||||
// return default;
|
||||
|
||||
// var symbol = data.QuoteResponse.Result.FirstOrDefault();
|
||||
var close = document.QuerySelector("li > span > fin-streamer[data-field='regularMarketPreviousClose']")
|
||||
?.TextContent
|
||||
?? "0";
|
||||
|
||||
// if (symbol is null)
|
||||
// return default;
|
||||
var price = document.QuerySelector("fin-streamer.livePrice > span")
|
||||
?.TextContent
|
||||
?? "0";
|
||||
|
||||
return new()
|
||||
{
|
||||
|
@@ -1,312 +0,0 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Modules.Searches.Common;
|
||||
using NadekoBot.Modules.Searches.Services;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace NadekoBot.Modules.Searches;
|
||||
|
||||
public partial class Searches
|
||||
{
|
||||
[Group]
|
||||
public partial class PathOfExileCommands : NadekoModule<SearchesService>
|
||||
{
|
||||
private const string POE_URL = "https://www.pathofexile.com/character-window/get-characters?accountName=";
|
||||
private const string PON_URL = "http://poe.ninja/api/Data/GetCurrencyOverview?league=";
|
||||
private const string POGS_URL = "http://pathofexile.gamepedia.com/api.php?action=opensearch&search=";
|
||||
|
||||
private const string POG_URL =
|
||||
"https://pathofexile.gamepedia.com/api.php?action=browsebysubject&format=json&subject=";
|
||||
|
||||
private const string POGI_URL =
|
||||
"https://pathofexile.gamepedia.com/api.php?action=query&prop=imageinfo&iiprop=url&format=json&titles=File:";
|
||||
|
||||
private const string PROFILE_URL = "https://www.pathofexile.com/account/view-profile/";
|
||||
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
|
||||
private Dictionary<string, string> currencyDictionary = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "Chaos Orb", "Chaos Orb" },
|
||||
{ "Orb of Alchemy", "Orb of Alchemy" },
|
||||
{ "Jeweller's Orb", "Jeweller's Orb" },
|
||||
{ "Exalted Orb", "Exalted Orb" },
|
||||
{ "Mirror of Kalandra", "Mirror of Kalandra" },
|
||||
{ "Vaal Orb", "Vaal Orb" },
|
||||
{ "Orb of Alteration", "Orb of Alteration" },
|
||||
{ "Orb of Scouring", "Orb of Scouring" },
|
||||
{ "Divine Orb", "Divine Orb" },
|
||||
{ "Orb of Annulment", "Orb of Annulment" },
|
||||
{ "Master Cartographer's Sextant", "Master Cartographer's Sextant" },
|
||||
{ "Journeyman Cartographer's Sextant", "Journeyman Cartographer's Sextant" },
|
||||
{ "Apprentice Cartographer's Sextant", "Apprentice Cartographer's Sextant" },
|
||||
{ "Blessed Orb", "Blessed Orb" },
|
||||
{ "Orb of Regret", "Orb of Regret" },
|
||||
{ "Gemcutter's Prism", "Gemcutter's Prism" },
|
||||
{ "Glassblower's Bauble", "Glassblower's Bauble" },
|
||||
{ "Orb of Fusing", "Orb of Fusing" },
|
||||
{ "Cartographer's Chisel", "Cartographer's Chisel" },
|
||||
{ "Chromatic Orb", "Chromatic Orb" },
|
||||
{ "Orb of Augmentation", "Orb of Augmentation" },
|
||||
{ "Blacksmith's Whetstone", "Blacksmith's Whetstone" },
|
||||
{ "Orb of Transmutation", "Orb of Transmutation" },
|
||||
{ "Armourer's Scrap", "Armourer's Scrap" },
|
||||
{ "Scroll of Wisdom", "Scroll of Wisdom" },
|
||||
{ "Regal Orb", "Regal Orb" },
|
||||
{ "Chaos", "Chaos Orb" },
|
||||
{ "Alch", "Orb of Alchemy" },
|
||||
{ "Alchs", "Orb of Alchemy" },
|
||||
{ "Jews", "Jeweller's Orb" },
|
||||
{ "Jeweller", "Jeweller's Orb" },
|
||||
{ "Jewellers", "Jeweller's Orb" },
|
||||
{ "Jeweller's", "Jeweller's Orb" },
|
||||
{ "X", "Exalted Orb" },
|
||||
{ "Ex", "Exalted Orb" },
|
||||
{ "Exalt", "Exalted Orb" },
|
||||
{ "Exalts", "Exalted Orb" },
|
||||
{ "Mirror", "Mirror of Kalandra" },
|
||||
{ "Mirrors", "Mirror of Kalandra" },
|
||||
{ "Vaal", "Vaal Orb" },
|
||||
{ "Alt", "Orb of Alteration" },
|
||||
{ "Alts", "Orb of Alteration" },
|
||||
{ "Scour", "Orb of Scouring" },
|
||||
{ "Scours", "Orb of Scouring" },
|
||||
{ "Divine", "Divine Orb" },
|
||||
{ "Annul", "Orb of Annulment" },
|
||||
{ "Annulment", "Orb of Annulment" },
|
||||
{ "Master Sextant", "Master Cartographer's Sextant" },
|
||||
{ "Journeyman Sextant", "Journeyman Cartographer's Sextant" },
|
||||
{ "Apprentice Sextant", "Apprentice Cartographer's Sextant" },
|
||||
{ "Blessed", "Blessed Orb" },
|
||||
{ "Regret", "Orb of Regret" },
|
||||
{ "Regrets", "Orb of Regret" },
|
||||
{ "Gcp", "Gemcutter's Prism" },
|
||||
{ "Glassblowers", "Glassblower's Bauble" },
|
||||
{ "Glassblower's", "Glassblower's Bauble" },
|
||||
{ "Fusing", "Orb of Fusing" },
|
||||
{ "Fuses", "Orb of Fusing" },
|
||||
{ "Fuse", "Orb of Fusing" },
|
||||
{ "Chisel", "Cartographer's Chisel" },
|
||||
{ "Chisels", "Cartographer's Chisel" },
|
||||
{ "Chance", "Orb of Chance" },
|
||||
{ "Chances", "Orb of Chance" },
|
||||
{ "Chrome", "Chromatic Orb" },
|
||||
{ "Chromes", "Chromatic Orb" },
|
||||
{ "Aug", "Orb of Augmentation" },
|
||||
{ "Augmentation", "Orb of Augmentation" },
|
||||
{ "Augment", "Orb of Augmentation" },
|
||||
{ "Augments", "Orb of Augmentation" },
|
||||
{ "Whetstone", "Blacksmith's Whetstone" },
|
||||
{ "Whetstones", "Blacksmith's Whetstone" },
|
||||
{ "Transmute", "Orb of Transmutation" },
|
||||
{ "Transmutes", "Orb of Transmutation" },
|
||||
{ "Armourers", "Armourer's Scrap" },
|
||||
{ "Armourer's", "Armourer's Scrap" },
|
||||
{ "Wisdom Scroll", "Scroll of Wisdom" },
|
||||
{ "Wisdom Scrolls", "Scroll of Wisdom" },
|
||||
{ "Regal", "Regal Orb" },
|
||||
{ "Regals", "Regal Orb" }
|
||||
};
|
||||
|
||||
public PathOfExileCommands(IHttpClientFactory httpFactory)
|
||||
=> _httpFactory = httpFactory;
|
||||
|
||||
[Cmd]
|
||||
public async Task PathOfExile(string usr, string league = "", int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(usr))
|
||||
{
|
||||
await Response().Error("Please provide an account name.").SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var characters = new List<Account>();
|
||||
|
||||
try
|
||||
{
|
||||
using var http = _httpFactory.CreateClient();
|
||||
var res = await http.GetStringAsync($"{POE_URL}{usr}");
|
||||
characters = JsonConvert.DeserializeObject<List<Account>>(res);
|
||||
}
|
||||
catch
|
||||
{
|
||||
var embed = _sender.CreateEmbed().WithDescription(GetText(strs.account_not_found)).WithErrorColor();
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(league))
|
||||
characters.RemoveAll(c => c.League != league);
|
||||
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(characters)
|
||||
.PageSize(9)
|
||||
.CurrentPage(page)
|
||||
.Page((items, curPage) =>
|
||||
{
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor($"Characters on {usr}'s account",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
$"{PROFILE_URL}{usr}")
|
||||
.WithOkColor();
|
||||
|
||||
if (characters.Count == 0)
|
||||
return embed.WithDescription("This account has no characters.");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"```{"#",-5}{"Character Name",-23}{"League",-10}{"Class",-13}{"Level",-3}");
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
var character = items[i];
|
||||
|
||||
sb.AppendLine(
|
||||
$"#{i + 1 + (curPage * 9),-4}{character.Name,-23}{ShortLeagueName(character.League),-10}{character.Class,-13}{character.Level,-3}");
|
||||
}
|
||||
|
||||
sb.AppendLine("```");
|
||||
embed.WithDescription(sb.ToString());
|
||||
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async Task PathOfExileLeagues()
|
||||
{
|
||||
var leagues = new List<Leagues>();
|
||||
|
||||
try
|
||||
{
|
||||
using var http = _httpFactory.CreateClient();
|
||||
var res = await http.GetStringAsync("http://api.pathofexile.com/leagues?type=main&compact=1");
|
||||
leagues = JsonConvert.DeserializeObject<List<Leagues>>(res);
|
||||
}
|
||||
catch
|
||||
{
|
||||
var eembed = _sender.CreateEmbed().WithDescription(GetText(strs.leagues_not_found)).WithErrorColor();
|
||||
|
||||
await Response().Embed(eembed).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor("Path of Exile Leagues",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
"https://www.pathofexile.com")
|
||||
.WithOkColor();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"```{"#",-5}{"League Name",-23}");
|
||||
for (var i = 0; i < leagues.Count; i++)
|
||||
{
|
||||
var league = leagues[i];
|
||||
|
||||
sb.AppendLine($"#{i + 1,-4}{league.Id,-23}");
|
||||
}
|
||||
|
||||
sb.AppendLine("```");
|
||||
|
||||
embed.WithDescription(sb.ToString());
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async Task PathOfExileCurrency(
|
||||
string leagueName,
|
||||
string currencyName,
|
||||
string convertName = "Chaos Orb")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(leagueName))
|
||||
{
|
||||
await Response().Error("Please provide league name.").SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(currencyName))
|
||||
{
|
||||
await Response().Error("Please provide currency name.").SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var cleanCurrency = ShortCurrencyName(currencyName);
|
||||
var cleanConvert = ShortCurrencyName(convertName);
|
||||
|
||||
try
|
||||
{
|
||||
var res = $"{PON_URL}{leagueName}";
|
||||
using var http = _httpFactory.CreateClient();
|
||||
var obj = JObject.Parse(await http.GetStringAsync(res));
|
||||
|
||||
var chaosEquivalent = 0.0F;
|
||||
var conversionEquivalent = 0.0F;
|
||||
|
||||
// poe.ninja API does not include a "chaosEquivalent" property for Chaos Orbs.
|
||||
if (cleanCurrency == "Chaos Orb")
|
||||
chaosEquivalent = 1.0F;
|
||||
else
|
||||
{
|
||||
var currencyInput = obj["lines"]
|
||||
.Values<JObject>()
|
||||
.Where(i => i["currencyTypeName"].Value<string>() == cleanCurrency)
|
||||
.FirstOrDefault();
|
||||
chaosEquivalent = float.Parse(currencyInput["chaosEquivalent"].ToString(),
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (cleanConvert == "Chaos Orb")
|
||||
conversionEquivalent = 1.0F;
|
||||
else
|
||||
{
|
||||
var currencyOutput = obj["lines"]
|
||||
.Values<JObject>()
|
||||
.Where(i => i["currencyTypeName"].Value<string>() == cleanConvert)
|
||||
.FirstOrDefault();
|
||||
conversionEquivalent = float.Parse(currencyOutput["chaosEquivalent"].ToString(),
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithAuthor($"{leagueName} Currency Exchange",
|
||||
"https://web.poecdn.com/image/favicon/ogimage.png",
|
||||
"http://poe.ninja")
|
||||
.AddField("Currency Type", cleanCurrency, true)
|
||||
.AddField($"{cleanConvert} Equivalent", chaosEquivalent / conversionEquivalent, true)
|
||||
.WithOkColor();
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
var embed = _sender.CreateEmbed().WithDescription(GetText(strs.ninja_not_found)).WithErrorColor();
|
||||
|
||||
await Response().Embed(embed).SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private string ShortCurrencyName(string str)
|
||||
{
|
||||
if (currencyDictionary.ContainsValue(str))
|
||||
return str;
|
||||
|
||||
var currency = currencyDictionary[str];
|
||||
|
||||
return currency;
|
||||
}
|
||||
|
||||
private static string ShortLeagueName(string str)
|
||||
{
|
||||
var league = str.Replace("Hardcore", "HC", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
return league;
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using NadekoBot.Modules.Searches.Common;
|
||||
using NadekoBot.Modules.Searches.Services;
|
||||
using NadekoBot.Modules.Utility;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SixLabors.ImageSharp;
|
||||
@@ -168,7 +169,7 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
.AddField("Rating", movie.ImdbRating, true)
|
||||
.AddField("Genre", movie.Genre, true)
|
||||
.AddField("Year", movie.Year, true)
|
||||
.WithImageUrl(movie.Poster))
|
||||
.WithImageUrl(Uri.IsWellFormedUriString(movie.Poster, UriKind.Absolute) ? movie.Poster : null))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user