mirror of
https://github.com/C9Glax/tranga.git
synced 2025-10-11 05:09:49 +02:00
Fix issues with namespaces in xpath
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Web;
|
||||||
using API.MangaDownloadClients;
|
using API.MangaDownloadClients;
|
||||||
using API.Schema.MangaContext;
|
using API.Schema.MangaContext;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
@@ -29,7 +30,7 @@ public class MangaDex : MangaConnector
|
|||||||
while(offset < total)
|
while(offset < total)
|
||||||
{
|
{
|
||||||
string requestUrl =
|
string requestUrl =
|
||||||
$"https://api.mangadex.org/manga?limit={Limit}&offset={offset}&title={mangaSearchName}" +
|
$"https://api.mangadex.org/manga?limit={Limit}&offset={offset}&title={HttpUtility.UrlEncode(mangaSearchName)}" +
|
||||||
$"&contentRating%5B%5D=safe&contentRating%5B%5D=suggestive&contentRating%5B%5D=erotica" +
|
$"&contentRating%5B%5D=safe&contentRating%5B%5D=suggestive&contentRating%5B%5D=erotica" +
|
||||||
$"&includes%5B%5D=manga&includes%5B%5D=cover_art&includes%5B%5D=author&includes%5B%5D=artist&includes%5B%5D=tag'";
|
$"&includes%5B%5D=manga&includes%5B%5D=cover_art&includes%5B%5D=author&includes%5B%5D=artist&includes%5B%5D=tag'";
|
||||||
offset += Limit;
|
offset += Limit;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Web;
|
||||||
using API.MangaDownloadClients;
|
using API.MangaDownloadClients;
|
||||||
using API.Schema.MangaContext;
|
using API.Schema.MangaContext;
|
||||||
using HtmlAgilityPack;
|
using HtmlAgilityPack;
|
||||||
@@ -27,23 +28,20 @@ public class MangaPark : MangaConnector
|
|||||||
private (Manga, MangaConnectorId<Manga>)[]? SearchMangaWithDomain(string mangaSearchName, string domain)
|
private (Manga, MangaConnectorId<Manga>)[]? SearchMangaWithDomain(string mangaSearchName, string domain)
|
||||||
{
|
{
|
||||||
Uri baseUri = new($"https://{domain}/");
|
Uri baseUri = new($"https://{domain}/");
|
||||||
Uri search = new(baseUri, $"search?word={mangaSearchName}&lang={Tranga.Settings.DownloadLanguage}");
|
|
||||||
|
|
||||||
HtmlDocument document = new();
|
|
||||||
List<(Manga, MangaConnectorId<Manga>)> ret = [];
|
List<(Manga, MangaConnectorId<Manga>)> ret = [];
|
||||||
|
|
||||||
for (int page = 1;; page++) // break; in loop
|
for (int page = 1;; page++) // break; in loop
|
||||||
{
|
{
|
||||||
Uri pageSearch = new(search, $"&page={page}");
|
Uri searchUri = new(baseUri, $"search?word={HttpUtility.UrlEncode(mangaSearchName)}&lang={Tranga.Settings.DownloadLanguage}&page={page}");
|
||||||
if (downloadClient.MakeRequest(pageSearch.ToString(), RequestType.Default) is { statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
if (downloadClient.MakeRequest(searchUri.ToString(), RequestType.Default) is { statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
||||||
{
|
{
|
||||||
document.Load(result.result);
|
HtmlDocument document= result.CreateDocument();
|
||||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract HAP sucks with nullable types
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract HAP sucks with nullable types
|
||||||
if (document.DocumentNode.SelectSingleNode("//button[contains(text(),\"No Data\")]") is not null) // No results found
|
if (document.DocumentNode.SelectSingleNode("//button[contains(text(),\"No Data\")]") is not null) // No results found
|
||||||
break;
|
break;
|
||||||
|
|
||||||
HtmlNode resultsListNode = document.GetNodeWith("jp_1");
|
ret.AddRange(document.GetNodesWith("q4_9").Select(n => ParseSingleMangaFromSearchResultsList(baseUri, n)));
|
||||||
ret.AddRange(resultsListNode.ChildNodes.Select(n => ParseSingleMangaFromSearchResultsList(baseUri, n)));
|
|
||||||
}else
|
}else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -78,16 +76,23 @@ public class MangaPark : MangaConnector
|
|||||||
if (downloadClient.MakeRequest(url, RequestType.Default) is
|
if (downloadClient.MakeRequest(url, RequestType.Default) is
|
||||||
{ statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
{ statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
||||||
{
|
{
|
||||||
HtmlDocument document = new();
|
HtmlDocument document= result.CreateDocument();
|
||||||
document.Load(result.result);
|
|
||||||
|
|
||||||
string name = document.GetNodeWith("2x", "q:id").InnerText;
|
if (document.GetNodeWith("q1_1")?.GetAttributeValue("title", string.Empty) is not { Length: >0 } name)
|
||||||
string description = document.GetNodeWith("0a_9").InnerText;
|
{
|
||||||
|
Log.Error("Name not found.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string description = document.GetNodeWith("0a_9")?.InnerText ?? string.Empty;
|
||||||
|
|
||||||
string coverRelative = document.GetNodeWith("q1_1").GetAttributeValue("src", "");
|
if (document.GetNodeWith("q1_1")?.GetAttributeValue("src", string.Empty) is not { Length: >0 } coverRelative)
|
||||||
string coverUrl = $"{url.Substring(0, url.IndexOf('/', 9))}{coverRelative}";
|
{
|
||||||
|
Log.Error("Cover not found.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string coverUrl = $"{url[..url.IndexOf('/', 9)]}{coverRelative}";
|
||||||
|
|
||||||
MangaReleaseStatus releaseStatus = document.GetNodeWith("Yn_5").InnerText.ToLower() switch
|
MangaReleaseStatus releaseStatus = document.GetNodeWith("Yn_5")?.InnerText.ToLower() switch
|
||||||
{
|
{
|
||||||
"pending" => MangaReleaseStatus.Unreleased,
|
"pending" => MangaReleaseStatus.Unreleased,
|
||||||
"ongoing" => MangaReleaseStatus.Continuing,
|
"ongoing" => MangaReleaseStatus.Continuing,
|
||||||
@@ -97,21 +102,24 @@ public class MangaPark : MangaConnector
|
|||||||
_ => MangaReleaseStatus.Unreleased
|
_ => MangaReleaseStatus.Unreleased
|
||||||
};
|
};
|
||||||
|
|
||||||
ICollection<Author> authors = document.GetNodeWith("tz_4")
|
ICollection<Author> authors = document.GetNodeWith("tz_4")?
|
||||||
.ChildNodes.Where(n => n.Name == "a")
|
.ChildNodes.Where(n => n.Name == "a")
|
||||||
.Select(n => n.InnerText)
|
.Select(n => n.InnerText)
|
||||||
.Select(t => new Author(t)).ToList();
|
.Select(t => new Author(t))
|
||||||
|
.ToList()??[];
|
||||||
|
|
||||||
ICollection<MangaTag> mangaTags = document.GetNodesWith("kd_0")
|
ICollection<MangaTag> mangaTags = document.GetNodesWith("kd_0")?
|
||||||
.Select(n => n.InnerText)
|
.Select(n => n.InnerText)
|
||||||
.Select(t => new MangaTag(t)).ToList();
|
.Select(t => new MangaTag(t))
|
||||||
|
.ToList()??[];
|
||||||
|
|
||||||
ICollection<Link> links = [];
|
ICollection<Link> links = [];
|
||||||
|
|
||||||
ICollection<AltTitle> altTitles = document.GetNodeWith("tz_2")
|
ICollection<AltTitle> altTitles = document.GetNodeWith("tz_2")?
|
||||||
.ChildNodes.Where(n => n.InnerText.Length > 1)
|
.ChildNodes.Where(n => n.InnerText.Length > 1)
|
||||||
.Select(n => n.InnerText)
|
.Select(n => n.InnerText)
|
||||||
.Select(t => new AltTitle(string.Empty, t)).ToList();
|
.Select(t => new AltTitle(string.Empty, t))
|
||||||
|
.ToList()??[];
|
||||||
|
|
||||||
Manga m = new (name, description, coverUrl, releaseStatus, authors, mangaTags, links, altTitles);
|
Manga m = new (name, description, coverUrl, releaseStatus, authors, mangaTags, links, altTitles);
|
||||||
MangaConnectorId<Manga> mcId = new(m, this, url.Split('/').Last(), url);
|
MangaConnectorId<Manga> mcId = new(m, this, url.Split('/').Last(), url);
|
||||||
@@ -136,8 +144,7 @@ public class MangaPark : MangaConnector
|
|||||||
if (downloadClient.MakeRequest(requestUri.ToString(), RequestType.Default) is
|
if (downloadClient.MakeRequest(requestUri.ToString(), RequestType.Default) is
|
||||||
{ statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
{ statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
||||||
{
|
{
|
||||||
HtmlDocument document = new();
|
HtmlDocument document= result.CreateDocument();
|
||||||
document.Load(result.result);
|
|
||||||
|
|
||||||
HtmlNodeCollection chapterNodes = document.GetNodesWith("8t_8");
|
HtmlNodeCollection chapterNodes = document.GetNodesWith("8t_8");
|
||||||
|
|
||||||
@@ -189,8 +196,7 @@ public class MangaPark : MangaConnector
|
|||||||
if (downloadClient.MakeRequest(requestUri.ToString(), RequestType.Default) is
|
if (downloadClient.MakeRequest(requestUri.ToString(), RequestType.Default) is
|
||||||
{ statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
{ statusCode: >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous } result)
|
||||||
{
|
{
|
||||||
HtmlDocument document = new();
|
HtmlDocument document= result.CreateDocument();
|
||||||
document.Load(result.result);
|
|
||||||
|
|
||||||
HtmlNodeCollection imageNodes = document.GetNodesWith("8X_2");
|
HtmlNodeCollection imageNodes = document.GetNodesWith("8X_2");
|
||||||
|
|
||||||
@@ -200,8 +206,20 @@ public class MangaPark : MangaConnector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class Helper
|
internal static class MangaParkHelper
|
||||||
{
|
{
|
||||||
internal static HtmlNode GetNodeWith(this HtmlDocument document, string search, string selector = "q:key") => document.DocumentNode.SelectSingleNode($"//*[@${selector}=${search}]");
|
internal static HtmlDocument CreateDocument(this RequestResult result)
|
||||||
internal static HtmlNodeCollection GetNodesWith(this HtmlDocument document, string search, string selector = "q:key") => document.DocumentNode.SelectNodes($"//*[@${selector}=${search}]");
|
{
|
||||||
|
HtmlDocument document = new();
|
||||||
|
StreamReader sr = new (result.result);
|
||||||
|
string htmlStr = sr.ReadToEnd().Replace("q:key", "qkey");
|
||||||
|
document.LoadHtml(htmlStr);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static HtmlNode? GetNodeWith(this HtmlDocument document, string search) => document.DocumentNode.SelectSingleNode("/html").GetNodeWith(search);
|
||||||
|
internal static HtmlNode? GetNodeWith(this HtmlNode node, string search) => node.SelectNodes($"{node.XPath}//*[@qkey='{search}']").FirstOrDefault();
|
||||||
|
internal static HtmlNodeCollection GetNodesWith(this HtmlDocument document, string search) => document.DocumentNode.SelectSingleNode("/html ").GetNodesWith(search);
|
||||||
|
internal static HtmlNodeCollection GetNodesWith(this HtmlNode node, string search) => node.SelectNodes($"{node.XPath}//*[@qkey='{search}']");
|
||||||
}
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Web;
|
||||||
using API.MangaDownloadClients;
|
using API.MangaDownloadClients;
|
||||||
using API.Schema.MangaContext;
|
using API.Schema.MangaContext;
|
||||||
using HtmlAgilityPack;
|
using HtmlAgilityPack;
|
||||||
@@ -27,7 +28,7 @@ public sealed class Mangaworld : MangaConnector
|
|||||||
public override (Manga, MangaConnectorId<Manga>)[] SearchManga(string mangaSearchName)
|
public override (Manga, MangaConnectorId<Manga>)[] SearchManga(string mangaSearchName)
|
||||||
{
|
{
|
||||||
Uri baseUri = new ("https://www.mangaworld.cx/");
|
Uri baseUri = new ("https://www.mangaworld.cx/");
|
||||||
Uri searchUrl = new (baseUri, "archive?keyword=" + Uri.EscapeDataString(mangaSearchName));
|
Uri searchUrl = new (baseUri, "archive?keyword=" + HttpUtility.UrlEncode(mangaSearchName));
|
||||||
|
|
||||||
RequestResult res = downloadClient.MakeRequest(searchUrl.ToString(), RequestType.Default);
|
RequestResult res = downloadClient.MakeRequest(searchUrl.ToString(), RequestType.Default);
|
||||||
if ((int)res.statusCode < 200 || (int)res.statusCode >= 300)
|
if ((int)res.statusCode < 200 || (int)res.statusCode >= 300)
|
||||||
|
Reference in New Issue
Block a user