2
0

Compare commits

..

No commits in common. "0f29da00def5303b44b76a20d2e8d4532f614335" and "9b2a6de8412ef0cb837cc4a186b361f3336ea7ac" have entirely different histories.

8 changed files with 90 additions and 215 deletions

View File

@ -46,29 +46,8 @@ internal sealed class TrangaCli : Command<TrangaCli.Settings>
string? logFilePath = settings.fileLoggerPath ?? ""; string? logFilePath = settings.fileLoggerPath ?? "";
Logger logger = new(enabledLoggers.ToArray(), Console.Out, Console.OutputEncoding, logFilePath); Logger logger = new(enabledLoggers.ToArray(), Console.Out, Console.OutputEncoding, logFilePath);
TrangaSettings? trangaSettings = null;
if (settings.downloadLocation is not null && settings.workingDirectory is not null) TrangaSettings trangaSettings = new (settings.downloadLocation, settings.workingDirectory, settings.apiPort);
{
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.downloadLocation);
Directory.CreateDirectory(trangaSettings.workingDirectory); Directory.CreateDirectory(trangaSettings.workingDirectory);

View File

@ -26,4 +26,4 @@ WORKDIR /publish
COPY --from=build-env /publish . COPY --from=build-env /publish .
USER 0 USER 0
RUN chown 1000:1000 /publish RUN chown 1000:1000 /publish
ENTRYPOINT ["dotnet", "/publish/Tranga.dll", "-f -c"] ENTRYPOINT ["dotnet", "/publish/Tranga.dll", "-c"]

View File

@ -9,8 +9,7 @@ namespace Tranga;
public abstract class GlobalBase public abstract class GlobalBase
{ {
[JsonIgnore] protected Logger? logger { get; init; }
public Logger? logger { get; init; }
protected TrangaSettings settings { get; init; } protected TrangaSettings settings { get; init; }
protected HashSet<NotificationConnector> notificationConnectors { get; init; } protected HashSet<NotificationConnector> notificationConnectors { get; init; }
protected HashSet<LibraryConnector> libraryConnectors { get; init; } protected HashSet<LibraryConnector> libraryConnectors { get; init; }
@ -89,7 +88,7 @@ public abstract class GlobalBase
while(IsFileInUse(settings.libraryConnectorsFilePath)) while(IsFileInUse(settings.libraryConnectorsFilePath))
Thread.Sleep(100); Thread.Sleep(100);
Log("Exporting libraryConnectors"); Log("Exporting libraryConnectors");
File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented)); File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors));
} }
protected void DeleteLibraryConnector(LibraryConnector.LibraryType libraryType) protected void DeleteLibraryConnector(LibraryConnector.LibraryType libraryType)
@ -99,12 +98,10 @@ public abstract class GlobalBase
while(IsFileInUse(settings.libraryConnectorsFilePath)) while(IsFileInUse(settings.libraryConnectorsFilePath))
Thread.Sleep(100); Thread.Sleep(100);
Log("Exporting libraryConnectors"); Log("Exporting libraryConnectors");
File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented)); File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors));
} }
protected bool IsFileInUse(string filePath) => IsFileInUse(filePath, this.logger); protected bool IsFileInUse(string filePath)
public static bool IsFileInUse(string filePath, Logger? logger)
{ {
if (!File.Exists(filePath)) if (!File.Exists(filePath))
return false; return false;
@ -116,7 +113,7 @@ public abstract class GlobalBase
} }
catch (IOException) catch (IOException)
{ {
logger?.WriteLine($"File is in use {filePath}"); Log($"File is in use {filePath}");
return true; return true;
} }
} }

View File

