Fixing studios & genres related items API

This commit is contained in:
Zoe Roux 2020-08-16 22:57:40 +02:00
parent b7bbc1a14c
commit b7a5b0579a
9 changed files with 132 additions and 22 deletions

View File

@ -46,6 +46,17 @@ namespace Kyoo.Controllers
Task<Genre> GetGenre(string slug);
Task<Studio> GetStudio(string slug);
Task<People> GetPeople(string slug);
// Get by predicate
Task<Library> GetLibrary(Expression<Func<Library, bool>> where);
Task<Collection> GetCollection(Expression<Func<Collection, bool>> where);
Task<Show> GetShow(Expression<Func<Show, bool>> where);
Task<Season> GetSeason(Expression<Func<Season, bool>> where);
Task<Episode> GetEpisode(Expression<Func<Episode, bool>> where);
Task<Track> GetTrack(Expression<Func<Track, bool>> where);
Task<Genre> GetGenre(Expression<Func<Genre, bool>> where);
Task<Studio> GetStudio(Expression<Func<Studio, bool>> where);
Task<People> GetPerson(Expression<Func<People, bool>> where);
// Get by relations
Task<ICollection<Season>> GetSeasonsFromShow(int showID,

View File

@ -78,6 +78,7 @@ namespace Kyoo.Controllers
{
Task<T> Get(int id);
Task<T> Get(string slug);
async Task<T> Get(Expression<Func<T, bool>> where) => (await GetAll(where, limit: 1)).FirstOrDefault();
Task<ICollection<T>> Search(string query);
Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,

View File

@ -175,6 +175,51 @@ namespace Kyoo.Controllers
return PeopleRepository.Get(slug);
}
public Task<Library> GetLibrary(Expression<Func<Library, bool>> where)
{
return LibraryRepository.Get(where);
}
public Task<Collection> GetCollection(Expression<Func<Collection, bool>> where)
{
return CollectionRepository.Get(where);
}
public Task<Show> GetShow(Expression<Func<Show, bool>> where)
{
return ShowRepository.Get(where);
}
public Task<Season> GetSeason(Expression<Func<Season, bool>> where)
{
return SeasonRepository.Get(where);
}
public Task<Episode> GetEpisode(Expression<Func<Episode, bool>> where)
{
return EpisodeRepository.Get(where);
}
public Task<Track> GetTrack(Expression<Func<Track, bool>> where)
{
return TrackRepository.Get(where);
}
public Task<Genre> GetGenre(Expression<Func<Genre, bool>> where)
{
return GenreRepository.Get(where);
}
public Task<Studio> GetStudio(Expression<Func<Studio, bool>> where)
{
return StudioRepository.Get(where);
}
public Task<People> GetPerson(Expression<Func<People, bool>> where)
{
return PeopleRepository.Get(where);
}
public Task<ICollection<Library>> GetLibraries(Expression<Func<Library, bool>> where = null,
Sort<Library> sort = default,
Pagination page = default)

View File

@ -76,26 +76,35 @@ namespace Kyoo
public static T Assign<T>(T first, T second)
{
Type type = typeof(T);
foreach (PropertyInfo property in type.GetProperties())
IEnumerable<PropertyInfo> properties = type.GetProperties()
.Where(x => x.CanRead && x.CanWrite
&& Attribute.GetCustomAttribute(x, typeof(NotMergableAttribute)) == null);
foreach (PropertyInfo property in properties)
{
if (!property.CanRead || !property.CanWrite)
continue;
object value = property.GetValue(second);
property.SetValue(first, value);
}
if (first is IOnMerge merge)
merge.OnMerge(second);
return first;
}
public static T Complete<T>(T first, T second)
{
if (first == null)
throw new ArgumentNullException(nameof(first));
if (second == null)
return first;
Type type = typeof(T);
foreach (PropertyInfo property in type.GetProperties())
IEnumerable<PropertyInfo> properties = type.GetProperties()
.Where(x => x.CanRead && x.CanWrite
&& Attribute.GetCustomAttribute(x, typeof(NotMergableAttribute)) == null);
foreach (PropertyInfo property in properties)
{
if (!property.CanRead || !property.CanWrite)
continue;
object value = property.GetValue(second);
object defaultValue = property.PropertyType.IsValueType
? Activator.CreateInstance(property.PropertyType)
@ -105,6 +114,8 @@ namespace Kyoo
property.SetValue(first, value);
}
if (first is IOnMerge merge)
merge.OnMerge(second);
return first;
}
@ -116,11 +127,12 @@ namespace Kyoo
return first;
Type type = typeof(T);
foreach (PropertyInfo property in type.GetProperties().Where(x => x.CanRead && x.CanWrite))
IEnumerable<PropertyInfo> properties = type.GetProperties()
.Where(x => x.CanRead && x.CanWrite
&& Attribute.GetCustomAttribute(x, typeof(NotMergableAttribute)) == null);
foreach (PropertyInfo property in properties)
{
if (Attribute.GetCustomAttribute(property, typeof(NotMergableAttribute)) != null)
continue;
object oldValue = property.GetValue(first);
object newValue = property.GetValue(second);
object defaultValue = property.PropertyType.IsValueType
@ -135,8 +147,8 @@ namespace Kyoo
property.SetValue(first, RunGenericMethod(
typeof(Utility),
"MergeLists",
GetEnumerableType(property.PropertyType),
new []{ oldValue, newValue, null}));
GetEnumerableType(property.PropertyType),
oldValue, newValue, null));
}
}
@ -247,11 +259,42 @@ namespace Kyoo
return string.Empty;
return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}"));
}
public static Task<T> Then<T>(this Task<T> task, Action<T> map)
{
return task.ContinueWith(x =>
{
if (x.IsFaulted)
throw x.Exception!.InnerException!;
if (x.IsCanceled)
throw new TaskCanceledException();
map(x.Result);
return x.Result;
}, TaskContinuationOptions.ExecuteSynchronously);
}
public static Task<TResult> Map<T, TResult>(this Task<T> task, Func<T, TResult> map)
{
return task.ContinueWith(x =>
{
if (x.IsFaulted)
throw x.Exception!.InnerException!;
if (x.IsCanceled)
throw new TaskCanceledException();
return map(x.Result);
}, TaskContinuationOptions.ExecuteSynchronously);
}
public static Task<T> Cast<T>(this Task task)
{
return task.ContinueWith(x => (T)((dynamic)x).Result,
TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion);
return task.ContinueWith(x =>
{
if (x.IsFaulted)
throw x.Exception!.InnerException!;
if (x.IsCanceled)
throw new TaskCanceledException();
return (T)((dynamic)x).Result;
}, TaskContinuationOptions.ExecuteSynchronously);
}
public static Expression<T> Convert<T>([CanBeNull] this Expression expr)

