2023-05-25 10:25:24 +02:00
|
|
|
using System.Runtime.InteropServices;
|
2023-05-21 21:12:32 +02:00
|
|
|
using Logging;
|
|
|
|
using Tranga;
|
2023-06-08 19:24:46 +02:00
|
|
|
using Tranga.TrangaTasks;
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-05-25 10:25:24 +02:00
|
|
|
string applicationFolderPath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Tranga-API");
|
|
|
|
string downloadFolderPath = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(applicationFolderPath, "Manga");
|
|
|
|
string logsFolderPath = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/var/logs/Tranga" : Path.Join(applicationFolderPath, "logs");
|
2023-05-21 21:12:32 +02:00
|
|
|
string logFilePath = Path.Join(logsFolderPath, $"log-{DateTime.Now:dd-M-yyyy-HH-mm-ss}.txt");
|
2023-05-22 00:13:24 +02:00
|
|
|
string settingsFilePath = Path.Join(applicationFolderPath, "settings.json");
|
2023-05-21 21:12:32 +02:00
|
|
|
|
|
|
|
Directory.CreateDirectory(logsFolderPath);
|
2023-05-25 14:23:33 +02:00
|
|
|
Logger logger = new(new[] { Logger.LoggerType.FileLogger, Logger.LoggerType.ConsoleLogger }, Console.Out, Console.Out.Encoding, logFilePath);
|
2023-05-25 10:25:24 +02:00
|
|
|
|
2023-05-25 14:23:33 +02:00
|
|
|
logger.WriteLine("Tranga", "Loading settings.");
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-05-22 00:13:24 +02:00
|
|
|
TrangaSettings settings;
|
2023-05-21 21:12:32 +02:00
|
|
|
if (File.Exists(settingsFilePath))
|
2023-06-03 15:02:15 +02:00
|
|
|
settings = TrangaSettings.LoadSettings(settingsFilePath, logger);
|
2023-05-21 21:12:32 +02:00
|
|
|
else
|
2023-06-03 15:17:08 +02:00
|
|
|
settings = new TrangaSettings(downloadFolderPath, applicationFolderPath, new HashSet<LibraryManager>());
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-05-25 14:23:33 +02:00
|
|
|
Directory.CreateDirectory(settings.workingDirectory);
|
|
|
|
Directory.CreateDirectory(settings.downloadLocation);
|
|
|
|
Directory.CreateDirectory(settings.coverImageCache);
|
|
|
|
|
|
|
|
logger.WriteLine("Tranga",$"Application-Folder: {settings.workingDirectory}");
|
|
|
|
logger.WriteLine("Tranga",$"Settings-File-Path: {settings.settingsFilePath}");
|
|
|
|
logger.WriteLine("Tranga",$"Download-Folder-Path: {settings.downloadLocation}");
|
|
|
|
logger.WriteLine("Tranga",$"Logfile-Path: {logFilePath}");
|
|
|
|
logger.WriteLine("Tranga",$"Image-Cache-Path: {settings.coverImageCache}");
|
|
|
|
|
|
|
|
logger.WriteLine("Tranga", "Loading Taskmanager.");
|
2023-05-21 21:12:32 +02:00
|
|
|
TaskManager taskManager = new (settings, logger);
|
|
|
|
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
2023-05-21 22:01:28 +02:00
|
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
|
|
builder.Services.AddSwaggerGen();
|
2023-05-21 21:12:32 +02:00
|
|
|
builder.Services.AddControllers().AddNewtonsoftJson();
|
2023-05-23 13:16:37 +02:00
|
|
|
|
|
|
|
string corsHeader = "Tranga";
|
|
|
|
builder.Services.AddCors(options =>
|
|
|
|
{
|
|
|
|
options.AddPolicy(name: corsHeader,
|
|
|
|
policy =>
|
|
|
|
{
|
2023-05-24 22:56:10 +02:00
|
|
|
policy.AllowAnyOrigin();
|
2023-05-23 18:11:18 +02:00
|
|
|
policy.WithMethods("GET", "POST", "DELETE");
|
2023-05-23 13:16:37 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-05-21 21:12:32 +02:00
|
|
|
var app = builder.Build();
|
2023-05-21 22:01:28 +02:00
|
|
|
app.UseSwagger();
|
|
|
|
app.UseSwaggerUI();
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-05-23 13:16:37 +02:00
|
|
|
app.UseCors(corsHeader);
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-06-08 19:24:46 +02:00
|
|
|
app.MapGet("/Controllers/Get", () => taskManager.GetAvailableConnectors().Keys.ToArray());
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-06-08 19:24:46 +02:00
|
|
|
app.MapGet("/Publications/GetKnown", (string? internalId) =>
|
|
|
|
{
|
|
|
|
if(internalId is null)
|
|
|
|
return taskManager.GetAllPublications();
|
|
|
|
|
|
|
|
return new [] { taskManager.GetAllPublications().FirstOrDefault(pub => pub.internalId == internalId) };
|
|
|
|
});
|
2023-05-23 13:17:05 +02:00
|
|
|
|
2023-06-08 19:24:46 +02:00
|
|
|
app.MapGet("/Publications/GetFromConnector", (string connectorName, string title) =>
|
2023-05-21 21:12:32 +02:00
|
|
|
{
|
|
|
|
Connector? connector = taskManager.GetAvailableConnectors().FirstOrDefault(con => con.Key == connectorName).Value;
|
|
|
|
if (connector is null)
|
|
|
|
return Array.Empty<Publication>();
|
|
|
|
if(title.Length < 4)
|
|
|
|
return Array.Empty<Publication>();
|
|
|
|
return taskManager.GetPublicationsFromConnector(connector, title);
|
|
|
|
});
|
|
|
|
|
2023-06-08 19:24:46 +02:00
|
|
|
app.MapGet("/Publications/GetChapters", (string connectorName, string internalId, string? language) =>
|
|
|
|
{
|
|
|
|
Connector? connector = taskManager.GetAvailableConnectors().FirstOrDefault(con => con.Key == connectorName).Value;
|
|
|
|
if (connector is null)
|
|
|
|
return Array.Empty<Chapter>();
|
|
|
|
Publication? publication = taskManager.GetAllPublications().FirstOrDefault(pub => pub.internalId == internalId);
|
|
|
|
if (publication is null)
|
|
|
|
return Array.Empty<Chapter>();
|
|
|
|
return connector.GetChapters((Publication)publication, language??"en");
|
|
|
|
});
|
|
|
|
|
|
|
|
app.MapGet("/Tasks/GetTypes", () => Enum.GetNames(typeof(TrangaTask.Task)));
|
2023-05-21 21:12:32 +02:00
|
|
|
|
|
|
|
|
2023-06-08 19:24:46 +02:00
|
|
|
app.MapPost("/Tasks/CreateMonitorTask",
|
|
|
|
(string connectorName, string internalId, string reoccurrenceTime, string? language) =>
|
|
|
|
{
|
|
|
|
Connector? connector =
|
|
|
|
taskManager.GetAvailableConnectors().FirstOrDefault(con => con.Key == connectorName).Value;
|
|
|
|
if (connector is null)
|
|
|
|
return;
|
|
|
|
Publication? publication = taskManager.GetAllPublications().FirstOrDefault(pub => pub.internalId == internalId);
|
|
|
|
if (publication is null)
|
|
|
|
return;
|
|
|
|
taskManager.AddTask(new DownloadNewChaptersTask(TrangaTask.Task.DownloadNewChapters, connectorName,
|
|
|
|
(Publication)publication,
|
|
|
|
TimeSpan.Parse(reoccurrenceTime), language ?? "en"));
|
|
|
|
});
|
|
|
|
|
|
|
|
app.MapPost("/Tasks/CreateUpdateLibraryTask", (string reoccurrenceTime) =>
|
2023-05-21 21:12:32 +02:00
|
|
|
{
|
2023-06-08 19:24:46 +02:00
|
|
|
taskManager.AddTask(new UpdateLibrariesTask(TrangaTask.Task.UpdateLibraries, TimeSpan.Parse(reoccurrenceTime)));
|
|
|
|
});
|
|
|
|
|
|
|
|
app.MapPost("/Tasks/CreateDownloadChaptersTask", (string connectorName, string internalId, string chapters, string? language) => {
|
|
|
|
|
|
|
|
Connector? connector =
|
|
|
|
taskManager.GetAvailableConnectors().FirstOrDefault(con => con.Key == connectorName).Value;
|
|
|
|
if (connector is null)
|
|
|
|
return;
|
|
|
|
Publication? publication = taskManager.GetAllPublications().FirstOrDefault(pub => pub.internalId == internalId);
|
|
|
|
if (publication is null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Chapter[] availableChapters = connector.GetChapters((Publication)publication, language??"en");;
|
2023-06-08 19:53:05 +02:00
|
|
|
IEnumerable<Chapter> toDownload;
|
2023-06-08 19:24:46 +02:00
|
|
|
|
2023-06-08 19:53:05 +02:00
|
|
|
if (chapters.Contains("vol", StringComparison.InvariantCultureIgnoreCase))
|
2023-06-08 19:24:46 +02:00
|
|
|
{
|
2023-06-08 19:53:05 +02:00
|
|
|
if (chapters.Contains('-'))
|
|
|
|
{
|
|
|
|
string selectString = chapters.Split(' ').First(str => str.Contains('-'));
|
|
|
|
int start = Convert.ToInt32(selectString.Split('-')[0]);
|
|
|
|
int end = Convert.ToInt32(selectString.Split('-')[1]);
|
|
|
|
toDownload = availableChapters.Where(chapter =>
|
|
|
|
Convert.ToInt32(chapter.volumeNumber) >= start && Convert.ToInt32(chapter.volumeNumber) <= end);
|
|
|
|
}
|
|
|
|
else
|
2023-06-08 19:24:46 +02:00
|
|
|
{
|
2023-06-08 19:53:05 +02:00
|
|
|
string selectString = chapters.Split(' ').First(str => !str.Contains("vol", StringComparison.InvariantCultureIgnoreCase));
|
|
|
|
toDownload = availableChapters.Where(chapter => chapter.volumeNumber.Equals(selectString));
|
2023-06-08 19:24:46 +02:00
|
|
|
}
|
|
|
|
}
|
2023-06-08 19:53:05 +02:00
|
|
|
else if (chapters.Contains('-'))
|
|
|
|
{
|
|
|
|
int start = Convert.ToInt32(chapters.Split('-')[0]);
|
|
|
|
int end = Convert.ToInt32(chapters.Split('-')[1]) + 1;
|
|
|
|
toDownload = availableChapters[start..end];
|
|
|
|
}
|
2023-06-08 19:24:46 +02:00
|
|
|
else
|
2023-06-08 19:53:05 +02:00
|
|
|
{
|
|
|
|
toDownload = new[] { availableChapters[Convert.ToInt32(chapters)] };
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach(Chapter chapter in toDownload)
|
2023-06-08 19:24:46 +02:00
|
|
|
taskManager.AddTask(new DownloadChapterTask(TrangaTask.Task.DownloadChapter, connectorName,
|
2023-06-08 19:53:05 +02:00
|
|
|
(Publication)publication, chapter, "en"));
|
2023-05-21 21:12:32 +02:00
|
|
|
});
|
|
|
|
|
2023-05-21 22:24:12 +02:00
|
|
|
app.MapDelete("/Tasks/Delete", (string taskType, string? connectorName, string? publicationId) =>
|
2023-05-21 21:12:32 +02:00
|
|
|
{
|
|
|
|
TrangaTask.Task task = Enum.Parse<TrangaTask.Task>(taskType);
|
2023-06-05 20:52:21 +02:00
|
|
|
taskManager.DeleteTask(task, connectorName, publicationId);
|
2023-05-21 21:12:32 +02:00
|
|
|
});
|
|
|
|
|
2023-05-24 21:04:24 +02:00
|
|
|
app.MapGet("/Tasks/Get", (string taskType, string? connectorName, string? searchString) =>
|
|
|
|
{
|
2023-05-24 23:52:40 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
TrangaTask.Task task = Enum.Parse<TrangaTask.Task>(taskType);
|
2023-06-05 00:35:57 +02:00
|
|
|
return taskManager.GetTasksMatching(task, connectorName:connectorName, searchString:searchString);
|
2023-05-24 23:52:40 +02:00
|
|
|
}
|
|
|
|
catch (ArgumentException)
|
|
|
|
{
|
|
|
|
return Array.Empty<TrangaTask>();
|
|
|
|
}
|
2023-05-24 21:04:24 +02:00
|
|
|
});
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-06-08 19:24:46 +02:00
|
|
|
app.MapGet("/Tasks/GetProgress", (string taskType, string? connectorName, string? publicationId) =>
|
2023-06-01 23:08:43 +02:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
2023-06-05 00:35:57 +02:00
|
|
|
TrangaTask? task = taskManager
|
2023-06-05 00:50:51 +02:00
|
|
|
.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId)?.First();
|
2023-06-05 00:35:57 +02:00
|
|
|
|
2023-06-01 23:08:43 +02:00
|
|
|
if (task is null)
|
|
|
|
return -1f;
|
|
|
|
|
|
|
|
return task.progress;
|
|
|
|
}
|
|
|
|
catch (ArgumentException)
|
|
|
|
{
|
|
|
|
return -1f;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-06-05 00:50:51 +02:00
|
|
|
app.MapPost("/Tasks/Start", (string taskType, string? connectorName, string? internalId) =>
|
2023-05-21 21:12:32 +02:00
|
|
|
{
|
2023-05-24 23:52:40 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
2023-06-05 00:35:57 +02:00
|
|
|
TrangaTask? task = taskManager
|
2023-06-05 00:50:51 +02:00
|
|
|
.GetTasksMatching(pTask, connectorName: connectorName, internalId: internalId)?.FirstOrDefault();
|
2023-05-24 23:52:40 +02:00
|
|
|
|
|
|
|
if (task is null)
|
|
|
|
return;
|
|
|
|
taskManager.ExecuteTaskNow(task);
|
|
|
|
}
|
|
|
|
catch (ArgumentException)
|
|
|
|
{
|
2023-05-21 21:12:32 +02:00
|
|
|
return;
|
2023-05-24 23:52:40 +02:00
|
|
|
}
|
|
|
|
|
2023-05-21 21:12:32 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
app.MapGet("/Tasks/GetRunningTasks",
|
|
|
|
() => taskManager.GetAllTasks().Where(task => task.state is TrangaTask.ExecutionState.Running));
|
|
|
|
|
|
|
|
app.MapGet("/Queue/GetList",
|
|
|
|
() => taskManager.GetAllTasks().Where(task => task.state is TrangaTask.ExecutionState.Enqueued));
|
|
|
|
|
|
|
|
app.MapPost("/Queue/Enqueue", (string taskType, string? connectorName, string? publicationId) =>
|
|
|
|
{
|
2023-05-24 23:52:40 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
2023-06-05 00:35:57 +02:00
|
|
|
TrangaTask? task = taskManager
|
2023-06-05 00:50:51 +02:00
|
|
|
.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId)?.First();
|
2023-05-24 23:52:40 +02:00
|
|
|
|
|
|
|
if (task is null)
|
|
|
|
return;
|
|
|
|
taskManager.AddTaskToQueue(task);
|
|
|
|
}
|
|
|
|
catch (ArgumentException)
|
|
|
|
{
|
2023-05-21 21:12:32 +02:00
|
|
|
return;
|
2023-05-24 23:52:40 +02:00
|
|
|
}
|
2023-05-21 21:12:32 +02:00
|
|
|
});
|
|
|
|
|
2023-05-21 22:24:12 +02:00
|
|
|
app.MapDelete("/Queue/Dequeue", (string taskType, string? connectorName, string? publicationId) =>
|
2023-05-21 21:12:32 +02:00
|
|
|
{
|
2023-05-24 23:52:40 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
2023-06-05 00:35:57 +02:00
|
|
|
TrangaTask? task = taskManager
|
2023-06-05 00:50:51 +02:00
|
|
|
.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId)?.First();
|
2023-05-24 23:52:40 +02:00
|
|
|
|
|
|
|
if (task is null)
|
|
|
|
return;
|
|
|
|
taskManager.RemoveTaskFromQueue(task);
|
|
|
|
}
|
|
|
|
catch (ArgumentException)
|
|
|
|
{
|
2023-05-21 21:12:32 +02:00
|
|
|
return;
|
2023-05-24 23:52:40 +02:00
|
|
|
}
|
2023-05-21 21:12:32 +02:00
|
|
|
});
|
|
|
|
|
2023-05-22 01:49:53 +02:00
|
|
|
app.MapGet("/Settings/Get", () => taskManager.settings);
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-06-03 15:17:08 +02:00
|
|
|
app.MapPost("/Settings/Update",
|
2023-06-03 21:26:29 +02:00
|
|
|
(string? downloadLocation, string? komgaUrl, string? komgaAuth, string? kavitaUrl, string? kavitaUsername, string? kavitaPassword) =>
|
|
|
|
taskManager.UpdateSettings(downloadLocation, komgaUrl, komgaAuth, kavitaUrl, kavitaUsername, kavitaPassword));
|
2023-05-21 21:12:32 +02:00
|
|
|
|
2023-05-22 01:49:53 +02:00
|
|
|
app.Run();
|