Adding shows/people route & GetPeopleByShow

This commit is contained in:
Zoe Roux 2020-07-25 03:47:30 +02:00
parent c47a4b2e15
commit b73be95f11
18 changed files with 312 additions and 105 deletions

View File

@ -36,44 +36,44 @@ namespace Kyoo.Controllers
Task<People> GetPeople(string slug);
// Get by relations
Task<ICollection<Season>> GetSeasons(int showID,
Task<ICollection<Season>> GetSeasonsFromShow(int showID,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default);
Task<ICollection<Season>> GetSeasons(int showID,
Task<ICollection<Season>> GetSeasonsFromShow(int showID,
[Optional] Expression<Func<Season, bool>> where,
Expression<Func<Season, object>> sort,
Pagination limit = default
) => GetSeasons(showID, where, new Sort<Season>(sort), limit);
Task<ICollection<Season>> GetSeasons(string showSlug,
) => GetSeasonsFromShow(showID, where, new Sort<Season>(sort), limit);
Task<ICollection<Season>> GetSeasonsFromShow(string showSlug,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default);
Task<ICollection<Season>> GetSeasons(string showSlug,
Task<ICollection<Season>> GetSeasonsFromShow(string showSlug,
[Optional] Expression<Func<Season, bool>> where,
Expression<Func<Season, object>> sort,
Pagination limit = default
) => GetSeasons(showSlug, where, new Sort<Season>(sort), limit);
) => GetSeasonsFromShow(showSlug, where, new Sort<Season>(sort), limit);
Task<ICollection<Episode>> GetEpisodes(int showID,
Task<ICollection<Episode>> GetEpisodesFromShow(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(int showID,
Task<ICollection<Episode>> GetEpisodesFromShow(int showID,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showID, where, new Sort<Episode>(sort), limit);
) => GetEpisodesFromShow(showID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
Task<ICollection<Episode>> GetEpisodesFromShow(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
Task<ICollection<Episode>> GetEpisodesFromShow(string showSlug,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showSlug, where, new Sort<Episode>(sort), limit);
) => GetEpisodesFromShow(showSlug, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
Expression<Func<Episode, bool>> where = null,
@ -108,6 +108,26 @@ namespace Kyoo.Controllers
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(showSlug, seasonNumber, where, new Sort<Episode>(sort), limit);
Task<ICollection<PeopleLink>> GetPeopleFromShow(int showID,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> sort = default,
Pagination limit = default);
Task<ICollection<PeopleLink>> GetPeopleFromShow(int showID,
[Optional] Expression<Func<PeopleLink, bool>> where,
Expression<Func<PeopleLink, object>> sort,
Pagination limit = default
) => GetPeopleFromShow(showID, where, new Sort<PeopleLink>(sort), limit);
Task<ICollection<PeopleLink>> GetPeopleFromShow(string showSlug,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> sort = default,
Pagination limit = default);
Task<ICollection<PeopleLink>> GetPeopleFromShow(string showSlug,
[Optional] Expression<Func<PeopleLink, bool>> where,
Expression<Func<PeopleLink, object>> sort,
Pagination limit = default
) => GetPeopleFromShow(showSlug, where, new Sort<PeopleLink>(sort), limit);
// Helpers
@ -124,10 +144,10 @@ namespace Kyoo.Controllers
Task<ICollection<Show>> GetShows(Expression<Func<Show, bool>> where = null,
Sort<Show> sort = default,
Pagination limit = default);
Task<ICollection<Season>> GetSeasons(Expression<Func<Season, bool>> where = null,
Task<ICollection<Season>> GetSeasonsFromShow(Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(Expression<Func<Episode, bool>> where = null,
Task<ICollection<Episode>> GetEpisodesFromShow(Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Track>> GetTracks(Expression<Func<Track, bool>> where = null,
@ -158,14 +178,14 @@ namespace Kyoo.Controllers
Expression<Func<Show, object>> sort,
Pagination limit = default
) => GetShows(where, new Sort<Show>(sort), limit);
Task<ICollection<Season>> GetSeasons([Optional] Expression<Func<Season, bool>> where,
Task<ICollection<Season>> GetSeasonsFromShow([Optional] Expression<Func<Season, bool>> where,
Expression<Func<Season, object>> sort,
Pagination limit = default
) => GetSeasons(where, new Sort<Season>(sort), limit);
Task<ICollection<Episode>> GetEpisodes([Optional] Expression<Func<Episode, bool>> where,
) => GetSeasonsFromShow(where, new Sort<Season>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromShow([Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(where, new Sort<Episode>(sort), limit);
) => GetEpisodesFromShow(where, new Sort<Episode>(sort), limit);
Task<ICollection<Track>> GetTracks([Optional] Expression<Func<Track, bool>> where,
Expression<Func<Track, object>> sort,
Pagination limit = default

View File

@ -23,10 +23,10 @@ namespace Kyoo.Controllers
public static implicit operator Pagination(int limit) => new Pagination(limit);
}
public readonly struct Sort<T>
public struct Sort<T>
{
public Expression<Func<T, object>> Key { get; }
public bool Descendant { get; }
public Expression<Func<T, object>> Key;
public bool Descendant;
public Sort(Expression<Func<T, object>> key, bool descendant = false)
{
@ -110,25 +110,25 @@ namespace Kyoo.Controllers
Task<Season> Get(string showSlug, int seasonNumber);
Task Delete(string showSlug, int seasonNumber);
Task<ICollection<Season>> GetSeasons(int showID,
Task<ICollection<Season>> GetFromShow(int showID,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default);
Task<ICollection<Season>> GetSeasons(int showID,
Task<ICollection<Season>> GetFromShow(int showID,
[Optional] Expression<Func<Season, bool>> where,
Expression<Func<Season, object>> sort,
Pagination limit = default
) => GetSeasons(showID, where, new Sort<Season>(sort), limit);
) => GetFromShow(showID, where, new Sort<Season>(sort), limit);
Task<ICollection<Season>> GetSeasons(string showSlug,
Task<ICollection<Season>> GetFromShow(string showSlug,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default);
Task<ICollection<Season>> GetSeasons(string showSlug,
Task<ICollection<Season>> GetFromShow(string showSlug,
[Optional] Expression<Func<Season, bool>> where,
Expression<Func<Season, object>> sort,
Pagination limit = default
) => GetSeasons(showSlug, where, new Sort<Season>(sort), limit);
) => GetFromShow(showSlug, where, new Sort<Season>(sort), limit);
}
public interface IEpisodeRepository : IRepository<Episode>
@ -136,57 +136,57 @@ namespace Kyoo.Controllers
Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber);
Task Delete(string showSlug, int seasonNumber, int episodeNumber);
Task<ICollection<Episode>> GetEpisodes(int showID,
Task<ICollection<Episode>> GetFromShow(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(int showID,
Task<ICollection<Episode>> GetFromShow(int showID,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showID, where, new Sort<Episode>(sort), limit);
) => GetFromShow(showID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
Task<ICollection<Episode>> GetFromShow(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodes(string showSlug,
Task<ICollection<Episode>> GetFromShow(string showSlug,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodes(showSlug, where, new Sort<Episode>(sort), limit);
) => GetFromShow(showSlug, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
Task<ICollection<Episode>> GetFromSeason(int seasonID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
Task<ICollection<Episode>> GetFromSeason(int seasonID,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(seasonID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
) => GetFromSeason(seasonID, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetFromSeason(int showID,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
Task<ICollection<Episode>> GetFromSeason(int showID,
int seasonNumber,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(showID, seasonNumber, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
) => GetFromSeason(showID, seasonNumber, where, new Sort<Episode>(sort), limit);
Task<ICollection<Episode>> GetFromSeason(string showSlug,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default);
Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
Task<ICollection<Episode>> GetFromSeason(string showSlug,
int seasonNumber,
[Optional] Expression<Func<Episode, bool>> where,
Expression<Func<Episode, object>> sort,
Pagination limit = default
) => GetEpisodesFromSeason(showSlug, seasonNumber, where, new Sort<Episode>(sort), limit);
) => GetFromSeason(showSlug, seasonNumber, where, new Sort<Episode>(sort), limit);
}
public interface ITrackRepository : IRepository<Track>
@ -197,6 +197,28 @@ namespace Kyoo.Controllers
public interface ICollectionRepository : IRepository<Collection> {}
public interface IGenreRepository : IRepository<Genre> {}
public interface IStudioRepository : IRepository<Studio> {}
public interface IPeopleRepository : IRepository<People> {}
public interface IPeopleRepository : IRepository<People>
{
Task<ICollection<PeopleLink>> GetFromShow(int showID,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> sort = default,
Pagination limit = default);
Task<ICollection<PeopleLink>> GetFromShow(int showID,
[Optional] Expression<Func<PeopleLink, bool>> where,
Expression<Func<PeopleLink, object>> sort,
Pagination limit = default
) => GetFromShow(showID, where, new Sort<PeopleLink>(sort), limit);
Task<ICollection<PeopleLink>> GetFromShow(string showSlug,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> sort = default,
Pagination limit = default);
Task<ICollection<PeopleLink>> GetFromShow(string showSlug,
[Optional] Expression<Func<PeopleLink, bool>> where,
Expression<Func<PeopleLink, object>> sort,
Pagination limit = default
) => GetFromShow(showSlug, where, new Sort<PeopleLink>(sort), limit);
}
public interface IProviderRepository : IRepository<ProviderID> {}
}

View File

@ -148,14 +148,14 @@ namespace Kyoo.Controllers
return ShowRepository.GetAll(where, sort, limit);
}
public Task<ICollection<Season>> GetSeasons(Expression<Func<Season, bool>> where = null,
public Task<ICollection<Season>> GetSeasonsFromShow(Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination page = default)
{
return SeasonRepository.GetAll(where, sort, page);
}
public Task<ICollection<Episode>> GetEpisodes(Expression<Func<Episode, bool>> where = null,
public Task<ICollection<Episode>> GetEpisodesFromShow(Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination page = default)
{
@ -197,36 +197,36 @@ namespace Kyoo.Controllers
return ProviderRepository.GetAll(where, sort, page);
}
public Task<ICollection<Season>> GetSeasons(int showID,
public Task<ICollection<Season>> GetSeasonsFromShow(int showID,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default)
{
return SeasonRepository.GetSeasons(showID, where, sort, limit);
return SeasonRepository.GetFromShow(showID, where, sort, limit);
}
public Task<ICollection<Season>> GetSeasons(string showSlug,
public Task<ICollection<Season>> GetSeasonsFromShow(string showSlug,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default)
{
return SeasonRepository.GetSeasons(showSlug, where, sort, limit);
return SeasonRepository.GetFromShow(showSlug, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodes(int showID,
public Task<ICollection<Episode>> GetEpisodesFromShow(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodes(showID, where, sort, limit);
return EpisodeRepository.GetFromShow(showID, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodes(string showSlug,
public Task<ICollection<Episode>> GetEpisodesFromShow(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodes(showSlug, where, sort, limit);
return EpisodeRepository.GetFromShow(showSlug, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
@ -234,7 +234,7 @@ namespace Kyoo.Controllers
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodesFromSeason(seasonID, where, sort, limit);
return EpisodeRepository.GetFromSeason(seasonID, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
@ -243,7 +243,7 @@ namespace Kyoo.Controllers
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodesFromSeason(showID, seasonNumber, where, sort, limit);
return EpisodeRepository.GetFromSeason(showID, seasonNumber, where, sort, limit);
}
public Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
@ -252,7 +252,23 @@ namespace Kyoo.Controllers
Sort<Episode> sort = default,
Pagination limit = default)
{
return EpisodeRepository.GetEpisodesFromSeason(showSlug, seasonNumber, where, sort, limit);
return EpisodeRepository.GetFromSeason(showSlug, seasonNumber, where, sort, limit);
}
public Task<ICollection<PeopleLink>> GetPeopleFromShow(int showID,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> sort = default,
Pagination limit = default)
{
return PeopleRepository.GetFromShow(showID, where, sort, limit);
}
public Task<ICollection<PeopleLink>> GetPeopleFromShow(string showSlug,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> sort = default,
Pagination limit = default)
{
return PeopleRepository.GetFromShow(showSlug, where, sort, limit);
}
public Task AddShowLink(int showID, int? libraryID, int? collectionID)

View File

@ -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; }

View File

@ -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;
}

View File

@ -52,24 +52,34 @@ namespace Kyoo.Controllers
return ApplyFilters(_database.Set<T>(), where, sort, limit);
}
protected async Task<ICollection<T>> ApplyFilters(IQueryable<T> query,
protected Task<ICollection<T>> ApplyFilters(IQueryable<T> query,
Expression<Func<T, bool>> where = null,
Sort<T> sort = default,
Pagination limit = default)
{
return ApplyFilters(query, Get, DefaultSort, where, sort, limit);
}
protected async Task<ICollection<TValue>> ApplyFilters<TValue>(IQueryable<TValue> query,
Func<int, Task<TValue>> get,
Expression<Func<TValue, object>> defaultSort,
Expression<Func<TValue, bool>> where = null,
Sort<TValue> sort = default,
Pagination limit = default)
{
if (where != null)
query = query.Where(where);
Expression<Func<T, object>> sortKey = sort.Key ?? DefaultSort;
Expression<Func<TValue, object>> 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<Func<T, bool>>(
query = query.Where(Expression.Lambda<Func<TValue, bool>>(
ApiHelper.StringCompatibleExpression(Expression.GreaterThan, sortKey.Body, Expression.Constant(afterObj)),
(ParameterExpression)((MemberExpression)sortKey.Body).Expression
sortKey.Parameters.First()
));
}
if (limit.Count > 0)

View File

@ -21,7 +21,7 @@ namespace Kyoo.Controllers
T ret = new T();
IEnumerable<IMetadataProvider> 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<T> ret = new List<T>();
IEnumerable<IMetadataProvider> 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;

View File

@ -113,7 +113,7 @@ namespace Kyoo.Controllers
}
}
public async Task<ICollection<Episode>> GetEpisodes(int showID,
public async Task<ICollection<Episode>> GetFromShow(int showID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
@ -127,7 +127,7 @@ namespace Kyoo.Controllers
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodes(string showSlug,
public async Task<ICollection<Episode>> GetFromShow(string showSlug,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
@ -141,7 +141,7 @@ namespace Kyoo.Controllers
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodesFromSeason(int seasonID,
public async Task<ICollection<Episode>> GetFromSeason(int seasonID,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
Pagination limit = default)
@ -155,7 +155,7 @@ namespace Kyoo.Controllers
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodesFromSeason(int showID,
public async Task<ICollection<Episode>> GetFromSeason(int showID,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,
@ -171,7 +171,7 @@ namespace Kyoo.Controllers
return episodes;
}
public async Task<ICollection<Episode>> GetEpisodesFromSeason(string showSlug,
public async Task<ICollection<Episode>> GetFromSeason(string showSlug,
int seasonNumber,
Expression<Func<Episode, bool>> where = null,
Sort<Episode> sort = default,

View File

@ -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<IShowRepository> _shows;
protected override Expression<Func<People, object>> 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<IShowRepository>(services.GetRequiredService<IShowRepository>);
}
@ -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<ICollection<People>> 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<ICollection<PeopleLink>> GetFromShow(int showID,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> 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<PeopleLink> 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<ICollection<PeopleLink>> GetFromShow(string showSlug,
Expression<Func<PeopleLink, bool>> where = null,
Sort<PeopleLink> 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<PeopleLink> 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;
}
}
}

View File

@ -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;

View File

@ -116,7 +116,7 @@ namespace Kyoo.Controllers
}
}
public async Task<ICollection<Season>> GetSeasons(int showID,
public async Task<ICollection<Season>> GetFromShow(int showID,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default)
@ -130,7 +130,7 @@ namespace Kyoo.Controllers
return seasons;
}
public async Task<ICollection<Season>> GetSeasons(string showSlug,
public async Task<ICollection<Season>> GetFromShow(string showSlug,
Expression<Func<Season, bool>> where = null,
Sort<Season> sort = default,
Pagination limit = default)

View File

@ -60,7 +60,7 @@ namespace Kyoo
public DbSet<Episode> Episodes { get; set; }
public DbSet<Track> Tracks { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<People> Peoples { get; set; }
public DbSet<People> People { get; set; }
public DbSet<Studio> Studios { get; set; }
public DbSet<ProviderID> Providers { get; set; }
public DbSet<MetadataID> MetadataIds { get; set; }
@ -167,7 +167,7 @@ namespace Kyoo
.HasIndex(x => x.Slug)
.IsUnique();
modelBuilder.Entity<ProviderID>()
.HasIndex(x => x.Name)
.HasIndex(x => x.Slug)
.IsUnique();
modelBuilder.Entity<Season>()
.HasIndex(x => new {x.ShowID, x.SeasonNumber})

View File

@ -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<string>("Name")
.HasColumnType("text");
b.Property<string>("Slug")
.HasColumnType("text");
b.HasKey("ID");
b.HasIndex("Name")
b.HasIndex("Slug")
.IsUnique();
b.ToTable("Providers");

View File

@ -55,7 +55,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
});
migrationBuilder.CreateTable(
name: "Peoples",
name: "People",
columns: table => new
{
ID = table.Column<int>(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<int>(nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Slug = table.Column<string>(nullable: true),
Name = table.Column<string>(nullable: true),
Logo = table.Column<string>(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");

View File

@ -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<string>("Name")
.HasColumnType("text");
b.Property<string>("Slug")
.HasColumnType("text");
b.HasKey("ID");
b.HasIndex("Name")
b.HasIndex("Slug")
.IsUnique();
b.ToTable("Providers");

View File

@ -63,7 +63,7 @@ namespace Kyoo.Controllers
if (!Directory.Exists(show.Path))
await libraryManager.DeleteShow(show);
ICollection<Episode> episodes = await libraryManager.GetEpisodes();
ICollection<Episode> episodes = await libraryManager.GetEpisodesFromShow();
ICollection<Library> libraries = argument == null
? await libraryManager.GetLibraries()
: new [] { await libraryManager.GetLibrary(argument)};

View File

@ -23,7 +23,7 @@ namespace Kyoo.Tasks
DatabaseContext database = serviceScope.ServiceProvider.GetService<DatabaseContext>();
IPluginManager pluginManager = serviceScope.ServiceProvider.GetService<IPluginManager>();
foreach (IMetadataProvider provider in pluginManager.GetPlugins<IMetadataProvider>())
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;
}

View File

@ -41,7 +41,7 @@ namespace Kyoo.Api
try
{
ICollection<Season> ressources = await _libraryManager.GetSeasons(showID,
ICollection<Season> ressources = await _libraryManager.GetSeasonsFromShow(showID,
ApiHelper.ParseWhere<Season>(where),
new Sort<Season>(sortBy),
new Pagination(limit, afterID));
@ -74,7 +74,7 @@ namespace Kyoo.Api
try
{
ICollection<Season> ressources = await _libraryManager.GetSeasons(slug,
ICollection<Season> ressources = await _libraryManager.GetSeasonsFromShow(slug,
ApiHelper.ParseWhere<Season>(where),
new Sort<Season>(sortBy),
new Pagination(limit, afterID));
@ -107,7 +107,7 @@ namespace Kyoo.Api
try
{
ICollection<Episode> ressources = await _libraryManager.GetEpisodes(showID,
ICollection<Episode> ressources = await _libraryManager.GetEpisodesFromShow(showID,
ApiHelper.ParseWhere<Episode>(where),
new Sort<Episode>(sortBy),
new Pagination(limit, afterID));
@ -131,7 +131,7 @@ namespace Kyoo.Api
[FromQuery] string sortBy,
[FromQuery] int afterID,
[FromQuery] Dictionary<string, string> where,
[FromQuery] int limit = 20)
[FromQuery] int limit = 50)
{
where.Remove("slug");
where.Remove("sortBy");
@ -140,7 +140,7 @@ namespace Kyoo.Api
try
{
ICollection<Episode> ressources = await _libraryManager.GetEpisodes(slug,
ICollection<Episode> ressources = await _libraryManager.GetEpisodesFromShow(slug,
ApiHelper.ParseWhere<Episode>(where),
new Sort<Episode>(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<ActionResult<Page<PeopleLink>>> GetPeople(int showID,
[FromQuery] string sortBy,
[FromQuery] int afterID,
[FromQuery] Dictionary<string, string> where,
[FromQuery] int limit = 30)
{
where.Remove("showID");
where.Remove("sortBy");
where.Remove("limit");
where.Remove("afterID");
try
{
ICollection<PeopleLink> ressources = await _libraryManager.GetPeopleFromShow(showID,
ApiHelper.ParseWhere<PeopleLink>(where),
new Sort<PeopleLink>(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<ActionResult<Page<PeopleLink>>> GetPeople(string slug,
[FromQuery] string sortBy,
[FromQuery] int afterID,
[FromQuery] Dictionary<string, string> where,
[FromQuery] int limit = 30)
{
where.Remove("slug");
where.Remove("sortBy");
where.Remove("limit");
where.Remove("afterID");
try
{
ICollection<PeopleLink> ressources = await _libraryManager.GetPeopleFromShow(slug,
ApiHelper.ParseWhere<PeopleLink>(where),
new Sort<PeopleLink>(sortBy),
new Pagination(limit, afterID));
return Page(ressources, limit);
}
catch (ItemNotFound)
{
return NotFound();
}
catch (ArgumentException ex)
{
return BadRequest(new {Error = ex.Message});
}
}
}
}