From 58040ecb10eb8e58cdde25e216d88cf50986ee64 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 18:06:08 +0200 Subject: [PATCH 01/30] Order of returned API Jobs/MonitorJobs And Jobs/Waiting --- Tranga/Server.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tranga/Server.cs b/Tranga/Server.cs index bf71ffc..bd9625e 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -192,10 +192,10 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.OK, response, _parent.jobBoss.jobs.Where(jjob => jjob.progressToken.state is ProgressToken.State.Running)); break; 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).OrderBy(jjob => jjob.nextExecution)); break; case "Jobs/MonitorJobs": - SendResponse(HttpStatusCode.OK, response, _parent.jobBoss.jobs.Where(jjob => jjob is DownloadNewChapters)); + SendResponse(HttpStatusCode.OK, response, _parent.jobBoss.jobs.Where(jjob => jjob is DownloadNewChapters).OrderBy(jjob => ((DownloadNewChapters)jjob).manga.sortName)); break; case "Settings": SendResponse(HttpStatusCode.OK, response, settings); From c580fafc62ea3ff6f84063d3e6daebbe3a44269b Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:00:00 +0200 Subject: [PATCH 02/30] Added user tranga to container and set permissions --- Dockerfile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6bab183..b495a44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,20 @@ RUN dotnet restore /src/Tranga/Tranga.csproj RUN dotnet publish -c Release -o /publish FROM glax/tranga-base:latest as runtime +EXPOSE 6531 +ARG UNAME=tranga +ARG UID=1000 +ARG GID=1000 +RUN groupadd -g $GID -o $UNAME +RUN useradd -m -u $UID -g $GID -o -s /bin/bash $UNAME +RUN mkdir /usr/share/tranga-api +RUN mkdir /Manga +RUN chown 1000:1000 /usr/share/tranga-api +RUN chown 1000:1000 /Manga +USER $UNAME + WORKDIR /publish COPY --from=build-env /publish . -EXPOSE 6531 +USER 0 +RUN chown 1000:1000 /publish ENTRYPOINT ["dotnet", "/publish/Tranga.dll", "-c"] From 1fe4b75ac7b9eb97034e8bc1e7bdcc9dfed1d64d Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:04:55 +0200 Subject: [PATCH 03/30] Folder permissions --- Tranga/MangaConnectors/MangaConnector.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Tranga/MangaConnectors/MangaConnector.cs b/Tranga/MangaConnectors/MangaConnector.cs index 74b49e9..3fe7066 100644 --- a/Tranga/MangaConnectors/MangaConnector.cs +++ b/Tranga/MangaConnectors/MangaConnector.cs @@ -193,7 +193,11 @@ public abstract class MangaConnector : GlobalBase //Check if Publication Directory already exists string directoryPath = Path.GetDirectoryName(saveArchiveFilePath)!; if (!Directory.Exists(directoryPath)) - Directory.CreateDirectory(directoryPath); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + Directory.CreateDirectory(directoryPath, + UserRead | UserWrite | UserExecute | GroupRead | GroupWrite | GroupExecute ); + else + Directory.CreateDirectory(directoryPath); if (File.Exists(saveArchiveFilePath)) //Don't download twice. return HttpStatusCode.OK; @@ -229,7 +233,7 @@ public abstract class MangaConnector : GlobalBase //ZIP-it and ship-it ZipFile.CreateFromDirectory(tempFolder, saveArchiveFilePath); if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - File.SetUnixFileMode(saveArchiveFilePath, GroupRead | GroupWrite | OtherRead | OtherWrite | UserRead | UserWrite); + File.SetUnixFileMode(saveArchiveFilePath, UserRead | UserWrite | UserExecute | GroupRead | GroupWrite | GroupExecute); Directory.Delete(tempFolder, true); //Cleanup progressToken?.Complete(); From 48d312da0baca5494c9888df192bcfa2a469be48 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:21:37 +0200 Subject: [PATCH 04/30] File Permissions --- Tranga/MangaConnectors/MangaConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tranga/MangaConnectors/MangaConnector.cs b/Tranga/MangaConnectors/MangaConnector.cs index 3fe7066..09fb7f2 100644 --- a/Tranga/MangaConnectors/MangaConnector.cs +++ b/Tranga/MangaConnectors/MangaConnector.cs @@ -162,7 +162,7 @@ public abstract class MangaConnector : GlobalBase Log($"Cloning cover {fileInCache} -> {newFilePath}"); File.Copy(fileInCache, newFilePath, true); if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - File.SetUnixFileMode(newFilePath, GroupRead | GroupWrite | OtherRead | OtherWrite | UserRead | UserWrite); + File.SetUnixFileMode(newFilePath, GroupRead | GroupWrite | UserRead | UserWrite); } /// From 4f4b0cb3a80963aa3fd6f68938526df8447194a7 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:22:49 +0200 Subject: [PATCH 05/30] LibraryConnector baseUrl regex --- Tranga/LibraryConnectors/LibraryConnector.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Tranga/LibraryConnectors/LibraryConnector.cs b/Tranga/LibraryConnectors/LibraryConnector.cs index e3e3caa..cbf4446 100644 --- a/Tranga/LibraryConnectors/LibraryConnector.cs +++ b/Tranga/LibraryConnectors/LibraryConnector.cs @@ -1,5 +1,6 @@ using System.Net; using System.Net.Http.Headers; +using System.Text.RegularExpressions; using Logging; namespace Tranga.LibraryConnectors; @@ -20,7 +21,10 @@ public abstract class LibraryConnector : GlobalBase protected LibraryConnector(GlobalBase clone, string baseUrl, string auth, LibraryType libraryType) : base(clone) { - this.baseUrl = baseUrl; + Regex urlRex = new(@"https?:\/\/[0-9A-z\.]*"); + if (!urlRex.IsMatch(baseUrl)) + throw new ArgumentException("Base url does not match pattern"); + this.baseUrl = urlRex.Match(baseUrl).Value; this.auth = auth; this.libraryType = libraryType; } From 27c4ed719c60a46848ae2f50065eca2511538c92 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:33:43 +0200 Subject: [PATCH 06/30] Cancel failed jobs --- Tranga/MangaConnectors/MangaDex.cs | 10 ++++++++++ Tranga/MangaConnectors/MangaKatana.cs | 7 +++++++ Tranga/MangaConnectors/Manganato.cs | 11 +++++++++++ Tranga/MangaConnectors/Mangasee.cs | 17 ++++++++++++++--- Tranga/MangaConnectors/Mangaworld.cs | 11 +++++++++++ 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/Tranga/MangaConnectors/MangaDex.cs b/Tranga/MangaConnectors/MangaDex.cs index f0203bd..cd0226e 100644 --- a/Tranga/MangaConnectors/MangaDex.cs +++ b/Tranga/MangaConnectors/MangaDex.cs @@ -225,17 +225,27 @@ public class MangaDex : MangaConnector public override HttpStatusCode DownloadChapter(Chapter chapter, ProgressToken? progressToken = null) { if (progressToken?.cancellationRequested ?? false) + { + progressToken?.Cancel(); return HttpStatusCode.RequestTimeout; + } + Manga chapterParentManga = chapter.parentManga; Log($"Retrieving chapter-info {chapter} {chapterParentManga}"); //Request URLs for Chapter-Images DownloadClient.RequestResult requestResult = downloadClient.MakeRequest($"https://api.mangadex.org/at-home/server/{chapter.url}?forcePort443=false'", (byte)RequestType.AtHomeServer); if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) + { + progressToken?.Cancel(); return requestResult.statusCode; + } JsonObject? result = JsonSerializer.Deserialize(requestResult.result); if (result is null) + { + progressToken?.Cancel(); return HttpStatusCode.NoContent; + } string baseUrl = result["baseUrl"]!.GetValue(); string hash = result["chapter"]!["hash"]!.GetValue(); diff --git a/Tranga/MangaConnectors/MangaKatana.cs b/Tranga/MangaConnectors/MangaKatana.cs index 12f15cd..70c60b2 100644 --- a/Tranga/MangaConnectors/MangaKatana.cs +++ b/Tranga/MangaConnectors/MangaKatana.cs @@ -186,7 +186,11 @@ public class MangaKatana : MangaConnector public override HttpStatusCode DownloadChapter(Chapter chapter, ProgressToken? progressToken = null) { if (progressToken?.cancellationRequested ?? false) + { + progressToken?.Cancel(); return HttpStatusCode.RequestTimeout; + } + Manga chapterParentManga = chapter.parentManga; Log($"Retrieving chapter-info {chapter} {chapterParentManga}"); string requestUrl = chapter.url; @@ -194,7 +198,10 @@ public class MangaKatana : MangaConnector DownloadClient.RequestResult requestResult = downloadClient.MakeRequest(requestUrl, 1); if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) + { + progressToken?.Cancel(); return requestResult.statusCode; + } string[] imageUrls = ParseImageUrlsFromHtml(requestUrl); diff --git a/Tranga/MangaConnectors/Manganato.cs b/Tranga/MangaConnectors/Manganato.cs index 6b3cd23..d56a298 100644 --- a/Tranga/MangaConnectors/Manganato.cs +++ b/Tranga/MangaConnectors/Manganato.cs @@ -172,17 +172,28 @@ public class Manganato : MangaConnector public override HttpStatusCode DownloadChapter(Chapter chapter, ProgressToken? progressToken = null) { if (progressToken?.cancellationRequested ?? false) + { + progressToken?.Cancel(); return HttpStatusCode.RequestTimeout; + } + Manga chapterParentManga = chapter.parentManga; Log($"Retrieving chapter-info {chapter} {chapterParentManga}"); string requestUrl = chapter.url; DownloadClient.RequestResult requestResult = downloadClient.MakeRequest(requestUrl, 1); if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) + { + progressToken?.Cancel(); return requestResult.statusCode; + } if (requestResult.htmlDocument is null) + { + progressToken?.Cancel(); return HttpStatusCode.InternalServerError; + } + string[] imageUrls = ParseImageUrlsFromHtml(requestResult.htmlDocument); string comicInfoPath = Path.GetTempFileName(); diff --git a/Tranga/MangaConnectors/Mangasee.cs b/Tranga/MangaConnectors/Mangasee.cs index aeae553..382b1c2 100644 --- a/Tranga/MangaConnectors/Mangasee.cs +++ b/Tranga/MangaConnectors/Mangasee.cs @@ -179,16 +179,27 @@ public class Mangasee : MangaConnector public override HttpStatusCode DownloadChapter(Chapter chapter, ProgressToken? progressToken = null) { if (progressToken?.cancellationRequested ?? false) + { + progressToken?.Cancel(); return HttpStatusCode.RequestTimeout; + } + Manga chapterParentManga = chapter.parentManga; - if (progressToken?.cancellationRequested??false) + if (progressToken?.cancellationRequested ?? false) + { + progressToken?.Cancel(); return HttpStatusCode.RequestTimeout; - + } + Log($"Retrieving chapter-info {chapter} {chapterParentManga}"); DownloadClient.RequestResult requestResult = this.downloadClient.MakeRequest(chapter.url, 1); - if(requestResult.htmlDocument is null) + if (requestResult.htmlDocument is null) + { + progressToken?.Cancel(); return HttpStatusCode.RequestTimeout; + } + HtmlDocument document = requestResult.htmlDocument; HtmlNode gallery = document.DocumentNode.Descendants("div").First(div => div.HasClass("ImageGallery")); diff --git a/Tranga/MangaConnectors/Mangaworld.cs b/Tranga/MangaConnectors/Mangaworld.cs index ae61871..9501b21 100644 --- a/Tranga/MangaConnectors/Mangaworld.cs +++ b/Tranga/MangaConnectors/Mangaworld.cs @@ -153,17 +153,28 @@ public class Mangaworld: MangaConnector public override HttpStatusCode DownloadChapter(Chapter chapter, ProgressToken? progressToken = null) { if (progressToken?.cancellationRequested ?? false) + { + progressToken?.Cancel(); return HttpStatusCode.RequestTimeout; + } + Manga chapterParentManga = chapter.parentManga; Log($"Retrieving chapter-info {chapter} {chapterParentManga}"); string requestUrl = $"{chapter.url}?style=list"; DownloadClient.RequestResult requestResult = downloadClient.MakeRequest(requestUrl, 1); if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300) + { + progressToken?.Cancel(); return requestResult.statusCode; + } if (requestResult.htmlDocument is null) + { + progressToken?.Cancel(); return HttpStatusCode.InternalServerError; + } + string[] imageUrls = ParseImageUrlsFromHtml(requestResult.htmlDocument); string comicInfoPath = Path.GetTempFileName(); From 64ec0963e173b62becc795926079dd2faba9db66 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:42:50 +0200 Subject: [PATCH 07/30] copy cover --- Tranga/Jobs/DownloadChapter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Tranga/Jobs/DownloadChapter.cs b/Tranga/Jobs/DownloadChapter.cs index 8a27929..9d0fe10 100644 --- a/Tranga/Jobs/DownloadChapter.cs +++ b/Tranga/Jobs/DownloadChapter.cs @@ -31,6 +31,7 @@ public class DownloadChapter : Job { Task downloadTask = new(delegate { + mangaConnector.CopyCoverFromCacheToDownloadLocation(chapter.parentManga); mangaConnector.DownloadChapter(chapter, this.progressToken); UpdateLibraries(); SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}"); From 3ee53b743641bf06e94be345d13aca1824808a60 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:43:39 +0200 Subject: [PATCH 08/30] copy cover --- Tranga/Jobs/DownloadNewChapters.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tranga/Jobs/DownloadNewChapters.cs b/Tranga/Jobs/DownloadNewChapters.cs index a386b98..b90b30b 100644 --- a/Tranga/Jobs/DownloadNewChapters.cs +++ b/Tranga/Jobs/DownloadNewChapters.cs @@ -36,6 +36,8 @@ public class DownloadNewChapters : Job Chapter[] chapters = mangaConnector.GetNewChapters(manga, this.translatedLanguage); this.progressToken.increments = chapters.Length; List jobs = new(); + if(chapters.Any()) + mangaConnector.CopyCoverFromCacheToDownloadLocation(manga); foreach (Chapter chapter in chapters) { DownloadChapter downloadChapterJob = new(this, this.mangaConnector, chapter, parentJobId: this.id); From c4d69c27a48e541c77bd924d562d093babc8180b Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:43:58 +0200 Subject: [PATCH 09/30] copy cover --- Tranga/Jobs/DownloadNewChapters.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tranga/Jobs/DownloadNewChapters.cs b/Tranga/Jobs/DownloadNewChapters.cs index b90b30b..6e2e3f2 100644 --- a/Tranga/Jobs/DownloadNewChapters.cs +++ b/Tranga/Jobs/DownloadNewChapters.cs @@ -36,8 +36,7 @@ public class DownloadNewChapters : Job Chapter[] chapters = mangaConnector.GetNewChapters(manga, this.translatedLanguage); this.progressToken.increments = chapters.Length; List jobs = new(); - if(chapters.Any()) - mangaConnector.CopyCoverFromCacheToDownloadLocation(manga); + mangaConnector.CopyCoverFromCacheToDownloadLocation(manga); foreach (Chapter chapter in chapters) { DownloadChapter downloadChapterJob = new(this, this.mangaConnector, chapter, parentJobId: this.id); From e31820eb004da001487b8489d1382ff6ad6ae2bc Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:49:42 +0200 Subject: [PATCH 10/30] Export Jobs list when finished. --- Tranga/Jobs/JobBoss.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index a54a023..d8a04a7 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -220,12 +220,15 @@ public class JobBoss : GlobalBase queueHead.progressToken.Complete(); break; } + queueHead.ResetProgress(); jobQueue.Dequeue(); + ExportJobsList(); }else if (queueHead.progressToken.state is ProgressToken.State.Standby) { Job[] subJobs = jobQueue.Peek().ExecuteReturnSubTasks().ToArray(); AddJobs(subJobs); AddJobsToQueue(subJobs); + ExportJobsList(); } } } From 0209159c5c3ecab14f6c4fa9631164d3c082e726 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:50:39 +0200 Subject: [PATCH 11/30] Add log to see wait time --- Tranga/Jobs/JobBoss.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index d8a04a7..6c5314f 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -223,6 +223,7 @@ public class JobBoss : GlobalBase queueHead.ResetProgress(); jobQueue.Dequeue(); ExportJobsList(); + Log($"Next job in {jobQueue.Peek().nextExecution.Subtract(DateTime.Now)}"); }else if (queueHead.progressToken.state is ProgressToken.State.Standby) { Job[] subJobs = jobQueue.Peek().ExecuteReturnSubTasks().ToArray(); From b149d377dc381bbb6da441e003d22e37399fa594 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:54:00 +0200 Subject: [PATCH 12/30] Add log to see wait time --- Tranga/Jobs/JobBoss.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 6c5314f..db5e17e 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -223,7 +223,7 @@ public class JobBoss : GlobalBase queueHead.ResetProgress(); jobQueue.Dequeue(); ExportJobsList(); - Log($"Next job in {jobQueue.Peek().nextExecution.Subtract(DateTime.Now)}"); + Log($"Next job in {jobs.OrderBy(job => job.nextExecution).First().nextExecution.Subtract(DateTime.Now)}"); }else if (queueHead.progressToken.state is ProgressToken.State.Standby) { Job[] subJobs = jobQueue.Peek().ExecuteReturnSubTasks().ToArray(); From 2553a150d13ff0d84959c0109be7b591a4d85da8 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:54:26 +0200 Subject: [PATCH 13/30] Add log to see wait time --- Tranga/Jobs/JobBoss.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index db5e17e..20a450b 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -223,7 +223,7 @@ public class JobBoss : GlobalBase queueHead.ResetProgress(); jobQueue.Dequeue(); ExportJobsList(); - Log($"Next job in {jobs.OrderBy(job => job.nextExecution).First().nextExecution.Subtract(DateTime.Now)}"); + Log($"Next job in {jobs.MinBy(job => job.nextExecution)?.nextExecution.Subtract(DateTime.Now)}"); }else if (queueHead.progressToken.state is ProgressToken.State.Standby) { Job[] subJobs = jobQueue.Peek().ExecuteReturnSubTasks().ToArray(); From f5b6b1785f0870b99467437cba0f65f1628c9646 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:57:35 +0200 Subject: [PATCH 14/30] small improvements --- Tranga/Jobs/Job.cs | 4 ++-- Tranga/Jobs/JobBoss.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tranga/Jobs/Job.cs b/Tranga/Jobs/Job.cs index 86d5b19..f76253c 100644 --- a/Tranga/Jobs/Job.cs +++ b/Tranga/Jobs/Job.cs @@ -59,13 +59,13 @@ public abstract class Job : GlobalBase public void ResetProgress() { - this.progressToken.increments = this.progressToken.increments - this.progressToken.incrementsCompleted; + this.progressToken.increments -= progressToken.incrementsCompleted; this.lastExecution = DateTime.Now; } public void ExecutionEnqueue() { - this.progressToken.increments = this.progressToken.increments - this.progressToken.incrementsCompleted; + this.progressToken.increments -= progressToken.incrementsCompleted; this.lastExecution = recurrenceTime is not null ? DateTime.Now.Subtract((TimeSpan)recurrenceTime) : DateTime.UnixEpoch; this.progressToken.Standby(); } diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 20a450b..8ab05e4 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -223,7 +223,7 @@ public class JobBoss : GlobalBase queueHead.ResetProgress(); jobQueue.Dequeue(); ExportJobsList(); - Log($"Next job in {jobs.MinBy(job => job.nextExecution)?.nextExecution.Subtract(DateTime.Now)}"); + Log($"Next job in {jobs.MinBy(job => job.nextExecution)?.nextExecution.Subtract(DateTime.Now)} {jobs.MinBy(job => job.nextExecution)?.id}"); }else if (queueHead.progressToken.state is ProgressToken.State.Standby) { Job[] subJobs = jobQueue.Peek().ExecuteReturnSubTasks().ToArray(); From c1aa4cf6b57f5a765f1949cb3a2be47fdf40a06f Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 19:59:51 +0200 Subject: [PATCH 15/30] Fi bug with exportjobslist not exporting updated jobs --- Tranga/Jobs/JobBoss.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 8ab05e4..477e402 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -167,14 +167,11 @@ public class JobBoss : GlobalBase foreach (Job job in this.jobs) { string jobFilePath = Path.Join(settings.jobsFolderPath, $"{job.id}.json"); - if (!File.Exists(jobFilePath)) - { - string jobStr = JsonConvert.SerializeObject(job); - while(IsFileInUse(jobFilePath)) - Thread.Sleep(10); - Log($"Exporting Job {jobFilePath}"); - File.WriteAllText(jobFilePath, jobStr); - } + string jobStr = JsonConvert.SerializeObject(job); + while(IsFileInUse(jobFilePath)) + Thread.Sleep(10); + Log($"Exporting Job {jobFilePath}"); + File.WriteAllText(jobFilePath, jobStr); } //Remove files with jobs not in this.jobs-list From 87ea0772810514b37f67449b3a419ee0520b73e2 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 20:02:56 +0200 Subject: [PATCH 16/30] Remove log clutter and filewrites --- Tranga/Jobs/JobBoss.cs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 477e402..01c4fc5 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -161,18 +161,21 @@ public class JobBoss : GlobalBase cachedPublications.Add(ncJob.manga); } + public void ExportJob(Job job) + { + string jobFilePath = Path.Join(settings.jobsFolderPath, $"{job.id}.json"); + string jobStr = JsonConvert.SerializeObject(job); + while(IsFileInUse(jobFilePath)) + Thread.Sleep(10); + Log($"Exporting Job {jobFilePath}"); + File.WriteAllText(jobFilePath, jobStr); + } + public void ExportJobsList() { Log("Exporting Jobs"); foreach (Job job in this.jobs) - { - string jobFilePath = Path.Join(settings.jobsFolderPath, $"{job.id}.json"); - string jobStr = JsonConvert.SerializeObject(job); - while(IsFileInUse(jobFilePath)) - Thread.Sleep(10); - Log($"Exporting Job {jobFilePath}"); - File.WriteAllText(jobFilePath, jobStr); - } + ExportJob(job); //Remove files with jobs not in this.jobs-list Regex idRex = new (@"(.*)\.json"); @@ -219,14 +222,13 @@ public class JobBoss : GlobalBase } queueHead.ResetProgress(); jobQueue.Dequeue(); - ExportJobsList(); + ExportJob(queueHead); Log($"Next job in {jobs.MinBy(job => job.nextExecution)?.nextExecution.Subtract(DateTime.Now)} {jobs.MinBy(job => job.nextExecution)?.id}"); }else if (queueHead.progressToken.state is ProgressToken.State.Standby) { Job[] subJobs = jobQueue.Peek().ExecuteReturnSubTasks().ToArray(); AddJobs(subJobs); AddJobsToQueue(subJobs); - ExportJobsList(); } } } From cb6482ebaece7b03477d3b3e8adbd385bc934b03 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 20:04:25 +0200 Subject: [PATCH 17/30] Add logmessage on startup for next job --- Tranga/Jobs/JobBoss.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 01c4fc5..c0426b0 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -14,6 +14,7 @@ public class JobBoss : GlobalBase this.jobs = new(); LoadJobsList(connectors); this.mangaConnectorJobQueue = new(); + Log($"Next job in {jobs.MinBy(job => job.nextExecution)?.nextExecution.Subtract(DateTime.Now)} {jobs.MinBy(job => job.nextExecution)?.id}"); } public void AddJob(Job job) From 0875e7ee123a5fe599e0d53c5a7f4dac206f8f08 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 23:07:26 +0200 Subject: [PATCH 18/30] Remove log clutter and filewrites --- Tranga/Jobs/JobBoss.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index c0426b0..141aec1 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -27,7 +27,7 @@ public class JobBoss : GlobalBase { Log($"Added {job}"); this.jobs.Add(job); - ExportJobsList(); + ExportJob(job); } } @@ -57,7 +57,7 @@ public class JobBoss : GlobalBase this.jobs.Remove(job); if(job.subJobs is not null) RemoveJobs(job.subJobs); - ExportJobsList(); + ExportJob(job); } public void RemoveJobs(IEnumerable jobsToRemove) From b6cdb07e3f59fd23d716ee521dae0886472dc88d Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 23:15:18 +0200 Subject: [PATCH 19/30] Remove filewrites --- Tranga/Jobs/JobBoss.cs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 141aec1..6ecd8ea 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -165,11 +165,28 @@ public class JobBoss : GlobalBase public void ExportJob(Job job) { string jobFilePath = Path.Join(settings.jobsFolderPath, $"{job.id}.json"); - string jobStr = JsonConvert.SerializeObject(job); - while(IsFileInUse(jobFilePath)) - Thread.Sleep(10); Log($"Exporting Job {jobFilePath}"); - File.WriteAllText(jobFilePath, jobStr); + + if (!this.jobs.Any(jjob => jjob.id == job.id)) + { + try + { + while(IsFileInUse(jobFilePath)) + Thread.Sleep(10); + File.Delete(jobFilePath); + } + catch (Exception e) + { + Log(e.ToString()); + } + } + else + { + string jobStr = JsonConvert.SerializeObject(job); + while(IsFileInUse(jobFilePath)) + Thread.Sleep(10); + File.WriteAllText(jobFilePath, jobStr); + } } public void ExportJobsList() From 482fcb710209d48a4a0c7d6fa66100cbbc62c117 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 19 Sep 2023 23:24:39 +0200 Subject: [PATCH 20/30] better logging for removing files --- Tranga/Jobs/JobBoss.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 6ecd8ea..8640600 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -165,12 +165,12 @@ public class JobBoss : GlobalBase public void ExportJob(Job job) { string jobFilePath = Path.Join(settings.jobsFolderPath, $"{job.id}.json"); - Log($"Exporting Job {jobFilePath}"); if (!this.jobs.Any(jjob => jjob.id == job.id)) { try { + Log($"Deleting Job-file {jobFilePath}"); while(IsFileInUse(jobFilePath)) Thread.Sleep(10); File.Delete(jobFilePath); @@ -182,6 +182,7 @@ public class JobBoss : GlobalBase } else { + Log($"Exporting Job {jobFilePath}"); string jobStr = JsonConvert.SerializeObject(job); while(IsFileInUse(jobFilePath)) Thread.Sleep(10); From 660f6a16480e94564c0037328688735a779737e6 Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 13:28:09 +0200 Subject: [PATCH 21/30] Logmessages for creation of library and notification Connector --- Tranga/LibraryConnectors/LibraryConnector.cs | 1 + Tranga/NotificationConnectors/NotificationConnector.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Tranga/LibraryConnectors/LibraryConnector.cs b/Tranga/LibraryConnectors/LibraryConnector.cs index cbf4446..5da0131 100644 --- a/Tranga/LibraryConnectors/LibraryConnector.cs +++ b/Tranga/LibraryConnectors/LibraryConnector.cs @@ -21,6 +21,7 @@ public abstract class LibraryConnector : GlobalBase protected LibraryConnector(GlobalBase clone, string baseUrl, string auth, LibraryType libraryType) : base(clone) { + Log($"Creating libraryConnector {Enum.GetName(libraryType)}"); Regex urlRex = new(@"https?:\/\/[0-9A-z\.]*"); if (!urlRex.IsMatch(baseUrl)) throw new ArgumentException("Base url does not match pattern"); diff --git a/Tranga/NotificationConnectors/NotificationConnector.cs b/Tranga/NotificationConnectors/NotificationConnector.cs index 7734371..c497657 100644 --- a/Tranga/NotificationConnectors/NotificationConnector.cs +++ b/Tranga/NotificationConnectors/NotificationConnector.cs @@ -6,6 +6,7 @@ public abstract class NotificationConnector : GlobalBase protected NotificationConnector(GlobalBase clone, NotificationConnectorType notificationConnectorType) : base(clone) { + Log($"Creating notificationConnector {Enum.GetName(notificationConnectorType)}"); this.notificationConnectorType = notificationConnectorType; } From 7a14583d6ac7da94f8c442382906678ed55f8429 Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 13:30:52 +0200 Subject: [PATCH 22/30] Moved Regex for baseUrl to Globalbase --- Tranga/GlobalBase.cs | 2 ++ Tranga/LibraryConnectors/LibraryConnector.cs | 5 ++--- Tranga/NotificationConnectors/Gotify.cs | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Tranga/GlobalBase.cs b/Tranga/GlobalBase.cs index 34b3cd7..89e66f0 100644 --- a/Tranga/GlobalBase.cs +++ b/Tranga/GlobalBase.cs @@ -1,4 +1,5 @@ using System.Globalization; +using System.Text.RegularExpressions; using Logging; using Newtonsoft.Json; using Tranga.LibraryConnectors; @@ -14,6 +15,7 @@ public abstract class GlobalBase protected HashSet libraryConnectors { get; init; } protected List cachedPublications { get; init; } protected static readonly NumberFormatInfo numberFormatDecimalPoint = new (){ NumberDecimalSeparator = "." }; + protected static readonly Regex baseUrlRex = new(@"https?:\/\/[0-9A-z\.]*"); protected GlobalBase(GlobalBase clone) { diff --git a/Tranga/LibraryConnectors/LibraryConnector.cs b/Tranga/LibraryConnectors/LibraryConnector.cs index 5da0131..64ba213 100644 --- a/Tranga/LibraryConnectors/LibraryConnector.cs +++ b/Tranga/LibraryConnectors/LibraryConnector.cs @@ -22,10 +22,9 @@ public abstract class LibraryConnector : GlobalBase protected LibraryConnector(GlobalBase clone, string baseUrl, string auth, LibraryType libraryType) : base(clone) { Log($"Creating libraryConnector {Enum.GetName(libraryType)}"); - Regex urlRex = new(@"https?:\/\/[0-9A-z\.]*"); - if (!urlRex.IsMatch(baseUrl)) + if (!baseUrlRex.IsMatch(baseUrl)) throw new ArgumentException("Base url does not match pattern"); - this.baseUrl = urlRex.Match(baseUrl).Value; + this.baseUrl = baseUrlRex.Match(baseUrl).Value; this.auth = auth; this.libraryType = libraryType; } diff --git a/Tranga/NotificationConnectors/Gotify.cs b/Tranga/NotificationConnectors/Gotify.cs index deb8b57..cbe3d9c 100644 --- a/Tranga/NotificationConnectors/Gotify.cs +++ b/Tranga/NotificationConnectors/Gotify.cs @@ -13,7 +13,9 @@ public class Gotify : NotificationConnector [JsonConstructor] public Gotify(GlobalBase clone, string endpoint, string appToken) : base(clone, NotificationConnectorType.Gotify) { - this.endpoint = endpoint; + if (!baseUrlRex.IsMatch(endpoint)) + throw new ArgumentException("endpoint does not match pattern"); + this.endpoint = baseUrlRex.Match(endpoint).Value;; this.appToken = appToken; } From 2699f35b62addfc34f3d520e641f81d3350a0700 Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 13:33:13 +0200 Subject: [PATCH 23/30] housekeeping --- Tranga/Jobs/DownloadChapter.cs | 3 +-- Tranga/LibraryConnectors/LibraryConnector.cs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Tranga/Jobs/DownloadChapter.cs b/Tranga/Jobs/DownloadChapter.cs index 9d0fe10..dc81368 100644 --- a/Tranga/Jobs/DownloadChapter.cs +++ b/Tranga/Jobs/DownloadChapter.cs @@ -1,5 +1,4 @@ -using System.Text; -using Tranga.MangaConnectors; +using Tranga.MangaConnectors; namespace Tranga.Jobs; diff --git a/Tranga/LibraryConnectors/LibraryConnector.cs b/Tranga/LibraryConnectors/LibraryConnector.cs index 64ba213..3c975e7 100644 --- a/Tranga/LibraryConnectors/LibraryConnector.cs +++ b/Tranga/LibraryConnectors/LibraryConnector.cs @@ -1,6 +1,5 @@ using System.Net; using System.Net.Http.Headers; -using System.Text.RegularExpressions; using Logging; namespace Tranga.LibraryConnectors; From b3b1971dad3ed1f4224230f178505aa87df21beb Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 13:58:10 +0200 Subject: [PATCH 24/30] Startup notification --- Tranga/Tranga.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tranga/Tranga.cs b/Tranga/Tranga.cs index 02ccded..86ffc1e 100644 --- a/Tranga/Tranga.cs +++ b/Tranga/Tranga.cs @@ -27,6 +27,8 @@ public partial class Tranga : GlobalBase jobBoss = new(this, this._connectors); StartJobBoss(); this._server = new Server(this); + string[] emojis = { "(•‿•)", "(づ \u25d5‿\u25d5 )づ", "( \u02d8\u25bd\u02d8)っ\u2668", "=\uff3e\u25cf \u22cf \u25cf\uff3e=", "(ΦωΦ)", "(\u272a\u3268\u272a)", "( ノ・o・ )ノ", "(〜^\u2207^ )〜", "~(\u2267ω\u2266)~","૮ \u00b4• ﻌ \u00b4• ა", "(\u02c3ᆺ\u02c2)", "(=\ud83d\udf66 \u0f1d \ud83d\udf66=)"}; + SendNotifications("Tranga Started", emojis[Random.Shared.Next(0,emojis.Length-1)]); } public MangaConnector? GetConnector(string name) From 4e5a6fe97b779dc4af68e82bf0214dd549666e25 Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 14:11:31 +0200 Subject: [PATCH 25/30] Export Library and notification connectors on deletion Added logging --- Tranga/GlobalBase.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Tranga/GlobalBase.cs b/Tranga/GlobalBase.cs index 89e66f0..bdc104e 100644 --- a/Tranga/GlobalBase.cs +++ b/Tranga/GlobalBase.cs @@ -54,11 +54,12 @@ public abstract class GlobalBase protected void AddNotificationConnector(NotificationConnector notificationConnector) { Log($"Adding {notificationConnector}"); - notificationConnectors.RemoveWhere(nc => nc.GetType() == notificationConnector.GetType()); + notificationConnectors.RemoveWhere(nc => nc.notificationConnectorType == notificationConnector.notificationConnectorType); notificationConnectors.Add(notificationConnector); while(IsFileInUse(settings.notificationConnectorsFilePath)) Thread.Sleep(100); + Log("Exporting notificationConnectors"); File.WriteAllText(settings.notificationConnectorsFilePath, JsonConvert.SerializeObject(notificationConnectors)); } @@ -66,6 +67,10 @@ public abstract class GlobalBase { Log($"Removing {notificationConnectorType}"); notificationConnectors.RemoveWhere(nc => nc.notificationConnectorType == notificationConnectorType); + while(IsFileInUse(settings.notificationConnectorsFilePath)) + Thread.Sleep(100); + Log("Exporting notificationConnectors"); + File.WriteAllText(settings.notificationConnectorsFilePath, JsonConvert.SerializeObject(notificationConnectors)); } protected void UpdateLibraries() @@ -77,11 +82,12 @@ public abstract class GlobalBase protected void AddLibraryConnector(LibraryConnector libraryConnector) { Log($"Adding {libraryConnector}"); - libraryConnectors.RemoveWhere(lc => lc.GetType() == libraryConnector.GetType()); + libraryConnectors.RemoveWhere(lc => lc.libraryType == libraryConnector.libraryType); libraryConnectors.Add(libraryConnector); while(IsFileInUse(settings.libraryConnectorsFilePath)) Thread.Sleep(100); + Log("Exporting libraryConnectors"); File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors)); } @@ -89,6 +95,10 @@ public abstract class GlobalBase { Log($"Removing {libraryType}"); libraryConnectors.RemoveWhere(lc => lc.libraryType == libraryType); + while(IsFileInUse(settings.libraryConnectorsFilePath)) + Thread.Sleep(100); + Log("Exporting libraryConnectors"); + File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors)); } protected bool IsFileInUse(string filePath) From 3ceee63dfc893d84733b8a2deaa6b83fb06a005d Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 14:40:03 +0200 Subject: [PATCH 26/30] Only send notification on successful downloads --- Tranga/Jobs/DownloadChapter.cs | 12 ++++++++---- Tranga/MangaConnectors/MangaConnector.cs | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Tranga/Jobs/DownloadChapter.cs b/Tranga/Jobs/DownloadChapter.cs index dc81368..d01fd49 100644 --- a/Tranga/Jobs/DownloadChapter.cs +++ b/Tranga/Jobs/DownloadChapter.cs @@ -1,4 +1,5 @@ -using Tranga.MangaConnectors; +using System.Net; +using Tranga.MangaConnectors; namespace Tranga.Jobs; @@ -31,9 +32,12 @@ public class DownloadChapter : Job Task downloadTask = new(delegate { mangaConnector.CopyCoverFromCacheToDownloadLocation(chapter.parentManga); - mangaConnector.DownloadChapter(chapter, this.progressToken); - UpdateLibraries(); - SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}"); + HttpStatusCode success = mangaConnector.DownloadChapter(chapter, this.progressToken); + if (success == HttpStatusCode.OK) + { + UpdateLibraries(); + SendNotifications("Chapter downloaded", $"{chapter.parentManga.sortName} - {chapter.chapterNumber}"); + } }); downloadTask.Start(); return Array.Empty(); diff --git a/Tranga/MangaConnectors/MangaConnector.cs b/Tranga/MangaConnectors/MangaConnector.cs index 09fb7f2..d8ddacb 100644 --- a/Tranga/MangaConnectors/MangaConnector.cs +++ b/Tranga/MangaConnectors/MangaConnector.cs @@ -200,7 +200,7 @@ public abstract class MangaConnector : GlobalBase Directory.CreateDirectory(directoryPath); if (File.Exists(saveArchiveFilePath)) //Don't download twice. - return HttpStatusCode.OK; + return HttpStatusCode.Created; //Create a temporary folder to store images string tempFolder = Directory.CreateTempSubdirectory().FullName; From 23cda74487a202ecc3a91824450e7c8c1077904c Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 21:33:53 +0200 Subject: [PATCH 27/30] Fix wrong domain regex --- Tranga/GlobalBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tranga/GlobalBase.cs b/Tranga/GlobalBase.cs index bdc104e..52f7540 100644 --- a/Tranga/GlobalBase.cs +++ b/Tranga/GlobalBase.cs @@ -15,7 +15,7 @@ public abstract class GlobalBase protected HashSet libraryConnectors { get; init; } protected List cachedPublications { get; init; } protected static readonly NumberFormatInfo numberFormatDecimalPoint = new (){ NumberDecimalSeparator = "." }; - protected static readonly Regex baseUrlRex = new(@"https?:\/\/[0-9A-z\.]*"); + protected static readonly Regex baseUrlRex = new(@"https?:\/\/[0-9A-z\.-]*"); protected GlobalBase(GlobalBase clone) { From 306cb87d67292eb4fb0e5a4bf4d9c599642cdf66 Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 21:34:04 +0200 Subject: [PATCH 28/30] Fix Check for subjobs --- Tranga/Jobs/JobBoss.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 8640600..8ddf01d 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -55,7 +55,7 @@ public class JobBoss : GlobalBase Log($"Removing {job}"); job.Cancel(); this.jobs.Remove(job); - if(job.subJobs is not null) + if(job.subJobs is not null && job.subJobs.Any()) RemoveJobs(job.subJobs); ExportJob(job); } From 3c2ce266f6eb266c52e6c0507e94b392a421082f Mon Sep 17 00:00:00 2001 From: glax Date: Wed, 20 Sep 2023 21:59:39 +0200 Subject: [PATCH 29/30] Changed (fixed?) queuelogic --- Tranga/Jobs/Job.cs | 2 +- Tranga/Jobs/JobBoss.cs | 16 +++------------- Tranga/Jobs/ProgressToken.cs | 9 +++++++-- Tranga/Tranga.cs | 5 ----- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Tranga/Jobs/Job.cs b/Tranga/Jobs/Job.cs index f76253c..0f0fc5d 100644 --- a/Tranga/Jobs/Job.cs +++ b/Tranga/Jobs/Job.cs @@ -61,12 +61,12 @@ public abstract class Job : GlobalBase { this.progressToken.increments -= progressToken.incrementsCompleted; this.lastExecution = DateTime.Now; + this.progressToken.Waiting(); } public void ExecutionEnqueue() { this.progressToken.increments -= progressToken.incrementsCompleted; - this.lastExecution = recurrenceTime is not null ? DateTime.Now.Subtract((TimeSpan)recurrenceTime) : DateTime.UnixEpoch; this.progressToken.Standby(); } diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index 8ddf01d..7be8a0c 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -220,8 +220,7 @@ public class JobBoss : GlobalBase public void CheckJobs() { - foreach (Job job in jobs.Where(job => job.nextExecution < DateTime.Now && !QueueContainsJob(job)).OrderBy(job => job.nextExecution)) - AddJobToQueue(job); + AddJobsToQueue(jobs.Where(job => job.progressToken.state == ProgressToken.State.Waiting && job.nextExecution < DateTime.Now && !QueueContainsJob(job)).OrderBy(job => job.nextExecution)); foreach (Queue jobQueue in mangaConnectorJobQueue.Values) { if(jobQueue.Count < 1) @@ -229,19 +228,10 @@ public class JobBoss : GlobalBase Job queueHead = jobQueue.Peek(); if (queueHead.progressToken.state is ProgressToken.State.Complete or ProgressToken.State.Cancelled) { - switch (queueHead) - { - case DownloadChapter: - RemoveJob(queueHead); - break; - case DownloadNewChapters: - if(queueHead.recurring) - queueHead.progressToken.Complete(); - break; - } queueHead.ResetProgress(); + if(!queueHead.recurring) + RemoveJob(queueHead); jobQueue.Dequeue(); - ExportJob(queueHead); Log($"Next job in {jobs.MinBy(job => job.nextExecution)?.nextExecution.Subtract(DateTime.Now)} {jobs.MinBy(job => job.nextExecution)?.id}"); }else if (queueHead.progressToken.state is ProgressToken.State.Standby) { diff --git a/Tranga/Jobs/ProgressToken.cs b/Tranga/Jobs/ProgressToken.cs index 9bada05..f23819d 100644 --- a/Tranga/Jobs/ProgressToken.cs +++ b/Tranga/Jobs/ProgressToken.cs @@ -10,7 +10,7 @@ public class ProgressToken public DateTime executionStarted { get; private set; } public TimeSpan timeRemaining => GetTimeRemaining(); - public enum State { Running, Complete, Standby, Cancelled } + public enum State { Running, Complete, Standby, Cancelled, Waiting } public State state { get; private set; } public ProgressToken(int increments) @@ -18,7 +18,7 @@ public class ProgressToken this.cancellationRequested = false; this.increments = increments; this.incrementsCompleted = 0; - this.state = State.Complete; + this.state = State.Waiting; this.executionStarted = DateTime.UnixEpoch; } @@ -63,4 +63,9 @@ public class ProgressToken { state = State.Cancelled; } + + public void Waiting() + { + state = State.Waiting; + } } \ No newline at end of file diff --git a/Tranga/Tranga.cs b/Tranga/Tranga.cs index 86ffc1e..23846b8 100644 --- a/Tranga/Tranga.cs +++ b/Tranga/Tranga.cs @@ -72,11 +72,6 @@ public partial class Tranga : GlobalBase jobBoss.CheckJobs(); Thread.Sleep(100); } - - foreach (MangaConnector connector in _connectors) - { - - } }); t.Start(); } From fc7d5463c3e0c8f9c58ce83c0a999f95d3526388 Mon Sep 17 00:00:00 2001 From: glax Date: Tue, 26 Sep 2023 18:03:18 +0200 Subject: [PATCH 30/30] Fix #58 Mangaworld: Manga without volumes crash --- Tranga/MangaConnectors/Mangaworld.cs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Tranga/MangaConnectors/Mangaworld.cs b/Tranga/MangaConnectors/Mangaworld.cs index 9501b21..8b47866 100644 --- a/Tranga/MangaConnectors/Mangaworld.cs +++ b/Tranga/MangaConnectors/Mangaworld.cs @@ -134,15 +134,30 @@ public class Mangaworld: MangaConnector { List ret = new(); - foreach (HtmlNode volNode in document.DocumentNode.SelectNodes( - "//div[contains(concat(' ',normalize-space(@class),' '),'chapters-wrapper')]//div[contains(concat(' ',normalize-space(@class),' '),'volume-element')]")) + HtmlNode chaptersWrapper = + document.DocumentNode.SelectSingleNode( + "//div[contains(concat(' ',normalize-space(@class),' '),'chapters-wrapper')]"); + + if (chaptersWrapper.Descendants("div").Any(descendant => descendant.HasClass("volume-element"))) { - string volume = volNode.SelectNodes("div").First(node => node.HasClass("volume")).SelectSingleNode("p").InnerText.Split(' ')[^1]; - foreach (HtmlNode chNode in volNode.SelectNodes("div").First(node => node.HasClass("volume-chapters")).SelectNodes("div")) + foreach (HtmlNode volNode in document.DocumentNode.SelectNodes("//div[contains(concat(' ',normalize-space(@class),' '),'volume-element')]")) + { + string volume = volNode.SelectNodes("div").First(node => node.HasClass("volume")).SelectSingleNode("p").InnerText.Split(' ')[^1]; + foreach (HtmlNode chNode in volNode.SelectNodes("div").First(node => node.HasClass("volume-chapters")).SelectNodes("div")) + { + string number = chNode.SelectSingleNode("a").SelectSingleNode("span").InnerText.Split(" ")[^1]; + string url = chNode.SelectSingleNode("a").GetAttributeValue("href", ""); + ret.Add(new Chapter(manga, null, volume, number, url)); + } + } + } + else + { + foreach (HtmlNode chNode in chaptersWrapper.SelectNodes("div").Where(node => node.HasClass("chapter"))) { string number = chNode.SelectSingleNode("a").SelectSingleNode("span").InnerText.Split(" ")[^1]; string url = chNode.SelectSingleNode("a").GetAttributeValue("href", ""); - ret.Add(new Chapter(manga, null, volume, number, url)); + ret.Add(new Chapter(manga, null, null, number, url)); } }