Compare commits

..

No commits in common. "c965bc38d1a24441e8f2acfcd509554e75e51b43" and "38df54baffac5056619a9f4a2b9b144a3c7fd227" have entirely different histories.

11 changed files with 29 additions and 149 deletions

View File

@ -9,6 +9,5 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Manganato/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mangasee/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mangaworld/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ntfy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Taskmanager/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tranga/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -14,8 +14,8 @@ public abstract class GlobalBase
protected HashSet<NotificationConnector> notificationConnectors { get; init; }
protected HashSet<LibraryConnector> libraryConnectors { get; init; }
protected List<Manga> cachedPublications { get; init; }
public static readonly NumberFormatInfo numberFormatDecimalPoint = new (){ NumberDecimalSeparator = "." };
protected static readonly Regex baseUrlRex = new(@"https?:\/\/[0-9A-z\.-]+(:[0-9]+)?");
protected static readonly NumberFormatInfo numberFormatDecimalPoint = new (){ NumberDecimalSeparator = "." };
protected static readonly Regex baseUrlRex = new(@"https?:\/\/[0-9A-z\.-]*");
protected GlobalBase(GlobalBase clone)
{

View File

@ -33,7 +33,6 @@ public class DownloadChapter : Job
{
mangaConnector.CopyCoverFromCacheToDownloadLocation(chapter.parentManga);
HttpStatusCode success = mangaConnector.DownloadChapter(chapter, this.progressToken);
chapter.parentManga.UpdateLatestDownloadedChapter(chapter);
if (success == HttpStatusCode.OK)
{
UpdateLibraries();

View File

@ -37,19 +37,12 @@ public class Kavita : LibraryConnector
RequestUri = new Uri($"{baseUrl}/api/Account/login"),
Content = new StringContent($"{{\"username\":\"{username}\",\"password\":\"{password}\"}}", System.Text.Encoding.UTF8, "application/json")
};
try
{
HttpResponseMessage response = client.Send(requestMessage);
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(response.Content.ReadAsStream());
if (result is not null)
return result["token"]!.GetValue<string>();
}
catch (HttpRequestException e)
{
Console.WriteLine($"Unable to retrieve token:\n\r{e}");
}
Console.WriteLine("Kavita: Did not receive token.");
throw new Exception("Kavita: Did not receive token.");
else throw new Exception("Did not receive token.");
}
public override void UpdateLibrary()

View File

@ -26,14 +26,12 @@ public struct Manga
// ReSharper disable once MemberCanBePrivate.Global
public int? year { get; }
public string? originalLanguage { get; }
// ReSharper disable twice MemberCanBePrivate.Global
// ReSharper disable once MemberCanBePrivate.Global
public string status { get; }
public string folderName { get; private set; }
public string publicationId { get; }
public string internalId { get; }
public float ignoreChaptersBelow { get; set; }
public float latestChapterDownloaded { get; set; }
public float latestChapterAvailable { get; set; }
private static readonly Regex LegalCharacters = new (@"[A-Z]*[a-z]*[0-9]* *\.*-*,*'*\'*\)*\(*~*!*");
@ -58,8 +56,6 @@ public struct Manga
string onlyLowerLetters = string.Concat(this.sortName.ToLower().Where(Char.IsLetter));
this.internalId = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{onlyLowerLetters}{this.year}"));
this.ignoreChaptersBelow = ignoreChaptersBelow ?? 0f;
this.latestChapterDownloaded = 0;
this.latestChapterAvailable = 0;
}
public override string ToString()
@ -86,12 +82,6 @@ public struct Manga
Directory.Move(oldPath, newPath);
}
public void UpdateLatestDownloadedChapter(Chapter chapter)//TODO check files if chapters are all downloaded
{
float chapterNumber = Convert.ToSingle(chapter.chapterNumber, GlobalBase.numberFormatDecimalPoint);
latestChapterDownloaded = latestChapterDownloaded < chapterNumber ? chapterNumber : latestChapterDownloaded;
}
public void SaveSeriesInfoJson(string downloadDirectory)
{
string publicationFolder = CreatePublicationFolder(downloadDirectory);

View File

@ -56,15 +56,12 @@ public abstract class MangaConnector : GlobalBase
public Chapter[] GetNewChapters(Manga manga, string language = "en")
{
Log($"Getting new Chapters for {manga}");
Chapter[] allChapters = this.GetChapters(manga, language);
Chapter[] newChapters = this.GetChapters(manga, language);
Log($"Checking for duplicates {manga}");
List<Chapter> newChaptersList = allChapters.Where(nChapter => float.TryParse(nChapter.chapterNumber, numberFormatDecimalPoint, out float chapterNumber)
List<Chapter> newChaptersList = newChapters.Where(nChapter => float.TryParse(nChapter.chapterNumber, numberFormatDecimalPoint, out float chapterNumber)
&& chapterNumber > manga.ignoreChaptersBelow
&& !nChapter.CheckChapterIsDownloaded(settings.downloadLocation)).ToList();
Log($"{newChaptersList.Count} new chapters. {manga}");
Chapter latestChapterAvailable =
allChapters.MaxBy(chapter => Convert.ToSingle(chapter.chapterNumber, numberFormatDecimalPoint));
manga.latestChapterAvailable = Convert.ToSingle(latestChapterAvailable.chapterNumber, numberFormatDecimalPoint);
return newChaptersList.ToArray();
}

View File

@ -10,7 +10,7 @@ public abstract class NotificationConnector : GlobalBase
this.notificationConnectorType = notificationConnectorType;
}
public enum NotificationConnectorType : byte { Gotify = 0, LunaSea = 1, Ntfy = 2 }
public enum NotificationConnectorType : byte { Gotify = 0, LunaSea = 1 }
public abstract void SendNotification(string title, string notificationText);
}

