Compare commits

...

4 Commits

Author SHA1 Message Date
32fd75bdae Add Manga to cached on parsing 2023-09-02 22:12:49 +02:00
99ad702163 Fixed MangaDex GetMangaFromUrl Regex-Group and resultobject 2023-09-02 22:12:34 +02:00
6e3a9c2a78 Added Lock to MemoryLogger 2023-09-02 21:53:09 +02:00
ad1d4dfe23 Fixed naming errors containing Manga
Added GetMangaFromUrl(url) to Mangaconnector
2023-09-02 21:52:48 +02:00
7 changed files with 211 additions and 145 deletions

View File

@ -6,6 +6,7 @@ public class MemoryLogger : LoggerBase
{ {
private readonly SortedList<DateTime, LogMessage> _logMessages = new(); private readonly SortedList<DateTime, LogMessage> _logMessages = new();
private int _lastLogMessageIndex = 0; private int _lastLogMessageIndex = 0;
private bool _lockLogMessages = false;
public MemoryLogger(Encoding? encoding = null) : base(encoding) public MemoryLogger(Encoding? encoding = null) : base(encoding)
{ {
@ -14,8 +15,13 @@ public class MemoryLogger : LoggerBase
protected override void Write(LogMessage value) protected override void Write(LogMessage value)
{ {
while(!_logMessages.TryAdd(DateTime.Now, value)) if (!_lockLogMessages)
Thread.Sleep(10); {
_lockLogMessages = true;
while(!_logMessages.TryAdd(DateTime.Now, value))
Thread.Sleep(10);
_lockLogMessages = false;
}
} }
public string[] GetLogMessage() public string[] GetLogMessage()
@ -35,7 +41,12 @@ public class MemoryLogger : LoggerBase
for (int retIndex = 0; retIndex < ret.Length; retIndex++) for (int retIndex = 0; retIndex < ret.Length; retIndex++)
{ {
ret[retIndex] = _logMessages.GetValueAtIndex(_logMessages.Count - retLength + retIndex).ToString(); if (!_lockLogMessages)
{
_lockLogMessages = true;
ret[retIndex] = _logMessages.GetValueAtIndex(_logMessages.Count - retLength + retIndex).ToString();
_lockLogMessages = false;
}
} }
_lastLogMessageIndex = _logMessages.Count - 1; _lastLogMessageIndex = _logMessages.Count - 1;
@ -52,7 +63,12 @@ public class MemoryLogger : LoggerBase
{ {
try try
{ {
ret.Add(_logMessages.GetValueAtIndex(_lastLogMessageIndex + retIndex).ToString()); if (!_lockLogMessages)
{
_lockLogMessages = true;
ret.Add(_logMessages.GetValueAtIndex(_lastLogMessageIndex + retIndex).ToString());
_lockLogMessages = false;
}
} }
catch (NullReferenceException e)//Called when LogMessage has not finished writing catch (NullReferenceException e)//Called when LogMessage has not finished writing
{ {

View File

@ -29,7 +29,9 @@ public abstract class MangaConnector : GlobalBase
/// </summary> /// </summary>
/// <param name="publicationTitle">Search-Query</param> /// <param name="publicationTitle">Search-Query</param>
/// <returns>Publications matching the query</returns> /// <returns>Publications matching the query</returns>
public abstract Manga[] GetPublications(string publicationTitle = ""); public abstract Manga[] GetManga(string publicationTitle = "");
public abstract Manga? GetMangaFromUrl(string url);
/// <summary> /// <summary>
/// Returns all Chapters of the publication in the provided language. /// Returns all Chapters of the publication in the provided language.

View File

@ -1,8 +1,9 @@
using System.Globalization; using System.Globalization;
using System.Net; using System.Net;
using System.Text.Json;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using Tranga.Jobs; using Tranga.Jobs;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace Tranga.MangaConnectors; namespace Tranga.MangaConnectors;
public class MangaDex : MangaConnector public class MangaDex : MangaConnector
@ -31,13 +32,13 @@ public class MangaDex : MangaConnector
}); });
} }
public override Manga[] GetPublications(string publicationTitle = "") public override Manga[] GetManga(string publicationTitle = "")
{ {
Log($"Searching Publications. Term=\"{publicationTitle}\""); Log($"Searching Publications. Term=\"{publicationTitle}\"");
const int limit = 100; //How many values we want returned at once const int limit = 100; //How many values we want returned at once
int offset = 0; //"Page" int offset = 0; //"Page"
int total = int.MaxValue; //How many total results are there, is updated on first request int total = int.MaxValue; //How many total results are there, is updated on first request
HashSet<Manga> publications = new(); HashSet<Manga> retManga = new();
int loadedPublicationData = 0; int loadedPublicationData = 0;
while (offset < total) //As long as we haven't requested all "Pages" while (offset < total) //As long as we haven't requested all "Pages"
{ {
@ -57,98 +58,118 @@ public class MangaDex : MangaConnector
JsonArray mangaInResult = result["data"]!.AsArray(); //Manga-data-Array JsonArray mangaInResult = result["data"]!.AsArray(); //Manga-data-Array
//Loop each Manga and extract information from JSON //Loop each Manga and extract information from JSON
foreach (JsonNode? mangeNode in mangaInResult) foreach (JsonNode? mangaNode in mangaInResult)
{ {
Log($"Getting publication data. {++loadedPublicationData}/{total}"); Log($"Getting publication data. {++loadedPublicationData}/{total}");
JsonObject manga = (JsonObject)mangeNode!; Manga manga = MangaFromJsonObject((JsonObject)mangaNode);
JsonObject attributes = manga["attributes"]!.AsObject(); retManga.Add(manga); //Add Publication (Manga) to result
}
}
Log($"Retrieved {retManga.Count} publications. Term=\"{publicationTitle}\"");
return retManga.ToArray();
}
public override Manga? GetMangaFromUrl(string url)
{
Regex idRex = new (@"https:\/\/mangadex.org\/title\/([A-z0-9-]*)\/.*");
string id = idRex.Match(url).Groups[1].Value;
Log($"Got id {id} from {url}");
DownloadClient.RequestResult requestResult =
downloadClient.MakeRequest($"https://api.mangadex.org/manga/{id}", (byte)RequestType.Manga);
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
return null;
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
if(result is not null)
return MangaFromJsonObject(result["data"]!.AsObject());
return null;
}
private Manga MangaFromJsonObject(JsonObject manga)
{
JsonObject attributes = manga["attributes"]!.AsObject();
string publicationId = manga["id"]!.GetValue<string>(); string publicationId = manga["id"]!.GetValue<string>();
string title = attributes["title"]!.AsObject().ContainsKey("en") && attributes["title"]!["en"] is not null string title = attributes["title"]!.AsObject().ContainsKey("en") && attributes["title"]!["en"] is not null
? attributes["title"]!["en"]!.GetValue<string>() ? attributes["title"]!["en"]!.GetValue<string>()
: attributes["title"]![((IDictionary<string, JsonNode?>)attributes["title"]!.AsObject()).Keys.First()]!.GetValue<string>(); : attributes["title"]![((IDictionary<string, JsonNode?>)attributes["title"]!.AsObject()).Keys.First()]!.GetValue<string>();
string? description = attributes["description"]!.AsObject().ContainsKey("en") && attributes["description"]!["en"] is not null string? description = attributes["description"]!.AsObject().ContainsKey("en") && attributes["description"]!["en"] is not null
? attributes["description"]!["en"]!.GetValue<string?>() ? attributes["description"]!["en"]!.GetValue<string?>()
: null; : null;
JsonArray altTitlesObject = attributes["altTitles"]!.AsArray(); JsonArray altTitlesObject = attributes["altTitles"]!.AsArray();
Dictionary<string, string> altTitlesDict = new(); Dictionary<string, string> altTitlesDict = new();
foreach (JsonNode? altTitleNode in altTitlesObject) foreach (JsonNode? altTitleNode in altTitlesObject)
{ {
JsonObject altTitleObject = (JsonObject)altTitleNode!; JsonObject altTitleObject = (JsonObject)altTitleNode!;
string key = ((IDictionary<string, JsonNode?>)altTitleObject).Keys.ToArray()[0]; string key = ((IDictionary<string, JsonNode?>)altTitleObject).Keys.ToArray()[0];
altTitlesDict.TryAdd(key, altTitleObject[key]!.GetValue<string>()); altTitlesDict.TryAdd(key, altTitleObject[key]!.GetValue<string>());
} }
JsonArray tagsObject = attributes["tags"]!.AsArray(); JsonArray tagsObject = attributes["tags"]!.AsArray();
HashSet<string> tags = new(); HashSet<string> tags = new();
foreach (JsonNode? tagNode in tagsObject) foreach (JsonNode? tagNode in tagsObject)
{ {
JsonObject tagObject = (JsonObject)tagNode!; JsonObject tagObject = (JsonObject)tagNode!;
if(tagObject["attributes"]!["name"]!.AsObject().ContainsKey("en")) if(tagObject["attributes"]!["name"]!.AsObject().ContainsKey("en"))
tags.Add(tagObject["attributes"]!["name"]!["en"]!.GetValue<string>()); tags.Add(tagObject["attributes"]!["name"]!["en"]!.GetValue<string>());
} }
string? posterId = null; string? posterId = null;
HashSet<string> authorIds = new(); HashSet<string> authorIds = new();
if (manga.ContainsKey("relationships") && manga["relationships"] is not null) if (manga.ContainsKey("relationships") && manga["relationships"] is not null)
{ {
JsonArray relationships = manga["relationships"]!.AsArray(); JsonArray relationships = manga["relationships"]!.AsArray();
posterId = relationships.FirstOrDefault(relationship => relationship!["type"]!.GetValue<string>() == "cover_art")!["id"]!.GetValue<string>(); posterId = relationships.FirstOrDefault(relationship => relationship!["type"]!.GetValue<string>() == "cover_art")!["id"]!.GetValue<string>();
foreach (JsonNode? node in relationships.Where(relationship => foreach (JsonNode? node in relationships.Where(relationship =>
relationship!["type"]!.GetValue<string>() == "author")) relationship!["type"]!.GetValue<string>() == "author"))
authorIds.Add(node!["id"]!.GetValue<string>()); authorIds.Add(node!["id"]!.GetValue<string>());
} }
string? coverUrl = GetCoverUrl(publicationId, posterId); string? coverUrl = GetCoverUrl(publicationId, posterId);
string? coverCacheName = null; string? coverCacheName = null;
if (coverUrl is not null) if (coverUrl is not null)
coverCacheName = SaveCoverImageToCache(coverUrl, (byte)RequestType.AtHomeServer); coverCacheName = SaveCoverImageToCache(coverUrl, (byte)RequestType.AtHomeServer);
List<string> authors = GetAuthors(authorIds); List<string> authors = GetAuthors(authorIds);
Dictionary<string, string> linksDict = new(); Dictionary<string, string> linksDict = new();
if (attributes.ContainsKey("links") && attributes["links"] is not null) if (attributes.ContainsKey("links") && attributes["links"] is not null)
{ {
JsonObject linksObject = attributes["links"]!.AsObject(); JsonObject linksObject = attributes["links"]!.AsObject();
foreach (string key in ((IDictionary<string, JsonNode?>)linksObject).Keys) foreach (string key in ((IDictionary<string, JsonNode?>)linksObject).Keys)
{ {
linksDict.Add(key, linksObject[key]!.GetValue<string>()); linksDict.Add(key, linksObject[key]!.GetValue<string>());
}
}
int? year = attributes.ContainsKey("year") && attributes["year"] is not null
? attributes["year"]!.GetValue<int?>()
: null;
string? originalLanguage = attributes.ContainsKey("originalLanguage") && attributes["originalLanguage"] is not null
? attributes["originalLanguage"]!.GetValue<string?>()
: null;
string status = attributes["status"]!.GetValue<string>();
Manga pub = new (
title,
authors,
description,
altTitlesDict,
tags.ToArray(),
coverUrl,
coverCacheName,
linksDict,
year,
originalLanguage,
status,
publicationId
);
publications.Add(pub); //Add Publication (Manga) to result
} }
} }
cachedPublications.AddRange(publications); int? year = attributes.ContainsKey("year") && attributes["year"] is not null
Log($"Retrieved {publications.Count} publications. Term=\"{publicationTitle}\""); ? attributes["year"]!.GetValue<int?>()
return publications.ToArray(); : null;
string? originalLanguage =
attributes.ContainsKey("originalLanguage") && attributes["originalLanguage"] is not null
? attributes["originalLanguage"]!.GetValue<string?>()
: null;
string status = attributes["status"]!.GetValue<string>();
Manga pub = new(
title,
authors,
description,
altTitlesDict,
tags.ToArray(),
coverUrl,
coverCacheName,
linksDict,
year,
originalLanguage,
status,
publicationId
);
cachedPublications.Add(pub);
return pub;
} }
public override Chapter[] GetChapters(Manga manga, string language="en") public override Chapter[] GetChapters(Manga manga, string language="en")

View File

@ -19,7 +19,7 @@ public class MangaKatana : MangaConnector
}); });
} }
public override Manga[] GetPublications(string publicationTitle = "") public override Manga[] GetManga(string publicationTitle = "")
{ {
Log($"Searching Publications. Term=\"{publicationTitle}\""); Log($"Searching Publications. Term=\"{publicationTitle}\"");
string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*").Where(m => m.Value.Length > 0)).ToLower(); string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*").Where(m => m.Value.Length > 0)).ToLower();
@ -39,11 +39,19 @@ public class MangaKatana : MangaConnector
} }
Manga[] publications = ParsePublicationsFromHtml(requestResult.result); Manga[] publications = ParsePublicationsFromHtml(requestResult.result);
cachedPublications.AddRange(publications);
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\""); Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
return publications; return publications;
} }
public override Manga? GetMangaFromUrl(string url)
{
DownloadClient.RequestResult requestResult =
downloadClient.MakeRequest(url, 1);
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
return null;
return ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]);
}
private Manga[] ParsePublicationsFromHtml(Stream html) private Manga[] ParsePublicationsFromHtml(Stream html)
{ {
StreamReader reader = new(html); StreamReader reader = new(html);
@ -63,12 +71,9 @@ public class MangaKatana : MangaConnector
HashSet<Manga> ret = new(); HashSet<Manga> ret = new();
foreach (string url in urls) foreach (string url in urls)
{ {
DownloadClient.RequestResult requestResult = Manga? manga = GetMangaFromUrl(url);
downloadClient.MakeRequest(url, 1); if (manga is not null)
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) ret.Add((Manga)manga);
return Array.Empty<Manga>();
ret.Add(ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]));
} }
return ret.ToArray(); return ret.ToArray();
@ -134,8 +139,10 @@ public class MangaKatana : MangaConnector
year = Convert.ToInt32(yearString); year = Convert.ToInt32(yearString);
} }
return new Manga(sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, coverFileNameInCache, links, Manga manga = new (sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, coverFileNameInCache, links,
year, originalLanguage, status, publicationId); year, originalLanguage, status, publicationId);
cachedPublications.Add(manga);
return manga;
} }
public override Chapter[] GetChapters(Manga manga, string language="en") public override Chapter[] GetChapters(Manga manga, string language="en")

