using System; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Core.Models.Options; using Microsoft.Extensions.Options; namespace Kyoo.Core.Api { [Route("api/show")] [Route("api/shows")] [Route("api/movie")] [Route("api/movies")] [ApiController] [PartialPermission(nameof(ShowApi))] public class ShowApi : CrudApi { private readonly ILibraryManager _libraryManager; private readonly IFileSystem _files; private readonly IThumbnailsManager _thumbs; public ShowApi(ILibraryManager libraryManager, IFileSystem files, IThumbnailsManager thumbs, IOptions options) : base(libraryManager.ShowRepository, options.Value.PublicUrl) { _libraryManager = libraryManager; _files = files; _thumbs = thumbs; } [HttpGet("{showID:int}/season")] [HttpGet("{showID:int}/seasons")] [PartialPermission(Kind.Read)] public async Task>> GetSeasons(int showID, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 20) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.ShowID == showID), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(showID) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{slug}/season")] [HttpGet("{slug}/seasons")] [PartialPermission(Kind.Read)] public async Task>> GetSeasons(string slug, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 20) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Show.Slug == slug), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(slug) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{showID:int}/episode")] [HttpGet("{showID:int}/episodes")] [PartialPermission(Kind.Read)] public async Task>> GetEpisodes(int showID, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 50) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.ShowID == showID), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(showID) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{slug}/episode")] [HttpGet("{slug}/episodes")] [PartialPermission(Kind.Read)] public async Task>> GetEpisodes(string slug, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 50) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Show.Slug == slug), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(slug) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{showID:int}/people")] [PartialPermission(Kind.Read)] public async Task>> GetPeople(int showID, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetPeopleFromShow(showID, ApiHelper.ParseWhere(where), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(showID) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{slug}/people")] [PartialPermission(Kind.Read)] public async Task>> GetPeople(string slug, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetPeopleFromShow(slug, ApiHelper.ParseWhere(where), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(slug) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{showID:int}/genre")] [HttpGet("{showID:int}/genres")] [PartialPermission(Kind.Read)] public async Task>> GetGenres(int showID, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Shows.Any(y => y.ID == showID)), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(showID) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{slug}/genre")] [HttpGet("{slug}/genres")] [PartialPermission(Kind.Read)] public async Task>> GetGenre(string slug, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Shows.Any(y => y.Slug == slug)), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(slug) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{showID:int}/studio")] [PartialPermission(Kind.Read)] public async Task> GetStudio(int showID) { try { return await _libraryManager.Get(x => x.Shows.Any(y => y.ID == showID)); } catch (ItemNotFoundException) { return NotFound(); } } [HttpGet("{slug}/studio")] [PartialPermission(Kind.Read)] public async Task> GetStudio(string slug) { try { return await _libraryManager.Get(x => x.Shows.Any(y => y.Slug == slug)); } catch (ItemNotFoundException) { return NotFound(); } } [HttpGet("{showID:int}/library")] [HttpGet("{showID:int}/libraries")] [PartialPermission(Kind.Read)] public async Task>> GetLibraries(int showID, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Shows.Any(y => y.ID == showID)), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(showID) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{slug}/library")] [HttpGet("{slug}/libraries")] [PartialPermission(Kind.Read)] public async Task>> GetLibraries(string slug, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Shows.Any(y => y.Slug == slug)), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(slug) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{showID:int}/collection")] [HttpGet("{showID:int}/collections")] [PartialPermission(Kind.Read)] public async Task>> GetCollections(int showID, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Shows.Any(y => y.ID == showID)), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(showID) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{slug}/collection")] [HttpGet("{slug}/collections")] [PartialPermission(Kind.Read)] public async Task>> GetCollections(string slug, [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, [FromQuery] int limit = 30) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, x => x.Shows.Any(y => y.Slug == slug)), new Sort(sortBy), new Pagination(limit, afterID)); if (!resources.Any() && await _libraryManager.GetOrDefault(slug) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new {Error = ex.Message}); } } [HttpGet("{slug}/font")] [HttpGet("{slug}/fonts")] [PartialPermission(Kind.Read)] public async Task>> GetFonts(string slug) { try { Show show = await _libraryManager.Get(slug); string path = _files.Combine(await _files.GetExtraDirectory(show), "Attachments"); return (await _files.ListFiles(path)) .ToDictionary(Path.GetFileNameWithoutExtension, x => $"{BaseURL}api/shows/{slug}/fonts/{Path.GetFileName(x)}"); } catch (ItemNotFoundException) { return NotFound(); } } [HttpGet("{showSlug}/font/{slug}")] [HttpGet("{showSlug}/fonts/{slug}")] [PartialPermission(Kind.Read)] public async Task GetFont(string showSlug, string slug) { try { Show show = await _libraryManager.Get(showSlug); string path = _files.Combine(await _files.GetExtraDirectory(show), "Attachments", slug); return _files.FileResult(path); } catch (ItemNotFoundException) { return NotFound(); } } [HttpGet("{slug}/poster")] public async Task GetPoster(string slug) { try { Show show = await _libraryManager.Get(slug); return _files.FileResult(await _thumbs.GetImagePath(show, Images.Poster)); } catch (ItemNotFoundException) { return NotFound(); } } [HttpGet("{slug}/logo")] public async Task GetLogo(string slug) { try { Show show = await _libraryManager.Get(slug); return _files.FileResult(await _thumbs.GetImagePath(show, Images.Logo)); } catch (ItemNotFoundException) { return NotFound(); } } [HttpGet("{slug}/backdrop")] [HttpGet("{slug}/thumbnail")] public async Task GetBackdrop(string slug) { try { Show show = await _libraryManager.Get(slug); return _files.FileResult(await _thumbs.GetImagePath(show, Images.Thumbnail)); } catch (ItemNotFoundException) { return NotFound(); } } } }