diff --git a/Tranga/Chapter.cs b/Tranga/Chapter.cs index a699cb5..3c47878 100644 --- a/Tranga/Chapter.cs +++ b/Tranga/Chapter.cs @@ -91,18 +91,22 @@ public readonly struct Chapter : IComparable { if (!Directory.Exists(Path.Join(downloadLocation, parentManga.folderName))) return false; - FileInfo[] archives = new DirectoryInfo(Path.Join(downloadLocation, parentManga.folderName)).GetFiles(); + FileInfo[] archives = new DirectoryInfo(Path.Join(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; - return archives.Select(archive => archive.Name).Any(archiveFileName => + string thisPath = GetArchiveFilePath(downloadLocation); + FileInfo? archive = archives.FirstOrDefault(archive => { - Match m = volChRex.Match(archiveFileName); + Match m = volChRex.Match(archive.Name); string archiveVolNum = m.Groups[1].Success ? m.Groups[1].Value : "0"; string archiveChNum = m.Groups[2].Value; - return archiveVolNum == t.volumeNumber && - archiveChNum == t.chapterNumber; + return archiveVolNum == t.volumeNumber && archiveChNum == t.chapterNumber || + archiveVolNum == "0" && archiveChNum == t.chapterNumber; }); + if(archive is not null && thisPath != archive.FullName) + archive.MoveTo(thisPath); + return archive is not null; } /// /// Creates full file path of chapter-archive diff --git a/Tranga/MangaConnectors/MangaConnector.cs b/Tranga/MangaConnectors/MangaConnector.cs index 630489b..6dbcb45 100644 --- a/Tranga/MangaConnectors/MangaConnector.cs +++ b/Tranga/MangaConnectors/MangaConnector.cs @@ -299,6 +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); File.WriteAllBytes(saveImagePath, ms.ToArray()); Log($"Saving cover to {saveImagePath}"); return saveImagePath; diff --git a/Tranga/MangaConnectors/Mangaworld.cs b/Tranga/MangaConnectors/Mangaworld.cs index 186a7c1..9558a73 100644 --- a/Tranga/MangaConnectors/Mangaworld.cs +++ b/Tranga/MangaConnectors/Mangaworld.cs @@ -111,7 +111,7 @@ public class Mangaworld: MangaConnector string posterUrl = document.DocumentNode.SelectSingleNode("//img[@class='rounded']").GetAttributeValue("src", ""); - string coverFileNameInCache = SaveCoverImageToCache(posterUrl, publicationId, RequestType.MangaCover); + string coverFileNameInCache = SaveCoverImageToCache(posterUrl, publicationId.Replace('/', '-'), RequestType.MangaCover); string description = document.DocumentNode.SelectSingleNode("//div[@id='noidungm']").InnerText; diff --git a/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs b/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs index c5963c2..6f310e1 100644 --- a/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs +++ b/Tranga/NotificationConnectors/NotificationManagerJsonConverter.cs @@ -28,7 +28,7 @@ public class NotificationManagerJsonConverter : JsonConverter case (byte)NotificationConnector.NotificationConnectorType.LunaSea: return new LunaSea(this._clone, jo.GetValue("id")!.Value()!); case (byte)NotificationConnector.NotificationConnectorType.Ntfy: - return new Ntfy(this._clone, jo.GetValue("endpoint")!.Value()!, jo.GetValue("auth")!.Value()!); + return new Ntfy(this._clone, jo.GetValue("endpoint")!.Value()!, jo.GetValue("topic")!.Value()!, jo.GetValue("auth")!.Value()!); } throw new Exception(); diff --git a/Tranga/NotificationConnectors/Ntfy.cs b/Tranga/NotificationConnectors/Ntfy.cs index 13d220e..f19fe34 100644 --- a/Tranga/NotificationConnectors/Ntfy.cs +++ b/Tranga/NotificationConnectors/Ntfy.cs @@ -11,30 +11,43 @@ public class Ntfy : NotificationConnector public string auth { get; init; } public string topic { get; init; } private readonly HttpClient _client = new(); - - public Ntfy(GlobalBase clone, string endpoint, string auth) : base(clone, NotificationConnectorType.Ntfy) - { - if (!baseUrlRex.IsMatch(endpoint)) - throw new ArgumentException("endpoint does not match pattern"); - Regex rootUriRex = new(@"(https?:\/\/[a-zA-Z0-9-\.]+\.[a-zA-Z0-9]+)(?:\/([a-zA-Z0-9-\.]+))?.*"); - Match match = rootUriRex.Match(endpoint); - if(!match.Success) - Log($"Error getting URI from provided endpoint-URI: {endpoint}"); - this.endpoint = match.Groups[1].Value; - if (match.Groups[2].Success) - topic = match.Groups[2].Value; - else - topic = "tranga"; - this.auth = auth; - } [JsonConstructor] - public Ntfy(GlobalBase clone, string endpoint, string auth, string topic) : base(clone, NotificationConnectorType.Ntfy) + public Ntfy(GlobalBase clone, string endpoint, string topic, string auth) : base(clone, NotificationConnectorType.Ntfy) { this.endpoint = endpoint; - this.topic = topic.Length > 0 ? topic : "tranga"; + this.topic = topic; this.auth = auth; } + + public Ntfy(GlobalBase clone, string endpoint, string username, string password, string? topic = null) : + this(clone, EndpointAndTopicFromUrl(endpoint)[0], topic??EndpointAndTopicFromUrl(endpoint)[1], AuthFromUsernamePassword(username, password)) + { + + } + + private static string AuthFromUsernamePassword(string username, string password) + { + string authHeader = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}")); + string authParam = Convert.ToBase64String(Encoding.UTF8.GetBytes(authHeader)).Replace("=",""); + return authParam; + } + + private static string[] EndpointAndTopicFromUrl(string url) + { + string[] ret = new string[2]; + if (!baseUrlRex.IsMatch(url)) + throw new ArgumentException("url does not match pattern"); + Regex rootUriRex = new(@"(https?:\/\/[a-zA-Z0-9-\.]+\.[a-zA-Z0-9]+)(?:\/([a-zA-Z0-9-\.]+))?.*"); + Match match = rootUriRex.Match(url); + if(!match.Success) + throw new ArgumentException($"Error getting URI from provided endpoint-URI: {url}"); + + ret[0] = match.Groups[1].Value; + ret[1] = match.Groups[2].Success && match.Groups[2].Value.Length > 0 ? match.Groups[2].Value : "tranga"; + + return ret; + } public override string ToString() { diff --git a/Tranga/Server.cs b/Tranga/Server.cs index bef0941..e2f19f0 100644 --- a/Tranga/Server.cs +++ b/Tranga/Server.cs @@ -492,12 +492,13 @@ public class Server : GlobalBase }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Ntfy) { if (!requestVariables.TryGetValue("ntfyUrl", out string? ntfyUrl) || - !requestVariables.TryGetValue("ntfyAuth", out string? ntfyAuth)) + !requestVariables.TryGetValue("ntfyUser", out string? ntfyUser)|| + !requestVariables.TryGetValue("ntfyPass", out string? ntfyPass)) { SendResponse(HttpStatusCode.BadRequest, response); break; } - AddNotificationConnector(new Ntfy(this, ntfyUrl, ntfyAuth)); + AddNotificationConnector(new Ntfy(this, ntfyUrl, ntfyUser, ntfyPass, null)); SendResponse(HttpStatusCode.Accepted, response); } else @@ -534,12 +535,13 @@ public class Server : GlobalBase }else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Ntfy) { if (!requestVariables.TryGetValue("ntfyUrl", out string? ntfyUrl) || - !requestVariables.TryGetValue("ntfyAuth", out string? ntfyAuth)) + !requestVariables.TryGetValue("ntfyUser", out string? ntfyUser)|| + !requestVariables.TryGetValue("ntfyPass", out string? ntfyPass)) { SendResponse(HttpStatusCode.BadRequest, response); break; } - notificationConnector = new Ntfy(this, ntfyUrl, ntfyAuth); + notificationConnector = new Ntfy(this, ntfyUrl, ntfyUser, ntfyPass, null); } else {