View File

@ -19,7 +19,7 @@ public class Manganato : MangaConnector
}); });
} }
public override Manga[] GetPublications(string publicationTitle = "") public override Manga[] GetManga(string publicationTitle = "")
{ {
Log($"Searching Publications. Term=\"{publicationTitle}\""); Log($"Searching Publications. Term=\"{publicationTitle}\"");
string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*")).ToLower(); string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*")).ToLower();
@ -30,7 +30,6 @@ public class Manganato : MangaConnector
return Array.Empty<Manga>(); return Array.Empty<Manga>();
Manga[] publications = ParsePublicationsFromHtml(requestResult.result); Manga[] publications = ParsePublicationsFromHtml(requestResult.result);
cachedPublications.AddRange(publications);
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\""); Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
return publications; return publications;
} }
@ -52,17 +51,24 @@ public class Manganato : MangaConnector
HashSet<Manga> ret = new(); HashSet<Manga> ret = new();
foreach (string url in urls) foreach (string url in urls)
{ {
DownloadClient.RequestResult requestResult = Manga? manga = GetMangaFromUrl(url);
downloadClient.MakeRequest(url, 1); if (manga is not null)
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) ret.Add((Manga)manga);
return Array.Empty<Manga>();
ret.Add(ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]));
} }
return ret.ToArray(); return ret.ToArray();
} }
public override Manga? GetMangaFromUrl(string url)
{
DownloadClient.RequestResult requestResult =
downloadClient.MakeRequest(url, 1);
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
return null;
return ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]);
}
private Manga ParseSinglePublicationFromHtml(Stream html, string publicationId) private Manga ParseSinglePublicationFromHtml(Stream html, string publicationId)
{ {
StreamReader reader = new (html); StreamReader reader = new (html);
@ -122,8 +128,10 @@ public class Manganato : MangaConnector
.First(s => s.HasClass("chapter-time")).InnerText; .First(s => s.HasClass("chapter-time")).InnerText;
int year = Convert.ToInt32(yearString.Split(',')[^1]) + 2000; int year = Convert.ToInt32(yearString.Split(',')[^1]) + 2000;
return new Manga(sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, coverFileNameInCache, links, Manga manga = new (sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, coverFileNameInCache, links,
year, originalLanguage, status, publicationId); year, originalLanguage, status, publicationId);
cachedPublications.Add(manga);
return manga;
} }
public override Chapter[] GetChapters(Manga manga, string language="en") public override Chapter[] GetChapters(Manga manga, string language="en")

