mirror of
https://github.com/C9Glax/tranga.git
synced 2025-01-12 19:37:33 +01:00
Renamed Publication.cs to Manga.cs
Renamed Request-Paths "Tasks" to "Jobs"
This commit is contained in:
parent
e663163de8
commit
1fd36c91d6
@ -10,7 +10,7 @@ namespace Tranga;
|
|||||||
public readonly struct Chapter
|
public readonly struct Chapter
|
||||||
{
|
{
|
||||||
// ReSharper disable once MemberCanBePrivate.Global
|
// ReSharper disable once MemberCanBePrivate.Global
|
||||||
public Publication parentPublication { get; }
|
public Manga parentManga { get; }
|
||||||
public string? name { get; }
|
public string? name { get; }
|
||||||
public string? volumeNumber { get; }
|
public string? volumeNumber { get; }
|
||||||
public string chapterNumber { get; }
|
public string chapterNumber { get; }
|
||||||
@ -20,9 +20,9 @@ public readonly struct Chapter
|
|||||||
|
|
||||||
private static readonly Regex LegalCharacters = new (@"([A-z]*[0-9]* *\.*-*,*\]*\[*'*\'*\)*\(*~*!*)*");
|
private static readonly Regex LegalCharacters = new (@"([A-z]*[0-9]* *\.*-*,*\]*\[*'*\'*\)*\(*~*!*)*");
|
||||||
private static readonly Regex IllegalStrings = new(@"Vol(ume)?.?", RegexOptions.IgnoreCase);
|
private static readonly Regex IllegalStrings = new(@"Vol(ume)?.?", RegexOptions.IgnoreCase);
|
||||||
public Chapter(Publication parentPublication, string? name, string? volumeNumber, string chapterNumber, string url)
|
public Chapter(Manga parentManga, string? name, string? volumeNumber, string chapterNumber, string url)
|
||||||
{
|
{
|
||||||
this.parentPublication = parentPublication;
|
this.parentManga = parentManga;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.volumeNumber = volumeNumber;
|
this.volumeNumber = volumeNumber;
|
||||||
this.chapterNumber = chapterNumber;
|
this.chapterNumber = chapterNumber;
|
||||||
@ -38,7 +38,7 @@ public readonly struct Chapter
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"Chapter {parentPublication.sortName} {parentPublication.internalId} {chapterNumber} {name}";
|
return $"Chapter {parentManga.sortName} {parentManga.internalId} {chapterNumber} {name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -48,9 +48,9 @@ public readonly struct Chapter
|
|||||||
internal bool CheckChapterIsDownloaded(string downloadLocation)
|
internal bool CheckChapterIsDownloaded(string downloadLocation)
|
||||||
{
|
{
|
||||||
string newFilePath = GetArchiveFilePath(downloadLocation);
|
string newFilePath = GetArchiveFilePath(downloadLocation);
|
||||||
if (!Directory.Exists(Path.Join(downloadLocation, parentPublication.folderName)))
|
if (!Directory.Exists(Path.Join(downloadLocation, parentManga.folderName)))
|
||||||
return false;
|
return false;
|
||||||
FileInfo[] archives = new DirectoryInfo(Path.Join(downloadLocation, parentPublication.folderName)).GetFiles();
|
FileInfo[] archives = new DirectoryInfo(Path.Join(downloadLocation, parentManga.folderName)).GetFiles();
|
||||||
Regex chapterInfoRex = new(@"Ch\.[0-9.]+");
|
Regex chapterInfoRex = new(@"Ch\.[0-9.]+");
|
||||||
Regex chapterRex = new(@"[0-9]+(\.[0-9]+)?");
|
Regex chapterRex = new(@"[0-9]+(\.[0-9]+)?");
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public readonly struct Chapter
|
|||||||
/// <returns>Filepath</returns>
|
/// <returns>Filepath</returns>
|
||||||
internal string GetArchiveFilePath(string downloadLocation)
|
internal string GetArchiveFilePath(string downloadLocation)
|
||||||
{
|
{
|
||||||
return Path.Join(downloadLocation, parentPublication.folderName, $"{parentPublication.folderName} - {this.fileName}.cbz");
|
return Path.Join(downloadLocation, parentManga.folderName, $"{parentManga.folderName} - {this.fileName}.cbz");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -82,10 +82,10 @@ public readonly struct Chapter
|
|||||||
internal string GetComicInfoXmlString()
|
internal string GetComicInfoXmlString()
|
||||||
{
|
{
|
||||||
XElement comicInfo = new XElement("ComicInfo",
|
XElement comicInfo = new XElement("ComicInfo",
|
||||||
new XElement("Tags", string.Join(',', parentPublication.tags)),
|
new XElement("Tags", string.Join(',', parentManga.tags)),
|
||||||
new XElement("LanguageISO", parentPublication.originalLanguage),
|
new XElement("LanguageISO", parentManga.originalLanguage),
|
||||||
new XElement("Title", this.name),
|
new XElement("Title", this.name),
|
||||||
new XElement("Writer", string.Join(',', parentPublication.authors)),
|
new XElement("Writer", string.Join(',', parentManga.authors)),
|
||||||
new XElement("Volume", this.volumeNumber),
|
new XElement("Volume", this.volumeNumber),
|
||||||
new XElement("Number", this.chapterNumber)
|
new XElement("Number", this.chapterNumber)
|
||||||
);
|
);
|
||||||
|
@ -11,7 +11,7 @@ public abstract class GlobalBase
|
|||||||
protected TrangaSettings settings { get; init; }
|
protected TrangaSettings settings { get; init; }
|
||||||
protected HashSet<NotificationConnector> notificationConnectors { get; init; }
|
protected HashSet<NotificationConnector> notificationConnectors { get; init; }
|
||||||
protected HashSet<LibraryConnector> libraryConnectors { get; init; }
|
protected HashSet<LibraryConnector> libraryConnectors { get; init; }
|
||||||
protected List<Publication> cachedPublications { get; init; }
|
protected List<Manga> cachedPublications { get; init; }
|
||||||
|
|
||||||
protected GlobalBase(GlobalBase clone)
|
protected GlobalBase(GlobalBase clone)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@ public class DownloadChapter : Job
|
|||||||
|
|
||||||
protected override string GetId()
|
protected override string GetId()
|
||||||
{
|
{
|
||||||
return Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Concat(this.GetType().ToString(), chapter.parentPublication.internalId, chapter.chapterNumber)));
|
return Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Concat(this.GetType().ToString(), chapter.parentManga.internalId, chapter.chapterNumber)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -28,7 +28,7 @@ public class DownloadChapter : Job
|
|||||||
{
|
{
|
||||||
mangaConnector.DownloadChapter(chapter, this.progressToken);
|
mangaConnector.DownloadChapter(chapter, this.progressToken);
|
||||||
UpdateLibraries();
|
UpdateLibraries();
|
||||||
SendNotifications("Chapter downloaded", $"{chapter.parentPublication.sortName} - {chapter.chapterNumber}");
|
SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}");
|
||||||
});
|
});
|
||||||
downloadTask.Start();
|
downloadTask.Start();
|
||||||
return Array.Empty<Job>();
|
return Array.Empty<Job>();
|
||||||
|
@ -5,26 +5,26 @@ namespace Tranga.Jobs;
|
|||||||
|
|
||||||
public class DownloadNewChapters : Job
|
public class DownloadNewChapters : Job
|
||||||
{
|
{
|
||||||
public Publication publication { get; init; }
|
public Manga manga { get; init; }
|
||||||
|
|
||||||
public DownloadNewChapters(GlobalBase clone, MangaConnector connector, Publication publication, bool recurring = false, TimeSpan? recurrence = null) : base (clone, connector, recurring, recurrence)
|
public DownloadNewChapters(GlobalBase clone, MangaConnector connector, Manga manga, bool recurring = false, TimeSpan? recurrence = null) : base (clone, connector, recurring, recurrence)
|
||||||
{
|
{
|
||||||
this.publication = publication;
|
this.manga = manga;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string GetId()
|
protected override string GetId()
|
||||||
{
|
{
|
||||||
return Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Concat(this.GetType().ToString(), publication.internalId)));
|
return Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Concat(this.GetType().ToString(), manga.internalId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"DownloadChapter {id} {publication}";
|
return $"DownloadChapter {id} {manga}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<Job> ExecuteReturnSubTasksInternal()
|
protected override IEnumerable<Job> ExecuteReturnSubTasksInternal()
|
||||||
{
|
{
|
||||||
Chapter[] chapters = mangaConnector.GetNewChapters(publication);
|
Chapter[] chapters = mangaConnector.GetNewChapters(manga);
|
||||||
this.progressToken.increments = chapters.Length;
|
this.progressToken.increments = chapters.Length;
|
||||||
List<Job> subJobs = new();
|
List<Job> subJobs = new();
|
||||||
foreach (Chapter chapter in chapters)
|
foreach (Chapter chapter in chapters)
|
||||||
|
@ -44,7 +44,7 @@ public class JobBoss : GlobalBase
|
|||||||
{
|
{
|
||||||
if (jjob is not DownloadChapter job)
|
if (jjob is not DownloadChapter job)
|
||||||
return false;
|
return false;
|
||||||
return job.chapter.parentPublication.internalId == internalId &&
|
return job.chapter.parentManga.internalId == internalId &&
|
||||||
job.chapter.chapterNumber == chapterNumber;
|
job.chapter.chapterNumber == chapterNumber;
|
||||||
});
|
});
|
||||||
else if (internalId is not null)
|
else if (internalId is not null)
|
||||||
@ -52,12 +52,12 @@ public class JobBoss : GlobalBase
|
|||||||
{
|
{
|
||||||
if (jjob is not DownloadNewChapters job)
|
if (jjob is not DownloadNewChapters job)
|
||||||
return false;
|
return false;
|
||||||
return job.publication.internalId == internalId;
|
return job.manga.internalId == internalId;
|
||||||
});
|
});
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Job> GetJobsLike(MangaConnector? mangaConnector = null, Publication? publication = null,
|
public IEnumerable<Job> GetJobsLike(MangaConnector? mangaConnector = null, Manga? publication = null,
|
||||||
Chapter? chapter = null)
|
Chapter? chapter = null)
|
||||||
{
|
{
|
||||||
return GetJobsLike(mangaConnector?.name, publication?.internalId, chapter?.chapterNumber);
|
return GetJobsLike(mangaConnector?.name, publication?.internalId, chapter?.chapterNumber);
|
||||||
|
@ -9,7 +9,7 @@ namespace Tranga;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains information on a Publication (Manga)
|
/// Contains information on a Publication (Manga)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct Publication
|
public struct Manga
|
||||||
{
|
{
|
||||||
public string sortName { get; }
|
public string sortName { get; }
|
||||||
public List<string> authors { get; }
|
public List<string> authors { get; }
|
||||||
@ -36,7 +36,7 @@ public struct Publication
|
|||||||
private static readonly Regex LegalCharacters = new (@"[A-Z]*[a-z]*[0-9]* *\.*-*,*'*\'*\)*\(*~*!*");
|
private static readonly Regex LegalCharacters = new (@"[A-Z]*[a-z]*[0-9]* *\.*-*,*'*\'*\)*\(*~*!*");
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public Publication(string sortName, List<string> authors, string? description, Dictionary<string,string> altTitles, string[] tags, string? coverUrl, Dictionary<string,string>? links, int? year, string? originalLanguage, string status, string publicationId, string? folderName = null, float? ignoreChaptersBelow = 0)
|
public Manga(string sortName, List<string> authors, string? description, Dictionary<string,string> altTitles, string[] tags, string? coverUrl, Dictionary<string,string>? links, int? year, string? originalLanguage, string status, string publicationId, string? folderName = null, float? ignoreChaptersBelow = 0)
|
||||||
{
|
{
|
||||||
this.sortName = sortName;
|
this.sortName = sortName;
|
||||||
this.authors = authors;
|
this.authors = authors;
|
@ -29,40 +29,40 @@ 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 Publication[] GetPublications(string publicationTitle = "");
|
public abstract Manga[] GetPublications(string publicationTitle = "");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all Chapters of the publication in the provided language.
|
/// Returns all Chapters of the publication in the provided language.
|
||||||
/// If the language is empty or null, returns all Chapters in all Languages.
|
/// If the language is empty or null, returns all Chapters in all Languages.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="publication">Publication to get Chapters for</param>
|
/// <param name="manga">Publication to get Chapters for</param>
|
||||||
/// <param name="language">Language of the Chapters</param>
|
/// <param name="language">Language of the Chapters</param>
|
||||||
/// <returns>Array of Chapters matching Publication and Language</returns>
|
/// <returns>Array of Chapters matching Publication and Language</returns>
|
||||||
public abstract Chapter[] GetChapters(Publication publication, string language="en");
|
public abstract Chapter[] GetChapters(Manga manga, string language="en");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the available Chapters of a Publication
|
/// Updates the available Chapters of a Publication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="publication">Publication to check</param>
|
/// <param name="manga">Publication to check</param>
|
||||||
/// <param name="language">Language to receive chapters for</param>
|
/// <param name="language">Language to receive chapters for</param>
|
||||||
/// <returns>List of Chapters that were previously not in collection</returns>
|
/// <returns>List of Chapters that were previously not in collection</returns>
|
||||||
public Chapter[] GetNewChapters(Publication publication, string language = "en")
|
public Chapter[] GetNewChapters(Manga manga, string language = "en")
|
||||||
{
|
{
|
||||||
Log($"Getting new Chapters for {publication}");
|
Log($"Getting new Chapters for {manga}");
|
||||||
Chapter[] newChapters = this.GetChapters(publication, language);
|
Chapter[] newChapters = this.GetChapters(manga, language);
|
||||||
NumberFormatInfo decimalPoint = new (){ NumberDecimalSeparator = "." };
|
NumberFormatInfo decimalPoint = new (){ NumberDecimalSeparator = "." };
|
||||||
Log($"Checking for duplicates {publication}");
|
Log($"Checking for duplicates {manga}");
|
||||||
List<Chapter> newChaptersList = newChapters.Where(nChapter =>
|
List<Chapter> newChaptersList = newChapters.Where(nChapter =>
|
||||||
float.Parse(nChapter.chapterNumber, decimalPoint) > publication.ignoreChaptersBelow &&
|
float.Parse(nChapter.chapterNumber, decimalPoint) > manga.ignoreChaptersBelow &&
|
||||||
!nChapter.CheckChapterIsDownloaded(settings.downloadLocation)).ToList();
|
!nChapter.CheckChapterIsDownloaded(settings.downloadLocation)).ToList();
|
||||||
Log($"{newChaptersList.Count} new chapters. {publication}");
|
Log($"{newChaptersList.Count} new chapters. {manga}");
|
||||||
|
|
||||||
return newChaptersList.ToArray();
|
return newChaptersList.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Chapter[] SelectChapters(Publication publication, string searchTerm, string? language = null)
|
public Chapter[] SelectChapters(Manga manga, string searchTerm, string? language = null)
|
||||||
{
|
{
|
||||||
Chapter[] availableChapters = this.GetChapters(publication, language??"en");
|
Chapter[] availableChapters = this.GetChapters(manga, language??"en");
|
||||||
Regex volumeRegex = new ("((v(ol)*(olume)*){1} *([0-9]+(-[0-9]+)?){1})", RegexOptions.IgnoreCase);
|
Regex volumeRegex = new ("((v(ol)*(olume)*){1} *([0-9]+(-[0-9]+)?){1})", RegexOptions.IgnoreCase);
|
||||||
Regex chapterRegex = new ("((c(h)*(hapter)*){1} *([0-9]+(-[0-9]+)?){1})", RegexOptions.IgnoreCase);
|
Regex chapterRegex = new ("((c(h)*(hapter)*){1} *([0-9]+(-[0-9]+)?){1})", RegexOptions.IgnoreCase);
|
||||||
Regex singleResultRegex = new("([0-9]+)", RegexOptions.IgnoreCase);
|
Regex singleResultRegex = new("([0-9]+)", RegexOptions.IgnoreCase);
|
||||||
@ -138,20 +138,20 @@ public abstract class MangaConnector : GlobalBase
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copies the already downloaded cover from cache to downloadLocation
|
/// Copies the already downloaded cover from cache to downloadLocation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="publication">Publication to retrieve Cover for</param>
|
/// <param name="manga">Publication to retrieve Cover for</param>
|
||||||
public void CopyCoverFromCacheToDownloadLocation(Publication publication)
|
public void CopyCoverFromCacheToDownloadLocation(Manga manga)
|
||||||
{
|
{
|
||||||
Log($"Copy cover {publication}");
|
Log($"Copy cover {manga}");
|
||||||
//Check if Publication already has a Folder and cover
|
//Check if Publication already has a Folder and cover
|
||||||
string publicationFolder = publication.CreatePublicationFolder(settings.downloadLocation);
|
string publicationFolder = manga.CreatePublicationFolder(settings.downloadLocation);
|
||||||
DirectoryInfo dirInfo = new (publicationFolder);
|
DirectoryInfo dirInfo = new (publicationFolder);
|
||||||
if (dirInfo.EnumerateFiles().Any(info => info.Name.Contains("cover", StringComparison.InvariantCultureIgnoreCase)))
|
if (dirInfo.EnumerateFiles().Any(info => info.Name.Contains("cover", StringComparison.InvariantCultureIgnoreCase)))
|
||||||
{
|
{
|
||||||
Log($"Cover exists {publication}");
|
Log($"Cover exists {manga}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string fileInCache = Path.Join(settings.coverImageCache, publication.coverFileNameInCache);
|
string fileInCache = Path.Join(settings.coverImageCache, manga.coverFileNameInCache);
|
||||||
string newFilePath = Path.Join(publicationFolder, $"cover.{Path.GetFileName(fileInCache).Split('.')[^1]}" );
|
string newFilePath = Path.Join(publicationFolder, $"cover.{Path.GetFileName(fileInCache).Split('.')[^1]}" );
|
||||||
Log($"Cloning cover {fileInCache} -> {newFilePath}");
|
Log($"Cloning cover {fileInCache} -> {newFilePath}");
|
||||||
File.Copy(fileInCache, newFilePath, true);
|
File.Copy(fileInCache, newFilePath, true);
|
||||||
|
@ -31,13 +31,13 @@ public class MangaDex : MangaConnector
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Publication[] GetPublications(string publicationTitle = "")
|
public override Manga[] GetPublications(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<Publication> publications = new();
|
HashSet<Manga> publications = 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"
|
||||||
{
|
{
|
||||||
@ -125,7 +125,7 @@ public class MangaDex : MangaConnector
|
|||||||
|
|
||||||
string status = attributes["status"]!.GetValue<string>();
|
string status = attributes["status"]!.GetValue<string>();
|
||||||
|
|
||||||
Publication pub = new (
|
Manga pub = new (
|
||||||
title,
|
title,
|
||||||
authors,
|
authors,
|
||||||
description,
|
description,
|
||||||
@ -147,9 +147,9 @@ public class MangaDex : MangaConnector
|
|||||||
return publications.ToArray();
|
return publications.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Chapter[] GetChapters(Publication publication, string language="en")
|
public override Chapter[] GetChapters(Manga manga, string language="en")
|
||||||
{
|
{
|
||||||
Log($"Getting chapters {publication}");
|
Log($"Getting chapters {manga}");
|
||||||
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
|
||||||
@ -160,7 +160,7 @@ public class MangaDex : MangaConnector
|
|||||||
//Request next "Page"
|
//Request next "Page"
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(
|
downloadClient.MakeRequest(
|
||||||
$"https://api.mangadex.org/manga/{publication.publicationId}/feed?limit={limit}&offset={offset}&translatedLanguage%5B%5D={language}", (byte)RequestType.Feed);
|
$"https://api.mangadex.org/manga/{manga.publicationId}/feed?limit={limit}&offset={offset}&translatedLanguage%5B%5D={language}", (byte)RequestType.Feed);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
break;
|
break;
|
||||||
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
||||||
@ -191,13 +191,13 @@ public class MangaDex : MangaConnector
|
|||||||
: "null";
|
: "null";
|
||||||
|
|
||||||
if(chapterNum is not "null")
|
if(chapterNum is not "null")
|
||||||
chapters.Add(new Chapter(publication, title, volume, chapterNum, chapterId));
|
chapters.Add(new Chapter(manga, title, volume, chapterNum, chapterId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return Chapters ordered by Chapter-Number
|
//Return Chapters ordered by Chapter-Number
|
||||||
NumberFormatInfo chapterNumberFormatInfo = new() { NumberDecimalSeparator = "." };
|
NumberFormatInfo chapterNumberFormatInfo = new() { NumberDecimalSeparator = "." };
|
||||||
Log($"Got {chapters.Count} chapters. {publication}");
|
Log($"Got {chapters.Count} chapters. {manga}");
|
||||||
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,8 +205,8 @@ public class MangaDex : MangaConnector
|
|||||||
{
|
{
|
||||||
if (progressToken?.cancellationRequested ?? false)
|
if (progressToken?.cancellationRequested ?? false)
|
||||||
return HttpStatusCode.RequestTimeout;
|
return HttpStatusCode.RequestTimeout;
|
||||||
Publication chapterParentPublication = chapter.parentPublication;
|
Manga chapterParentManga = chapter.parentManga;
|
||||||
Log($"Retrieving chapter-info {chapter} {chapterParentPublication}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
//Request URLs for Chapter-Images
|
//Request URLs for Chapter-Images
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest($"https://api.mangadex.org/at-home/server/{chapter.url}?forcePort443=false'", (byte)RequestType.AtHomeServer);
|
downloadClient.MakeRequest($"https://api.mangadex.org/at-home/server/{chapter.url}?forcePort443=false'", (byte)RequestType.AtHomeServer);
|
||||||
@ -227,8 +227,8 @@ public class MangaDex : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
if (chapterParentPublication.coverUrl is not null)
|
if (chapterParentManga.coverUrl is not null)
|
||||||
chapterParentPublication.coverFileNameInCache = SaveCoverImageToCache(chapterParentPublication.coverUrl, (byte)RequestType.AtHomeServer);
|
chapterParentManga.coverFileNameInCache = SaveCoverImageToCache(chapterParentManga.coverUrl, (byte)RequestType.AtHomeServer);
|
||||||
//Download Chapter-Images
|
//Download Chapter-Images
|
||||||
return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), (byte)RequestType.AtHomeServer, comicInfoPath, progressToken:progressToken);
|
return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), (byte)RequestType.AtHomeServer, comicInfoPath, progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public class MangaKatana : MangaConnector
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Publication[] GetPublications(string publicationTitle = "")
|
public override Manga[] GetPublications(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();
|
||||||
@ -27,7 +27,7 @@ public class MangaKatana : MangaConnector
|
|||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, 1);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Publication>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
// ReSharper disable once MergeIntoPattern
|
// ReSharper disable once MergeIntoPattern
|
||||||
// If a single result is found, the user will be redirected to the results directly instead of a result page
|
// If a single result is found, the user will be redirected to the results directly instead of a result page
|
||||||
@ -38,13 +38,13 @@ public class MangaKatana : MangaConnector
|
|||||||
return new [] { ParseSinglePublicationFromHtml(requestResult.result, requestResult.redirectedToUrl.Split('/')[^1]) };
|
return new [] { ParseSinglePublicationFromHtml(requestResult.result, requestResult.redirectedToUrl.Split('/')[^1]) };
|
||||||
}
|
}
|
||||||
|
|
||||||
Publication[] publications = ParsePublicationsFromHtml(requestResult.result);
|
Manga[] publications = ParsePublicationsFromHtml(requestResult.result);
|
||||||
cachedPublications.AddRange(publications);
|
cachedPublications.AddRange(publications);
|
||||||
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
|
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
|
||||||
return publications;
|
return publications;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Publication[] ParsePublicationsFromHtml(Stream html)
|
private Manga[] ParsePublicationsFromHtml(Stream html)
|
||||||
{
|
{
|
||||||
StreamReader reader = new(html);
|
StreamReader reader = new(html);
|
||||||
string htmlString = reader.ReadToEnd();
|
string htmlString = reader.ReadToEnd();
|
||||||
@ -52,7 +52,7 @@ public class MangaKatana : MangaConnector
|
|||||||
document.LoadHtml(htmlString);
|
document.LoadHtml(htmlString);
|
||||||
IEnumerable<HtmlNode> searchResults = document.DocumentNode.SelectNodes("//*[@id='book_list']/div");
|
IEnumerable<HtmlNode> searchResults = document.DocumentNode.SelectNodes("//*[@id='book_list']/div");
|
||||||
if (searchResults is null || !searchResults.Any())
|
if (searchResults is null || !searchResults.Any())
|
||||||
return Array.Empty<Publication>();
|
return Array.Empty<Manga>();
|
||||||
List<string> urls = new();
|
List<string> urls = new();
|
||||||
foreach (HtmlNode mangaResult in searchResults)
|
foreach (HtmlNode mangaResult in searchResults)
|
||||||
{
|
{
|
||||||
@ -60,13 +60,13 @@ public class MangaKatana : MangaConnector
|
|||||||
.First(a => a.Name == "href").Value);
|
.First(a => a.Name == "href").Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashSet<Publication> ret = new();
|
HashSet<Manga> ret = new();
|
||||||
foreach (string url in urls)
|
foreach (string url in urls)
|
||||||
{
|
{
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(url, 1);
|
downloadClient.MakeRequest(url, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Publication>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
ret.Add(ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]));
|
ret.Add(ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]));
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ public class MangaKatana : MangaConnector
|
|||||||
return ret.ToArray();
|
return ret.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Publication ParseSinglePublicationFromHtml(Stream html, string publicationId)
|
private Manga ParseSinglePublicationFromHtml(Stream html, string publicationId)
|
||||||
{
|
{
|
||||||
StreamReader reader = new(html);
|
StreamReader reader = new(html);
|
||||||
string htmlString = reader.ReadToEnd();
|
string htmlString = reader.ReadToEnd();
|
||||||
@ -132,14 +132,14 @@ public class MangaKatana : MangaConnector
|
|||||||
year = Convert.ToInt32(yearString);
|
year = Convert.ToInt32(yearString);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Publication(sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, links,
|
return new Manga(sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, links,
|
||||||
year, originalLanguage, status, publicationId);
|
year, originalLanguage, status, publicationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Chapter[] GetChapters(Publication publication, string language="en")
|
public override Chapter[] GetChapters(Manga manga, string language="en")
|
||||||
{
|
{
|
||||||
Log($"Getting chapters {publication}");
|
Log($"Getting chapters {manga}");
|
||||||
string requestUrl = $"https://mangakatana.com/manga/{publication.publicationId}";
|
string requestUrl = $"https://mangakatana.com/manga/{manga.publicationId}";
|
||||||
// Leaving this in for verification if the page exists
|
// Leaving this in for verification if the page exists
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, 1);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
@ -151,12 +151,12 @@ public class MangaKatana : MangaConnector
|
|||||||
{
|
{
|
||||||
NumberDecimalSeparator = "."
|
NumberDecimalSeparator = "."
|
||||||
};
|
};
|
||||||
List<Chapter> chapters = ParseChaptersFromHtml(publication, requestUrl);
|
List<Chapter> chapters = ParseChaptersFromHtml(manga, requestUrl);
|
||||||
Log($"Got {chapters.Count} chapters. {publication}");
|
Log($"Got {chapters.Count} chapters. {manga}");
|
||||||
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Chapter> ParseChaptersFromHtml(Publication publication, string mangaUrl)
|
private List<Chapter> ParseChaptersFromHtml(Manga manga, string mangaUrl)
|
||||||
{
|
{
|
||||||
// Using HtmlWeb will include the chapters since they are loaded with js
|
// Using HtmlWeb will include the chapters since they are loaded with js
|
||||||
HtmlWeb web = new();
|
HtmlWeb web = new();
|
||||||
@ -175,7 +175,7 @@ public class MangaKatana : MangaConnector
|
|||||||
string chapterName = string.Concat(fullString.Split(':')[1..]);
|
string chapterName = string.Concat(fullString.Split(':')[1..]);
|
||||||
string url = chapterInfo.Descendants("a").First()
|
string url = chapterInfo.Descendants("a").First()
|
||||||
.GetAttributeValue("href", "");
|
.GetAttributeValue("href", "");
|
||||||
ret.Add(new Chapter(publication, chapterName, volumeNumber, chapterNumber, url));
|
ret.Add(new Chapter(manga, chapterName, volumeNumber, chapterNumber, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -185,8 +185,8 @@ public class MangaKatana : MangaConnector
|
|||||||
{
|
{
|
||||||
if (progressToken?.cancellationRequested ?? false)
|
if (progressToken?.cancellationRequested ?? false)
|
||||||
return HttpStatusCode.RequestTimeout;
|
return HttpStatusCode.RequestTimeout;
|
||||||
Publication chapterParentPublication = chapter.parentPublication;
|
Manga chapterParentManga = chapter.parentManga;
|
||||||
Log($"Retrieving chapter-info {chapter} {chapterParentPublication}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
string requestUrl = chapter.url;
|
string requestUrl = chapter.url;
|
||||||
// Leaving this in to check if the page exists
|
// Leaving this in to check if the page exists
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
@ -199,8 +199,8 @@ public class MangaKatana : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
if (chapterParentPublication.coverUrl is not null)
|
if (chapterParentManga.coverUrl is not null)
|
||||||
chapterParentPublication.coverFileNameInCache = SaveCoverImageToCache(chapterParentPublication.coverUrl, 1);
|
chapterParentManga.coverFileNameInCache = SaveCoverImageToCache(chapterParentManga.coverUrl, 1);
|
||||||
|
|
||||||
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken);
|
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public class Manganato : MangaConnector
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Publication[] GetPublications(string publicationTitle = "")
|
public override Manga[] GetPublications(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();
|
||||||
@ -27,15 +27,15 @@ public class Manganato : MangaConnector
|
|||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, 1);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Publication>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
Publication[] publications = ParsePublicationsFromHtml(requestResult.result);
|
Manga[] publications = ParsePublicationsFromHtml(requestResult.result);
|
||||||
cachedPublications.AddRange(publications);
|
cachedPublications.AddRange(publications);
|
||||||
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
|
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
|
||||||
return publications;
|
return publications;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Publication[] ParsePublicationsFromHtml(Stream html)
|
private Manga[] ParsePublicationsFromHtml(Stream html)
|
||||||
{
|
{
|
||||||
StreamReader reader = new (html);
|
StreamReader reader = new (html);
|
||||||
string htmlString = reader.ReadToEnd();
|
string htmlString = reader.ReadToEnd();
|
||||||
@ -49,13 +49,13 @@ public class Manganato : MangaConnector
|
|||||||
.First(a => a.Name == "href").Value);
|
.First(a => a.Name == "href").Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashSet<Publication> ret = new();
|
HashSet<Manga> ret = new();
|
||||||
foreach (string url in urls)
|
foreach (string url in urls)
|
||||||
{
|
{
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(url, 1);
|
downloadClient.MakeRequest(url, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Publication>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
ret.Add(ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]));
|
ret.Add(ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]));
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ public class Manganato : MangaConnector
|
|||||||
return ret.ToArray();
|
return ret.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Publication ParseSinglePublicationFromHtml(Stream html, string publicationId)
|
private Manga ParseSinglePublicationFromHtml(Stream html, string publicationId)
|
||||||
{
|
{
|
||||||
StreamReader reader = new (html);
|
StreamReader reader = new (html);
|
||||||
string htmlString = reader.ReadToEnd();
|
string htmlString = reader.ReadToEnd();
|
||||||
@ -120,14 +120,14 @@ 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 Publication(sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, links,
|
return new Manga(sortName, authors.ToList(), description, altTitles, tags.ToArray(), posterUrl, links,
|
||||||
year, originalLanguage, status, publicationId);
|
year, originalLanguage, status, publicationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Chapter[] GetChapters(Publication publication, string language="en")
|
public override Chapter[] GetChapters(Manga manga, string language="en")
|
||||||
{
|
{
|
||||||
Log($"Getting chapters {publication}");
|
Log($"Getting chapters {manga}");
|
||||||
string requestUrl = $"https://chapmanganato.com/{publication.publicationId}";
|
string requestUrl = $"https://chapmanganato.com/{manga.publicationId}";
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, 1);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
@ -138,12 +138,12 @@ public class Manganato : MangaConnector
|
|||||||
{
|
{
|
||||||
NumberDecimalSeparator = "."
|
NumberDecimalSeparator = "."
|
||||||
};
|
};
|
||||||
List<Chapter> chapters = ParseChaptersFromHtml(publication, requestResult.result);
|
List<Chapter> chapters = ParseChaptersFromHtml(manga, requestResult.result);
|
||||||
Log($"Got {chapters.Count} chapters. {publication}");
|
Log($"Got {chapters.Count} chapters. {manga}");
|
||||||
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Chapter> ParseChaptersFromHtml(Publication publication, Stream html)
|
private List<Chapter> ParseChaptersFromHtml(Manga manga, Stream html)
|
||||||
{
|
{
|
||||||
StreamReader reader = new (html);
|
StreamReader reader = new (html);
|
||||||
string htmlString = reader.ReadToEnd();
|
string htmlString = reader.ReadToEnd();
|
||||||
@ -162,7 +162,7 @@ public class Manganato : MangaConnector
|
|||||||
string chapterName = string.Concat(fullString.Split(':')[1..]);
|
string chapterName = string.Concat(fullString.Split(':')[1..]);
|
||||||
string url = chapterInfo.Descendants("a").First(d => d.HasClass("chapter-name"))
|
string url = chapterInfo.Descendants("a").First(d => d.HasClass("chapter-name"))
|
||||||
.GetAttributeValue("href", "");
|
.GetAttributeValue("href", "");
|
||||||
ret.Add(new Chapter(publication, chapterName, volumeNumber, chapterNumber, url));
|
ret.Add(new Chapter(manga, chapterName, volumeNumber, chapterNumber, url));
|
||||||
}
|
}
|
||||||
ret.Reverse();
|
ret.Reverse();
|
||||||
return ret;
|
return ret;
|
||||||
@ -172,8 +172,8 @@ public class Manganato : MangaConnector
|
|||||||
{
|
{
|
||||||
if (progressToken?.cancellationRequested ?? false)
|
if (progressToken?.cancellationRequested ?? false)
|
||||||
return HttpStatusCode.RequestTimeout;
|
return HttpStatusCode.RequestTimeout;
|
||||||
Publication chapterParentPublication = chapter.parentPublication;
|
Manga chapterParentManga = chapter.parentManga;
|
||||||
Log($"Retrieving chapter-info {chapter} {chapterParentPublication}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
string requestUrl = chapter.url;
|
string requestUrl = chapter.url;
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, 1);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
@ -185,8 +185,8 @@ public class Manganato : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
if (chapterParentPublication.coverUrl is not null)
|
if (chapterParentManga.coverUrl is not null)
|
||||||
chapterParentPublication.coverFileNameInCache = SaveCoverImageToCache(chapterParentPublication.coverUrl, 1);
|
chapterParentManga.coverFileNameInCache = SaveCoverImageToCache(chapterParentManga.coverUrl, 1);
|
||||||
|
|
||||||
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://chapmanganato.com/", progressToken:progressToken);
|
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://chapmanganato.com/", progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
@ -69,22 +69,22 @@ public class Mangasee : MangaConnector
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Publication[] GetPublications(string publicationTitle = "")
|
public override Manga[] GetPublications(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";
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, 1);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Publication>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
Publication[] publications = ParsePublicationsFromHtml(requestResult.result, publicationTitle);
|
Manga[] publications = ParsePublicationsFromHtml(requestResult.result, publicationTitle);
|
||||||
cachedPublications.AddRange(publications);
|
cachedPublications.AddRange(publications);
|
||||||
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
|
Log($"Retrieved {publications.Length} publications. Term=\"{publicationTitle}\"");
|
||||||
return publications;
|
return publications;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Publication[] ParsePublicationsFromHtml(Stream html, string publicationTitle)
|
private Manga[] ParsePublicationsFromHtml(Stream html, string publicationTitle)
|
||||||
{
|
{
|
||||||
string jsonString = new StreamReader(html).ReadToEnd();
|
string jsonString = new StreamReader(html).ReadToEnd();
|
||||||
List<SearchResultItem> result = JsonConvert.DeserializeObject<List<SearchResultItem>>(jsonString)!;
|
List<SearchResultItem> result = JsonConvert.DeserializeObject<List<SearchResultItem>>(jsonString)!;
|
||||||
@ -101,7 +101,7 @@ public class Mangasee : MangaConnector
|
|||||||
|
|
||||||
Log($"Retrieved {queryFiltered.Count} publications.");
|
Log($"Retrieved {queryFiltered.Count} publications.");
|
||||||
|
|
||||||
HashSet<Publication> ret = new();
|
HashSet<Manga> ret = new();
|
||||||
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();
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ public class Mangasee : MangaConnector
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Publication ParseSinglePublicationFromHtml(Stream html, string sortName, string publicationId, string[] a)
|
private Manga ParseSinglePublicationFromHtml(Stream html, string sortName, string publicationId, string[] a)
|
||||||
{
|
{
|
||||||
StreamReader reader = new (html);
|
StreamReader reader = new (html);
|
||||||
HtmlDocument document = new ();
|
HtmlDocument document = new ();
|
||||||
@ -170,7 +170,7 @@ public class Mangasee : MangaConnector
|
|||||||
foreach(string at in a)
|
foreach(string at in a)
|
||||||
altTitles.Add((i++).ToString(), at);
|
altTitles.Add((i++).ToString(), at);
|
||||||
|
|
||||||
return new Publication(sortName, authors, description, altTitles, tags.ToArray(), posterUrl, links,
|
return new Manga(sortName, authors, description, altTitles, tags.ToArray(), posterUrl, links,
|
||||||
year, originalLanguage, status, publicationId);
|
year, originalLanguage, status, publicationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,10 +214,10 @@ public class Mangasee : MangaConnector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Chapter[] GetChapters(Publication publication, string language="en")
|
public override Chapter[] GetChapters(Manga manga, string language="en")
|
||||||
{
|
{
|
||||||
Log($"Getting chapters {publication}");
|
Log($"Getting chapters {manga}");
|
||||||
XDocument doc = XDocument.Load($"https://mangasee123.com/rss/{publication.publicationId}.xml");
|
XDocument doc = XDocument.Load($"https://mangasee123.com/rss/{manga.publicationId}.xml");
|
||||||
XElement[] chapterItems = doc.Descendants("item").ToArray();
|
XElement[] chapterItems = doc.Descendants("item").ToArray();
|
||||||
List<Chapter> chapters = new();
|
List<Chapter> chapters = new();
|
||||||
foreach (XElement chapter in chapterItems)
|
foreach (XElement chapter in chapterItems)
|
||||||
@ -228,7 +228,7 @@ public class Mangasee : MangaConnector
|
|||||||
|
|
||||||
string url = chapter.Descendants("link").First().Value;
|
string url = chapter.Descendants("link").First().Value;
|
||||||
url = url.Replace(Regex.Matches(url,"(-page-[0-9])")[0].ToString(),"");
|
url = url.Replace(Regex.Matches(url,"(-page-[0-9])")[0].ToString(),"");
|
||||||
chapters.Add(new Chapter(publication, "", volumeNumber, chapterNumber, url));
|
chapters.Add(new Chapter(manga, "", volumeNumber, chapterNumber, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return Chapters ordered by Chapter-Number
|
//Return Chapters ordered by Chapter-Number
|
||||||
@ -236,7 +236,7 @@ public class Mangasee : MangaConnector
|
|||||||
{
|
{
|
||||||
NumberDecimalSeparator = "."
|
NumberDecimalSeparator = "."
|
||||||
};
|
};
|
||||||
Log($"Got {chapters.Count} chapters. {publication}");
|
Log($"Got {chapters.Count} chapters. {manga}");
|
||||||
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ public class Mangasee : MangaConnector
|
|||||||
{
|
{
|
||||||
if (progressToken?.cancellationRequested ?? false)
|
if (progressToken?.cancellationRequested ?? false)
|
||||||
return HttpStatusCode.RequestTimeout;
|
return HttpStatusCode.RequestTimeout;
|
||||||
Publication chapterParentPublication = chapter.parentPublication;
|
Manga chapterParentManga = chapter.parentManga;
|
||||||
while (this._browser is null && !(progressToken?.cancellationRequested??false))
|
while (this._browser is null && !(progressToken?.cancellationRequested??false))
|
||||||
{
|
{
|
||||||
Log("Waiting for headless browser to download...");
|
Log("Waiting for headless browser to download...");
|
||||||
@ -253,7 +253,7 @@ public class Mangasee : MangaConnector
|
|||||||
if (progressToken?.cancellationRequested??false)
|
if (progressToken?.cancellationRequested??false)
|
||||||
return HttpStatusCode.RequestTimeout;
|
return HttpStatusCode.RequestTimeout;
|
||||||
|
|
||||||
Log($"Retrieving chapter-info {chapter} {chapterParentPublication}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
IPage page = _browser!.NewPageAsync().Result;
|
IPage page = _browser!.NewPageAsync().Result;
|
||||||
IResponse response = page.GoToAsync(chapter.url).Result;
|
IResponse response = page.GoToAsync(chapter.url).Result;
|
||||||
if (response.Ok)
|
if (response.Ok)
|
||||||
@ -270,8 +270,8 @@ public class Mangasee : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
if (chapterParentPublication.coverUrl is not null)
|
if (chapterParentManga.coverUrl is not null)
|
||||||
chapterParentPublication.coverFileNameInCache = SaveCoverImageToCache(chapterParentPublication.coverUrl, 1);
|
chapterParentManga.coverFileNameInCache = SaveCoverImageToCache(chapterParentManga.coverUrl, 1);
|
||||||
|
|
||||||
return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, progressToken:progressToken);
|
return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ public class Server : GlobalBase
|
|||||||
case "Connectors":
|
case "Connectors":
|
||||||
SendResponse(HttpStatusCode.OK, response, _parent.GetConnectors().Select(con => con.name).ToArray());
|
SendResponse(HttpStatusCode.OK, response, _parent.GetConnectors().Select(con => con.name).ToArray());
|
||||||
break;
|
break;
|
||||||
case "Publications/FromConnector":
|
case "Manga/FromConnector":
|
||||||
if (!requestVariables.TryGetValue("connector", out connectorName) ||
|
if (!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!requestVariables.TryGetValue("title", out string? title) ||
|
!requestVariables.TryGetValue("title", out string? title) ||
|
||||||
_parent.GetConnector(connectorName) is null)
|
_parent.GetConnector(connectorName) is null)
|
||||||
@ -124,7 +124,7 @@ public class Server : GlobalBase
|
|||||||
connector = _parent.GetConnector(connectorName)!;
|
connector = _parent.GetConnector(connectorName)!;
|
||||||
SendResponse(HttpStatusCode.OK, response, connector.GetPublications(title));
|
SendResponse(HttpStatusCode.OK, response, connector.GetPublications(title));
|
||||||
break;
|
break;
|
||||||
case "Publications/Chapters":
|
case "Manga/Chapters":
|
||||||
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!requestVariables.TryGetValue("internalId", out string? internalId) ||
|
!requestVariables.TryGetValue("internalId", out string? internalId) ||
|
||||||
_parent.GetConnector(connectorName) is null ||
|
_parent.GetConnector(connectorName) is null ||
|
||||||
@ -134,10 +134,10 @@ public class Server : GlobalBase
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connector = _parent.GetConnector(connectorName)!;
|
connector = _parent.GetConnector(connectorName)!;
|
||||||
Publication publication = (Publication)_parent.GetPublicationById(internalId)!;
|
Manga manga = (Manga)_parent.GetPublicationById(internalId)!;
|
||||||
SendResponse(HttpStatusCode.OK, response, connector.GetChapters(publication));
|
SendResponse(HttpStatusCode.OK, response, connector.GetChapters(manga));
|
||||||
break;
|
break;
|
||||||
case "Tasks":
|
case "Jobs":
|
||||||
if (!requestVariables.TryGetValue("jobId", out jobId))
|
if (!requestVariables.TryGetValue("jobId", out jobId))
|
||||||
{
|
{
|
||||||
if(!_parent._jobBoss.jobs.Any(jjob => jjob.id == jobId))
|
if(!_parent._jobBoss.jobs.Any(jjob => jjob.id == jobId))
|
||||||
@ -148,7 +148,7 @@ public class Server : GlobalBase
|
|||||||
}
|
}
|
||||||
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs);
|
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs);
|
||||||
break;
|
break;
|
||||||
case "Tasks/Progress":
|
case "Jobs/Progress":
|
||||||
if (!requestVariables.TryGetValue("jobId", out jobId))
|
if (!requestVariables.TryGetValue("jobId", out jobId))
|
||||||
{
|
{
|
||||||
if(!_parent._jobBoss.jobs.Any(jjob => jjob.id == jobId))
|
if(!_parent._jobBoss.jobs.Any(jjob => jjob.id == jobId))
|
||||||
@ -159,10 +159,10 @@ public class Server : GlobalBase
|
|||||||
}
|
}
|
||||||
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs.Select(jjob => jjob.progressToken));
|
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs.Select(jjob => jjob.progressToken));
|
||||||
break;
|
break;
|
||||||
case "Tasks/Running":
|
case "Jobs/Running":
|
||||||
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs.Where(jjob => jjob.progressToken.state is ProgressToken.State.Running));
|
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs.Where(jjob => jjob.progressToken.state is ProgressToken.State.Running));
|
||||||
break;
|
break;
|
||||||
case "Tasks/Waiting":
|
case "Jobs/Waiting":
|
||||||
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs.Where(jjob => jjob.progressToken.state is ProgressToken.State.Standby));
|
SendResponse(HttpStatusCode.OK, response, _parent._jobBoss.jobs.Where(jjob => jjob.progressToken.state is ProgressToken.State.Standby));
|
||||||
break;
|
break;
|
||||||
case "Settings":
|
case "Settings":
|
||||||
@ -191,11 +191,11 @@ public class Server : GlobalBase
|
|||||||
Dictionary<string, string> requestVariables = GetRequestVariables(request.Url!.Query);
|
Dictionary<string, string> requestVariables = GetRequestVariables(request.Url!.Query);
|
||||||
string? connectorName, internalId;
|
string? connectorName, internalId;
|
||||||
MangaConnector connector;
|
MangaConnector connector;
|
||||||
Publication publication;
|
Manga manga;
|
||||||
string path = Regex.Match(request.Url!.LocalPath, @"[A-z0-9]+(\/[A-z0-9]+)*").Value;
|
string path = Regex.Match(request.Url!.LocalPath, @"[A-z0-9]+(\/[A-z0-9]+)*").Value;
|
||||||
switch (path)
|
switch (path)
|
||||||
{
|
{
|
||||||
case "Tasks/MonitorManga":
|
case "Jobs/MonitorManga":
|
||||||
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!requestVariables.TryGetValue("internalId", out internalId) ||
|
!requestVariables.TryGetValue("internalId", out internalId) ||
|
||||||
!requestVariables.TryGetValue("interval", out string? intervalStr) ||
|
!requestVariables.TryGetValue("interval", out string? intervalStr) ||
|
||||||
@ -207,11 +207,11 @@ public class Server : GlobalBase
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connector = _parent.GetConnector(connectorName)!;
|
connector = _parent.GetConnector(connectorName)!;
|
||||||
publication = (Publication)_parent.GetPublicationById(internalId)!;
|
manga = (Manga)_parent.GetPublicationById(internalId)!;
|
||||||
_parent._jobBoss.AddJob(new DownloadNewChapters(this, connector, publication, true, interval));
|
_parent._jobBoss.AddJob(new DownloadNewChapters(this, connector, manga, true, interval));
|
||||||
SendResponse(HttpStatusCode.Accepted, response);
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
break;
|
break;
|
||||||
case "Tasks/DownloadNewChapters":
|
case "Jobs/DownloadNewChapters":
|
||||||
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!requestVariables.TryGetValue("internalId", out internalId) ||
|
!requestVariables.TryGetValue("internalId", out internalId) ||
|
||||||
_parent.GetConnector(connectorName) is null ||
|
_parent.GetConnector(connectorName) is null ||
|
||||||
@ -221,8 +221,8 @@ public class Server : GlobalBase
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connector = _parent.GetConnector(connectorName)!;
|
connector = _parent.GetConnector(connectorName)!;
|
||||||
publication = (Publication)_parent.GetPublicationById(internalId)!;
|
manga = (Manga)_parent.GetPublicationById(internalId)!;
|
||||||
_parent._jobBoss.AddJob(new DownloadNewChapters(this, connector, publication, false));
|
_parent._jobBoss.AddJob(new DownloadNewChapters(this, connector, manga, false));
|
||||||
SendResponse(HttpStatusCode.Accepted, response);
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
break;
|
break;
|
||||||
case "Settings/UpdateDownloadLocation":
|
case "Settings/UpdateDownloadLocation":
|
||||||
@ -325,11 +325,11 @@ public class Server : GlobalBase
|
|||||||
Dictionary<string, string> requestVariables = GetRequestVariables(request.Url!.Query);
|
Dictionary<string, string> requestVariables = GetRequestVariables(request.Url!.Query);
|
||||||
string? connectorName, internalId;
|
string? connectorName, internalId;
|
||||||
MangaConnector connector;
|
MangaConnector connector;
|
||||||
Publication publication;
|
Manga manga;
|
||||||
string path = Regex.Match(request.Url!.LocalPath, @"[A-z0-9]+(\/[A-z0-9]+)*").Value;
|
string path = Regex.Match(request.Url!.LocalPath, @"[A-z0-9]+(\/[A-z0-9]+)*").Value;
|
||||||
switch (path)
|
switch (path)
|
||||||
{
|
{
|
||||||
case "Tasks/DownloadChapter":
|
case "Jobs/DownloadChapter":
|
||||||
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!requestVariables.TryGetValue("internalId", out internalId) ||
|
!requestVariables.TryGetValue("internalId", out internalId) ||
|
||||||
!requestVariables.TryGetValue("chapterNumber", out string? chapterNumber) ||
|
!requestVariables.TryGetValue("chapterNumber", out string? chapterNumber) ||
|
||||||
@ -342,7 +342,7 @@ public class Server : GlobalBase
|
|||||||
_parent._jobBoss.RemoveJobs(_parent._jobBoss.GetJobsLike(connectorName, internalId, chapterNumber));
|
_parent._jobBoss.RemoveJobs(_parent._jobBoss.GetJobsLike(connectorName, internalId, chapterNumber));
|
||||||
SendResponse(HttpStatusCode.Accepted, response);
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
break;
|
break;
|
||||||
case "Tasks/MonitorManga":
|
case "Jobs/MonitorManga":
|
||||||
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!requestVariables.TryGetValue("internalId", out internalId) ||
|
!requestVariables.TryGetValue("internalId", out internalId) ||
|
||||||
_parent.GetConnector(connectorName) is null ||
|
_parent.GetConnector(connectorName) is null ||
|
||||||
@ -352,11 +352,11 @@ public class Server : GlobalBase
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connector = _parent.GetConnector(connectorName)!;
|
connector = _parent.GetConnector(connectorName)!;
|
||||||
publication = (Publication)_parent.GetPublicationById(internalId)!;
|
manga = (Manga)_parent.GetPublicationById(internalId)!;
|
||||||
_parent._jobBoss.RemoveJobs(_parent._jobBoss.GetJobsLike(connector, publication));
|
_parent._jobBoss.RemoveJobs(_parent._jobBoss.GetJobsLike(connector, manga));
|
||||||
SendResponse(HttpStatusCode.Accepted, response);
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
break;
|
break;
|
||||||
case "Tasks/DownloadNewChapters":
|
case "Jobs/DownloadNewChapters":
|
||||||
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
if(!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!requestVariables.TryGetValue("internalId", out internalId) ||
|
!requestVariables.TryGetValue("internalId", out internalId) ||
|
||||||
_parent.GetConnector(connectorName) is null ||
|
_parent.GetConnector(connectorName) is null ||
|
||||||
@ -366,8 +366,8 @@ public class Server : GlobalBase
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connector = _parent.GetConnector(connectorName)!;
|
connector = _parent.GetConnector(connectorName)!;
|
||||||
publication = (Publication)_parent.GetPublicationById(internalId)!;
|
manga = (Manga)_parent.GetPublicationById(internalId)!;
|
||||||
_parent._jobBoss.RemoveJobs(_parent._jobBoss.GetJobsLike(connector, publication));
|
_parent._jobBoss.RemoveJobs(_parent._jobBoss.GetJobsLike(connector, manga));
|
||||||
SendResponse(HttpStatusCode.Accepted, response);
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
break;
|
break;
|
||||||
case "NotificationConnectors":
|
case "NotificationConnectors":
|
||||||
|
@ -39,7 +39,7 @@ public partial class Tranga : GlobalBase
|
|||||||
return connectors;
|
return connectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Publication? GetPublicationById(string internalId)
|
public Manga? GetPublicationById(string internalId)
|
||||||
{
|
{
|
||||||
if (cachedPublications.Exists(publication => publication.internalId == internalId))
|
if (cachedPublications.Exists(publication => publication.internalId == internalId))
|
||||||
return cachedPublications.First(publication => publication.internalId == internalId);
|
return cachedPublications.First(publication => publication.internalId == internalId);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user