using API.Schema;
using API.Schema.Contexts;
using API.Schema.MetadataFetchers;
using Asp.Versioning;
using log4net;
using Microsoft.AspNetCore.Mvc;
using static Microsoft.AspNetCore.Http.StatusCodes;
// ReSharper disable InconsistentNaming
namespace API.Controllers;
[ApiVersion(2)]
[ApiController]
[Route("v{v:apiVersion}/[controller]")]
public class MetadataFetcherController(PgsqlContext context, ILog Log) : Controller
{
///
/// Get all available Connectors (Metadata-Sites)
///
/// Names of Metadata-Fetchers
[HttpGet]
[ProducesResponseType(Status200OK, "application/json")]
public IActionResult GetConnectors()
{
string[] connectors = Tranga.MetadataFetchers.Select(f => f.MetadataFetcherName).ToArray();
return Ok(connectors);
}
///
/// Returns all Mangas which have a linked Metadata-Provider
///
///
[HttpGet("Links")]
[ProducesResponseType(Status200OK, "application/json")]
public IActionResult GetLinkedEntries()
{
return Ok(context.MetadataEntries.ToArray());
}
///
/// Tries linking a Manga to a Metadata-Provider-Site
///
///
/// Metadata-fetcher with Name does not exist
/// Manga with ID not found
/// Could not find Entry on Metadata-Provider for Manga
/// Error during Database Operation
[HttpPost("{MetadataFetcherName}/{MangaId}/TryLink")]
[ProducesResponseType(Status200OK, "application/json")]
[ProducesResponseType(Status400BadRequest)]
[ProducesResponseType(Status404NotFound)]
[ProducesResponseType(Status417ExpectationFailed)]
[ProducesResponseType(Status500InternalServerError, "text/plain")]
public IActionResult LinkMangaToMetadataFetcher(string MangaId, string MetadataFetcherName)
{
if(context.Mangas.Find(MangaId) is not { } manga)
return NotFound();
if(Tranga.MetadataFetchers.FirstOrDefault(f => f.MetadataFetcherName == MetadataFetcherName) is not { } fetcher)
return BadRequest();
if (!fetcher.TryGetMetadataEntry(manga, out MetadataEntry? entry))
{
return StatusCode(Status417ExpectationFailed, "Metadata entry not found");
}
try
{
//Unlink previous metadata-entries
IQueryable metadataEntries = context.MetadataEntries.Where(e => e.MangaId == MangaId);
context.MetadataEntries.RemoveRange(metadataEntries);
//Add new metadata-entry
context.MetadataEntries.Add(entry);
context.SaveChanges();
return Ok(entry);
}
catch (Exception e)
{
Log.Error(e);
return StatusCode(500, e.Message);
}
}
///
/// Tries linking a Manga to a Metadata-Provider-Site
///
///
/// Manga has no linked entry with MetadataFetcher
/// Error during Database Operation
[HttpPost("{MetadataFetcherName}/{MangaId}/UpdateMetadata")]
[ProducesResponseType(Status200OK)]
[ProducesResponseType(Status400BadRequest)]
[ProducesResponseType(Status500InternalServerError, "text/plain")]
public IActionResult UpdateMetadata(string MangaId, string MetadataFetcherName)
{
if(context.MetadataEntries.Find(MangaId, MetadataFetcherName) is not { } entry)
return BadRequest();
MetadataFetcher fetcher = Tranga.MetadataFetchers.FirstOrDefault(f => f.MetadataFetcherName == MetadataFetcherName)!;
try
{
fetcher.UpdateMetadata(entry, context);
}
catch (Exception e)
{
Log.Error(e);
return StatusCode(500, e.Message);
}
return Ok();
}
}