View File

@ -69,7 +69,7 @@ public class Mangasee : MangaConnector
}); });
} }
public override Manga[] GetPublications(string publicationTitle = "") public override Manga[] GetManga(string publicationTitle = "")
{ {
Log($"Searching Publications. Term=\"{publicationTitle}\""); Log($"Searching Publications. Term=\"{publicationTitle}\"");
string requestUrl = $"https://mangasee123.com/_search.php"; string requestUrl = $"https://mangasee123.com/_search.php";
@ -79,11 +79,32 @@ public class Mangasee : MangaConnector
return Array.Empty<Manga>(); return Array.Empty<Manga>();
Manga[] publications = ParsePublicationsFromHtml(requestResult.result, publicationTitle); Manga[] publications = ParsePublicationsFromHtml(requestResult.result, publicationTitle);
cachedPublications.AddRange(publications);
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\""); Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
return publications; return publications;
} }
public override Manga? GetMangaFromUrl(string url)
{
while (this._browser is null)
{
Log("Waiting for headless browser to download...");
Thread.Sleep(1000);
}
IPage page = _browser!.NewPageAsync().Result;
IResponse response = page.GoToAsync(url, WaitUntilNavigation.DOMContentLoaded).Result;
if (response.Ok)
{
HtmlDocument document = new();
document.LoadHtml(page.GetContentAsync().Result);
page.CloseAsync();
return ParseSinglePublicationFromHtml(document);
}
return null;
}
private Manga[] ParsePublicationsFromHtml(Stream html, string publicationTitle) private Manga[] ParsePublicationsFromHtml(Stream html, string publicationTitle)
{ {
string jsonString = new StreamReader(html).ReadToEnd(); string jsonString = new StreamReader(html).ReadToEnd();
@ -105,74 +126,54 @@ public class Mangasee : MangaConnector
List<SearchResultItem> orderedFiltered = List<SearchResultItem> orderedFiltered =
queryFiltered.OrderBy(item => item.Value).ToDictionary(item => item.Key, item => item.Value).Keys.ToList(); queryFiltered.OrderBy(item => item.Value).ToDictionary(item => item.Key, item => item.Value).Keys.ToList();
uint index = 1;
foreach (SearchResultItem orderedItem in orderedFiltered) foreach (SearchResultItem orderedItem in orderedFiltered)
{ {
DownloadClient.RequestResult requestResult = Manga? manga = GetMangaFromUrl($"https://mangasee123.com/manga/{orderedItem.i}");
downloadClient.MakeRequest($"https://mangasee123.com/manga/{orderedItem.i}", 1); if (manga is not null)
if ((int)requestResult.statusCode >= 200 || (int)requestResult.statusCode < 300) ret.Add((Manga)manga);
{
Log($"Retrieving Publication info: {orderedItem.s} {index++}/{orderedFiltered.Count}");
ret.Add(ParseSinglePublicationFromHtml(requestResult.result, orderedItem.s, orderedItem.i, orderedItem.a));
}
} }
return ret.ToArray(); return ret.ToArray();
} }
private Manga ParseSinglePublicationFromHtml(Stream html, string sortName, string publicationId, string[] a) private Manga ParseSinglePublicationFromHtml(HtmlDocument document)
{ {
StreamReader reader = new (html);
HtmlDocument document = new ();
document.LoadHtml(reader.ReadToEnd());
string originalLanguage = "", status = ""; string originalLanguage = "", status = "";
Dictionary<string, string> altTitles = new(), links = new(); Dictionary<string, string> altTitles = new(), links = new();
HashSet<string> tags = new(); HashSet<string> tags = new();
HtmlNode posterNode = HtmlNode posterNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//img");
document.DocumentNode.Descendants("img").First(img => img.HasClass("img-fluid") && img.HasClass("bottom-5"));
string posterUrl = posterNode.GetAttributeValue("src", ""); string posterUrl = posterNode.GetAttributeValue("src", "");
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1); string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1);
HtmlNode attributes = document.DocumentNode.Descendants("div") HtmlNode titleNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//h1");
.First(div => div.HasClass("col-md-9") && div.HasClass("col-sm-8") && div.HasClass("top-5")) string sortName = titleNode.InnerText;
.Descendants("ul").First(); string publicationId = sortName;
HtmlNode[] authorsNodes = attributes.Descendants("li") HtmlNode[] authorsNodes = document.DocumentNode.SelectNodes("//div[@class='BoxBody']//div[@class='row']//span[text()='Author(s):']/..").Descendants("a").ToArray();
.First(node => node.InnerText.Contains("author(s):", StringComparison.CurrentCultureIgnoreCase))
.Descendants("a").ToArray();
List<string> authors = new(); List<string> authors = new();
foreach(HtmlNode authorNode in authorsNodes) foreach(HtmlNode authorNode in authorsNodes)
authors.Add(authorNode.InnerText); authors.Add(authorNode.InnerText);
HtmlNode[] genreNodes = attributes.Descendants("li") HtmlNode[] genreNodes = document.DocumentNode.SelectNodes("//div[@class='BoxBody']//div[@class='row']//span[text()='Genre(s):']/..").Descendants("a").ToArray();
.First(node => node.InnerText.Contains("genre(s):", StringComparison.CurrentCultureIgnoreCase))
.Descendants("a").ToArray();
foreach (HtmlNode genreNode in genreNodes) foreach (HtmlNode genreNode in genreNodes)
tags.Add(genreNode.InnerText); tags.Add(genreNode.InnerText);
HtmlNode yearNode = attributes.Descendants("li") HtmlNode yearNode = document.DocumentNode.SelectNodes("//div[@class='BoxBody']//div[@class='row']//span[text()='Released:']/..").Descendants("a").First();
.First(node => node.InnerText.Contains("released:", StringComparison.CurrentCultureIgnoreCase))
.Descendants("a").First();
int year = Convert.ToInt32(yearNode.InnerText); int year = Convert.ToInt32(yearNode.InnerText);
HtmlNode[] statusNodes = attributes.Descendants("li") HtmlNode[] statusNodes = document.DocumentNode.SelectNodes("//div[@class='BoxBody']//div[@class='row']//span[text()='Status:']/..").Descendants("a").ToArray();
.First(node => node.InnerText.Contains("status:", StringComparison.CurrentCultureIgnoreCase))
.Descendants("a").ToArray();
foreach(HtmlNode statusNode in statusNodes) foreach(HtmlNode statusNode in statusNodes)
if (statusNode.InnerText.Contains("publish", StringComparison.CurrentCultureIgnoreCase)) if (statusNode.InnerText.Contains("publish", StringComparison.CurrentCultureIgnoreCase))
status = statusNode.InnerText.Split(' ')[0]; status = statusNode.InnerText.Split(' ')[0];
HtmlNode descriptionNode = attributes.Descendants("li").First(node => node.InnerText.Contains("description:", StringComparison.CurrentCultureIgnoreCase)).Descendants("div").First(); HtmlNode descriptionNode = document.DocumentNode.SelectNodes("//div[@class='BoxBody']//div[@class='row']//span[text()='Description:']/..").Descendants("div").First();
string description = descriptionNode.InnerText; string description = descriptionNode.InnerText;
int i = 0; Manga manga = new (sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, coverFileNameInCache, links,
foreach(string at in a)
altTitles.Add((i++).ToString(), at);
return new Manga(sortName, authors, description, altTitles, tags.ToArray(), posterUrl, coverFileNameInCache, links,
year, originalLanguage, status, publicationId); year, originalLanguage, status, publicationId);
cachedPublications.Add(manga);
return manga;
} }
// ReSharper disable once ClassNeverInstantiated.Local Will be instantiated during deserialization // ReSharper disable once ClassNeverInstantiated.Local Will be instantiated during deserialization

View File

@ -134,14 +134,25 @@ public class Server : GlobalBase
} }
break; break;
case "Manga/FromConnector": case "Manga/FromConnector":
requestVariables.TryGetValue("title", out string? title);
requestVariables.TryGetValue("url", out string? url);
if (!requestVariables.TryGetValue("connector", out connectorName) || if (!requestVariables.TryGetValue("connector", out connectorName) ||
!requestVariables.TryGetValue("title", out string? title) || !_parent.TryGetConnector(connectorName, out connector) ||
!_parent.TryGetConnector(connectorName, out connector)) (title is null && url is null))
{ {
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);
break; break;
} }
SendResponse(HttpStatusCode.OK, response, connector!.GetPublications(title));
if (url is not null)
{
HashSet<Manga> ret = new();
manga = connector!.GetMangaFromUrl(url);
if (manga is not null)
ret.Add((Manga)manga);
SendResponse(HttpStatusCode.OK, response, ret);
}else
SendResponse(HttpStatusCode.OK, response, connector!.GetManga(title!));
break; break;
case "Manga/Chapters": case "Manga/Chapters":
if(!requestVariables.TryGetValue("connector", out connectorName) || if(!requestVariables.TryGetValue("connector", out connectorName) ||