@ -1,5 +1,4 @@
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
using Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using JsonSerializer = System.Text.Json.JsonSerializer; using JsonSerializer = System.Text.Json.JsonSerializer;
@ -9,7 +8,7 @@ public class Kavita : LibraryConnector
{ {
public Kavita(GlobalBase clone, string baseUrl, string username, string password) : public Kavita(GlobalBase clone, string baseUrl, string username, string password) :
base(clone, baseUrl, GetToken(baseUrl, username, password, clone.logger), LibraryType.Kavita) base(clone, baseUrl, GetToken(baseUrl, username, password), LibraryType.Kavita)
{ {
} }
@ -23,7 +22,7 @@ public class Kavita : LibraryConnector
return $"Kavita {baseUrl}"; return $"Kavita {baseUrl}";
} }
private static string GetToken(string baseUrl, string username, string password, Logger? logger = null) private static string GetToken(string baseUrl, string username, string password)
{ {
HttpClient client = new() HttpClient client = new()
{ {
@ -41,24 +40,16 @@ public class Kavita : LibraryConnector
try try
{ {
HttpResponseMessage response = client.Send(requestMessage); HttpResponseMessage response = client.Send(requestMessage);
logger?.WriteLine($"Kavita | GetToken {requestMessage.RequestUri} -> {response.StatusCode}"); JsonObject? result = JsonSerializer.Deserialize<JsonObject>(response.Content.ReadAsStream());
if (response.IsSuccessStatusCode) if (result is not null)
{ return result["token"]!.GetValue<string>();
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(response.Content.ReadAsStream());
if (result is not null)
return result["token"]!.GetValue<string>();
}
else
{
logger?.WriteLine($"Kavita | {response.Content}");
}
} }
catch (HttpRequestException e) catch (HttpRequestException e)
{ {
logger?.WriteLine($"Kavita | Unable to retrieve token:\n\r{e}"); Console.WriteLine($"Unable to retrieve token:\n\r{e}");
} }
logger?.WriteLine("Kavita | Did not receive token."); Console.WriteLine("Kavita: Did not receive token.");
return ""; throw new Exception("Kavita: Did not receive token.");
} }
public override void UpdateLibrary() public override void UpdateLibrary()

View File

@ -23,8 +23,6 @@ public abstract class LibraryConnector : GlobalBase
Log($"Creating libraryConnector {Enum.GetName(libraryType)}"); Log($"Creating libraryConnector {Enum.GetName(libraryType)}");
if (!baseUrlRex.IsMatch(baseUrl)) if (!baseUrlRex.IsMatch(baseUrl))
throw new ArgumentException("Base url does not match pattern"); throw new ArgumentException("Base url does not match pattern");
if(auth == "")
throw new ArgumentNullException(nameof(auth), "Auth can not be empty");
this.baseUrl = baseUrlRex.Match(baseUrl).Value; this.baseUrl = baseUrlRex.Match(baseUrl).Value;
this.auth = auth; this.auth = auth;
this.libraryType = libraryType; this.libraryType = libraryType;

View File

@ -203,9 +203,6 @@ public class Server : GlobalBase
case "Settings/userAgent": case "Settings/userAgent":
SendResponse(HttpStatusCode.OK, response, settings.userAgent); SendResponse(HttpStatusCode.OK, response, settings.userAgent);
break; break;
case "Settings/customRequestLimit":
SendResponse(HttpStatusCode.OK, response, settings.requestLimits);
break;
case "NotificationConnectors": case "NotificationConnectors":
SendResponse(HttpStatusCode.OK, response, notificationConnectors); SendResponse(HttpStatusCode.OK, response, notificationConnectors);
break; break;
@ -223,40 +220,6 @@ public class Server : GlobalBase
case "Ping": case "Ping":
SendResponse(HttpStatusCode.OK, response, "Pong"); SendResponse(HttpStatusCode.OK, response, "Pong");
break; break;
case "LogMessages":
if (logger is null || !File.Exists(logger?.logFilePath))
{
SendResponse(HttpStatusCode.NotFound, response);
break;
}
if (requestVariables.TryGetValue("count", out string? count))
{
try
{
uint messageCount = uint.Parse(count);
SendResponse(HttpStatusCode.OK, response, logger.Tail(messageCount));
}
catch (FormatException f)
{
SendResponse(HttpStatusCode.InternalServerError, response, f);
}
}else
SendResponse(HttpStatusCode.OK, response, logger.GetLog());
break;
case "LogFile":
if (logger is null || !File.Exists(logger?.logFilePath))
{
SendResponse(HttpStatusCode.NotFound, response);
break;
}
string logDir = new FileInfo(logger.logFilePath).DirectoryName!;
string tmpFilePath = Path.Join(logDir, "Tranga.log");
File.Copy(logger.logFilePath, tmpFilePath);
SendResponse(HttpStatusCode.OK, response, new FileStream(tmpFilePath, FileMode.Open));
File.Delete(tmpFilePath);
break;
default: default:
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);
break; break;
@ -266,13 +229,11 @@ public class Server : GlobalBase
private void HandlePost(HttpListenerRequest request, HttpListenerResponse response) private void HandlePost(HttpListenerRequest request, HttpListenerResponse response)
{ {
Dictionary<string, string> requestVariables = GetRequestVariables(request.Url!.Query); Dictionary<string, string> requestVariables = GetRequestVariables(request.Url!.Query);
string? connectorName, internalId, jobId, chapterNumStr, customFolderName, translatedLanguage, notificationConnectorStr, libraryConnectorStr; string? connectorName, internalId, jobId, chapterNumStr, customFolderName, translatedLanguage;
MangaConnector? connector; MangaConnector? connector;
Manga? tmpManga; Manga? tmpManga;
Manga manga; Manga manga;
Job? job; Job? job;
NotificationConnector.NotificationConnectorType notificationConnectorType;
LibraryConnector.LibraryType libraryConnectorType;
string path = Regex.Match(request.Url!.LocalPath, @"[A-z0-9]+(\/[A-z0-9]+)*").Value; string path = Regex.Match(request.Url!.LocalPath, @"[A-z0-9]+(\/[A-z0-9]+)*").Value;
switch (path) switch (path)
{ {
@ -405,6 +366,18 @@ public class Server : GlobalBase
settings.UpdateDownloadLocation(downloadLocation, moveFiles); settings.UpdateDownloadLocation(downloadLocation, moveFiles);
SendResponse(HttpStatusCode.Accepted, response); SendResponse(HttpStatusCode.Accepted, response);
break; 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": /*case "Settings/UpdateWorkingDirectory":
if (!requestVariables.TryGetValue("workingDirectory", out string? workingDirectory)) if (!requestVariables.TryGetValue("workingDirectory", out string? workingDirectory))
{ {
@ -423,10 +396,6 @@ public class Server : GlobalBase
settings.UpdateUserAgent(customUserAgent); settings.UpdateUserAgent(customUserAgent);
SendResponse(HttpStatusCode.Accepted, response); SendResponse(HttpStatusCode.Accepted, response);
break; break;
case "Settings/userAgent/Reset":
settings.UpdateUserAgent(null);
SendResponse(HttpStatusCode.Accepted, response);
break;
case "Settings/customRequestLimit": case "Settings/customRequestLimit":
if (!requestVariables.TryGetValue("requestType", out string? requestTypeStr) || if (!requestVariables.TryGetValue("requestType", out string? requestTypeStr) ||
!requestVariables.TryGetValue("requestsPerMinute", out string? requestsPerMinuteStr) || !requestVariables.TryGetValue("requestsPerMinute", out string? requestsPerMinuteStr) ||
@ -443,15 +412,10 @@ public class Server : GlobalBase
SendResponse(HttpStatusCode.Accepted, response); SendResponse(HttpStatusCode.Accepted, response);
}else }else
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);
settings.ExportSettings();
break;
case "Settings/customRequestLimit/Reset":
settings.requestLimits = TrangaSettings.DefaultRequestLimits;
settings.ExportSettings();
break; break;
case "NotificationConnectors/Update": case "NotificationConnectors/Update":
if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) || if (!requestVariables.TryGetValue("notificationConnector", out string? notificationConnectorStr) ||
!Enum.TryParse(notificationConnectorStr, out notificationConnectorType)) !Enum.TryParse(notificationConnectorStr, out NotificationConnector.NotificationConnectorType notificationConnectorType))
{ {
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);
break; break;
@ -492,64 +456,9 @@ public class Server : GlobalBase
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);
} }
break; break;
case "NotificationConnectors/Test":
NotificationConnector notificationConnector;
if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) ||
!Enum.TryParse(notificationConnectorStr, out notificationConnectorType))
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
if (notificationConnectorType is NotificationConnector.NotificationConnectorType.Gotify)
{
if (!requestVariables.TryGetValue("gotifyUrl", out string? gotifyUrl) ||
!requestVariables.TryGetValue("gotifyAppToken", out string? gotifyAppToken))
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
notificationConnector = new Gotify(this, gotifyUrl, gotifyAppToken);
}else if (notificationConnectorType is NotificationConnector.NotificationConnectorType.LunaSea)
{
if (!requestVariables.TryGetValue("lunaseaWebhook", out string? lunaseaWebhook))
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
notificationConnector = new LunaSea(this, lunaseaWebhook);
}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;
}
notificationConnector = new Ntfy(this, ntfyUrl, ntfyAuth);
}
else
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
notificationConnector.SendNotification("Tranga Test", "This is Test-Notification.");
SendResponse(HttpStatusCode.Accepted, response);
break;
case "NotificationConnectors/Reset":
if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) ||
!Enum.TryParse(notificationConnectorStr, out notificationConnectorType))
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
DeleteNotificationConnector(notificationConnectorType);
SendResponse(HttpStatusCode.Accepted, response);
break;
case "LibraryConnectors/Update": case "LibraryConnectors/Update":
if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) || if (!requestVariables.TryGetValue("libraryConnector", out string? libraryConnectorStr) ||
!Enum.TryParse(libraryConnectorStr, out libraryConnectorType)) !Enum.TryParse(libraryConnectorStr, out LibraryConnector.LibraryType libraryConnectorType))
{ {
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);
break; break;
@ -582,52 +491,39 @@ public class Server : GlobalBase
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);
} }
break; break;
case "LibraryConnectors/Test": case "LogMessages":
LibraryConnector libraryConnector; if (logger is null || !File.Exists(logger?.logFilePath))
if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) ||
!Enum.TryParse(libraryConnectorStr, out libraryConnectorType))
{ {
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.NotFound, response);
break; break;
} }
if (libraryConnectorType is LibraryConnector.LibraryType.Kavita) if (requestVariables.TryGetValue("count", out string? count))
{ {
if (!requestVariables.TryGetValue("kavitaUrl", out string? kavitaUrl) || try
!requestVariables.TryGetValue("kavitaUsername", out string? kavitaUsername) ||
!requestVariables.TryGetValue("kavitaPassword", out string? kavitaPassword))
{ {
SendResponse(HttpStatusCode.BadRequest, response); uint messageCount = uint.Parse(count);
break; SendResponse(HttpStatusCode.OK, response, logger.Tail(messageCount));
} }
libraryConnector = new Kavita(this, kavitaUrl, kavitaUsername, kavitaPassword); catch (FormatException f)
}else if (libraryConnectorType is LibraryConnector.LibraryType.Komga)
{
if (!requestVariables.TryGetValue("komgaUrl", out string? komgaUrl) ||
!requestVariables.TryGetValue("komgaAuth", out string? komgaAuth))
{ {
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.InternalServerError, response, f);
break;
} }
libraryConnector = new Komga(this, komgaUrl, komgaAuth); }else
} SendResponse(HttpStatusCode.OK, response, logger.GetLog());
else
{
SendResponse(HttpStatusCode.BadRequest, response);
break;
}
libraryConnector.UpdateLibrary();
SendResponse(HttpStatusCode.Accepted, response);
break; break;
case "LibraryConnectors/Reset": case "LogFile":
if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) || if (logger is null || !File.Exists(logger?.logFilePath))
!Enum.TryParse(libraryConnectorStr, out libraryConnectorType))
{ {
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.NotFound, response);
break; break;
} }
DeleteLibraryConnector(libraryConnectorType);
SendResponse(HttpStatusCode.Accepted, response); string logDir = new FileInfo(logger.logFilePath).DirectoryName!;
string tmpFilePath = Path.Join(logDir, "Tranga.log");
File.Copy(logger.logFilePath, tmpFilePath);
SendResponse(HttpStatusCode.OK, response, new FileStream(tmpFilePath, FileMode.Open));
File.Delete(tmpFilePath);
break; break;
default: default:
SendResponse(HttpStatusCode.BadRequest, response); SendResponse(HttpStatusCode.BadRequest, response);

