mirror of
https://github.com/C9Glax/tranga.git
synced 2025-07-02 00:44:16 +02:00
Manga and Chapters are shared across Connectors
This commit is contained in:
@ -37,7 +37,7 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
[ProducesResponseType<Job[]>(Status200OK, "application/json")]
|
||||
public IActionResult GetJobs([FromBody]string[] ids)
|
||||
{
|
||||
Job[] ret = context.Jobs.Where(job => ids.Contains(job.JobId)).ToArray();
|
||||
Job[] ret = context.Jobs.Where(job => ids.Contains(job.Key)).ToArray();
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
@ -103,11 +103,11 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
/// <summary>
|
||||
/// Create a new DownloadAvailableChaptersJob
|
||||
/// </summary>
|
||||
/// <param name="MangaId">ID of Manga</param>
|
||||
/// <param name="MangaId">ID of Obj</param>
|
||||
/// <param name="record">Job-Configuration</param>
|
||||
/// <response code="201">Job-IDs</response>
|
||||
/// <response code="400">Could not find ToLibrary with ID</response>
|
||||
/// <response code="404">Could not find Manga with ID</response>
|
||||
/// <response code="400">Could not find ToFileLibrary with ID</response>
|
||||
/// <response code="404">Could not find Obj with ID</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpPut("DownloadAvailableChaptersJob/{MangaId}")]
|
||||
[ProducesResponseType<string[]>(Status201Created, "application/json")]
|
||||
@ -122,7 +122,7 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
LocalLibrary? l = context.LocalLibraries.Find(record.localLibraryId);
|
||||
FileLibrary? l = context.LocalLibraries.Find(record.localLibraryId);
|
||||
if (l is null)
|
||||
return BadRequest();
|
||||
m.Library = l;
|
||||
@ -166,9 +166,9 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
/// <summary>
|
||||
/// Create a new UpdateChaptersDownloadedJob
|
||||
/// </summary>
|
||||
/// <param name="MangaId">ID of the Manga</param>
|
||||
/// <param name="MangaId">ID of the Obj</param>
|
||||
/// <response code="201">Job-IDs</response>
|
||||
/// <response code="201">Could not find Manga with ID</response>
|
||||
/// <response code="201">Could not find Obj with ID</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpPut("UpdateFilesJob/{MangaId}")]
|
||||
[ProducesResponseType<string[]>(Status201Created, "application/json")]
|
||||
@ -183,7 +183,7 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new UpdateMetadataJob for all Manga
|
||||
/// Create a new UpdateMetadataJob for all Obj
|
||||
/// </summary>
|
||||
/// <response code="201">Job-IDs</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
@ -209,9 +209,9 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
/// <summary>
|
||||
/// Not Implemented: Create a new UpdateMetadataJob
|
||||
/// </summary>
|
||||
/// <param name="MangaId">ID of the Manga</param>
|
||||
/// <param name="MangaId">ID of the Obj</param>
|
||||
/// <response code="201">Job-IDs</response>
|
||||
/// <response code="404">Could not find Manga with ID</response>
|
||||
/// <response code="404">Could not find Obj with ID</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpPut("UpdateMetadataJob/{MangaId}")]
|
||||
[ProducesResponseType<string[]>(Status201Created, "application/json")]
|
||||
@ -223,7 +223,7 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not Implemented: Create a new UpdateMetadataJob for all Manga
|
||||
/// Not Implemented: Create a new UpdateMetadataJob for all Obj
|
||||
/// </summary>
|
||||
/// <response code="201">Job-IDs</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
@ -241,7 +241,7 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
{
|
||||
context.Jobs.AddRange(jobs);
|
||||
context.SaveChanges();
|
||||
return new CreatedResult((string?)null, jobs.Select(j => j.JobId).ToArray());
|
||||
return new CreatedResult((string?)null, jobs.Select(j => j.Key).ToArray());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -279,15 +279,6 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
}
|
||||
|
||||
private IQueryable<Job> GetChildJobs(string parentJobId)
|
||||
{
|
||||
IQueryable<Job> children = context.Jobs.Where(j => j.ParentJobId == parentJobId);
|
||||
foreach (Job child in children)
|
||||
foreach (Job grandChild in GetChildJobs(child.JobId))
|
||||
children.Append(grandChild);
|
||||
return children;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modify Job with ID
|
||||
/// </summary>
|
||||
@ -314,7 +305,7 @@ public class JobController(PgsqlContext context, ILog Log) : Controller
|
||||
ret.Enabled = modifyJobRecord.Enabled ?? ret.Enabled;
|
||||
|
||||
context.SaveChanges();
|
||||
return new AcceptedResult(ret.JobId, ret);
|
||||
return new AcceptedResult(ret.Key, ret);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using API.Schema;
|
||||
using API.Schema.Contexts;
|
||||
using API.Schema.Contexts;
|
||||
using API.Schema.LibraryConnectors;
|
||||
using Asp.Versioning;
|
||||
using log4net;
|
||||
@ -14,7 +13,7 @@ namespace API.Controllers;
|
||||
public class LibraryConnectorController(LibraryContext context, ILog Log) : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all configured ToLibrary-Connectors
|
||||
/// Gets all configured ToFileLibrary-Connectors
|
||||
/// </summary>
|
||||
/// <response code="200"></response>
|
||||
[HttpGet]
|
||||
@ -26,9 +25,9 @@ public class LibraryConnectorController(LibraryContext context, ILog Log) : Cont
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns ToLibrary-Connector with requested ID
|
||||
/// Returns ToFileLibrary-Connector with requested ID
|
||||
/// </summary>
|
||||
/// <param name="LibraryControllerId">ToLibrary-Connector-ID</param>
|
||||
/// <param name="LibraryControllerId">ToFileLibrary-Connector-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">Connector with ID not found.</response>
|
||||
[HttpGet("{LibraryControllerId}")]
|
||||
@ -45,9 +44,9 @@ public class LibraryConnectorController(LibraryContext context, ILog Log) : Cont
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ToLibrary-Connector
|
||||
/// Creates a new ToFileLibrary-Connector
|
||||
/// </summary>
|
||||
/// <param name="libraryConnector">ToLibrary-Connector</param>
|
||||
/// <param name="libraryConnector">ToFileLibrary-Connector</param>
|
||||
/// <response code="201"></response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpPut]
|
||||
@ -69,9 +68,9 @@ public class LibraryConnectorController(LibraryContext context, ILog Log) : Cont
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the ToLibrary-Connector with the requested ID
|
||||
/// Deletes the ToFileLibrary-Connector with the requested ID
|
||||
/// </summary>
|
||||
/// <param name="LibraryControllerId">ToLibrary-Connector-ID</param>
|
||||
/// <param name="LibraryControllerId">ToFileLibrary-Connector-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">Connector with ID not found.</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
|
@ -14,18 +14,18 @@ namespace API.Controllers;
|
||||
public class LocalLibrariesController(PgsqlContext context, ILog Log) : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResponseType<LocalLibrary[]>(Status200OK, "application/json")]
|
||||
[ProducesResponseType<FileLibrary[]>(Status200OK, "application/json")]
|
||||
public IActionResult GetLocalLibraries()
|
||||
{
|
||||
return Ok(context.LocalLibraries);
|
||||
}
|
||||
|
||||
[HttpGet("{LibraryId}")]
|
||||
[ProducesResponseType<LocalLibrary>(Status200OK, "application/json")]
|
||||
[ProducesResponseType<FileLibrary>(Status200OK, "application/json")]
|
||||
[ProducesResponseType(Status404NotFound)]
|
||||
public IActionResult GetLocalLibrary(string LibraryId)
|
||||
{
|
||||
LocalLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
FileLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
if (library is null)
|
||||
return NotFound();
|
||||
return Ok(library);
|
||||
@ -38,7 +38,7 @@ public class LocalLibrariesController(PgsqlContext context, ILog Log) : Controll
|
||||
[ProducesResponseType<string>(Status500InternalServerError, "text/plain")]
|
||||
public IActionResult UpdateLocalLibrary(string LibraryId, [FromBody]NewLibraryRecord record)
|
||||
{
|
||||
LocalLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
FileLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
if (library is null)
|
||||
return NotFound();
|
||||
if (record.Validate() == false)
|
||||
@ -68,7 +68,7 @@ public class LocalLibrariesController(PgsqlContext context, ILog Log) : Controll
|
||||
{
|
||||
try
|
||||
{
|
||||
LocalLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
FileLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
if (library is null)
|
||||
return NotFound();
|
||||
|
||||
@ -96,7 +96,7 @@ public class LocalLibrariesController(PgsqlContext context, ILog Log) : Controll
|
||||
{
|
||||
try
|
||||
{
|
||||
LocalLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
FileLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
if (library is null)
|
||||
return NotFound();
|
||||
|
||||
@ -116,7 +116,7 @@ public class LocalLibrariesController(PgsqlContext context, ILog Log) : Controll
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[ProducesResponseType<LocalLibrary>(Status200OK, "application/json")]
|
||||
[ProducesResponseType<FileLibrary>(Status200OK, "application/json")]
|
||||
[ProducesResponseType(Status400BadRequest)]
|
||||
[ProducesResponseType<string>(Status500InternalServerError, "text/plain")]
|
||||
public IActionResult CreateNewLibrary([FromBody]NewLibraryRecord library)
|
||||
@ -125,11 +125,11 @@ public class LocalLibrariesController(PgsqlContext context, ILog Log) : Controll
|
||||
return BadRequest();
|
||||
try
|
||||
{
|
||||
LocalLibrary newLibrary = new (library.path, library.name);
|
||||
context.LocalLibraries.Add(newLibrary);
|
||||
FileLibrary newFileLibrary = new (library.path, library.name);
|
||||
context.LocalLibraries.Add(newFileLibrary);
|
||||
context.SaveChanges();
|
||||
|
||||
return Ok(newLibrary);
|
||||
return Ok(newFileLibrary);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -147,7 +147,7 @@ public class LocalLibrariesController(PgsqlContext context, ILog Log) : Controll
|
||||
|
||||
try
|
||||
{
|
||||
LocalLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
FileLibrary? library = context.LocalLibraries.Find(LibraryId);
|
||||
if (library is null)
|
||||
return NotFound();
|
||||
context.Remove(library);
|
||||
|
@ -4,6 +4,7 @@ using API.Schema.Jobs;
|
||||
using Asp.Versioning;
|
||||
using log4net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||
@ -20,7 +21,7 @@ namespace API.Controllers;
|
||||
public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all cached Manga
|
||||
/// Returns all cached Obj
|
||||
/// </summary>
|
||||
/// <response code="200"></response>
|
||||
[HttpGet]
|
||||
@ -32,24 +33,24 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all cached Manga with IDs
|
||||
/// Returns all cached Obj with IDs
|
||||
/// </summary>
|
||||
/// <param name="ids">Array of Manga-IDs</param>
|
||||
/// <param name="ids">Array of Obj-IDs</param>
|
||||
/// <response code="200"></response>
|
||||
[HttpPost("WithIDs")]
|
||||
[ProducesResponseType<Manga[]>(Status200OK, "application/json")]
|
||||
public IActionResult GetManga([FromBody]string[] ids)
|
||||
{
|
||||
Manga[] ret = context.Mangas.Where(m => ids.Contains(m.MangaId)).ToArray();
|
||||
Manga[] ret = context.Mangas.Where(m => ids.Contains(m.Key)).ToArray();
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return Manga with ID
|
||||
/// Return Obj with ID
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">Manga with ID not found</response>
|
||||
/// <response code="404">Obj with ID not found</response>
|
||||
[HttpGet("{MangaId}")]
|
||||
[ProducesResponseType<Manga>(Status200OK, "application/json")]
|
||||
[ProducesResponseType(Status404NotFound)]
|
||||
@ -62,11 +63,11 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete Manga with ID
|
||||
/// Delete Obj with ID
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">Manga with ID not found</response>
|
||||
/// <response code="404">Obj with ID not found</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpDelete("{MangaId}")]
|
||||
[ProducesResponseType(Status200OK)]
|
||||
@ -91,16 +92,45 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns Cover of Manga
|
||||
/// Merge two Manga into one. THIS IS NOT REVERSIBLE!
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">MangaId not found</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpPatch("{MangaIdFrom}/MergeInto/{MangaIdTo}")]
|
||||
[ProducesResponseType<byte[]>(Status200OK,"image/jpeg")]
|
||||
[ProducesResponseType(Status404NotFound)]
|
||||
[ProducesResponseType<string>(Status500InternalServerError, "text/plain")]
|
||||
public IActionResult MergeIntoManga(string MangaIdFrom, string MangaIdTo)
|
||||
{
|
||||
if(context.Mangas.Find(MangaIdFrom) is not { } from)
|
||||
return NotFound(MangaIdFrom);
|
||||
if(context.Mangas.Find(MangaIdTo) is not { } to)
|
||||
return NotFound(MangaIdTo);
|
||||
try
|
||||
{
|
||||
to.MergeFrom(from, context);
|
||||
return Ok();
|
||||
}
|
||||
catch (DbUpdateException e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return StatusCode(500, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Cover of Obj
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <param name="width">If width is provided, height needs to also be provided</param>
|
||||
/// <param name="height">If height is provided, width needs to also be provided</param>
|
||||
/// <response code="200">JPEG Image</response>
|
||||
/// <response code="204">Cover not loaded</response>
|
||||
/// <response code="400">The formatting-request was invalid</response>
|
||||
/// <response code="404">Manga with ID not found</response>
|
||||
/// <response code="404">Obj with ID not found</response>
|
||||
/// <response code="503">Retry later, downloading cover</response>
|
||||
[HttpGet("{MangaId}/Cover")]
|
||||
[ProducesResponseType<byte[]>(Status200OK,"image/jpeg")]
|
||||
@ -115,7 +145,7 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
|
||||
if (!System.IO.File.Exists(m.CoverFileNameInCache))
|
||||
{
|
||||
List<Job> coverDownloadJobs = context.Jobs.Where(j => j.JobType == JobType.DownloadMangaCoverJob).ToList();
|
||||
List<Job> coverDownloadJobs = context.Jobs.Where(j => j.JobType == JobType.DownloadMangaCoverJob).Include(j => ((DownloadMangaCoverJob)j).Manga).ToList();
|
||||
if (coverDownloadJobs.Any(j => j is DownloadMangaCoverJob dmc && dmc.MangaId == MangaId && dmc.state < JobState.Completed))
|
||||
{
|
||||
Response.Headers.Append("Retry-After", $"{TrangaSettings.startNewJobTimeoutMs * coverDownloadJobs.Count() * 2 / 1000:D}");
|
||||
@ -146,11 +176,11 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all Chapters of Manga
|
||||
/// Returns all Chapters of Obj
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">Manga with ID not found</response>
|
||||
/// <response code="404">Obj with ID not found</response>
|
||||
[HttpGet("{MangaId}/Chapters")]
|
||||
[ProducesResponseType<Chapter[]>(Status200OK, "application/json")]
|
||||
[ProducesResponseType(Status404NotFound)]
|
||||
@ -164,12 +194,12 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all downloaded Chapters for Manga with ID
|
||||
/// Returns all downloaded Chapters for Obj with ID
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="204">No available chapters</response>
|
||||
/// <response code="404">Manga with ID not found.</response>
|
||||
/// <response code="404">Obj with ID not found.</response>
|
||||
[HttpGet("{MangaId}/Chapters/Downloaded")]
|
||||
[ProducesResponseType<Chapter[]>(Status200OK, "application/json")]
|
||||
[ProducesResponseType(Status204NoContent)]
|
||||
@ -187,12 +217,12 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all Chapters not downloaded for Manga with ID
|
||||
/// Returns all Chapters not downloaded for Obj with ID
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="204">No available chapters</response>
|
||||
/// <response code="404">Manga with ID not found.</response>
|
||||
/// <response code="404">Obj with ID not found.</response>
|
||||
[HttpGet("{MangaId}/Chapters/NotDownloaded")]
|
||||
[ProducesResponseType<Chapter[]>(Status200OK, "application/json")]
|
||||
[ProducesResponseType(Status204NoContent)]
|
||||
@ -210,12 +240,12 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the latest Chapter of requested Manga available on Website
|
||||
/// Returns the latest Chapter of requested Obj available on Website
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="204">No available chapters</response>
|
||||
/// <response code="404">Manga with ID not found.</response>
|
||||
/// <response code="404">Obj with ID not found.</response>
|
||||
/// <response code="500">Could not retrieve the maximum chapter-number</response>
|
||||
/// <response code="503">Retry after timeout, updating value</response>
|
||||
[HttpGet("{MangaId}/Chapter/LatestAvailable")]
|
||||
@ -232,7 +262,7 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
List<Chapter> chapters = m.Chapters.ToList();
|
||||
if (chapters.Count == 0)
|
||||
{
|
||||
List<Job> retrieveChapterJobs = context.Jobs.Where(j => j.JobType == JobType.RetrieveChaptersJob).ToList();
|
||||
List<Job> retrieveChapterJobs = context.Jobs.Where(j => j.JobType == JobType.RetrieveChaptersJob).Include(j => ((RetrieveChaptersJob)j).Manga).ToList();
|
||||
if (retrieveChapterJobs.Any(j => j is RetrieveChaptersJob rcj && rcj.MangaId == MangaId && rcj.state < JobState.Completed))
|
||||
{
|
||||
Response.Headers.Append("Retry-After", $"{TrangaSettings.startNewJobTimeoutMs * retrieveChapterJobs.Count() * 2 / 1000:D}");
|
||||
@ -249,12 +279,12 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the latest Chapter of requested Manga that is downloaded
|
||||
/// Returns the latest Chapter of requested Obj that is downloaded
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="204">No available chapters</response>
|
||||
/// <response code="404">Manga with ID not found.</response>
|
||||
/// <response code="404">Obj with ID not found.</response>
|
||||
/// <response code="500">Could not retrieve the maximum chapter-number</response>
|
||||
/// <response code="503">Retry after timeout, updating value</response>
|
||||
[HttpGet("{MangaId}/Chapter/LatestDownloaded")]
|
||||
@ -271,7 +301,7 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
List<Chapter> chapters = m.Chapters.ToList();
|
||||
if (chapters.Count == 0)
|
||||
{
|
||||
List<Job> retrieveChapterJobs = context.Jobs.Where(j => j.JobType == JobType.RetrieveChaptersJob).ToList();
|
||||
List<Job> retrieveChapterJobs = context.Jobs.Where(j => j.JobType == JobType.RetrieveChaptersJob).Include(j => ((RetrieveChaptersJob)j).Manga).ToList();
|
||||
if (retrieveChapterJobs.Any(j => j is RetrieveChaptersJob rcj && rcj.MangaId == MangaId && rcj.state < JobState.Completed))
|
||||
{
|
||||
Response.Headers.Append("Retry-After", $"{TrangaSettings.startNewJobTimeoutMs * retrieveChapterJobs.Count() * 2 / 1000:D}");
|
||||
@ -288,12 +318,12 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configure the cut-off for Manga
|
||||
/// Configure the cut-off for Obj
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <param name="chapterThreshold">Threshold (Chapter Number)</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">Manga with ID not found.</response>
|
||||
/// <response code="404">Obj with ID not found.</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpPatch("{MangaId}/IgnoreChaptersBefore")]
|
||||
[ProducesResponseType(Status200OK)]
|
||||
@ -319,10 +349,10 @@ public class MangaController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move Manga to different ToLibrary
|
||||
/// Move Obj to different ToFileLibrary
|
||||
/// </summary>
|
||||
/// <param name="MangaId">Manga-ID</param>
|
||||
/// <param name="LibraryId">ToLibrary-Id</param>
|
||||
/// <param name="MangaId">Obj-ID</param>
|
||||
/// <param name="LibraryId">ToFileLibrary-Id</param>
|
||||
/// <response code="202">Folder is going to be moved</response>
|
||||
/// <response code="404">MangaId or LibraryId not found</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
|
@ -95,7 +95,7 @@ public class NotificationConnectorController(NotificationsContext context, ILog
|
||||
|
||||
NotificationConnector gotifyConnector = new NotificationConnector(TokenGen.CreateToken("Gotify"),
|
||||
gotifyData.endpoint,
|
||||
new Dictionary<string, string>() { { "X-Gotify-Key", gotifyData.appToken } },
|
||||
new Dictionary<string, string>() { { "X-Gotify-IDOnConnector", gotifyData.appToken } },
|
||||
"POST",
|
||||
$"{{\"message\": \"%text\", \"title\": \"%title\", \"priority\": {gotifyData.priority}}}");
|
||||
return CreateConnector(gotifyConnector);
|
||||
|
@ -69,18 +69,18 @@ public class QueryController(PgsqlContext context, ILog Log) : Controller
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">AltTitle with ID not found</response>
|
||||
[HttpGet("AltTitle/{AltTitleId}")]
|
||||
[ProducesResponseType<MangaAltTitle>(Status200OK, "application/json")]
|
||||
[ProducesResponseType<AltTitle>(Status200OK, "application/json")]
|
||||
[ProducesResponseType(Status404NotFound)]
|
||||
public IActionResult GetAltTitle(string AltTitleId)
|
||||
{
|
||||
MangaAltTitle? ret = context.AltTitles.Find(AltTitleId);
|
||||
AltTitle? ret = context.AltTitles.Find(AltTitleId);
|
||||
if (ret is null)
|
||||
return NotFound();
|
||||
return Ok(ret);
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Returns all Manga with Tag
|
||||
/// Returns all Obj with Tag
|
||||
/// </summary>
|
||||
/// <param name="Tag"></param>
|
||||
/// <response code="200"></response>
|
||||
|
@ -1,7 +1,5 @@
|
||||
using API.Schema;
|
||||
using API.Schema.Contexts;
|
||||
using API.Schema.Jobs;
|
||||
using API.Schema.MangaConnectors;
|
||||
using Asp.Versioning;
|
||||
using log4net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -18,7 +16,7 @@ namespace API.Controllers;
|
||||
public class SearchController(PgsqlContext context, ILog Log) : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Initiate a search for a Manga on a specific Connector
|
||||
/// Initiate a search for a Obj on a specific Connector
|
||||
/// </summary>
|
||||
/// <param name="MangaConnectorName"></param>
|
||||
/// <param name="Query"></param>
|
||||
@ -38,9 +36,9 @@ public class SearchController(PgsqlContext context, ILog Log) : Controller
|
||||
else if (connector.Enabled is false)
|
||||
return StatusCode(Status406NotAcceptable);
|
||||
|
||||
Manga[] mangas = connector.SearchManga(Query);
|
||||
(Manga, MangaConnectorId<Manga>)[] mangas = connector.SearchManga(Query);
|
||||
List<Manga> retMangas = new();
|
||||
foreach (Manga manga in mangas)
|
||||
foreach ((Manga manga, MangaConnectorId<Manga> mcId) manga in mangas)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -58,7 +56,7 @@ public class SearchController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search for a known Manga
|
||||
/// Search for a known Obj
|
||||
/// </summary>
|
||||
/// <param name="Query"></param>
|
||||
/// <response code="200"></response>
|
||||
@ -73,12 +71,12 @@ public class SearchController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Manga from MangaConnector associated with URL
|
||||
/// Returns Obj from MangaConnector associated with URL
|
||||
/// </summary>
|
||||
/// <param name="url">Manga-Page URL</param>
|
||||
/// <param name="url">Obj-Page URL</param>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="300">Multiple connectors found for URL</response>
|
||||
/// <response code="404">Manga not found</response>
|
||||
/// <response code="404">Obj not found</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
[HttpPost("Url")]
|
||||
[ProducesResponseType<Manga>(Status200OK, "application/json")]
|
||||
@ -104,12 +102,13 @@ public class SearchController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
}
|
||||
|
||||
private Manga? AddMangaToContext(Manga manga)
|
||||
private Manga? AddMangaToContext((Manga, MangaConnectorId<Manga>) manga) => AddMangaToContext(manga.Item1, manga.Item2, context);
|
||||
|
||||
internal static Manga? AddMangaToContext(Manga addManga, MangaConnectorId<Manga> addMcId, PgsqlContext context)
|
||||
{
|
||||
context.Mangas.Load();
|
||||
context.Authors.Load();
|
||||
context.Tags.Load();
|
||||
context.MangaConnectors.Load();
|
||||
Manga manga = context.Mangas.Find(addManga.Key) ?? addManga;
|
||||
MangaConnectorId<Manga> mcId = context.MangaConnectorToManga.Find(addMcId.Key) ?? addMcId;
|
||||
mcId.Obj = manga;
|
||||
|
||||
IEnumerable<MangaTag> mergedTags = manga.MangaTags.Select(mt =>
|
||||
{
|
||||
@ -120,26 +119,19 @@ public class SearchController(PgsqlContext context, ILog Log) : Controller
|
||||
|
||||
IEnumerable<Author> mergedAuthors = manga.Authors.Select(ma =>
|
||||
{
|
||||
Author? inDb = context.Authors.Find(ma.AuthorId);
|
||||
Author? inDb = context.Authors.Find(ma.Key);
|
||||
return inDb ?? ma;
|
||||
});
|
||||
manga.Authors = mergedAuthors.ToList();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
if (context.Mangas.Find(manga.MangaId) is { } r)
|
||||
{
|
||||
context.Mangas.Remove(r);
|
||||
context.SaveChanges();
|
||||
}
|
||||
context.Mangas.Add(manga);
|
||||
context.Jobs.Add(new DownloadMangaCoverJob(manga));
|
||||
if(context.MangaConnectorToManga.Find(addMcId.Key) is null)
|
||||
context.MangaConnectorToManga.Add(mcId);
|
||||
context.SaveChanges();
|
||||
}
|
||||
catch (DbUpdateException e)
|
||||
{
|
||||
Log.Error(e);
|
||||
return null;
|
||||
}
|
||||
return manga;
|
||||
|
@ -1,12 +1,10 @@
|
||||
using System.Net.Http.Headers;
|
||||
using API.MangaDownloadClients;
|
||||
using API.MangaDownloadClients;
|
||||
using API.Schema;
|
||||
using API.Schema.Contexts;
|
||||
using API.Schema.Jobs;
|
||||
using Asp.Versioning;
|
||||
using log4net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static Microsoft.AspNetCore.Http.StatusCodes;
|
||||
|
||||
@ -210,14 +208,14 @@ public class SettingsController(PgsqlContext context, ILog Log) : Controller
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Placeholders:
|
||||
/// %M Manga Name
|
||||
/// %M Obj Name
|
||||
/// %V Volume
|
||||
/// %C Chapter
|
||||
/// %T Title
|
||||
/// %A Author (first in list)
|
||||
/// %I Chapter Internal ID
|
||||
/// %i Manga Internal ID
|
||||
/// %Y Year (Manga)
|
||||
/// %i Obj Internal ID
|
||||
/// %Y Year (Obj)
|
||||
///
|
||||
/// ?_(...) replace _ with a value from above:
|
||||
/// Everything inside the braces will only be added if the value of %_ is not null
|
||||
@ -235,14 +233,14 @@ public class SettingsController(PgsqlContext context, ILog Log) : Controller
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Placeholders:
|
||||
/// %M Manga Name
|
||||
/// %M Obj Name
|
||||
/// %V Volume
|
||||
/// %C Chapter
|
||||
/// %T Title
|
||||
/// %A Author (first in list)
|
||||
/// %I Chapter Internal ID
|
||||
/// %i Manga Internal ID
|
||||
/// %Y Year (Manga)
|
||||
/// %i Obj Internal ID
|
||||
/// %Y Year (Obj)
|
||||
///
|
||||
/// ?_(...) replace _ with a value from above:
|
||||
/// Everything inside the braces will only be added if the value of %_ is not null
|
||||
@ -271,7 +269,7 @@ public class SettingsController(PgsqlContext context, ILog Log) : Controller
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a UpdateCoverJob for all Manga
|
||||
/// Creates a UpdateCoverJob for all Obj
|
||||
/// </summary>
|
||||
/// <response code="200">Array of JobIds</response>
|
||||
/// <response code="500">Error during Database Operation</response>
|
||||
@ -285,7 +283,7 @@ public class SettingsController(PgsqlContext context, ILog Log) : Controller
|
||||
Tranga.RemoveStaleFiles(context);
|
||||
List<UpdateCoverJob> newJobs = context.Mangas.ToList().Select(m => new UpdateCoverJob(m, 0)).ToList();
|
||||
context.Jobs.AddRange(newJobs);
|
||||
return Ok(newJobs.Select(j => j.JobId));
|
||||
return Ok(newJobs.Select(j => j.Key));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
Reference in New Issue
Block a user