commit
0f29da00de
@ -46,8 +46,29 @@ 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;
|
||||||
|
|
||||||
TrangaSettings trangaSettings = new (settings.downloadLocation, settings.workingDirectory, settings.apiPort);
|
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.downloadLocation);
|
||||||
Directory.CreateDirectory(trangaSettings.workingDirectory);
|
Directory.CreateDirectory(trangaSettings.workingDirectory);
|
||||||
|
@ -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", "-c"]
|
ENTRYPOINT ["dotnet", "/publish/Tranga.dll", "-f -c"]
|
||||||
|
@ -9,7 +9,8 @@ namespace Tranga;
|
|||||||
|
|
||||||
public abstract class GlobalBase
|
public abstract class GlobalBase
|
||||||
{
|
{
|
||||||
protected Logger? logger { get; init; }
|
[JsonIgnore]
|
||||||
|
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; }
|
||||||
@ -88,7 +89,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));
|
File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void DeleteLibraryConnector(LibraryConnector.LibraryType libraryType)
|
protected void DeleteLibraryConnector(LibraryConnector.LibraryType libraryType)
|
||||||
@ -98,10 +99,12 @@ 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));
|
File.WriteAllText(settings.libraryConnectorsFilePath, JsonConvert.SerializeObject(libraryConnectors, Formatting.Indented));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool IsFileInUse(string filePath)
|
protected bool IsFileInUse(string filePath) => IsFileInUse(filePath, this.logger);
|
||||||
|
|
||||||
|
public static bool IsFileInUse(string filePath, Logger? logger)
|
||||||
{
|
{
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
return false;
|
return false;
|
||||||
@ -113,7 +116,7 @@ public abstract class GlobalBase
|
|||||||
}
|
}
|
||||||
catch (IOException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
Log($"File is in use {filePath}");
|
logger?.WriteLine($"File is in use {filePath}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
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;
|
||||||
|
|
||||||
@ -8,7 +9,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), LibraryType.Kavita)
|
base(clone, baseUrl, GetToken(baseUrl, username, password, clone.logger), LibraryType.Kavita)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ public class Kavita : LibraryConnector
|
|||||||
return $"Kavita {baseUrl}";
|
return $"Kavita {baseUrl}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetToken(string baseUrl, string username, string password)
|
private static string GetToken(string baseUrl, string username, string password, Logger? logger = null)
|
||||||
{
|
{
|
||||||
HttpClient client = new()
|
HttpClient client = new()
|
||||||
{
|
{
|
||||||
@ -40,16 +41,24 @@ public class Kavita : LibraryConnector
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = client.Send(requestMessage);
|
HttpResponseMessage response = client.Send(requestMessage);
|
||||||
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(response.Content.ReadAsStream());
|
logger?.WriteLine($"Kavita | GetToken {requestMessage.RequestUri} -> {response.StatusCode}");
|
||||||
if (result is not null)
|
if (response.IsSuccessStatusCode)
|
||||||
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)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Unable to retrieve token:\n\r{e}");
|
logger?.WriteLine($"Kavita | Unable to retrieve token:\n\r{e}");
|
||||||
}
|
}
|
||||||
Console.WriteLine("Kavita: Did not receive token.");
|
logger?.WriteLine("Kavita | Did not receive token.");
|
||||||
throw new Exception("Kavita: Did not receive token.");
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateLibrary()
|
public override void UpdateLibrary()
|
||||||
|
@ -23,6 +23,8 @@ 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;
|
||||||
|
178
Tranga/Server.cs
178
Tranga/Server.cs
@ -203,6 +203,9 @@ 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;
|
||||||
@ -220,6 +223,40 @@ 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;
|
||||||
@ -229,11 +266,13 @@ 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;
|
string? connectorName, internalId, jobId, chapterNumStr, customFolderName, translatedLanguage, notificationConnectorStr, libraryConnectorStr;
|
||||||
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)
|
||||||
{
|
{
|
||||||
@ -366,18 +405,6 @@ 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))
|
||||||
{
|
{
|
||||||
@ -396,6 +423,10 @@ 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) ||
|
||||||
@ -412,10 +443,15 @@ 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 string? notificationConnectorStr) ||
|
if (!requestVariables.TryGetValue("notificationConnector", out notificationConnectorStr) ||
|
||||||
!Enum.TryParse(notificationConnectorStr, out NotificationConnector.NotificationConnectorType notificationConnectorType))
|
!Enum.TryParse(notificationConnectorStr, out notificationConnectorType))
|
||||||
{
|
{
|
||||||
SendResponse(HttpStatusCode.BadRequest, response);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
break;
|
break;
|
||||||
@ -456,9 +492,64 @@ 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 string? libraryConnectorStr) ||
|
if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) ||
|
||||||
!Enum.TryParse(libraryConnectorStr, out LibraryConnector.LibraryType libraryConnectorType))
|
!Enum.TryParse(libraryConnectorStr, out libraryConnectorType))
|
||||||
{
|
{
|
||||||
SendResponse(HttpStatusCode.BadRequest, response);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
break;
|
break;
|
||||||
@ -491,39 +582,52 @@ public class Server : GlobalBase
|
|||||||
SendResponse(HttpStatusCode.BadRequest, response);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "LogMessages":
|
case "LibraryConnectors/Test":
|
||||||
if (logger is null || !File.Exists(logger?.logFilePath))
|
LibraryConnector libraryConnector;
|
||||||
|
if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) ||
|
||||||
|
!Enum.TryParse(libraryConnectorStr, out libraryConnectorType))
|
||||||
{
|
{
|
||||||
SendResponse(HttpStatusCode.NotFound, response);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestVariables.TryGetValue("count", out string? count))
|
if (libraryConnectorType is LibraryConnector.LibraryType.Kavita)
|
||||||
{
|
{
|
||||||
try
|
if (!requestVariables.TryGetValue("kavitaUrl", out string? kavitaUrl) ||
|
||||||
|
!requestVariables.TryGetValue("kavitaUsername", out string? kavitaUsername) ||
|
||||||
|
!requestVariables.TryGetValue("kavitaPassword", out string? kavitaPassword))
|
||||||
{
|
{
|
||||||
uint messageCount = uint.Parse(count);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
SendResponse(HttpStatusCode.OK, response, logger.Tail(messageCount));
|
break;
|
||||||
}
|
}
|
||||||
catch (FormatException f)
|
libraryConnector = new Kavita(this, kavitaUrl, kavitaUsername, kavitaPassword);
|
||||||
|
}else if (libraryConnectorType is LibraryConnector.LibraryType.Komga)
|
||||||
|
{
|
||||||
|
if (!requestVariables.TryGetValue("komgaUrl", out string? komgaUrl) ||
|
||||||
|
!requestVariables.TryGetValue("komgaAuth", out string? komgaAuth))
|
||||||
{
|
{
|
||||||
SendResponse(HttpStatusCode.InternalServerError, response, f);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}else
|
libraryConnector = new Komga(this, komgaUrl, komgaAuth);
|
||||||
SendResponse(HttpStatusCode.OK, response, logger.GetLog());
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
libraryConnector.UpdateLibrary();
|
||||||
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
break;
|
break;
|
||||||
case "LogFile":
|
case "LibraryConnectors/Reset":
|
||||||
if (logger is null || !File.Exists(logger?.logFilePath))
|
if (!requestVariables.TryGetValue("libraryConnector", out libraryConnectorStr) ||
|
||||||
|
!Enum.TryParse(libraryConnectorStr, out libraryConnectorType))
|
||||||
{
|
{
|
||||||
SendResponse(HttpStatusCode.NotFound, response);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
DeleteLibraryConnector(libraryConnectorType);
|
||||||
string logDir = new FileInfo(logger.logFilePath).DirectoryName!;
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
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);
|
||||||
|
@ -16,7 +16,9 @@ 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 = fileLogger?[0];//TODO validate path
|
string? filePath = GetArg(args, ArgEnum.FileLoggerPath)?[0];
|
||||||
|
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)
|
||||||
@ -105,7 +107,8 @@ 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"}, 1, "Enables the fileLogger, Directory where logfiles are saved") },
|
{ ArgEnum.FileLogger, new(new []{"-f", "--fileLogger"}, 0, "Enables the fileLogger") },
|
||||||
|
{ 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, "") }
|
||||||
};
|
};
|
||||||
@ -117,6 +120,7 @@ public partial class Tranga : GlobalBase
|
|||||||
WorkingDirectory,
|
WorkingDirectory,
|
||||||
ConsoleLogger,
|
ConsoleLogger,
|
||||||
FileLogger,
|
FileLogger,
|
||||||
|
FileLoggerPath,
|
||||||
Help
|
Help
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ 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");
|
||||||
@ -37,34 +36,40 @@ 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 lockFilePath = $"{settingsFilePath}.lock";
|
string wd = workingDirectory ?? Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api");
|
||||||
if (File.Exists(settingsFilePath) && !File.Exists(lockFilePath))
|
string sfp = Path.Join(wd, "settings.json");
|
||||||
|
|
||||||
|
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(settingsFilePath);
|
string settingsStr = File.ReadAllText(sfp);
|
||||||
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(settingsFilePath))
|
else if(!File.Exists(sfp))
|
||||||
{//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);
|
||||||
}
|
}
|
||||||
@ -97,17 +102,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)
|
public void UpdateDownloadLocation(string newPath, bool moveFiles = true)
|
||||||
{
|
{
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
@ -135,9 +129,9 @@ public class TrangaSettings
|
|||||||
ExportSettings();
|
ExportSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateUserAgent(string customUserAgent)
|
public void UpdateUserAgent(string? customUserAgent)
|
||||||
{
|
{
|
||||||
this.userAgent = customUserAgent;
|
this.userAgent = customUserAgent ?? DefaultUserAgent;
|
||||||
ExportSettings();
|
ExportSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,24 +139,12 @@ public class TrangaSettings
|
|||||||
{
|
{
|
||||||
if (File.Exists(settingsFilePath))
|
if (File.Exists(settingsFilePath))
|
||||||
{
|
{
|
||||||
bool inUse = true;
|
while(GlobalBase.IsFileInUse(settingsFilePath, null))
|
||||||
while (inUse)
|
Thread.Sleep(100);
|
||||||
{
|
|
||||||
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));
|
File.WriteAllText(settingsFilePath, JsonConvert.SerializeObject(this, Formatting.Indented));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetFullCoverPath(Manga manga)
|
public string GetFullCoverPath(Manga manga)
|
||||||
|
Loading…
Reference in New Issue
Block a user