View File

@ -21,15 +21,11 @@ public class NotificationManagerJsonConverter : JsonConverter
JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
switch (jo["notificationConnectorType"]!.Value<byte>())
{
case (byte)NotificationConnector.NotificationConnectorType.Gotify:
if (jo["notificationConnectorType"]!.Value<byte>() == (byte)NotificationConnector.NotificationConnectorType.Gotify)
return new Gotify(this._clone, jo.GetValue("endpoint")!.Value<string>()!, jo.GetValue("appToken")!.Value<string>()!);
case (byte)NotificationConnector.NotificationConnectorType.LunaSea:
else if (jo["notificationConnectorType"]!.Value<byte>() ==
(byte)NotificationConnector.NotificationConnectorType.LunaSea)
return new LunaSea(this._clone, jo.GetValue("id")!.Value<string>()!);
case (byte)NotificationConnector.NotificationConnectorType.Ntfy:
return new Ntfy(this._clone, jo.GetValue("endpoint")!.Value<string>()!, jo.GetValue("auth")!.Value<string>()!);
}
throw new Exception();
}

View File

@ -1,58 +0,0 @@
using System.Text;
using Newtonsoft.Json;
namespace Tranga.NotificationConnectors;
public class Ntfy : NotificationConnector
{
// ReSharper disable once MemberCanBePrivate.Global
public string endpoint { get; init; }
private string auth { get; init; }
private const string Topic = "tranga";
private readonly HttpClient _client = new();
[JsonConstructor]
public Ntfy(GlobalBase clone, string endpoint, string auth) : base(clone, NotificationConnectorType.Ntfy)
{
if (!baseUrlRex.IsMatch(endpoint))
throw new ArgumentException("endpoint does not match pattern");
this.endpoint = endpoint;
this.auth = auth;
}
public override string ToString()
{
return $"Ntfy {endpoint} {Topic}";
}
public override void SendNotification(string title, string notificationText)
{
Log($"Sending notification: {title} - {notificationText}");
MessageData message = new(title, notificationText);
HttpRequestMessage request = new(HttpMethod.Post, $"{this.endpoint}?auth={this.auth}");
request.Content = new StringContent(JsonConvert.SerializeObject(message, Formatting.None), Encoding.UTF8, "application/json");
HttpResponseMessage response = _client.Send(request);
if (!response.IsSuccessStatusCode)
{
StreamReader sr = new (response.Content.ReadAsStream());
Log($"{response.StatusCode}: {sr.ReadToEnd()}");
}
}
private class MessageData
{
// ReSharper disable UnusedAutoPropertyAccessor.Local
public string topic { get; }
public string title { get; }
public string message { get; }
public int priority { get; }
public MessageData(string title, string message)
{
this.topic = Topic;
this.title = title;
this.message = message;
this.priority = 3;
}
}
}

View File

