From 63b493fa9ce4d858a8577584a3ae8959e124275d Mon Sep 17 00:00:00 2001 From: Glax Date: Mon, 26 Aug 2024 12:36:35 +0200 Subject: [PATCH] Rework TrangaSettings --- CLI/Program.cs | 33 +--- Tranga/Chapter.cs | 12 +- Tranga/GlobalBase.cs | 25 ++- Tranga/Jobs/DownloadNewChapters.cs | 2 +- Tranga/Jobs/JobBoss.cs | 12 +- Tranga/Jobs/UpdateMetadata.cs | 2 +- Tranga/Manga.cs | 4 +- Tranga/MangaConnectors/Bato.cs | 2 +- Tranga/MangaConnectors/DownloadClient.cs | 6 +- Tranga/MangaConnectors/HttpDownloadClient.cs | 2 +- Tranga/MangaConnectors/MangaConnector.cs | 10 +- Tranga/MangaConnectors/MangaDex.cs | 2 +- Tranga/MangaConnectors/MangaHere.cs | 2 +- Tranga/MangaConnectors/MangaKatana.cs | 2 +- Tranga/MangaConnectors/MangaLife.cs | 2 +- Tranga/MangaConnectors/Manganato.cs | 2 +- Tranga/MangaConnectors/Mangasee.cs | 2 +- Tranga/MangaConnectors/Mangaworld.cs | 2 +- Tranga/MangaConnectors/ManhuaPlus.cs | 2 +- Tranga/Server.cs | 38 ++--- Tranga/Tranga.cs | 5 +- Tranga/TrangaArgs.cs | 32 +--- Tranga/TrangaSettings.cs | 163 ++++++++++--------- 23 files changed, 163 insertions(+), 201 deletions(-) diff --git a/CLI/Program.cs b/CLI/Program.cs index ec21751..f927ea2 100644 --- a/CLI/Program.cs +++ b/CLI/Program.cs @@ -47,37 +47,16 @@ internal sealed class TrangaCli : Command string? logFolderPath = settings.fileLoggerPath ?? ""; Logger logger = new(enabledLoggers.ToArray(), Console.Out, Console.OutputEncoding, logFolderPath); - TrangaSettings? trangaSettings = null; - - if (settings.downloadLocation is not null && settings.workingDirectory is not null) - { - trangaSettings = new TrangaSettings(settings.downloadLocation, settings.workingDirectory); - }else if (settings.downloadLocation is not null) - { - if (trangaSettings is null) - trangaSettings = new TrangaSettings(downloadLocation: settings.downloadLocation); - else - trangaSettings = new TrangaSettings(downloadLocation: settings.downloadLocation, settings.workingDirectory); - }else if (settings.workingDirectory is not null) - { - if (trangaSettings is null) - trangaSettings = new TrangaSettings(downloadLocation: settings.workingDirectory); - else - trangaSettings = new TrangaSettings(settings.downloadLocation, settings.workingDirectory); - } - else - { - trangaSettings = new TrangaSettings(); - } - - Directory.CreateDirectory(trangaSettings.downloadLocation); - Directory.CreateDirectory(trangaSettings.workingDirectory); + if(settings.workingDirectory is not null) + TrangaSettings.LoadFromWorkingDirectory(settings.workingDirectory); + if(settings.downloadLocation is not null) + TrangaSettings.CreateOrUpdate(downloadDirectory: settings.downloadLocation); Tranga.Tranga? api = null; Thread trangaApi = new Thread(() => { - api = new(logger, trangaSettings); + api = new(logger); }); trangaApi.Start(); @@ -120,7 +99,7 @@ internal sealed class TrangaCli : Command parameters.Add(new ValueTuple(name, value)); } - string requestString = $"http://localhost:{trangaSettings.apiPortNumber}/{requestPath}"; + string requestString = $"http://localhost:{TrangaSettings.apiPortNumber}/{requestPath}"; if (parameters.Any()) { requestString += "?"; diff --git a/Tranga/Chapter.cs b/Tranga/Chapter.cs index 4677d7b..369b8fc 100644 --- a/Tranga/Chapter.cs +++ b/Tranga/Chapter.cs @@ -87,15 +87,15 @@ public readonly struct Chapter : IComparable /// Checks if a chapter-archive is already present /// /// true if chapter is present - internal bool CheckChapterIsDownloaded(string downloadLocation) + internal bool CheckChapterIsDownloaded() { - if (!Directory.Exists(Path.Join(downloadLocation, parentManga.folderName))) + if (!Directory.Exists(Path.Join(TrangaSettings.downloadLocation, parentManga.folderName))) return false; - FileInfo[] archives = new DirectoryInfo(Path.Join(downloadLocation, parentManga.folderName)).GetFiles().Where(file => file.Name.Split('.')[^1] == "cbz").ToArray(); + FileInfo[] archives = new DirectoryInfo(Path.Join(TrangaSettings.downloadLocation, parentManga.folderName)).GetFiles().Where(file => file.Name.Split('.')[^1] == "cbz").ToArray(); Regex volChRex = new(@"(?:Vol(?:ume)?\.([0-9]+)\D*)?Ch(?:apter)?\.([0-9]+(?:\.[0-9]+)*)"); Chapter t = this; - string thisPath = GetArchiveFilePath(downloadLocation); + string thisPath = GetArchiveFilePath(); FileInfo? archive = archives.FirstOrDefault(archive => { Match m = volChRex.Match(archive.Name); @@ -112,9 +112,9 @@ public readonly struct Chapter : IComparable /// Creates full file path of chapter-archive /// /// Filepath - internal string GetArchiveFilePath(string downloadLocation) + internal string GetArchiveFilePath() { - return Path.Join(downloadLocation, parentManga.folderName, $"{parentManga.folderName} - {this.fileName}.cbz"); + return Path.Join(TrangaSettings.downloadLocation, parentManga.folderName, $"{parentManga.folderName} - {this.fileName}.cbz"); } /// diff --git a/Tranga/GlobalBase.cs b/Tranga/GlobalBase.cs index f372f2c..49a0d79 100644 --- a/Tranga/GlobalBase.cs +++ b/Tranga/GlobalBase.cs @@ -11,7 +11,6 @@ public abstract class GlobalBase { [JsonIgnore] public Logger? logger { get; init; } - protected TrangaSettings settings { get; init; } protected HashSet notificationConnectors { get; init; } protected HashSet libraryConnectors { get; init; } private Dictionary cachedPublications { get; init; } @@ -21,18 +20,16 @@ public abstract class GlobalBase protected GlobalBase(GlobalBase clone) { this.logger = clone.logger; - this.settings = clone.settings; this.notificationConnectors = clone.notificationConnectors; this.libraryConnectors = clone.libraryConnectors; this.cachedPublications = clone.cachedPublications; } - protected GlobalBase(Logger? logger, TrangaSettings settings) + protected GlobalBase(Logger? logger) { this.logger = logger; - this.settings = settings; - this.notificationConnectors = settings.LoadNotificationConnectors(this); - this.libraryConnectors = settings.LoadLibraryConnectors(this); + this.notificationConnectors = TrangaSettings.LoadNotificationConnectors(this); + this.libraryConnectors = TrangaSettings.LoadLibraryConnectors(this); this.cachedPublications = new(); } @@ -81,20 +78,20 @@ public abstract class GlobalBase notificationConnectors.RemoveWhere(nc => nc.notificationConnectorType == notificationConnector.notificationConnectorType); notificationConnectors.Add(notificationConnector); - while(IsFileInUse(settings.notificationConnectorsFilePath)) + while(IsFileInUse(TrangaSettings.notificationConnectorsFilePath)) Thread.Sleep(100); Log("Exporting notificationConnectors"); - File.WriteAllText(settings.notificationConnectorsFilePath, JsonConvert.SerializeObject(notificationConnectors)); + File.WriteAllText(TrangaSettings.notificationConnectorsFilePath, JsonConvert.SerializeObject(notificationConnectors)); } protected void DeleteNotificationConnector(NotificationConnector.NotificationConnectorType notificationConnectorType) { Log($"Removing {notificationConnectorType}"); notificationConnectors.RemoveWhere(nc => nc.notificationConnectorType == notificationConnectorType); - while(IsFileInUse(settings.notificationConnectorsFilePath)) + while(IsFileInUse(TrangaSettings.notificationConnectorsFilePath)) Thread.Sleep(100); Log("Exporting notificationConnectors"); - File.WriteAllText(settings.notificationConnectorsFilePath, JsonConvert.SerializeObject(notificationConnectors)); + File.WriteAllText(TrangaSettings.notificationConnectorsFilePath, JsonConvert.SerializeObject(notificationConnectors)); } protected void UpdateLibraries() @@ -109,20 +106,20 @@ public abstract class GlobalBase libraryConnectors.RemoveWhere(lc => lc.libraryType == libraryConnector.libraryType); libraryConnectors.Add(libraryConnector); - while(IsFileInUse(settings.libraryConnectorsFilePath)) + while(IsFileInUse(TrangaSettings.libraryConnectorsFilePath)) Thread.Sleep(100); Log("Exporting libraryConnectors"); - File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented)); + File.WriteAllText(TrangaSettings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented)); } protected void DeleteLibraryConnector(LibraryConnector.LibraryType libraryType) { Log($"Removing {libraryType}"); libraryConnectors.RemoveWhere(lc => lc.libraryType == libraryType); - while(IsFileInUse(settings.libraryConnectorsFilePath)) + while(IsFileInUse(TrangaSettings.libraryConnectorsFilePath)) Thread.Sleep(100); Log("Exporting libraryConnectors"); - File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented)); + File.WriteAllText(TrangaSettings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented)); } protected bool IsFileInUse(string filePath) => IsFileInUse(filePath, this.logger); diff --git a/Tranga/Jobs/DownloadNewChapters.cs b/Tranga/Jobs/DownloadNewChapters.cs index ebcbde7..29c3e60 100644 --- a/Tranga/Jobs/DownloadNewChapters.cs +++ b/Tranga/Jobs/DownloadNewChapters.cs @@ -33,7 +33,7 @@ public class DownloadNewChapters : Job protected override IEnumerable ExecuteReturnSubTasksInternal(JobBoss jobBoss) { - manga.SaveSeriesInfoJson(settings.downloadLocation); + manga.SaveSeriesInfoJson(); Chapter[] chapters = mangaConnector.GetNewChapters(manga, this.translatedLanguage); this.progressToken.increments = chapters.Length; List jobs = new(); diff --git a/Tranga/Jobs/JobBoss.cs b/Tranga/Jobs/JobBoss.cs index c5324d0..610d70c 100644 --- a/Tranga/Jobs/JobBoss.cs +++ b/Tranga/Jobs/JobBoss.cs @@ -140,15 +140,15 @@ public class JobBoss : GlobalBase private void LoadJobsList(HashSet connectors) { - if (!Directory.Exists(settings.jobsFolderPath)) //No jobs to load + if (!Directory.Exists(TrangaSettings.jobsFolderPath)) //No jobs to load { - Directory.CreateDirectory(settings.jobsFolderPath); + Directory.CreateDirectory(TrangaSettings.jobsFolderPath); return; } Regex idRex = new (@"(.*)\.json"); //Load json-job-files - foreach (FileInfo file in new DirectoryInfo(settings.jobsFolderPath).EnumerateFiles().Where(fileInfo => idRex.IsMatch(fileInfo.Name))) + foreach (FileInfo file in new DirectoryInfo(TrangaSettings.jobsFolderPath).EnumerateFiles().Where(fileInfo => idRex.IsMatch(fileInfo.Name))) { Log($"Adding {file.Name}"); Job? job = JsonConvert.DeserializeObject(File.ReadAllText(file.FullName), @@ -180,14 +180,14 @@ public class JobBoss : GlobalBase AddMangaToCache(dncJob.manga); } - string[] coverFiles = Directory.GetFiles(settings.coverImageCache); + string[] coverFiles = Directory.GetFiles(TrangaSettings.coverImageCache); foreach(string fileName in coverFiles.Where(fileName => !GetAllCachedManga().Any(manga => manga.coverFileNameInCache == fileName))) File.Delete(fileName); } internal void UpdateJobFile(Job job, string? oldFile = null) { - string newJobFilePath = Path.Join(settings.jobsFolderPath, $"{job.id}.json"); + string newJobFilePath = Path.Join(TrangaSettings.jobsFolderPath, $"{job.id}.json"); if (!this.jobs.Any(jjob => jjob.id == job.id)) { @@ -234,7 +234,7 @@ public class JobBoss : GlobalBase //Remove files with jobs not in this.jobs-list Regex idRex = new (@"(.*)\.json"); - foreach (FileInfo file in new DirectoryInfo(settings.jobsFolderPath).EnumerateFiles()) + foreach (FileInfo file in new DirectoryInfo(TrangaSettings.jobsFolderPath).EnumerateFiles()) { if (idRex.IsMatch(file.Name)) { diff --git a/Tranga/Jobs/UpdateMetadata.cs b/Tranga/Jobs/UpdateMetadata.cs index 4dc3ae7..72b5a60 100644 --- a/Tranga/Jobs/UpdateMetadata.cs +++ b/Tranga/Jobs/UpdateMetadata.cs @@ -34,7 +34,7 @@ public class UpdateMetadata : Job } this.manga = manga.WithMetadata(updatedManga); - this.manga.SaveSeriesInfoJson(settings.downloadLocation, true); + this.manga.SaveSeriesInfoJson(true); this.mangaConnector.CopyCoverFromCacheToDownloadLocation(manga); foreach (Job job in jobBoss.GetJobsLike(publication: this.manga)) { diff --git a/Tranga/Manga.cs b/Tranga/Manga.cs index 22fc99a..5ebad19 100644 --- a/Tranga/Manga.cs +++ b/Tranga/Manga.cs @@ -140,9 +140,9 @@ public struct Manga latestChapterDownloaded = latestChapterDownloaded < chapterNumber ? chapterNumber : latestChapterDownloaded; } - public void SaveSeriesInfoJson(string downloadDirectory, bool overwrite = false) + public void SaveSeriesInfoJson(bool overwrite = false) { - string publicationFolder = CreatePublicationFolder(downloadDirectory); + string publicationFolder = CreatePublicationFolder(TrangaSettings.downloadLocation); string seriesInfoPath = Path.Join(publicationFolder, "series.json"); if(overwrite || (!overwrite && !File.Exists(seriesInfoPath))) File.WriteAllText(seriesInfoPath,this.GetSeriesInfoJson()); diff --git a/Tranga/MangaConnectors/Bato.cs b/Tranga/MangaConnectors/Bato.cs index d50081b..5b5f370 100644 --- a/Tranga/MangaConnectors/Bato.cs +++ b/Tranga/MangaConnectors/Bato.cs @@ -193,7 +193,7 @@ public class Bato : MangaConnector string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); - return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken); + return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken); } private string[] ParseImageUrlsFromHtml(string mangaUrl) diff --git a/Tranga/MangaConnectors/DownloadClient.cs b/Tranga/MangaConnectors/DownloadClient.cs index f6f876d..298774f 100644 --- a/Tranga/MangaConnectors/DownloadClient.cs +++ b/Tranga/MangaConnectors/DownloadClient.cs @@ -14,15 +14,15 @@ internal abstract class DownloadClient : GlobalBase public RequestResult MakeRequest(string url, RequestType requestType, string? referrer = null, string? clickButton = null) { - if (!settings.requestLimits.ContainsKey(requestType)) + if (!TrangaSettings.requestLimits.ContainsKey(requestType)) { Log("RequestType not configured for rate-limit."); return new RequestResult(HttpStatusCode.NotAcceptable, null, Stream.Null); } - int rateLimit = settings.userAgent == TrangaSettings.DefaultUserAgent + int rateLimit = TrangaSettings.userAgent == TrangaSettings.DefaultUserAgent ? TrangaSettings.DefaultRequestLimits[requestType] - : settings.requestLimits[requestType]; + : TrangaSettings.requestLimits[requestType]; TimeSpan timeBetweenRequests = TimeSpan.FromMinutes(1).Divide(rateLimit); _lastExecutedRateLimit.TryAdd(requestType, DateTime.Now.Subtract(timeBetweenRequests)); diff --git a/Tranga/MangaConnectors/HttpDownloadClient.cs b/Tranga/MangaConnectors/HttpDownloadClient.cs index 3b2e5c3..238306b 100644 --- a/Tranga/MangaConnectors/HttpDownloadClient.cs +++ b/Tranga/MangaConnectors/HttpDownloadClient.cs @@ -13,7 +13,7 @@ internal class HttpDownloadClient : DownloadClient public HttpDownloadClient(GlobalBase clone) : base(clone) { - Client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", settings.userAgent); + Client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", TrangaSettings.userAgent); } internal override RequestResult MakeRequestInternal(string url, string? referrer = null, string? clickButton = null) diff --git a/Tranga/MangaConnectors/MangaConnector.cs b/Tranga/MangaConnectors/MangaConnector.cs index 5c71de8..5af28e5 100644 --- a/Tranga/MangaConnectors/MangaConnector.cs +++ b/Tranga/MangaConnectors/MangaConnector.cs @@ -23,7 +23,7 @@ public abstract class MangaConnector : GlobalBase protected MangaConnector(GlobalBase clone, string name) : base(clone) { this.name = name; - Directory.CreateDirectory(settings.coverImageCache); + Directory.CreateDirectory(TrangaSettings.coverImageCache); } public string name { get; } //Name of the Connector (e.g. Website) @@ -65,7 +65,7 @@ public abstract class MangaConnector : GlobalBase Log($"Checking for duplicates {manga}"); List newChaptersList = allChapters.Where(nChapter => float.TryParse(nChapter.chapterNumber, numberFormatDecimalPoint, out float chapterNumber) && chapterNumber > manga.ignoreChaptersBelow - && !nChapter.CheckChapterIsDownloaded(settings.downloadLocation)).ToList(); + && !nChapter.CheckChapterIsDownloaded()).ToList(); Log($"{newChaptersList.Count} new chapters. {manga}"); try { @@ -167,7 +167,7 @@ public abstract class MangaConnector : GlobalBase { Log($"Copy cover {manga}"); //Check if Publication already has a Folder and cover - string publicationFolder = manga.CreatePublicationFolder(settings.downloadLocation); + string publicationFolder = manga.CreatePublicationFolder(TrangaSettings.downloadLocation); DirectoryInfo dirInfo = new (publicationFolder); if (dirInfo.EnumerateFiles().Any(info => info.Name.Contains("cover", StringComparison.InvariantCultureIgnoreCase))) { @@ -291,7 +291,7 @@ public abstract class MangaConnector : GlobalBase //https?:\/\/[a-zA-Z0-9-]+\.([a-zA-Z0-9-]+\.[a-zA-Z0-9]+)\/(?:.+\/)*(.+\.([a-zA-Z]+)) for only second level domains Match match = urlRex.Match(url); string filename = $"{match.Groups[1].Value}-{mangaInternalId}.{match.Groups[3].Value}"; - string saveImagePath = Path.Join(settings.coverImageCache, filename); + string saveImagePath = Path.Join(TrangaSettings.coverImageCache, filename); if (File.Exists(saveImagePath)) return saveImagePath; @@ -299,7 +299,7 @@ public abstract class MangaConnector : GlobalBase RequestResult coverResult = downloadClient.MakeRequest(url, requestType); using MemoryStream ms = new(); coverResult.result.CopyTo(ms); - Directory.CreateDirectory(settings.coverImageCache); + Directory.CreateDirectory(TrangaSettings.coverImageCache); File.WriteAllBytes(saveImagePath, ms.ToArray()); Log($"Saving cover to {saveImagePath}"); return saveImagePath; diff --git a/Tranga/MangaConnectors/MangaDex.cs b/Tranga/MangaConnectors/MangaDex.cs index 60f05fd..005da07 100644 --- a/Tranga/MangaConnectors/MangaDex.cs +++ b/Tranga/MangaConnectors/MangaDex.cs @@ -290,6 +290,6 @@ public class MangaDex : MangaConnector File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); //Download Chapter-Images - return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); + return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); } } \ No newline at end of file diff --git a/Tranga/MangaConnectors/MangaHere.cs b/Tranga/MangaConnectors/MangaHere.cs index fc9406e..0da1c5a 100644 --- a/Tranga/MangaConnectors/MangaHere.cs +++ b/Tranga/MangaConnectors/MangaHere.cs @@ -186,7 +186,7 @@ public class MangaHere : MangaConnector if (progressToken is not null) progressToken.increments = images;//we blip to normal length, in downloadchapterimages it is increasaed by the amount of urls again - return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); + return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); } private string[] ParseImageUrlsFromHtml(HtmlDocument document) diff --git a/Tranga/MangaConnectors/MangaKatana.cs b/Tranga/MangaConnectors/MangaKatana.cs index e2284c4..64ab6c4 100644 --- a/Tranga/MangaConnectors/MangaKatana.cs +++ b/Tranga/MangaConnectors/MangaKatana.cs @@ -217,7 +217,7 @@ public class MangaKatana : MangaConnector string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); - return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken); + return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken); } private string[] ParseImageUrlsFromHtml(string mangaUrl) diff --git a/Tranga/MangaConnectors/MangaLife.cs b/Tranga/MangaConnectors/MangaLife.cs index 43ca2e0..44b54a5 100644 --- a/Tranga/MangaConnectors/MangaLife.cs +++ b/Tranga/MangaConnectors/MangaLife.cs @@ -194,6 +194,6 @@ public class MangaLife : MangaConnector string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); - return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); + return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); } } \ No newline at end of file diff --git a/Tranga/MangaConnectors/Manganato.cs b/Tranga/MangaConnectors/Manganato.cs index 1f3a0e5..c0a922a 100644 --- a/Tranga/MangaConnectors/Manganato.cs +++ b/Tranga/MangaConnectors/Manganato.cs @@ -209,7 +209,7 @@ public class Manganato : MangaConnector string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); - return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://chapmanganato.com/", progressToken:progressToken); + return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, "https://chapmanganato.com/", progressToken:progressToken); } private string[] ParseImageUrlsFromHtml(HtmlDocument document) diff --git a/Tranga/MangaConnectors/Mangasee.cs b/Tranga/MangaConnectors/Mangasee.cs index 1bc7445..7128910 100644 --- a/Tranga/MangaConnectors/Mangasee.cs +++ b/Tranga/MangaConnectors/Mangasee.cs @@ -225,6 +225,6 @@ public class Mangasee : MangaConnector string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); - return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); + return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); } } \ No newline at end of file diff --git a/Tranga/MangaConnectors/Mangaworld.cs b/Tranga/MangaConnectors/Mangaworld.cs index d5725d7..7cbe7ef 100644 --- a/Tranga/MangaConnectors/Mangaworld.cs +++ b/Tranga/MangaConnectors/Mangaworld.cs @@ -209,7 +209,7 @@ public class Mangaworld: MangaConnector string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); - return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://www.mangaworld.bz/", progressToken:progressToken); + return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, "https://www.mangaworld.bz/", progressToken:progressToken); } private string[] ParseImageUrlsFromHtml(HtmlDocument document) diff --git a/Tranga/MangaConnectors/ManhuaPlus.cs b/Tranga/MangaConnectors/ManhuaPlus.cs index 3fe392c..524c267 100644 --- a/Tranga/MangaConnectors/ManhuaPlus.cs +++ b/Tranga/MangaConnectors/ManhuaPlus.cs @@ -179,6 +179,6 @@ public class ManhuaPlus : MangaConnector string comicInfoPath = Path.GetTempFileName(); File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString()); - return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); + return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(), RequestType.MangaImage, comicInfoPath, progressToken:progressToken); } } \ No newline at end of file diff --git a/Tranga/Server.cs b/Tranga/Server.cs index e2f19f0..95dad91 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -19,9 +19,9 @@ public class Server : GlobalBase { this._parent = parent; if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - this._listener.Prefixes.Add($"http://*:{settings.apiPortNumber}/"); + this._listener.Prefixes.Add($"http://*:{TrangaSettings.apiPortNumber}/"); else - this._listener.Prefixes.Add($"http://localhost:{settings.apiPortNumber}/"); + this._listener.Prefixes.Add($"http://localhost:{TrangaSettings.apiPortNumber}/"); Thread listenThread = new (Listen); listenThread.Start(); Thread watchThread = new(WatchRunning); @@ -198,16 +198,16 @@ public class Server : GlobalBase 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); + SendResponse(HttpStatusCode.OK, response, TrangaSettings.Serialize()); break; case "Settings/userAgent": - SendResponse(HttpStatusCode.OK, response, settings.userAgent); + SendResponse(HttpStatusCode.OK, response, TrangaSettings.userAgent); break; case "Settings/customRequestLimit": - SendResponse(HttpStatusCode.OK, response, settings.requestLimits); + SendResponse(HttpStatusCode.OK, response, TrangaSettings.requestLimits); break; case "Settings/AprilFoolsMode": - SendResponse(HttpStatusCode.OK, response, settings.aprilFoolsMode); + SendResponse(HttpStatusCode.OK, response, TrangaSettings.aprilFoolsMode); break; case "NotificationConnectors": SendResponse(HttpStatusCode.OK, response, notificationConnectors); @@ -314,7 +314,7 @@ public class Server : GlobalBase } if (requestVariables.TryGetValue("customFolderName", out customFolderName)) - manga.MovePublicationFolder(settings.downloadLocation, customFolderName); + manga.MovePublicationFolder(TrangaSettings.downloadLocation, customFolderName); requestVariables.TryGetValue("translatedLanguage", out translatedLanguage); _parent.jobBoss.AddJob(new DownloadNewChapters(this, connector!, manga, true, interval, translatedLanguage: translatedLanguage??"en")); @@ -343,7 +343,7 @@ public class Server : GlobalBase } if (requestVariables.TryGetValue("customFolderName", out customFolderName)) - manga.MovePublicationFolder(settings.downloadLocation, customFolderName); + manga.MovePublicationFolder(TrangaSettings.downloadLocation, customFolderName); requestVariables.TryGetValue("translatedLanguage", out translatedLanguage); _parent.jobBoss.AddJob(new DownloadNewChapters(this, connector!, manga, false, translatedLanguage: translatedLanguage??"en")); @@ -405,7 +405,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.BadRequest, response); break; } - settings.UpdateDownloadLocation(downloadLocation, moveFiles); + TrangaSettings.UpdateDownloadLocation(downloadLocation, moveFiles); SendResponse(HttpStatusCode.Accepted, response); break; case "Settings/AprilFoolsMode": @@ -415,7 +415,7 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.BadRequest, response); break; } - settings.UpdateAprilFoolsMode(aprilFoolsModeEnabled); + TrangaSettings.UpdateAprilFoolsMode(aprilFoolsModeEnabled); SendResponse(HttpStatusCode.Accepted, response); break; /*case "Settings/UpdateWorkingDirectory": @@ -433,11 +433,11 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.BadRequest, response); break; } - settings.UpdateUserAgent(customUserAgent); + TrangaSettings.UpdateUserAgent(customUserAgent); SendResponse(HttpStatusCode.Accepted, response); break; case "Settings/userAgent/Reset": - settings.UpdateUserAgent(null); + TrangaSettings.UpdateUserAgent(null); SendResponse(HttpStatusCode.Accepted, response); break; case "Settings/customRequestLimit": @@ -449,18 +449,12 @@ public class Server : GlobalBase SendResponse(HttpStatusCode.BadRequest, response); break; } - - if (settings.requestLimits.ContainsKey(requestType)) - { - settings.requestLimits[requestType] = requestsPerMinute; - SendResponse(HttpStatusCode.Accepted, response); - }else - SendResponse(HttpStatusCode.BadRequest, response); - settings.ExportSettings(); + + TrangaSettings.UpdateRateLimit(requestType, requestsPerMinute); + SendResponse(HttpStatusCode.Accepted, response); break; case "Settings/customRequestLimit/Reset": - settings.requestLimits = TrangaSettings.DefaultRequestLimits; - settings.ExportSettings(); + TrangaSettings.ResetRateLimits(); break; case "NotificationConnectors/Update": if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) || diff --git a/Tranga/Tranga.cs b/Tranga/Tranga.cs index 1471365..3c9a209 100644 --- a/Tranga/Tranga.cs +++ b/Tranga/Tranga.cs @@ -11,10 +11,9 @@ public partial class Tranga : GlobalBase private Server _server; private HashSet _connectors; - public Tranga(Logger? logger, TrangaSettings settings) : base(logger, settings) + public Tranga(Logger? logger) : base(logger) { Log("\n\n _______ \n|_ _|.----..---.-..-----..-----..---.-.\n | | | _|| _ || || _ || _ |\n |___| |__| |___._||__|__||___ ||___._|\n |_____| \n\n"); - Log(settings.ToString()); keepRunning = true; _connectors = new HashSet() { @@ -70,7 +69,7 @@ public partial class Tranga : GlobalBase { while (keepRunning) { - if(!settings.aprilFoolsMode || !IsAprilFirst()) + if(!TrangaSettings.aprilFoolsMode || !IsAprilFirst()) jobBoss.CheckJobs(); else Log("April Fools Mode in Effect"); diff --git a/Tranga/TrangaArgs.cs b/Tranga/TrangaArgs.cs index e95ad91..77dfea3 100644 --- a/Tranga/TrangaArgs.cs +++ b/Tranga/TrangaArgs.cs @@ -36,34 +36,14 @@ public partial class Tranga : GlobalBase enabledLoggers.Add(Logger.LoggerType.FileLogger); Logger logger = new(enabledLoggers.ToArray(), Console.Out, Console.OutputEncoding, directoryPath); - TrangaSettings? settings = null; bool dlp = fetched.TryGetValue(downloadLocation, out string[]? downloadLocationPath); - bool wdp = fetched.TryGetValue(downloadLocation, out string[]? workingDirectoryPath); + bool wdp = fetched.TryGetValue(workingDirectory, out string[]? workingDirectoryPath); - if (dlp && wdp) - { - settings = new TrangaSettings(downloadLocationPath![0], workingDirectoryPath![0]); - }else if (dlp) - { - if (settings is null) - settings = new TrangaSettings(downloadLocation: downloadLocationPath![0]); - else - settings = new TrangaSettings(downloadLocation: downloadLocationPath![0], settings.workingDirectory); - }else if (wdp) - { - if (settings is null) - settings = new TrangaSettings(downloadLocation: workingDirectoryPath![0]); - else - settings = new TrangaSettings(settings.downloadLocation, workingDirectoryPath![0]); - } - else - { - settings = new TrangaSettings(); - } - - Directory.CreateDirectory(settings.downloadLocation);//TODO validate path - Directory.CreateDirectory(settings.workingDirectory);//TODO validate path + if (wdp) + TrangaSettings.LoadFromWorkingDirectory(workingDirectoryPath![0]); + if(dlp) + TrangaSettings.CreateOrUpdate(downloadDirectory: downloadLocationPath![0]); - Tranga _ = new (logger, settings); + Tranga _ = new (logger); } } \ No newline at end of file diff --git a/Tranga/TrangaSettings.cs b/Tranga/TrangaSettings.cs index 2ad9492..e2b9390 100644 --- a/Tranga/TrangaSettings.cs +++ b/Tranga/TrangaSettings.cs @@ -1,7 +1,6 @@ using System.Runtime.InteropServices; -using System.Text.Json.Nodes; -using System.Text.RegularExpressions; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Tranga.LibraryConnectors; using Tranga.MangaConnectors; using Tranga.NotificationConnectors; @@ -9,20 +8,20 @@ using static System.IO.UnixFileMode; namespace Tranga; -public class TrangaSettings +public static class TrangaSettings { - public string downloadLocation { get; private set; } - public string workingDirectory { get; private set; } - public int apiPortNumber { get; init; } - public string userAgent { get; private set; } = DefaultUserAgent; - [JsonIgnore] public string settingsFilePath => Path.Join(workingDirectory, "settings.json"); - [JsonIgnore] public string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json"); - [JsonIgnore] public string notificationConnectorsFilePath => Path.Join(workingDirectory, "notificationConnectors.json"); - [JsonIgnore] public string jobsFolderPath => Path.Join(workingDirectory, "jobs"); - [JsonIgnore] public string coverImageCache => Path.Join(workingDirectory, "imageCache"); [JsonIgnore] internal static readonly string DefaultUserAgent = $"Tranga ({Enum.GetName(Environment.OSVersion.Platform)}; {(Environment.Is64BitOperatingSystem ? "x64" : "")}) / 1.0"; - public ushort? version { get; } = 2; - public bool aprilFoolsMode { get; private set; } = true; + public static string downloadLocation { get; private set; } = (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(Directory.GetCurrentDirectory(), "Downloads")); + public static string workingDirectory { get; private set; } = Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api"); + public static int apiPortNumber { get; private set; } = 6531; + public static string userAgent { get; private set; } = DefaultUserAgent; + [JsonIgnore] public static string settingsFilePath => Path.Join(workingDirectory, "settings.json"); + [JsonIgnore] public static string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json"); + [JsonIgnore] public static string notificationConnectorsFilePath => Path.Join(workingDirectory, "notificationConnectors.json"); + [JsonIgnore] public static string jobsFolderPath => Path.Join(workingDirectory, "jobs"); + [JsonIgnore] public static string coverImageCache => Path.Join(workingDirectory, "imageCache"); + public static ushort? version { get; } = 2; + public static bool aprilFoolsMode { get; private set; } = true; [JsonIgnore]internal static readonly Dictionary DefaultRequestLimits = new () { {RequestType.MangaInfo, 250}, @@ -33,50 +32,38 @@ public class TrangaSettings {RequestType.Default, 60} }; - public Dictionary requestLimits { get; set; } = DefaultRequestLimits; + public static Dictionary requestLimits { get; set; } = DefaultRequestLimits; - public TrangaSettings(string? downloadLocation = null, string? workingDirectory = null, int? apiPortNumber = null) + public static void LoadFromWorkingDirectory(string directory) { - string wd = workingDirectory ?? Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api"); - string sfp = Path.Join(wd, "settings.json"); - - string lockFilePath = $"{sfp}.lock"; - if (File.Exists(sfp) && !File.Exists(lockFilePath)) - {//Load from settings file - FileStream lockFile = File.Create(lockFilePath,0, FileOptions.DeleteOnClose); //lock settingsfile - string settingsStr = File.ReadAllText(sfp); - settingsStr = Regex.Replace(settingsStr, @"""MangaDexAuthor"": [0-9]+,", "");//https://github.com/C9Glax/tranga/pull/161 Remove sometime in the future :3 - TrangaSettings settings = JsonConvert.DeserializeObject(settingsStr)!; - this.requestLimits = settings.requestLimits; - this.userAgent = settings.userAgent; - this.downloadLocation = downloadLocation ?? settings.downloadLocation; - this.workingDirectory = workingDirectory ?? settings.workingDirectory; - this.apiPortNumber = apiPortNumber ?? settings.apiPortNumber; - lockFile.Close(); //unlock settingsfile - } - else if(!File.Exists(sfp)) - {//No settings file exists - if (downloadLocation?.Length < 1 || workingDirectory?.Length < 1) - throw new ArgumentException("Download-location and working-directory paths can not be empty!"); - this.requestLimits = DefaultRequestLimits; - this.userAgent = DefaultUserAgent; - this.apiPortNumber = apiPortNumber ?? 6531; - this.downloadLocation = downloadLocation ?? (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(Directory.GetCurrentDirectory(), "Downloads")); - this.workingDirectory = workingDirectory ?? Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api"); - ExportSettings(); + TrangaSettings.workingDirectory = directory; + if (!File.Exists(settingsFilePath)) + { + return; } else - {//Settingsfile is locked - this.requestLimits = DefaultRequestLimits; - this.userAgent = DefaultUserAgent; - this.apiPortNumber = apiPortNumber!.Value; - this.downloadLocation = downloadLocation!; - this.workingDirectory = workingDirectory!; + { + Deserialize(File.ReadAllText(settingsFilePath)); } - UpdateDownloadLocation(this.downloadLocation, false); + + Directory.CreateDirectory(downloadLocation); + Directory.CreateDirectory(workingDirectory); + ExportSettings(); } - public HashSet LoadLibraryConnectors(GlobalBase clone) + public static void CreateOrUpdate(string? downloadDirectory = null, string? pWorkingDirectory = null, int? pApiPortNumber = null, string? pUserAgent = null, bool? pAprilFoolsMode = null) + { + TrangaSettings.downloadLocation = downloadDirectory ?? TrangaSettings.downloadLocation; + TrangaSettings.workingDirectory = pWorkingDirectory ?? TrangaSettings.workingDirectory; + TrangaSettings.apiPortNumber = pApiPortNumber ?? TrangaSettings.apiPortNumber; + TrangaSettings.userAgent = pUserAgent ?? TrangaSettings.userAgent; + TrangaSettings.aprilFoolsMode = pAprilFoolsMode ?? TrangaSettings.aprilFoolsMode; + Directory.CreateDirectory(downloadLocation); + Directory.CreateDirectory(workingDirectory); + ExportSettings(); + } + + public static HashSet LoadLibraryConnectors(GlobalBase clone) { if (!File.Exists(libraryConnectorsFilePath)) return new HashSet(); @@ -90,7 +77,7 @@ public class TrangaSettings })!; } - public HashSet LoadNotificationConnectors(GlobalBase clone) + public static HashSet LoadNotificationConnectors(GlobalBase clone) { if (!File.Exists(notificationConnectorsFilePath)) return new HashSet(); @@ -104,13 +91,13 @@ public class TrangaSettings })!; } - public void UpdateAprilFoolsMode(bool enabled) + public static void UpdateAprilFoolsMode(bool enabled) { - this.aprilFoolsMode = enabled; + TrangaSettings.aprilFoolsMode = enabled; ExportSettings(); } - public void UpdateDownloadLocation(string newPath, bool moveFiles = true) + public static void UpdateDownloadLocation(string newPath, bool moveFiles = true) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) Directory.CreateDirectory(newPath, @@ -118,32 +105,44 @@ public class TrangaSettings else Directory.CreateDirectory(newPath); - if (moveFiles && Directory.Exists(this.downloadLocation)) - Directory.Move(this.downloadLocation, newPath); + if (moveFiles && Directory.Exists(TrangaSettings.downloadLocation)) + Directory.Move(TrangaSettings.downloadLocation, newPath); - this.downloadLocation = newPath; + TrangaSettings.downloadLocation = newPath; ExportSettings(); } - public void UpdateWorkingDirectory(string newPath) + public static void UpdateWorkingDirectory(string newPath) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) Directory.CreateDirectory(newPath, GroupRead | GroupWrite | None | OtherRead | OtherWrite | UserRead | UserWrite); else Directory.CreateDirectory(newPath); - Directory.Move(this.workingDirectory, newPath); - this.workingDirectory = newPath; + Directory.Move(TrangaSettings.workingDirectory, newPath); + TrangaSettings.workingDirectory = newPath; ExportSettings(); } - public void UpdateUserAgent(string? customUserAgent) + public static void UpdateUserAgent(string? customUserAgent) { - this.userAgent = customUserAgent ?? DefaultUserAgent; + TrangaSettings.userAgent = customUserAgent ?? DefaultUserAgent; ExportSettings(); } - public void ExportSettings() + public static void UpdateRateLimit(RequestType requestType, int newLimit) + { + TrangaSettings.requestLimits[requestType] = newLimit; + ExportSettings(); + } + + public static void ResetRateLimits() + { + TrangaSettings.requestLimits = DefaultRequestLimits; + ExportSettings(); + } + + public static void ExportSettings() { if (File.Exists(settingsFilePath)) { @@ -152,22 +151,36 @@ public class TrangaSettings } else Directory.CreateDirectory(new FileInfo(settingsFilePath).DirectoryName!); - File.WriteAllText(settingsFilePath, JsonConvert.SerializeObject(this, Formatting.Indented)); + File.WriteAllText(settingsFilePath, Serialize()); } - public string GetFullCoverPath(Manga manga) + public static string Serialize() { - return Path.Join(this.coverImageCache, manga.coverFileNameInCache); + JObject jobj = new JObject(); + jobj.Add("downloadLocation", JToken.FromObject(TrangaSettings.downloadLocation)); + jobj.Add("workingDirectory", JToken.FromObject(TrangaSettings.workingDirectory)); + jobj.Add("apiPortNumber", JToken.FromObject(TrangaSettings.apiPortNumber)); + jobj.Add("userAgent", JToken.FromObject(TrangaSettings.userAgent)); + jobj.Add("aprilFoolsMode", JToken.FromObject(TrangaSettings.aprilFoolsMode)); + jobj.Add("version", JToken.FromObject(TrangaSettings.version)); + jobj.Add("requestLimits", JToken.FromObject(TrangaSettings.requestLimits)); + return jobj.ToString(); } - public override string ToString() + public static void Deserialize(string serialized) { - return $"TrangaSettings:\n" + - $"\tDownloadLocation: {downloadLocation}\n" + - $"\tworkingDirectory: {workingDirectory}\n" + - $"\tjobsFolderPath: {jobsFolderPath}\n" + - $"\tsettingsFilePath: {settingsFilePath}\n" + - $"\t\tnotificationConnectors: {notificationConnectorsFilePath}\n" + - $"\t\tlibraryConnectors: {libraryConnectorsFilePath}\n"; + JObject jobj = JObject.Parse(serialized); + if (jobj.TryGetValue("downloadLocation", out JToken? dl)) + TrangaSettings.downloadLocation = dl.Value()!; + if (jobj.TryGetValue("workingDirectory", out JToken? wd)) + TrangaSettings.workingDirectory = wd.Value()!; + if (jobj.TryGetValue("apiPortNumber", out JToken? apn)) + TrangaSettings.apiPortNumber = apn.Value(); + if (jobj.TryGetValue("userAgent", out JToken? ua)) + TrangaSettings.userAgent = ua.Value()!; + if (jobj.TryGetValue("aprilFoolsMode", out JToken? afm)) + TrangaSettings.aprilFoolsMode = afm.Value()!; + if (jobj.TryGetValue("requestLimits", out JToken? rl)) + TrangaSettings.requestLimits = rl.ToObject>()!; } } \ No newline at end of file