View File

@ -24,7 +24,7 @@ namespace Kyoo.CommonApi
Expression<Func<T, bool>> defaultWhere = null)
{
if (where == null || where.Count == 0)
return null;
return defaultWhere;
ParameterExpression param = Expression.Parameter(typeof(T));
Expression expression = defaultWhere?.Body;

View File

@ -231,14 +231,16 @@ namespace Kyoo.Controllers
{
TInternal obj = new TInternal();
Utility.Assign(obj, item);
return Create(obj).Cast<T>();
return Create(obj).Cast<T>()
.Then(x => item.ID = x.ID);
}
Task<T> IRepository<T>.CreateIfNotExists(T item)
{
TInternal obj = new TInternal();
Utility.Assign(obj, item);
return CreateIfNotExists(obj).Cast<T>();
return CreateIfNotExists(obj).Cast<T>()
.Then(x => item.ID = x.ID);
}
public Task<T> Edit(T edited, bool resetOld)

View File

@ -224,8 +224,7 @@ namespace Kyoo.Controllers
bool isMovie,
Library library)
{
Show show = (await libraryManager.GetShows(x => x.Path == showPath, limit: 1))
.FirstOrDefault();
Show show = await libraryManager.GetShow(x => x.Path == showPath);
if (show != null)
return show;
show = await _metadataProvider.SearchShow(showTitle, isMovie, library);

View File

@ -45,6 +45,8 @@ namespace Kyoo.Api
new Sort<Show>(sortBy),
new Pagination(limit, afterID));
if (!ressources.Any() && await _libraryManager.GetGenre(id) == null)
return NotFound();
return Page(ressources, limit);
}
catch (ItemNotFound)
@ -77,6 +79,8 @@ namespace Kyoo.Api
new Sort<Show>(sortBy),
new Pagination(limit, afterID));
if (!ressources.Any() && await _libraryManager.GetGenre(slug) == null)
return NotFound();
return Page(ressources, limit);
}
catch (ItemNotFound)

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Kyoo.CommonApi;
using Kyoo.Controllers;
@ -44,6 +45,8 @@ namespace Kyoo.Api
new Sort<Show>(sortBy),
new Pagination(limit, afterID));
if (!ressources.Any() && await _libraryManager.GetStudio(id) == null)
return NotFound();
return Page(ressources, limit);
}
catch (ItemNotFound)
@ -75,7 +78,9 @@ namespace Kyoo.Api
ApiHelper.ParseWhere<Show>(where, x => x.Studio.Slug == slug),
new Sort<Show>(sortBy),
new Pagination(limit, afterID));
if (!ressources.Any() && await _libraryManager.GetStudio(slug) == null)
return NotFound();
return Page(ressources, limit);
}
catch (ItemNotFound)