Files

128 lines
3.6 KiB
C#

using HtmlAgilityPack;
using MangaReader.Core.Http;
using MangaReader.Core.Metadata;
namespace MangaReader.Core.Sources.NatoManga.Metadata;
public class NatoMangaWebCrawler(IHtmlLoader htmlLoader) : MangaWebCrawler
{
public override string SourceId => "NatoManga";
public override async Task<SourceManga?> GetMangaAsync(string url, CancellationToken cancellationToken)
{
HtmlDocument document = await htmlLoader.GetHtmlDocumentAsync(url, cancellationToken);
NatoMangaHtmlDocument node = new(document);
SourceManga manga = new()
{
Title = new()
{
Name = node.TitleNode?.InnerText ?? string.Empty,
Language = Common.Language.Unknown
},
Genres = GetGenres(node.GenresNode),
Chapters = GetChapters(node.ChapterNodes)
};
return manga;
}
private static string[] GetGenres(HtmlNode? node)
{
if (node == null)
return [];
HtmlNodeCollection? genreNodes = node.SelectNodes(".//a");
if (genreNodes == null)
return [];
return [.. genreNodes.Select(genreNode => genreNode.InnerText.Trim())];
}
private static long GetViews(HtmlNode node)
{
string text = node.InnerText.Trim();
if (int.TryParse(text, out int number))
return number;
if (double.TryParse(text, out double doubleNumber))
return (int)doubleNumber;
ReadOnlySpan<char> shortText = text.AsSpan(0, text.Length - 1);
if (double.TryParse(shortText, out double formattedNumber) == false)
return 0;
char suffix = text[^1];
//if (char.GetNumericValue(suffix) > -1)
// return (int)formattedNumber;
long multiplier = GetMultiplier(suffix);
return (int)(formattedNumber * multiplier);
}
private static long GetMultiplier(char c)
{
return c switch
{
'K' => 1_000,
'M' => 1_000_000,
'B' => 1_000_000_000,
'T' => 1_000_000_000_000,
_ => 0,
};
}
private static SourceMangaChapter[] GetChapters(HtmlNodeCollection? chapterNodes)
{
if (chapterNodes == null)
return [];
List<SourceMangaChapter> chapters = [];
foreach (var node in chapterNodes)
{
HtmlNodeCollection? chapterPropertyNodes = node.SelectNodes(".//span");
if (chapterPropertyNodes == null || chapterPropertyNodes.Count < 3)
continue;
HtmlNode? chapterNameNode = chapterPropertyNodes[0].SelectSingleNode(".//a");
HtmlNode chapterViewNode = chapterPropertyNodes[1];
HtmlNode chapterTimeNode = chapterPropertyNodes[2];
if (chapterNameNode == null)
continue;
SourceMangaChapter chapter = new()
{
Number = GetChapterNumber(chapterNameNode),
Title = chapterNameNode.InnerText,
Url = chapterNameNode.Attributes["href"].Value,
Views = GetViews(chapterViewNode),
UploadDate = DateTime.Parse(chapterTimeNode.Attributes["title"].Value)
};
chapters.Add(chapter);
}
return [.. chapters];
}
private static float GetChapterNumber(HtmlNode chapterNameNode)
{
string url = chapterNameNode.Attributes["href"].Value;
int index = url.IndexOf("/chapter-");
if (index == -1)
return 0;
string chapterNumber = url[(index + "/chapter-".Length)..].Replace('-', '.');
return float.Parse(chapterNumber);
}
}