diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index a83721c0..c28daa61 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -36,44 +36,44 @@ namespace Kyoo.Controllers Task GetPeople(string slug); // Get by relations - Task> GetSeasons(int showID, + Task> GetSeasonsFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetSeasons(int showID, + Task> GetSeasonsFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetSeasons(showID, where, new Sort(sort), limit); - Task> GetSeasons(string showSlug, + ) => GetSeasonsFromShow(showID, where, new Sort(sort), limit); + Task> GetSeasonsFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetSeasons(string showSlug, + Task> GetSeasonsFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetSeasons(showSlug, where, new Sort(sort), limit); + ) => GetSeasonsFromShow(showSlug, where, new Sort(sort), limit); - Task> GetEpisodes(int showID, + Task> GetEpisodesFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodes(int showID, + Task> GetEpisodesFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodes(showID, where, new Sort(sort), limit); + ) => GetEpisodesFromShow(showID, where, new Sort(sort), limit); - Task> GetEpisodes(string showSlug, + Task> GetEpisodesFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodes(string showSlug, + Task> GetEpisodesFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodes(showSlug, where, new Sort(sort), limit); + ) => GetEpisodesFromShow(showSlug, where, new Sort(sort), limit); Task> GetEpisodesFromSeason(int seasonID, Expression> where = null, @@ -108,6 +108,26 @@ namespace Kyoo.Controllers Expression> sort, Pagination limit = default ) => GetEpisodesFromSeason(showSlug, seasonNumber, where, new Sort(sort), limit); + + Task> GetPeopleFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetPeopleFromShow(int showID, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetPeopleFromShow(showID, where, new Sort(sort), limit); + + Task> GetPeopleFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default); + Task> GetPeopleFromShow(string showSlug, + [Optional] Expression> where, + Expression> sort, + Pagination limit = default + ) => GetPeopleFromShow(showSlug, where, new Sort(sort), limit); // Helpers @@ -124,10 +144,10 @@ namespace Kyoo.Controllers Task> GetShows(Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetSeasons(Expression> where = null, + Task> GetSeasonsFromShow(Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodes(Expression> where = null, + Task> GetEpisodesFromShow(Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetTracks(Expression> where = null, @@ -158,14 +178,14 @@ namespace Kyoo.Controllers Expression> sort, Pagination limit = default ) => GetShows(where, new Sort(sort), limit); - Task> GetSeasons([Optional] Expression> where, + Task> GetSeasonsFromShow([Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetSeasons(where, new Sort(sort), limit); - Task> GetEpisodes([Optional] Expression> where, + ) => GetSeasonsFromShow(where, new Sort(sort), limit); + Task> GetEpisodesFromShow([Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodes(where, new Sort(sort), limit); + ) => GetEpisodesFromShow(where, new Sort(sort), limit); Task> GetTracks([Optional] Expression> where, Expression> sort, Pagination limit = default diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index 7588d652..d72908d2 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -23,10 +23,10 @@ namespace Kyoo.Controllers public static implicit operator Pagination(int limit) => new Pagination(limit); } - public readonly struct Sort + public struct Sort { - public Expression> Key { get; } - public bool Descendant { get; } + public Expression> Key; + public bool Descendant; public Sort(Expression> key, bool descendant = false) { @@ -110,25 +110,25 @@ namespace Kyoo.Controllers Task Get(string showSlug, int seasonNumber); Task Delete(string showSlug, int seasonNumber); - Task> GetSeasons(int showID, + Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetSeasons(int showID, + Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetSeasons(showID, where, new Sort(sort), limit); + ) => GetFromShow(showID, where, new Sort(sort), limit); - Task> GetSeasons(string showSlug, + Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetSeasons(string showSlug, + Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetSeasons(showSlug, where, new Sort(sort), limit); + ) => GetFromShow(showSlug, where, new Sort(sort), limit); } public interface IEpisodeRepository : IRepository @@ -136,57 +136,57 @@ namespace Kyoo.Controllers Task Get(string showSlug, int seasonNumber, int episodeNumber); Task Delete(string showSlug, int seasonNumber, int episodeNumber); - Task> GetEpisodes(int showID, + Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodes(int showID, + Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodes(showID, where, new Sort(sort), limit); + ) => GetFromShow(showID, where, new Sort(sort), limit); - Task> GetEpisodes(string showSlug, + Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodes(string showSlug, + Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodes(showSlug, where, new Sort(sort), limit); + ) => GetFromShow(showSlug, where, new Sort(sort), limit); - Task> GetEpisodesFromSeason(int seasonID, + Task> GetFromSeason(int seasonID, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodesFromSeason(int seasonID, + Task> GetFromSeason(int seasonID, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodesFromSeason(seasonID, where, new Sort(sort), limit); - Task> GetEpisodesFromSeason(int showID, + ) => GetFromSeason(seasonID, where, new Sort(sort), limit); + Task> GetFromSeason(int showID, int seasonNumber, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodesFromSeason(int showID, + Task> GetFromSeason(int showID, int seasonNumber, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodesFromSeason(showID, seasonNumber, where, new Sort(sort), limit); - Task> GetEpisodesFromSeason(string showSlug, + ) => GetFromSeason(showID, seasonNumber, where, new Sort(sort), limit); + Task> GetFromSeason(string showSlug, int seasonNumber, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetEpisodesFromSeason(string showSlug, + Task> GetFromSeason(string showSlug, int seasonNumber, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetEpisodesFromSeason(showSlug, seasonNumber, where, new Sort(sort), limit); + ) => GetFromSeason(showSlug, seasonNumber, where, new Sort(sort), limit); } public interface ITrackRepository : IRepository @@ -197,6 +197,28 @@ namespace Kyoo.Controllers public interface ICollectionRepository : IRepository {} public interface IGenreRepository : IRepository {} public interface IStudioRepository : IRepository {} - public interface IPeopleRepository : IRepository {} + + public interface IPeopleRepository : 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 IProviderRepository : IRepository {} } \ No newline at end of file diff --git a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs index 52f3a600..b46028ee 100644 --- a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs +++ b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs @@ -148,14 +148,14 @@ namespace Kyoo.Controllers return ShowRepository.GetAll(where, sort, limit); } - public Task> GetSeasons(Expression> where = null, + public Task> GetSeasonsFromShow(Expression> where = null, Sort sort = default, Pagination page = default) { return SeasonRepository.GetAll(where, sort, page); } - public Task> GetEpisodes(Expression> where = null, + public Task> GetEpisodesFromShow(Expression> where = null, Sort sort = default, Pagination page = default) { @@ -197,36 +197,36 @@ namespace Kyoo.Controllers return ProviderRepository.GetAll(where, sort, page); } - public Task> GetSeasons(int showID, + public Task> GetSeasonsFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default) { - return SeasonRepository.GetSeasons(showID, where, sort, limit); + return SeasonRepository.GetFromShow(showID, where, sort, limit); } - public Task> GetSeasons(string showSlug, + public Task> GetSeasonsFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default) { - return SeasonRepository.GetSeasons(showSlug, where, sort, limit); + return SeasonRepository.GetFromShow(showSlug, where, sort, limit); } - public Task> GetEpisodes(int showID, + public Task> GetEpisodesFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default) { - return EpisodeRepository.GetEpisodes(showID, where, sort, limit); + return EpisodeRepository.GetFromShow(showID, where, sort, limit); } - public Task> GetEpisodes(string showSlug, + public Task> GetEpisodesFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default) { - return EpisodeRepository.GetEpisodes(showSlug, where, sort, limit); + return EpisodeRepository.GetFromShow(showSlug, where, sort, limit); } public Task> GetEpisodesFromSeason(int seasonID, @@ -234,7 +234,7 @@ namespace Kyoo.Controllers Sort sort = default, Pagination limit = default) { - return EpisodeRepository.GetEpisodesFromSeason(seasonID, where, sort, limit); + return EpisodeRepository.GetFromSeason(seasonID, where, sort, limit); } public Task> GetEpisodesFromSeason(int showID, @@ -243,7 +243,7 @@ namespace Kyoo.Controllers Sort sort = default, Pagination limit = default) { - return EpisodeRepository.GetEpisodesFromSeason(showID, seasonNumber, where, sort, limit); + return EpisodeRepository.GetFromSeason(showID, seasonNumber, where, sort, limit); } public Task> GetEpisodesFromSeason(string showSlug, @@ -252,7 +252,23 @@ namespace Kyoo.Controllers Sort sort = default, Pagination limit = default) { - return EpisodeRepository.GetEpisodesFromSeason(showSlug, seasonNumber, where, sort, limit); + return EpisodeRepository.GetFromSeason(showSlug, seasonNumber, where, sort, limit); + } + + public Task> GetPeopleFromShow(int showID, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + return PeopleRepository.GetFromShow(showID, where, sort, limit); + } + + public Task> GetPeopleFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + return PeopleRepository.GetFromShow(showSlug, where, sort, limit); } public Task AddShowLink(int showID, int? libraryID, int? collectionID) diff --git a/Kyoo.Common/Models/PeopleLink.cs b/Kyoo.Common/Models/PeopleLink.cs index 509f2b93..d36f90bd 100644 --- a/Kyoo.Common/Models/PeopleLink.cs +++ b/Kyoo.Common/Models/PeopleLink.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; namespace Kyoo.Models { - public class PeopleLink + public class PeopleLink : IRessource { [JsonIgnore] public int ID { get; set; } [JsonIgnore] public int PeopleID { get; set; } diff --git a/Kyoo.Common/Models/Ressources/ProviderID.cs b/Kyoo.Common/Models/Ressources/ProviderID.cs index b7e6479a..12753fe2 100644 --- a/Kyoo.Common/Models/Ressources/ProviderID.cs +++ b/Kyoo.Common/Models/Ressources/ProviderID.cs @@ -5,15 +5,23 @@ namespace Kyoo.Models public class ProviderID : IRessource { [JsonIgnore] public int ID { get; set; } - public string Slug => Name; + public string Slug { get; set; } public string Name { get; set; } public string Logo { get; set; } public ProviderID() { } + public ProviderID(string name, string logo) + { + Slug = Utility.ToSlug(name); + Name = name; + Logo = logo; + } + public ProviderID(int id, string name, string logo) { ID = id; + Slug = Utility.ToSlug(name); Name = name; Logo = logo; } diff --git a/Kyoo.CommonAPI/LocalRepository.cs b/Kyoo.CommonAPI/LocalRepository.cs index 555538ab..1842efe1 100644 --- a/Kyoo.CommonAPI/LocalRepository.cs +++ b/Kyoo.CommonAPI/LocalRepository.cs @@ -52,24 +52,34 @@ namespace Kyoo.Controllers return ApplyFilters(_database.Set(), where, sort, limit); } - protected async Task> ApplyFilters(IQueryable query, + protected Task> ApplyFilters(IQueryable query, Expression> where = null, Sort sort = default, Pagination limit = default) + { + return ApplyFilters(query, Get, DefaultSort, where, sort, limit); + } + + protected async Task> ApplyFilters(IQueryable query, + Func> get, + Expression> defaultSort, + Expression> where = null, + Sort sort = default, + Pagination limit = default) { if (where != null) query = query.Where(where); - Expression> sortKey = sort.Key ?? DefaultSort; + Expression> sortKey = sort.Key ?? defaultSort; query = sort.Descendant ? query.OrderByDescending(sortKey) : query.OrderBy(sortKey); if (limit.AfterID != 0) { - T after = await Get(limit.AfterID); + TValue after = await get(limit.AfterID); object afterObj = sortKey.Compile()(after); - query = query.Where(Expression.Lambda>( + query = query.Where(Expression.Lambda>( ApiHelper.StringCompatibleExpression(Expression.GreaterThan, sortKey.Body, Expression.Constant(afterObj)), - (ParameterExpression)((MemberExpression)sortKey.Body).Expression + sortKey.Parameters.First() )); } if (limit.Count > 0) diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index 663898d1..a614e39a 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -21,7 +21,7 @@ namespace Kyoo.Controllers T ret = new T(); IEnumerable providers = library?.Providers - .Select(x => _providers.FirstOrDefault(y => y.Provider.Name == x.Name)) + .Select(x => _providers.FirstOrDefault(y => y.Provider.Slug == x.Slug)) .Where(x => x != null) ?? _providers; @@ -47,7 +47,7 @@ namespace Kyoo.Controllers List ret = new List(); IEnumerable providers = library?.Providers - .Select(x => _providers.FirstOrDefault(y => y.Provider.Name == x.Name)) + .Select(x => _providers.FirstOrDefault(y => y.Provider.Slug == x.Slug)) .Where(x => x != null) ?? _providers; diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index cbb8cd43..0392564c 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -113,7 +113,7 @@ namespace Kyoo.Controllers } } - public async Task> GetEpisodes(int showID, + public async Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default) @@ -127,7 +127,7 @@ namespace Kyoo.Controllers return episodes; } - public async Task> GetEpisodes(string showSlug, + public async Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default) @@ -141,7 +141,7 @@ namespace Kyoo.Controllers return episodes; } - public async Task> GetEpisodesFromSeason(int seasonID, + public async Task> GetFromSeason(int seasonID, Expression> where = null, Sort sort = default, Pagination limit = default) @@ -155,7 +155,7 @@ namespace Kyoo.Controllers return episodes; } - public async Task> GetEpisodesFromSeason(int showID, + public async Task> GetFromSeason(int showID, int seasonNumber, Expression> where = null, Sort sort = default, @@ -171,7 +171,7 @@ namespace Kyoo.Controllers return episodes; } - public async Task> GetEpisodesFromSeason(string showSlug, + public async Task> GetFromSeason(string showSlug, int seasonNumber, Expression> where = null, Sort sort = default, diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs index 77b5f356..b7b97572 100644 --- a/Kyoo/Controllers/Repositories/PeopleRepository.cs +++ b/Kyoo/Controllers/Repositories/PeopleRepository.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,12 +14,15 @@ namespace Kyoo.Controllers { private readonly DatabaseContext _database; private readonly IProviderRepository _providers; + private readonly Lazy _shows; protected override Expression> DefaultSort => x => x.Name; - public PeopleRepository(DatabaseContext database, IProviderRepository providers) : base(database) + public PeopleRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services) + : base(database) { _database = database; _providers = providers; + _shows = new Lazy(services.GetRequiredService); } @@ -26,17 +30,21 @@ namespace Kyoo.Controllers { _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) { - return await _database.Peoples + return await _database.People .Where(people => EF.Functions.ILike(people.Name, $"%{query}%")) .Take(20) .ToListAsync(); @@ -89,5 +97,57 @@ 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) + { + if (sort.Key?.Body is MemberExpression member) + { + sort.Key = member.Member.Name switch + { + "Name" => x => x.People.Name, + "Slug" => x => x.People.Slug, + _ => sort.Key + }; + } + + ICollection people = await ApplyFilters(_database.PeopleLinks.Where(x => x.ShowID == showID), + id => _database.PeopleLinks.FirstOrDefaultAsync(x => x.ID == id), + x => x.People.Name, + where, + sort, + limit); + if (!people.Any() && await _shows.Value.Get(showID) == null) + throw new ItemNotFound(); + return people; + } + + public async Task> GetFromShow(string showSlug, + Expression> where = null, + Sort sort = default, + Pagination limit = default) + { + if (sort.Key?.Body is MemberExpression member) + { + sort.Key = member.Member.Name switch + { + "Name" => x => x.People.Name, + "Slug" => x => x.People.Slug, + _ => sort.Key + }; + } + + ICollection people = await ApplyFilters(_database.PeopleLinks.Where(x => x.Show.Slug == showSlug), + id => _database.PeopleLinks.FirstOrDefaultAsync(x => x.ID == id), + x => x.People.Name, + where, + sort, + limit); + if (!people.Any() && await _shows.Value.Get(showSlug) == null) + throw new ItemNotFound(); + return people; + } } } \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/ProviderRepository.cs b/Kyoo/Controllers/Repositories/ProviderRepository.cs index f1477578..a74dc9b5 100644 --- a/Kyoo/Controllers/Repositories/ProviderRepository.cs +++ b/Kyoo/Controllers/Repositories/ProviderRepository.cs @@ -43,13 +43,13 @@ namespace Kyoo.Controllers { _database.DiscardChanges(); if (IsDuplicateException(ex)) - throw new DuplicatedItemException($"Trying to insert a duplicated provider (name {obj.Name} already exists)."); + throw new DuplicatedItemException($"Trying to insert a duplicated provider (slug {obj.Slug} already exists)."); throw; } return obj; } - + protected override Task Validate(ProviderID ressource) { return Task.CompletedTask; diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index f197d7c8..5668a25d 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -116,7 +116,7 @@ namespace Kyoo.Controllers } } - public async Task> GetSeasons(int showID, + public async Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default) @@ -130,7 +130,7 @@ namespace Kyoo.Controllers return seasons; } - public async Task> GetSeasons(string showSlug, + public async Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default) diff --git a/Kyoo/Models/DatabaseContext.cs b/Kyoo/Models/DatabaseContext.cs index a6e657f7..ac54a80c 100644 --- a/Kyoo/Models/DatabaseContext.cs +++ b/Kyoo/Models/DatabaseContext.cs @@ -60,7 +60,7 @@ namespace Kyoo public DbSet Episodes { get; set; } public DbSet Tracks { get; set; } public DbSet Genres { get; set; } - public DbSet Peoples { get; set; } + public DbSet People { get; set; } public DbSet Studios { get; set; } public DbSet Providers { get; set; } public DbSet MetadataIds { get; set; } @@ -167,7 +167,7 @@ namespace Kyoo .HasIndex(x => x.Slug) .IsUnique(); modelBuilder.Entity() - .HasIndex(x => x.Name) + .HasIndex(x => x.Slug) .IsUnique(); modelBuilder.Entity() .HasIndex(x => new {x.ShowID, x.SeasonNumber}) diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200623233713_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200724211017_Initial.Designer.cs similarity index 99% rename from Kyoo/Models/DatabaseMigrations/Internal/20200623233713_Initial.Designer.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200724211017_Initial.Designer.cs index a8f29bf5..36e43ea8 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200623233713_Initial.Designer.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200724211017_Initial.Designer.cs @@ -10,7 +10,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Kyoo.Models.DatabaseMigrations.Internal { [DbContext(typeof(DatabaseContext))] - [Migration("20200623233713_Initial")] + [Migration("20200724211017_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -274,7 +274,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Peoples"); + b.ToTable("People"); }); modelBuilder.Entity("Kyoo.Models.PeopleLink", b => @@ -318,9 +318,12 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Name") .HasColumnType("text"); + b.Property("Slug") + .HasColumnType("text"); + b.HasKey("ID"); - b.HasIndex("Name") + b.HasIndex("Slug") .IsUnique(); b.ToTable("Providers"); diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200623233713_Initial.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200724211017_Initial.cs similarity index 97% rename from Kyoo/Models/DatabaseMigrations/Internal/20200623233713_Initial.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200724211017_Initial.cs index 4bdd56d9..93aadbae 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200623233713_Initial.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200724211017_Initial.cs @@ -55,7 +55,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal }); migrationBuilder.CreateTable( - name: "Peoples", + name: "People", columns: table => new { ID = table.Column(nullable: false) @@ -66,7 +66,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal }, constraints: table => { - table.PrimaryKey("PK_Peoples", x => x.ID); + table.PrimaryKey("PK_People", x => x.ID); }); migrationBuilder.CreateTable( @@ -75,6 +75,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal { ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Slug = table.Column(nullable: true), Name = table.Column(nullable: true), Logo = table.Column(nullable: true) }, @@ -253,9 +254,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal { table.PrimaryKey("PK_PeopleLinks", x => x.ID); table.ForeignKey( - name: "FK_PeopleLinks_Peoples_PeopleID", + name: "FK_PeopleLinks_People_PeopleID", column: x => x.PeopleID, - principalTable: "Peoples", + principalTable: "People", principalColumn: "ID", onDelete: ReferentialAction.Cascade); table.ForeignKey( @@ -349,9 +350,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal principalColumn: "ID", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_MetadataIds_Peoples_PeopleID", + name: "FK_MetadataIds_People_PeopleID", column: x => x.PeopleID, - principalTable: "Peoples", + principalTable: "People", principalColumn: "ID", onDelete: ReferentialAction.Cascade); table.ForeignKey( @@ -485,6 +486,12 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table: "MetadataIds", column: "ShowID"); + migrationBuilder.CreateIndex( + name: "IX_People_Slug", + table: "People", + column: "Slug", + unique: true); + migrationBuilder.CreateIndex( name: "IX_PeopleLinks_PeopleID", table: "PeopleLinks", @@ -495,12 +502,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table: "PeopleLinks", column: "ShowID"); - migrationBuilder.CreateIndex( - name: "IX_Peoples_Slug", - table: "Peoples", - column: "Slug", - unique: true); - migrationBuilder.CreateIndex( name: "IX_ProviderLinks_LibraryID", table: "ProviderLinks", @@ -512,9 +513,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal column: "ProviderID"); migrationBuilder.CreateIndex( - name: "IX_Providers_Name", + name: "IX_Providers_Slug", table: "Providers", - column: "Name", + column: "Slug", unique: true); migrationBuilder.CreateIndex( @@ -576,7 +577,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Collections"); migrationBuilder.DropTable( - name: "Peoples"); + name: "People"); migrationBuilder.DropTable( name: "Libraries"); diff --git a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs index 2479152f..7e9761b4 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs @@ -272,7 +272,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Peoples"); + b.ToTable("People"); }); modelBuilder.Entity("Kyoo.Models.PeopleLink", b => @@ -316,9 +316,12 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Name") .HasColumnType("text"); + b.Property("Slug") + .HasColumnType("text"); + b.HasKey("ID"); - b.HasIndex("Name") + b.HasIndex("Slug") .IsUnique(); b.ToTable("Providers"); diff --git a/Kyoo/Tasks/Crawler.cs b/Kyoo/Tasks/Crawler.cs index 34468068..bc3b2eeb 100644 --- a/Kyoo/Tasks/Crawler.cs +++ b/Kyoo/Tasks/Crawler.cs @@ -63,7 +63,7 @@ namespace Kyoo.Controllers if (!Directory.Exists(show.Path)) await libraryManager.DeleteShow(show); - ICollection episodes = await libraryManager.GetEpisodes(); + ICollection episodes = await libraryManager.GetEpisodesFromShow(); ICollection libraries = argument == null ? await libraryManager.GetLibraries() : new [] { await libraryManager.GetLibrary(argument)}; diff --git a/Kyoo/Tasks/MetadataLoader.cs b/Kyoo/Tasks/MetadataLoader.cs index c66702c5..3d272217 100644 --- a/Kyoo/Tasks/MetadataLoader.cs +++ b/Kyoo/Tasks/MetadataLoader.cs @@ -23,7 +23,7 @@ namespace Kyoo.Tasks DatabaseContext database = serviceScope.ServiceProvider.GetService(); IPluginManager pluginManager = serviceScope.ServiceProvider.GetService(); foreach (IMetadataProvider provider in pluginManager.GetPlugins()) - database.Providers.AddIfNotExist(provider.Provider, x => x.Name == provider.Provider.Name); + database.Providers.AddIfNotExist(provider.Provider, x => x.Slug == provider.Provider.Slug); database.SaveChanges(); return Task.CompletedTask; } diff --git a/Kyoo/Views/API/ShowsApi.cs b/Kyoo/Views/API/ShowsApi.cs index cf7d300b..f04973df 100644 --- a/Kyoo/Views/API/ShowsApi.cs +++ b/Kyoo/Views/API/ShowsApi.cs @@ -41,7 +41,7 @@ namespace Kyoo.Api try { - ICollection ressources = await _libraryManager.GetSeasons(showID, + ICollection ressources = await _libraryManager.GetSeasonsFromShow(showID, ApiHelper.ParseWhere(where), new Sort(sortBy), new Pagination(limit, afterID)); @@ -74,7 +74,7 @@ namespace Kyoo.Api try { - ICollection ressources = await _libraryManager.GetSeasons(slug, + ICollection ressources = await _libraryManager.GetSeasonsFromShow(slug, ApiHelper.ParseWhere(where), new Sort(sortBy), new Pagination(limit, afterID)); @@ -107,7 +107,7 @@ namespace Kyoo.Api try { - ICollection ressources = await _libraryManager.GetEpisodes(showID, + ICollection ressources = await _libraryManager.GetEpisodesFromShow(showID, ApiHelper.ParseWhere(where), new Sort(sortBy), new Pagination(limit, afterID)); @@ -131,7 +131,7 @@ namespace Kyoo.Api [FromQuery] string sortBy, [FromQuery] int afterID, [FromQuery] Dictionary where, - [FromQuery] int limit = 20) + [FromQuery] int limit = 50) { where.Remove("slug"); where.Remove("sortBy"); @@ -140,7 +140,7 @@ namespace Kyoo.Api try { - ICollection ressources = await _libraryManager.GetEpisodes(slug, + ICollection ressources = await _libraryManager.GetEpisodesFromShow(slug, ApiHelper.ParseWhere(where), new Sort(sortBy), new Pagination(limit, afterID)); @@ -156,5 +156,69 @@ namespace Kyoo.Api return BadRequest(new {Error = ex.Message}); } } + + [HttpGet("{showID:int}/people")] + [Authorize(Policy = "Read")] + public async Task>> GetPeople(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.GetPeopleFromShow(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}/people")] + [Authorize(Policy = "Read")] + public async Task>> GetPeople(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.GetPeopleFromShow(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}); + } + } } }