@ -335,18 +335,6 @@ public class Server : GlobalBase
settings.UpdateDownloadLocation(downloadLocation, moveFiles);
SendResponse(HttpStatusCode.Accepted, response);
break;
case "Settings/ChangeStyleSheet":
if (!requestVariables.TryGetValue("styleSheet", out string? styleSheet))
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
if (settings.UpdateStyleSheet(styleSheet))
SendResponse(HttpStatusCode.Accepted, response);
else
SendResponse(HttpStatusCode.BadRequest, response, "Invalid parameter for styleSheet");
break;
/*case "Settings/UpdateWorkingDirectory":
if (!requestVariables.TryGetValue("workingDirectory", out string? workingDirectory))
{
@ -374,7 +362,10 @@ public class Server : GlobalBase
}
AddNotificationConnector(new Gotify(this, gotifyUrl, gotifyAppToken));
SendResponse(HttpStatusCode.Accepted, response);
}else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.LunaSea)
break;
}
if (notificationConnectorType is NotificationConnector.NotificationConnectorType.LunaSea)
{
if (!requestVariables.TryGetValue("lunaseaWebhook", out string? lunaseaWebhook))
{
@ -383,25 +374,13 @@ public class Server : GlobalBase
}
AddNotificationConnector(new LunaSea(this, lunaseaWebhook));
SendResponse(HttpStatusCode.Accepted, response);
}else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Ntfy)
{
if (!requestVariables.TryGetValue("ntfyUrl", out string? ntfyUrl) ||
!requestVariables.TryGetValue("ntfyAuth", out string? ntfyAuth))
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
AddNotificationConnector(new Ntfy(this, ntfyUrl, ntfyAuth));
SendResponse(HttpStatusCode.Accepted, response);
}
else
{
SendResponse(HttpStatusCode.BadRequest, response);
}
break;
case "LibraryConnectors/Update":
if (!requestVariables.TryGetValue("libraryConnector", out string? libraryConnectorStr) ||
!Enum.TryParse(libraryConnectorStr, out LibraryConnector.LibraryType libraryConnectorType))
!Enum.TryParse(libraryConnectorStr,
out LibraryConnector.LibraryType libraryConnectorType))
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
@ -418,7 +397,10 @@ public class Server : GlobalBase
}
AddLibraryConnector(new Kavita(this, kavitaUrl, kavitaUsername, kavitaPassword));
SendResponse(HttpStatusCode.Accepted, response);
}else if (libraryConnectorType is LibraryConnector.LibraryType.Komga)
break;
}
if (libraryConnectorType is LibraryConnector.LibraryType.Komga)
{
if (!requestVariables.TryGetValue("komgaUrl", out string? komgaUrl) ||
!requestVariables.TryGetValue("komgaAuth", out string? komgaAuth))
@ -428,10 +410,7 @@ public class Server : GlobalBase
}
AddLibraryConnector(new Komga(this, komgaUrl, komgaAuth));
SendResponse(HttpStatusCode.Accepted, response);
}
else
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
break;
case "LogMessages":

View File

@ -11,7 +11,6 @@ public class TrangaSettings
public string downloadLocation { get; private set; }
public string workingDirectory { get; private set; }
public int apiPortNumber { get; init; }
public string styleSheet { get; private set; }
[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");
@ -30,7 +29,6 @@ public class TrangaSettings
this.downloadLocation = downloadLocation ?? settings.downloadLocation;
this.workingDirectory = workingDirectory ?? settings.workingDirectory;
this.apiPortNumber = apiPortNumber ?? settings.apiPortNumber;
this.styleSheet = "default" ?? settings.styleSheet;
lockFile.Close(); //unlock settingsfile
}
else if(!File.Exists(settingsFilePath))
@ -40,7 +38,6 @@ public class TrangaSettings
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");
this.styleSheet = "default";
ExportSettings();
}
else
@ -48,7 +45,6 @@ public class TrangaSettings
this.apiPortNumber = apiPortNumber!.Value;
this.downloadLocation = downloadLocation!;
this.workingDirectory = workingDirectory!;
this.styleSheet = "default";
}
UpdateDownloadLocation(this.downloadLocation, false);
}
@ -81,17 +77,6 @@ public class TrangaSettings
})!;
}
public bool UpdateStyleSheet(string newStyleSheet)
{
string[] validStyleSheets = { "default", "hover" };
if (validStyleSheets.Contains(newStyleSheet))
{
this.styleSheet = newStyleSheet;
return true;
}
return false;
}
public void UpdateDownloadLocation(string newPath, bool moveFiles = true)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))