using API.Schema.MangaContext;
using API.Schema.MangaContext.MetadataFetchers;
using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using static Microsoft.AspNetCore.Http.StatusCodes;
// ReSharper disable InconsistentNaming
namespace API.Controllers;
[ApiVersion(2)]
[ApiController]
[Route("v{v:apiVersion}/[controller]")]
public class MetadataFetcherController(IServiceScope scope) : Controller
{
///
/// Get all (Metadata-Sites)
///
/// Names of (Metadata-Sites)
[HttpGet]
[ProducesResponseType(Status200OK, "application/json")]
public IActionResult GetConnectors()
{
return Ok(Tranga.MetadataFetchers.Select(m => m.Name).ToArray());
}
///
/// Returns all
///
///
[HttpGet("Links")]
[ProducesResponseType(Status200OK, "application/json")]
public IActionResult GetLinkedEntries()
{
MangaContext context = scope.ServiceProvider.GetRequiredService();
return Ok(context.MetadataEntries.ToArray());
}
///
/// Searches (Metadata-Sites) for Manga-Metadata
///
/// .Key
/// .Name
/// Instead of using the for search on Website, use a specific term
///
/// (Metadata-Sites) with does not exist
/// with not found
[HttpPost("{MetadataFetcherName}/SearchManga/{MangaId}")]
[ProducesResponseType(Status200OK, "application/json")]
[ProducesResponseType(Status400BadRequest)]
[ProducesResponseType(Status404NotFound)]
public IActionResult SearchMangaMetadata(string MangaId, string MetadataFetcherName, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)]string? searchTerm = null)
{
MangaContext context = scope.ServiceProvider.GetRequiredService();
if(context.Mangas.Find(MangaId) is not { } manga)
return NotFound();
if(Tranga.MetadataFetchers.FirstOrDefault(f => f.Name == MetadataFetcherName) is not { } fetcher)
return BadRequest();
MetadataSearchResult[] searchResults = searchTerm is null ? fetcher.SearchMetadataEntry(manga) : fetcher.SearchMetadataEntry(searchTerm);
return Ok(searchResults);
}
///
/// Links (Metadata-Sites) using Provider-Specific Identifier to
///
/// .Key
/// .Name
/// -Specific ID
///
/// (Metadata-Sites) with does not exist
/// with not found
/// Error during Database Operation
[HttpPost("{MetadataFetcherName}/Link/{MangaId}")]
[ProducesResponseType(Status200OK, "application/json")]
[ProducesResponseType(Status400BadRequest)]
[ProducesResponseType(Status404NotFound)]
[ProducesResponseType(Status500InternalServerError, "text/plain")]
public IActionResult LinkMangaMetadata(string MangaId, string MetadataFetcherName, [FromBody]string Identifier)
{
MangaContext context = scope.ServiceProvider.GetRequiredService();
if(context.Mangas.Find(MangaId) is not { } manga)
return NotFound();
if(Tranga.MetadataFetchers.FirstOrDefault(f => f.Name == MetadataFetcherName) is not { } fetcher)
return BadRequest();
MetadataEntry entry = fetcher.CreateMetadataEntry(manga, Identifier);
context.MetadataEntries.Add(entry);
if(context.Sync().Result is { } errorMessage)
return StatusCode(Status500InternalServerError, errorMessage);
return Ok(entry);
}
///
/// Un-Links (Metadata-Sites) from
///
///
/// (Metadata-Sites) with does not exist
/// with not found
/// No linking and found
/// Error during Database Operation
[HttpPost("{MetadataFetcherName}/Unlink/{MangaId}")]
[ProducesResponseType(Status200OK)]
[ProducesResponseType(Status400BadRequest)]
[ProducesResponseType(Status404NotFound)]
[ProducesResponseType(Status412PreconditionFailed, "text/plain")]
[ProducesResponseType(Status500InternalServerError, "text/plain")]
public IActionResult UnlinkMangaMetadata(string MangaId, string MetadataFetcherName)
{
MangaContext context = scope.ServiceProvider.GetRequiredService();
if(context.Mangas.Find(MangaId) is null)
return NotFound();
if(Tranga.MetadataFetchers.FirstOrDefault(f => f.Name == MetadataFetcherName) is null)
return BadRequest();
if(context.MetadataEntries.FirstOrDefault(e => e.MangaId == MangaId && e.MetadataFetcherName == MetadataFetcherName) is not { } entry)
return StatusCode(Status412PreconditionFailed, "No entry found");
context.Remove(entry);
if(context.Sync().Result is { success: false } result)
return StatusCode(Status500InternalServerError, result.exceptionMessage);
return Ok();
}
}