using API.Schema; using Asp.Versioning; using Microsoft.AspNetCore.Mvc; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Jpeg; using static Microsoft.AspNetCore.Http.StatusCodes; namespace API.Controllers; [ApiVersion(2)] [ApiController] [Produces("application/json")] [Route("v{v:apiVersion}/[controller]")] public class MangaController(PgsqlContext context) : Controller { /// /// Returns all cached Manga /// /// [HttpGet] [ProducesResponseType(Status200OK)] public IActionResult GetAllManga() { Manga[] ret = context.Manga.ToArray(); return Ok(ret); } /// /// Returns all cached Manga with IDs /// /// Array of Manga-IDs /// [HttpPost("WithIDs")] [ProducesResponseType(Status200OK)] public IActionResult GetManga([FromBody]string[] ids) { Manga[] ret = context.Manga.Where(m => ids.Contains(m.MangaId)).ToArray(); return Ok(ret); } /// /// Return Manga with ID /// /// Manga-ID /// /// Manga with ID not found [HttpGet("{id}")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status404NotFound)] public IActionResult GetManga(string id) { Manga? ret = context.Manga.Find(id); if (ret is null) return NotFound(); return Ok(ret); } /// /// Delete Manga with ID /// /// Manga-ID /// /// Manga with ID not found /// Error during Database Operation [HttpDelete("{id}")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status404NotFound)] [ProducesResponseType(Status500InternalServerError)] public IActionResult DeleteManga(string id) { try { Manga? ret = context.Manga.Find(id); if (ret is null) return NotFound(); context.Remove(ret); context.SaveChanges(); return Ok(); } catch (Exception e) { return StatusCode(500, e.Message); } } /// /// Returns Cover of Manga /// /// Manga-ID /// JPEG Image /// Cover not loaded /// Manga with ID not found [HttpGet("{id}/Cover")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status204NoContent)] [ProducesResponseType(Status404NotFound)] public IActionResult GetCover(string id) { Manga? m = context.Manga.Find(id); if (m is null) return NotFound(); if (!System.IO.File.Exists(m.CoverFileNameInCache)) return NoContent(); Image image = Image.Load(m.CoverFileNameInCache); using MemoryStream ms = new(); image.Save(ms, new JpegEncoder(){Quality = 100}); return File(ms, "image/jpeg"); } /// /// Returns all Chapters of Manga /// /// Manga-ID /// /// Manga with ID not found [HttpGet("{id}/Chapters")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status404NotFound)] public IActionResult GetChapters(string id) { Manga? m = context.Manga.Find(id); if (m is null) return NotFound(); Chapter[] ret = context.Chapters.Where(c => c.ParentMangaId == m.MangaId).ToArray(); return Ok(ret); } /// /// Returns the latest Chapter of requested Manga /// /// Manga-ID /// /// No available chapters /// Manga with ID not found. /// Could not retrieve the maximum chapter-number [HttpGet("{id}/Chapter/Latest")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status204NoContent)] [ProducesResponseType(Status404NotFound)] [ProducesResponseType(Status500InternalServerError)] public IActionResult GetLatestChapter(string id) { Manga? m = context.Manga.Find(id); if (m is null) return NotFound(); List chapters = context.Chapters.Where(c => c.ParentMangaId == m.MangaId).ToList(); if (chapters.Count == 0) return NoContent(); Chapter? max = chapters.Max(); if (max is null) return StatusCode(500, "Max chapter could not be found"); return Ok(max); } /// /// Configure the cut-off for Manga /// /// Manga-ID /// /// Manga with ID not found. [HttpPatch("{id}/IgnoreChaptersBefore")] [ProducesResponseType(Status200OK)] [ProducesResponseType(Status404NotFound)] public IActionResult IgnoreChaptersBefore(string id) { Manga? m = context.Manga.Find(id); if (m is null) return NotFound(); return Ok(m.IgnoreChapterBefore); } /// /// Move the Directory the .cbz-files are located in /// /// Manga-ID /// New Directory-Path /// NOT IMPLEMENTED [HttpPost("{id}/MoveFolder")] public IActionResult MoveFolder(string id, [FromBody]string folder) { throw new NotImplementedException(); } }