// Kyoo - A portable and vast media library solution. // Copyright (c) Kyoo. // // See AUTHORS.md and LICENSE file in the project root for full license information. // // Kyoo is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // Kyoo is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Exceptions; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Utils; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using static Kyoo.Abstractions.Models.Utils.Constants; namespace Kyoo.Core.Api { /// /// Information about one or multiple . /// [Route("api/libraries")] [Route("api/library", Order = AlternativeRoute)] [ApiController] [ResourceView] [PartialPermission(nameof(Library), Group = Group.Admin)] [ApiDefinition("Library", Group = ResourcesGroup)] public class LibraryApi : CrudApi { /// /// The library manager used to modify or retrieve information in the data store. /// private readonly ILibraryManager _libraryManager; /// /// Create a new . /// /// /// The library manager used to modify or retrieve information in the data store. /// public LibraryApi(ILibraryManager libraryManager) : base(libraryManager.LibraryRepository) { _libraryManager = libraryManager; } /// /// Get shows /// /// /// List the shows that are part of this library. /// /// The ID or slug of the . /// A key to sort shows by. /// An optional list of filters. /// The number of shows to return. /// An optional show's ID to start the query from this specific item. /// A page of shows. /// The filters or the sort parameters are invalid. /// No library with the given ID or slug could be found. [HttpGet("{identifier:id}/shows")] [HttpGet("{identifier:id}/show", Order = AlternativeRoute)] [PartialPermission(Kind.Read)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task>> GetShows(Identifier identifier, [FromQuery] string sortBy, [FromQuery] Dictionary where, [FromQuery] int limit = 50, [FromQuery] int? afterID = null) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, identifier.IsContainedIn(x => x.Libraries)), new Sort(sortBy), new Pagination(limit, afterID) ); if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame()) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new RequestError(ex.Message)); } } /// /// Get collections /// /// /// List the collections that are part of this library. /// /// The ID or slug of the . /// A key to sort collections by. /// An optional list of filters. /// The number of collections to return. /// An optional collection's ID to start the query from this specific item. /// A page of collections. /// The filters or the sort parameters are invalid. /// No library with the given ID or slug could be found. [HttpGet("{identifier:id}/collections")] [HttpGet("{identifier:id}/collection", Order = AlternativeRoute)] [PartialPermission(Kind.Read)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task>> GetCollections(Identifier identifier, [FromQuery] string sortBy, [FromQuery] Dictionary where, [FromQuery] int limit = 50, [FromQuery] int? afterID = null) { try { ICollection resources = await _libraryManager.GetAll( ApiHelper.ParseWhere(where, identifier.IsContainedIn(x => x.Libraries)), new Sort(sortBy), new Pagination(limit, afterID) ); if (!resources.Any() && await _libraryManager.GetOrDefault(identifier.IsSame()) == null) return NotFound(); return Page(resources, limit); } catch (ArgumentException ex) { return BadRequest(new RequestError(ex.Message)); } } /// /// Get items /// /// /// List all items of this library. /// An item can ether represent a collection or a show. /// This endpoint allow one to retrieve all collections and shows that are not contained in a collection. /// This is what is displayed on the /browse/library page of the webapp. /// /// The ID or slug of the . /// A key to sort items by. /// An optional list of filters. /// The number of items to return. /// An optional item's ID to start the query from this specific item. /// A page of items. /// The filters or the sort parameters are invalid. /// No library with the given ID or slug could be found. [HttpGet("{identifier:id}/items")] [HttpGet("{identifier:id}/item", Order = AlternativeRoute)] [PartialPermission(Kind.Read)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task>> GetItems(Identifier identifier, [FromQuery] string sortBy, [FromQuery] Dictionary where, [FromQuery] int limit = 50, [FromQuery] int? afterID = null) { try { Expression> whereQuery = ApiHelper.ParseWhere(where); Sort sort = new(sortBy); Pagination pagination = new(limit, afterID); ICollection resources = await identifier.Match( id => _libraryManager.GetItemsFromLibrary(id, whereQuery, sort, pagination), slug => _libraryManager.GetItemsFromLibrary(slug, whereQuery, sort, pagination) ); return Page(resources, limit); } catch (ItemNotFoundException) { return NotFound(); } catch (ArgumentException ex) { return BadRequest(new RequestError(ex.Message)); } } } }