diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index f6141aa8..129db913 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -151,6 +151,46 @@ namespace Kyoo.Controllers Task GetStudioFromShow(int showID); Task GetStudioFromShow(string showSlug); + + Task> GetLibrariesFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetLibrariesFromShow(int showID, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetLibrariesFromShow(showID, where, new Sort(sort), limit); + + Task> GetLibrariesFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetLibrariesFromShow(string showSlug, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetLibrariesFromShow(showSlug, where, new Sort(sort), limit); + + Task> GetCollectionsFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetCollectionsFromShow(int showID, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetCollectionsFromShow(showID, where, new Sort(sort), limit); + + Task> GetCollectionsFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetCollectionsFromShow(string showSlug, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetCollectionsFromShow(showSlug, where, new Sort(sort), limit); // Helpers diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index 4e2fa8c7..c273a89a 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -193,8 +193,52 @@ namespace Kyoo.Controllers { Task Get(int episodeID, string languageTag, bool isForced); } - public interface ILibraryRepository : IRepository {} - public interface ICollectionRepository : IRepository {} + + public interface ILibraryRepository : IRepository + { + Task> GetFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetFromShow(int showID, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetFromShow(showID, where, new Sort(sort), limit); + + Task> GetFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetFromShow(string showSlug, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetFromShow(showSlug, where, new Sort(sort), limit); + } + + public interface ICollectionRepository : IRepository + { + Task> GetFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetFromShow(int showID, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetFromShow(showID, where, new Sort(sort), limit); + + Task> GetFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetFromShow(string showSlug, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetFromShow(showSlug, where, new Sort(sort), limit); + } public interface IGenreRepository : IRepository { diff --git a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs index c707f9b0..0148b953 100644 --- a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs +++ b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs @@ -297,6 +297,38 @@ namespace Kyoo.Controllers return StudioRepository.GetFromShow(showSlug); } + public Task> GetLibrariesFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + return LibraryRepository.GetFromShow(showID, where, sort, limit); + } + + public Task> GetLibrariesFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + return LibraryRepository.GetFromShow(showSlug, where, sort, limit); + } + + public Task> GetCollectionsFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + return CollectionRepository.GetFromShow(showID, where, sort, limit); + } + + public Task> GetCollectionsFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + return CollectionRepository.GetFromShow(showSlug, where, sort, limit); + } + public Task AddShowLink(int showID, int? libraryID, int? collectionID) { return ShowRepository.AddShowLink(showID, libraryID, collectionID); diff --git a/Kyoo/Controllers/Repositories/CollectionRepository.cs b/Kyoo/Controllers/Repositories/CollectionRepository.cs index 72605d39..1d66634a 100644 --- a/Kyoo/Controllers/Repositories/CollectionRepository.cs +++ b/Kyoo/Controllers/Repositories/CollectionRepository.cs @@ -6,19 +6,36 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { public class CollectionRepository : LocalRepository, ICollectionRepository { private readonly DatabaseContext _database; + private readonly Lazy _shows; protected override Expression> DefaultSort => x => x.Name; - public CollectionRepository(DatabaseContext database) : base(database) + public CollectionRepository(DatabaseContext database, IServiceProvider services) : base(database) { _database = database; + _shows = new Lazy(services.GetRequiredService); } - + + public override void Dispose() + { + base.Dispose(); + if (_shows.IsValueCreated) + _shows.Value.Dispose(); + } + + public override async ValueTask DisposeAsync() + { + await _database.DisposeAsync(); + if (_shows.IsValueCreated) + await _shows.Value.DisposeAsync(); + } + public override async Task> Search(string query) { return await _database.Collections @@ -68,5 +85,37 @@ namespace Kyoo.Controllers _database.Entry(link).State = EntityState.Deleted; await _database.SaveChangesAsync(); } + + public async Task> GetFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + ICollection collections = await ApplyFilters(_database.CollectionLinks + .Where(x => x.ShowID == showID) + .Select(x => x.Collection), + where, + sort, + limit); + if (!collections.Any() & await _shows.Value.Get(showID) == null) + throw new ItemNotFound(); + return collections; + } + + public async Task> GetFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + ICollection collections = await ApplyFilters(_database.CollectionLinks + .Where(x => x.Show.Slug == showSlug) + .Select(x => x.Collection), + where, + sort, + limit); + if (!collections.Any() & await _shows.Value.Get(showSlug) == null) + throw new ItemNotFound(); + return collections; + } } } \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/GenreRepository.cs b/Kyoo/Controllers/Repositories/GenreRepository.cs index 982fad76..9f068e68 100644 --- a/Kyoo/Controllers/Repositories/GenreRepository.cs +++ b/Kyoo/Controllers/Repositories/GenreRepository.cs @@ -22,7 +22,20 @@ namespace Kyoo.Controllers _database = database; _shows = new Lazy(services.GetRequiredService); } - + + public override void Dispose() + { + base.Dispose(); + if (_shows.IsValueCreated) + _shows.Value.Dispose(); + } + + public override async ValueTask DisposeAsync() + { + await _database.DisposeAsync(); + if (_shows.IsValueCreated) + await _shows.Value.DisposeAsync(); + } public override async Task> Search(string query) { @@ -92,7 +105,8 @@ namespace Kyoo.Controllers Sort sort = default, Pagination limit = default) { - ICollection genres = await ApplyFilters(_database.GenreLinks.Where(x => x.Show.Slug == showSlug) + ICollection genres = await ApplyFilters(_database.GenreLinks + .Where(x => x.Show.Slug == showSlug) .Select(x => x.Genre), where, sort, diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs index 7766fe8e..43732277 100644 --- a/Kyoo/Controllers/Repositories/LibraryRepository.cs +++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { @@ -13,26 +14,32 @@ namespace Kyoo.Controllers { private readonly DatabaseContext _database; private readonly IProviderRepository _providers; + private readonly Lazy _shows; protected override Expression> DefaultSort => x => x.ID; - public LibraryRepository(DatabaseContext database, IProviderRepository providers) : base(database) + public LibraryRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services) + : base(database) { _database = database; _providers = providers; + _shows = new Lazy(services.GetRequiredService); } - - + public override void Dispose() { _database.Dispose(); _providers.Dispose(); + if (_shows.IsValueCreated) + _shows.Value.Dispose(); } public override async ValueTask DisposeAsync() { await _database.DisposeAsync(); await _providers.DisposeAsync(); + if (_shows.IsValueCreated) + await _shows.Value.DisposeAsync(); } public override async Task> Search(string query) @@ -90,5 +97,37 @@ namespace Kyoo.Controllers _database.Entry(entry).State = EntityState.Deleted; await _database.SaveChangesAsync(); } + + public async Task> GetFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + ICollection libraries = await ApplyFilters(_database.LibraryLinks + .Where(x => x.ShowID == showID) + .Select(x => x.Library), + where, + sort, + limit); + if (!libraries.Any() && await _shows.Value.Get(showID) == null) + throw new ItemNotFound(); + return libraries; + } + + public async Task> GetFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + ICollection libraries = await ApplyFilters(_database.LibraryLinks + .Where(x => x.Show.Slug == showSlug) + .Select(x => x.Library), + where, + sort, + limit); + if (!libraries.Any() && await _shows.Value.Get(showSlug) == null) + throw new ItemNotFound(); + return libraries; + } } } \ No newline at end of file diff --git a/Kyoo/Views/API/ShowsApi.cs b/Kyoo/Views/API/ShowsApi.cs index 84e77c0a..012b1931 100644 --- a/Kyoo/Views/API/ShowsApi.cs +++ b/Kyoo/Views/API/ShowsApi.cs @@ -314,5 +314,137 @@ namespace Kyoo.Api return NotFound(); } } + + [HttpGet("{showID:int}/library")] + [HttpGet("{showID:int}/libraries")] + [Authorize(Policy = "Read")] + public async Task>> GetLibraries(int showID, + [FromQuery] string sortBy, + [FromQuery] int afterID, + [FromQuery] Dictionary where, + [FromQuery] int limit = 30) + { + where.Remove("showID"); + where.Remove("sortBy"); + where.Remove("limit"); + where.Remove("afterID"); + + try + { + ICollection ressources = await _libraryManager.GetLibrariesFromShow(showID, + ApiHelper.ParseWhere(where), + new Sort(sortBy), + new Pagination(limit, afterID)); + + return Page(ressources, limit); + } + catch (ItemNotFound) + { + return NotFound(); + } + catch (ArgumentException ex) + { + return BadRequest(new {Error = ex.Message}); + } + } + + [HttpGet("{slug}/library")] + [HttpGet("{slug}/libraries")] + [Authorize(Policy = "Read")] + public async Task>> GetLibraries(string slug, + [FromQuery] string sortBy, + [FromQuery] int afterID, + [FromQuery] Dictionary where, + [FromQuery] int limit = 30) + { + where.Remove("slug"); + where.Remove("sortBy"); + where.Remove("limit"); + where.Remove("afterID"); + + try + { + ICollection ressources = await _libraryManager.GetLibrariesFromShow(slug, + ApiHelper.ParseWhere(where), + new Sort(sortBy), + new Pagination(limit, afterID)); + + return Page(ressources, limit); + } + catch (ItemNotFound) + { + return NotFound(); + } + catch (ArgumentException ex) + { + return BadRequest(new {Error = ex.Message}); + } + } + + [HttpGet("{showID:int}/collection")] + [HttpGet("{showID:int}/collections")] + [Authorize(Policy = "Read")] + public async Task>> GetCollections(int showID, + [FromQuery] string sortBy, + [FromQuery] int afterID, + [FromQuery] Dictionary where, + [FromQuery] int limit = 30) + { + where.Remove("showID"); + where.Remove("sortBy"); + where.Remove("limit"); + where.Remove("afterID"); + + try + { + ICollection ressources = await _libraryManager.GetCollectionsFromShow(showID, + ApiHelper.ParseWhere(where), + new Sort(sortBy), + new Pagination(limit, afterID)); + + return Page(ressources, limit); + } + catch (ItemNotFound) + { + return NotFound(); + } + catch (ArgumentException ex) + { + return BadRequest(new {Error = ex.Message}); + } + } + + [HttpGet("{slug}/collection")] + [HttpGet("{slug}/collections")] + [Authorize(Policy = "Read")] + public async Task>> GetCollections(string slug, + [FromQuery] string sortBy, + [FromQuery] int afterID, + [FromQuery] Dictionary where, + [FromQuery] int limit = 30) + { + where.Remove("slug"); + where.Remove("sortBy"); + where.Remove("limit"); + where.Remove("afterID"); + + try + { + ICollection ressources = await _libraryManager.GetCollectionsFromShow(slug, + ApiHelper.ParseWhere(where), + new Sort(sortBy), + new Pagination(limit, afterID)); + + return Page(ressources, limit); + } + catch (ItemNotFound) + { + return NotFound(); + } + catch (ArgumentException ex) + { + return BadRequest(new {Error = ex.Message}); + } + } } }