View File

@ -16,9 +16,7 @@ public partial class Tranga : GlobalBase
string[]? consoleLogger = GetArg(args, ArgEnum.ConsoleLogger); string[]? consoleLogger = GetArg(args, ArgEnum.ConsoleLogger);
string[]? fileLogger = GetArg(args, ArgEnum.FileLogger); string[]? fileLogger = GetArg(args, ArgEnum.FileLogger);
string? filePath = GetArg(args, ArgEnum.FileLoggerPath)?[0]; string? filePath = fileLogger?[0];//TODO validate path
if (filePath is not null && !Directory.Exists(new FileInfo(filePath).DirectoryName))
Directory.CreateDirectory(new FileInfo(filePath).DirectoryName!);
List<Logger.LoggerType> enabledLoggers = new(); List<Logger.LoggerType> enabledLoggers = new();
if(consoleLogger is not null) if(consoleLogger is not null)
@ -107,8 +105,7 @@ public partial class Tranga : GlobalBase
{ ArgEnum.DownloadLocation, new(new []{"-d", "--downloadLocation"}, 1, "Directory to which downloaded Manga are saved") }, { ArgEnum.DownloadLocation, new(new []{"-d", "--downloadLocation"}, 1, "Directory to which downloaded Manga are saved") },
{ ArgEnum.WorkingDirectory, new(new []{"-w", "--workingDirectory"}, 1, "Directory in which application-data is saved") }, { ArgEnum.WorkingDirectory, new(new []{"-w", "--workingDirectory"}, 1, "Directory in which application-data is saved") },
{ ArgEnum.ConsoleLogger, new(new []{"-c", "--consoleLogger"}, 0, "Enables the consoleLogger") }, { ArgEnum.ConsoleLogger, new(new []{"-c", "--consoleLogger"}, 0, "Enables the consoleLogger") },
{ ArgEnum.FileLogger, new(new []{"-f", "--fileLogger"}, 0, "Enables the fileLogger") }, { ArgEnum.FileLogger, new(new []{"-f", "--fileLogger"}, 1, "Enables the fileLogger, Directory where logfiles are saved") },
{ ArgEnum.FileLoggerPath, new (new []{"-l", "--fPath"}, 1, "LogFilePath" ) },
{ ArgEnum.Help, new(new []{"-h", "--help"}, 0, "Print this") } { ArgEnum.Help, new(new []{"-h", "--help"}, 0, "Print this") }
//{ ArgEnum., new(new []{""}, 1, "") } //{ ArgEnum., new(new []{""}, 1, "") }
}; };
@ -120,7 +117,6 @@ public partial class Tranga : GlobalBase
WorkingDirectory, WorkingDirectory,
ConsoleLogger, ConsoleLogger,
FileLogger, FileLogger,
FileLoggerPath,
Help Help
} }

View File

@ -13,6 +13,7 @@ public class TrangaSettings
public string downloadLocation { get; private set; } public string downloadLocation { get; private set; }
public string workingDirectory { get; private set; } public string workingDirectory { get; private set; }
public int apiPortNumber { get; init; } public int apiPortNumber { get; init; }
public string styleSheet { get; private set; }
public string userAgent { get; set; } = DefaultUserAgent; public string userAgent { get; set; } = DefaultUserAgent;
[JsonIgnore] public string settingsFilePath => Path.Join(workingDirectory, "settings.json"); [JsonIgnore] public string settingsFilePath => Path.Join(workingDirectory, "settings.json");
[JsonIgnore] public string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json"); [JsonIgnore] public string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json");
@ -36,40 +37,34 @@ public class TrangaSettings
public TrangaSettings(string? downloadLocation = null, string? workingDirectory = null, int? apiPortNumber = null) public TrangaSettings(string? downloadLocation = null, string? workingDirectory = null, int? apiPortNumber = null)
{ {
string wd = workingDirectory ?? Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api"); string lockFilePath = $"{settingsFilePath}.lock";
string sfp = Path.Join(wd, "settings.json"); if (File.Exists(settingsFilePath) && !File.Exists(lockFilePath))
string lockFilePath = $"{sfp}.lock";
if (File.Exists(sfp) && !File.Exists(lockFilePath))
{//Load from settings file {//Load from settings file
FileStream lockFile = File.Create(lockFilePath,0, FileOptions.DeleteOnClose); //lock settingsfile FileStream lockFile = File.Create(lockFilePath,0, FileOptions.DeleteOnClose); //lock settingsfile
string settingsStr = File.ReadAllText(sfp); string settingsStr = File.ReadAllText(settingsFilePath);
TrangaSettings settings = JsonConvert.DeserializeObject<TrangaSettings>(settingsStr)!; TrangaSettings settings = JsonConvert.DeserializeObject<TrangaSettings>(settingsStr)!;
this.requestLimits = settings.requestLimits;
this.userAgent = settings.userAgent;
this.downloadLocation = downloadLocation ?? settings.downloadLocation; this.downloadLocation = downloadLocation ?? settings.downloadLocation;
this.workingDirectory = workingDirectory ?? settings.workingDirectory; this.workingDirectory = workingDirectory ?? settings.workingDirectory;
this.apiPortNumber = apiPortNumber ?? settings.apiPortNumber; this.apiPortNumber = apiPortNumber ?? settings.apiPortNumber;
this.styleSheet = "default" ?? settings.styleSheet;
lockFile.Close(); //unlock settingsfile lockFile.Close(); //unlock settingsfile
} }
else if(!File.Exists(sfp)) else if(!File.Exists(settingsFilePath))
{//No settings file exists {//No settings file exists
if (downloadLocation?.Length < 1 || workingDirectory?.Length < 1) if (downloadLocation?.Length < 1 || workingDirectory?.Length < 1)
throw new ArgumentException("Download-location and working-directory paths can not be empty!"); throw new ArgumentException("Download-location and working-directory paths can not be empty!");
this.requestLimits = DefaultRequestLimits;
this.userAgent = DefaultUserAgent;
this.apiPortNumber = apiPortNumber ?? 6531; this.apiPortNumber = apiPortNumber ?? 6531;
this.downloadLocation = downloadLocation ?? (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(Directory.GetCurrentDirectory(), "Downloads")); 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.workingDirectory = workingDirectory ?? Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api");
this.styleSheet = "default";
ExportSettings(); ExportSettings();
} }
else else
{//Settingsfile is locked {//Settingsfile is locked
this.requestLimits = DefaultRequestLimits;
this.userAgent = DefaultUserAgent;
this.apiPortNumber = apiPortNumber!.Value; this.apiPortNumber = apiPortNumber!.Value;
this.downloadLocation = downloadLocation!; this.downloadLocation = downloadLocation!;
this.workingDirectory = workingDirectory!; this.workingDirectory = workingDirectory!;
this.styleSheet = "default";
} }
UpdateDownloadLocation(this.downloadLocation, false); UpdateDownloadLocation(this.downloadLocation, false);
} }
@ -102,6 +97,17 @@ 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) public void UpdateDownloadLocation(string newPath, bool moveFiles = true)
{ {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
@ -129,9 +135,9 @@ public class TrangaSettings
ExportSettings(); ExportSettings();
} }
public void UpdateUserAgent(string? customUserAgent) public void UpdateUserAgent(string customUserAgent)
{ {
this.userAgent = customUserAgent ?? DefaultUserAgent; this.userAgent = customUserAgent;
ExportSettings(); ExportSettings();
} }
@ -139,12 +145,24 @@ public class TrangaSettings
{ {
if (File.Exists(settingsFilePath)) if (File.Exists(settingsFilePath))
{ {
while(GlobalBase.IsFileInUse(settingsFilePath, null)) bool inUse = true;
Thread.Sleep(100); while (inUse)
{
try
{
using FileStream stream = new(settingsFilePath, FileMode.Open, FileAccess.Read, FileShare.None);
stream.Close();
inUse = false;
}
catch (IOException)
{
Thread.Sleep(100);
}
}
} }
else else
Directory.CreateDirectory(new FileInfo(settingsFilePath).DirectoryName!); Directory.CreateDirectory(new FileInfo(settingsFilePath).DirectoryName!);
File.WriteAllText(settingsFilePath, JsonConvert.SerializeObject(this, Formatting.Indented)); File.WriteAllText(settingsFilePath, JsonConvert.SerializeObject(this));
} }
public string GetFullCoverPath(Manga manga) public string GetFullCoverPath(Manga manga)