mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-02 13:14:29 -04:00
Starting to rework models
This commit is contained in:
parent
00ef372767
commit
8f6578dfb9
@ -66,6 +66,11 @@ namespace Kyoo.Controllers
|
|||||||
_ => throw new ArgumentException($"The sort order, if set, should be :asc or :desc but it was :{order}.")
|
_ => throw new ArgumentException($"The sort order, if set, should be :asc or :desc but it was :{order}.")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Sort<TValue> To<TValue>()
|
||||||
|
{
|
||||||
|
return new Sort<TValue>(Key.Convert<Func<TValue, object>>(), Descendant);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IRepository<T> : IDisposable, IAsyncDisposable where T : IResource
|
public interface IRepository<T> : IDisposable, IAsyncDisposable where T : IResource
|
||||||
|
@ -6,7 +6,10 @@ namespace Kyoo.Models.Exceptions
|
|||||||
{
|
{
|
||||||
public override string Message { get; }
|
public override string Message { get; }
|
||||||
|
|
||||||
public DuplicatedItemException() {}
|
public DuplicatedItemException()
|
||||||
|
{
|
||||||
|
Message = "Already exists in the databse.";
|
||||||
|
}
|
||||||
|
|
||||||
public DuplicatedItemException(string message)
|
public DuplicatedItemException(string message)
|
||||||
{
|
{
|
||||||
|
@ -1,31 +1,17 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Kyoo.Models.Attributes;
|
|
||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
{
|
{
|
||||||
public class Collection : IResource
|
public class Collection : IResource
|
||||||
{
|
{
|
||||||
[JsonIgnore] public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Poster { get; set; }
|
public string Poster { get; set; }
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<CollectionLink> Links { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Show> Shows { get; set; }
|
||||||
[JsonIgnore] public virtual IEnumerable<Show> Shows
|
[JsonIgnore] public virtual IEnumerable<Library> Libraries { get; set; }
|
||||||
{
|
|
||||||
get => Links.Select(x => x.Show);
|
|
||||||
set => Links = value.Select(x => new CollectionLink(this, x));
|
|
||||||
}
|
|
||||||
|
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<LibraryLink> LibraryLinks { get; set; }
|
|
||||||
|
|
||||||
[NotMergable] [JsonIgnore] public IEnumerable<Library> Libraries
|
|
||||||
{
|
|
||||||
get => LibraryLinks?.Select(x => x.Library);
|
|
||||||
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection() { }
|
public Collection() { }
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@ namespace Kyoo.Models
|
|||||||
{
|
{
|
||||||
public class Episode : IResource, IOnMerge
|
public class Episode : IResource, IOnMerge
|
||||||
{
|
{
|
||||||
[JsonIgnore] public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
[JsonIgnore] public int ShowID { get; set; }
|
public int ShowID { get; set; }
|
||||||
[JsonIgnore] public virtual Show Show { get; set; }
|
[JsonIgnore] public virtual Show Show { get; set; }
|
||||||
[JsonIgnore] public int? SeasonID { get; set; }
|
public int? SeasonID { get; set; }
|
||||||
[JsonIgnore] public virtual Season Season { get; set; }
|
[JsonIgnore] public virtual Season Season { get; set; }
|
||||||
|
|
||||||
public int SeasonNumber { get; set; } = -1;
|
public int SeasonNumber { get; set; } = -1;
|
||||||
@ -23,12 +23,12 @@ namespace Kyoo.Models
|
|||||||
|
|
||||||
public int Runtime { get; set; } //This runtime variable should be in minutes
|
public int Runtime { get; set; } //This runtime variable should be in minutes
|
||||||
|
|
||||||
[JsonIgnore] public string ImgPrimary { get; set; }
|
[JsonIgnore] public string Poster { get; set; }
|
||||||
public virtual IEnumerable<MetadataID> ExternalIDs { get; set; }
|
public virtual IEnumerable<MetadataID> ExternalIDs { get; set; }
|
||||||
|
|
||||||
[JsonIgnore] public virtual IEnumerable<Track> Tracks { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Track> Tracks { get; set; }
|
||||||
|
|
||||||
public string ShowTitle => Show.Title; // Used in the API response only
|
public string ShowTitle => Show.Title;
|
||||||
public string Slug => GetSlug(Show.Slug, SeasonNumber, EpisodeNumber);
|
public string Slug => GetSlug(Show.Slug, SeasonNumber, EpisodeNumber);
|
||||||
public string Thumb
|
public string Thumb
|
||||||
{
|
{
|
||||||
@ -36,7 +36,7 @@ namespace Kyoo.Models
|
|||||||
{
|
{
|
||||||
if (Show != null)
|
if (Show != null)
|
||||||
return "thumb/" + Slug;
|
return "thumb/" + Slug;
|
||||||
return ImgPrimary;
|
return Poster;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ namespace Kyoo.Models
|
|||||||
string overview,
|
string overview,
|
||||||
DateTime? releaseDate,
|
DateTime? releaseDate,
|
||||||
int runtime,
|
int runtime,
|
||||||
string imgPrimary,
|
string poster,
|
||||||
IEnumerable<MetadataID> externalIDs)
|
IEnumerable<MetadataID> externalIDs)
|
||||||
{
|
{
|
||||||
SeasonNumber = seasonNumber;
|
SeasonNumber = seasonNumber;
|
||||||
@ -60,7 +60,7 @@ namespace Kyoo.Models
|
|||||||
Overview = overview;
|
Overview = overview;
|
||||||
ReleaseDate = releaseDate;
|
ReleaseDate = releaseDate;
|
||||||
Runtime = runtime;
|
Runtime = runtime;
|
||||||
ImgPrimary = imgPrimary;
|
Poster = poster;
|
||||||
ExternalIDs = externalIDs;
|
ExternalIDs = externalIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ namespace Kyoo.Models
|
|||||||
string overview,
|
string overview,
|
||||||
DateTime? releaseDate,
|
DateTime? releaseDate,
|
||||||
int runtime,
|
int runtime,
|
||||||
string imgPrimary,
|
string poster,
|
||||||
IEnumerable<MetadataID> externalIDs)
|
IEnumerable<MetadataID> externalIDs)
|
||||||
{
|
{
|
||||||
ShowID = showID;
|
ShowID = showID;
|
||||||
@ -87,7 +87,7 @@ namespace Kyoo.Models
|
|||||||
Overview = overview;
|
Overview = overview;
|
||||||
ReleaseDate = releaseDate;
|
ReleaseDate = releaseDate;
|
||||||
Runtime = runtime;
|
Runtime = runtime;
|
||||||
ImgPrimary = imgPrimary;
|
Poster = poster;
|
||||||
ExternalIDs = externalIDs;
|
ExternalIDs = externalIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Kyoo.Models.Attributes;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
@ -11,13 +9,7 @@ namespace Kyoo.Models
|
|||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<GenreLink> Links { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Show> Shows { get; set; }
|
||||||
|
|
||||||
[NotMergable] [JsonIgnore] public IEnumerable<Show> Shows
|
|
||||||
{
|
|
||||||
get => Links.Select(x => x.Show);
|
|
||||||
set => Links = value?.Select(x => new GenreLink(x, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Genre() {}
|
public Genre() {}
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Kyoo.Models.Attributes;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
@ -12,28 +10,10 @@ namespace Kyoo.Models
|
|||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public IEnumerable<string> Paths { get; set; }
|
public IEnumerable<string> Paths { get; set; }
|
||||||
|
|
||||||
public IEnumerable<ProviderID> Providers
|
public virtual IEnumerable<ProviderID> Providers { get; set; }
|
||||||
{
|
|
||||||
get => ProviderLinks?.Select(x => x.Provider);
|
|
||||||
set => ProviderLinks = value.Select(x => new ProviderLink(x, this)).ToList();
|
|
||||||
}
|
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<ProviderLink> ProviderLinks { get; set; }
|
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<LibraryLink> Links { get; set; }
|
|
||||||
|
|
||||||
[JsonIgnore] public IEnumerable<Show> Shows
|
[JsonIgnore] public virtual IEnumerable<Show> Shows { get; set; }
|
||||||
{
|
[JsonIgnore] public virtual IEnumerable<Collection> Collections { get; set; }
|
||||||
get => Links?.Where(x => x.Show != null).Select(x => x.Show);
|
|
||||||
set => Links = Utility.MergeLists(
|
|
||||||
value?.Select(x => new LibraryLink(this, x)),
|
|
||||||
Links?.Where(x => x.Show == null));
|
|
||||||
}
|
|
||||||
[JsonIgnore] public IEnumerable<Collection> Collections
|
|
||||||
{
|
|
||||||
get => Links?.Where(x => x.Collection != null).Select(x => x.Collection);
|
|
||||||
set => Links = Utility.MergeLists(
|
|
||||||
value?.Select(x => new LibraryLink(this, x)),
|
|
||||||
Links?.Where(x => x.Collection == null));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Library() { }
|
public Library() { }
|
||||||
|
|
||||||
|
@ -7,8 +7,7 @@ namespace Kyoo.Models
|
|||||||
{
|
{
|
||||||
public class Show : IResource, IOnMerge
|
public class Show : IResource, IOnMerge
|
||||||
{
|
{
|
||||||
[JsonIgnore] public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public IEnumerable<string> Aliases { get; set; }
|
public IEnumerable<string> Aliases { get; set; }
|
||||||
@ -24,38 +23,19 @@ namespace Kyoo.Models
|
|||||||
public string Logo { get; set; }
|
public string Logo { get; set; }
|
||||||
public string Backdrop { get; set; }
|
public string Backdrop { get; set; }
|
||||||
|
|
||||||
public virtual IEnumerable<MetadataID> ExternalIDs { get; set; }
|
|
||||||
|
|
||||||
public bool IsMovie { get; set; }
|
public bool IsMovie { get; set; }
|
||||||
|
|
||||||
|
public virtual IEnumerable<MetadataID> ExternalIDs { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public virtual IEnumerable<Genre> Genres
|
|
||||||
{
|
|
||||||
get => GenreLinks?.Select(x => x.Genre);
|
|
||||||
set => GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList();
|
|
||||||
}
|
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<GenreLink> GenreLinks { get; set; }
|
|
||||||
[JsonIgnore] public int? StudioID { get; set; }
|
[JsonIgnore] public int? StudioID { get; set; }
|
||||||
public virtual Studio Studio { get; set; }
|
[JsonIgnore] public virtual Studio Studio { get; set; }
|
||||||
|
[JsonIgnore] public virtual IEnumerable<Genre> Genres { get; set; }
|
||||||
[JsonIgnore] public virtual IEnumerable<PeopleRole> People { get; set; }
|
[JsonIgnore] public virtual IEnumerable<PeopleRole> People { get; set; }
|
||||||
[JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
|
||||||
[JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
|
||||||
|
[JsonIgnore] public virtual IEnumerable<Library> Libraries { get; set; }
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<LibraryLink> LibraryLinks { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Collection> Collections { get; set; }
|
||||||
|
|
||||||
[NotMergable] [JsonIgnore] public IEnumerable<Library> Libraries
|
|
||||||
{
|
|
||||||
get => LibraryLinks?.Select(x => x.Library);
|
|
||||||
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
[NotMergable] [JsonIgnore] public virtual IEnumerable<CollectionLink> CollectionLinks { get; set; }
|
|
||||||
|
|
||||||
[NotMergable] [JsonIgnore] public IEnumerable<Collection> Collections
|
|
||||||
{
|
|
||||||
get => CollectionLinks?.Select(x => x.Collection);
|
|
||||||
set => CollectionLinks = value?.Select(x => new CollectionLink(x, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Show() { }
|
public Show() { }
|
||||||
|
|
||||||
@ -117,14 +97,11 @@ namespace Kyoo.Models
|
|||||||
return ExternalIDs?.FirstOrDefault(x => x.Provider.Name == provider)?.DataID;
|
return ExternalIDs?.FirstOrDefault(x => x.Provider.Name == provider)?.DataID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnMerge(object merged)
|
public virtual void OnMerge(object merged)
|
||||||
{
|
{
|
||||||
if (ExternalIDs != null)
|
if (ExternalIDs != null)
|
||||||
foreach (MetadataID id in ExternalIDs)
|
foreach (MetadataID id in ExternalIDs)
|
||||||
id.Show = this;
|
id.Show = this;
|
||||||
if (GenreLinks != null)
|
|
||||||
foreach (GenreLink genre in GenreLinks)
|
|
||||||
genre.Show = this;
|
|
||||||
if (People != null)
|
if (People != null)
|
||||||
foreach (PeopleRole link in People)
|
foreach (PeopleRole link in People)
|
||||||
link.Show = this;
|
link.Show = this;
|
||||||
|
@ -3,9 +3,11 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Attributes;
|
using Kyoo.Models.Attributes;
|
||||||
@ -71,6 +73,21 @@ namespace Kyoo
|
|||||||
return list.Concat(second.Where(x => !list.Any(y => isEqual(x, y)))).ToList();
|
return list.Concat(second.Where(x => !list.Any(y => isEqual(x, y)))).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T Assign<T>(T first, T second)
|
||||||
|
{
|
||||||
|
Type type = typeof(T);
|
||||||
|
foreach (PropertyInfo property in type.GetProperties())
|
||||||
|
{
|
||||||
|
if (!property.CanRead || !property.CanWrite)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
object value = property.GetValue(second);
|
||||||
|
property.SetValue(first, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
public static T Complete<T>(T first, T second)
|
public static T Complete<T>(T first, T second)
|
||||||
{
|
{
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
@ -149,7 +166,7 @@ namespace Kyoo
|
|||||||
[NotNull] Type owner,
|
[NotNull] Type owner,
|
||||||
[NotNull] string methodName,
|
[NotNull] string methodName,
|
||||||
[NotNull] Type type,
|
[NotNull] Type type,
|
||||||
IEnumerable<object> args)
|
params object[] args)
|
||||||
{
|
{
|
||||||
if (owner == null)
|
if (owner == null)
|
||||||
throw new ArgumentNullException(nameof(owner));
|
throw new ArgumentNullException(nameof(owner));
|
||||||
@ -157,7 +174,7 @@ namespace Kyoo
|
|||||||
throw new ArgumentNullException(nameof(methodName));
|
throw new ArgumentNullException(nameof(methodName));
|
||||||
if (type == null)
|
if (type == null)
|
||||||
throw new ArgumentNullException(nameof(type));
|
throw new ArgumentNullException(nameof(type));
|
||||||
MethodInfo method = owner.GetMethod(methodName);
|
MethodInfo method = owner.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
if (method == null)
|
if (method == null)
|
||||||
throw new NullReferenceException($"A method named {methodName} could not be found on {owner.FullName}");
|
throw new NullReferenceException($"A method named {methodName} could not be found on {owner.FullName}");
|
||||||
return method.MakeGenericMethod(type).Invoke(null, args?.ToArray());
|
return method.MakeGenericMethod(type).Invoke(null, args?.ToArray());
|
||||||
@ -167,7 +184,7 @@ namespace Kyoo
|
|||||||
[NotNull] object instance,
|
[NotNull] object instance,
|
||||||
[NotNull] string methodName,
|
[NotNull] string methodName,
|
||||||
[NotNull] Type type,
|
[NotNull] Type type,
|
||||||
IEnumerable<object> args)
|
params object[] args)
|
||||||
{
|
{
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
throw new ArgumentNullException(nameof(instance));
|
throw new ArgumentNullException(nameof(instance));
|
||||||
@ -175,7 +192,7 @@ namespace Kyoo
|
|||||||
throw new ArgumentNullException(nameof(methodName));
|
throw new ArgumentNullException(nameof(methodName));
|
||||||
if (type == null)
|
if (type == null)
|
||||||
throw new ArgumentNullException(nameof(type));
|
throw new ArgumentNullException(nameof(type));
|
||||||
MethodInfo method = instance.GetType().GetMethod(methodName);
|
MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
if (method == null)
|
if (method == null)
|
||||||
throw new NullReferenceException($"A method named {methodName} could not be found on {instance.GetType().FullName}");
|
throw new NullReferenceException($"A method named {methodName} could not be found on {instance.GetType().FullName}");
|
||||||
return method.MakeGenericMethod(type).Invoke(instance, args?.ToArray());
|
return method.MakeGenericMethod(type).Invoke(instance, args?.ToArray());
|
||||||
@ -230,5 +247,66 @@ namespace Kyoo
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}"));
|
return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Task<T> Cast<T>(this Task task)
|
||||||
|
{
|
||||||
|
return (Task<T>)task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Expression<T> Convert<T>(this Expression expr)
|
||||||
|
where T : Delegate
|
||||||
|
{
|
||||||
|
if (expr is LambdaExpression lambda)
|
||||||
|
return new ExpressionConverter<T>(lambda).VisitAndConvert();
|
||||||
|
throw new ArgumentException("Can't convert a non lambda.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ExpressionConverter<TTo> : ExpressionVisitor
|
||||||
|
where TTo : Delegate
|
||||||
|
{
|
||||||
|
private readonly LambdaExpression _expression;
|
||||||
|
private readonly ParameterExpression[] _newParams;
|
||||||
|
|
||||||
|
internal ExpressionConverter(LambdaExpression expression)
|
||||||
|
{
|
||||||
|
_expression = expression;
|
||||||
|
|
||||||
|
Type[] paramTypes = typeof(TTo).GetGenericArguments()[..^1];
|
||||||
|
if (paramTypes.Length != _expression.Parameters.Count)
|
||||||
|
throw new ArgumentException("Parameter count from internal and external lambda are not matched.");
|
||||||
|
|
||||||
|
_newParams = new ParameterExpression[paramTypes.Length];
|
||||||
|
for (int i = 0; i < paramTypes.Length; i++)
|
||||||
|
{
|
||||||
|
if (_expression.Parameters[i].Type == paramTypes[i])
|
||||||
|
_newParams[i] = _expression.Parameters[i];
|
||||||
|
else
|
||||||
|
_newParams[i] = Expression.Parameter(paramTypes[i], _expression.Parameters[i].Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Expression<TTo> VisitAndConvert()
|
||||||
|
{
|
||||||
|
return (Expression<TTo>)RunGenericMethod(
|
||||||
|
this,
|
||||||
|
"VisitLambda",
|
||||||
|
_expression.GetType().GetGenericArguments().First(),
|
||||||
|
_expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Expression VisitLambda<T>(Expression<T> node)
|
||||||
|
{
|
||||||
|
Type returnType = _expression.Type.GetGenericArguments().Last();
|
||||||
|
Expression body = node.ReturnType == returnType
|
||||||
|
? Visit(node.Body)
|
||||||
|
: Expression.Convert(Visit(node.Body)!, returnType);
|
||||||
|
return Expression.Lambda<TTo>(body!, _newParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Expression VisitParameter(ParameterExpression node)
|
||||||
|
{
|
||||||
|
return _newParams.First(x => x.Name == node.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,15 +9,16 @@ using Kyoo.CommonApi;
|
|||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Npgsql;
|
|
||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public abstract class LocalRepository<T> : IRepository<T> where T : class, IResource
|
public abstract class LocalRepository<T, TInternal> : IRepository<T>
|
||||||
|
where T : class, IResource
|
||||||
|
where TInternal : class, T
|
||||||
{
|
{
|
||||||
private readonly DbContext _database;
|
private readonly DbContext _database;
|
||||||
|
|
||||||
protected abstract Expression<Func<T, object>> DefaultSort { get; }
|
protected abstract Expression<Func<TInternal, object>> DefaultSort { get; }
|
||||||
|
|
||||||
|
|
||||||
protected LocalRepository(DbContext database)
|
protected LocalRepository(DbContext database)
|
||||||
@ -35,14 +36,24 @@ namespace Kyoo.Controllers
|
|||||||
return _database.DisposeAsync();
|
return _database.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task<T> Get(int id)
|
public Task<T> Get(int id)
|
||||||
{
|
{
|
||||||
return _database.Set<T>().FirstOrDefaultAsync(x => x.ID == id);
|
return _Get(id).Cast<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task<T> Get(string slug)
|
public Task<T> Get(string slug)
|
||||||
{
|
{
|
||||||
return _database.Set<T>().FirstOrDefaultAsync(x => x.Slug == slug);
|
return _Get(slug).Cast<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Task<TInternal> _Get(int id)
|
||||||
|
{
|
||||||
|
return _database.Set<TInternal>().FirstOrDefaultAsync(x => x.ID == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Task<TInternal> _Get(string slug)
|
||||||
|
{
|
||||||
|
return _database.Set<TInternal>().FirstOrDefaultAsync(x => x.Slug == slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Task<ICollection<T>> Search(string query);
|
public abstract Task<ICollection<T>> Search(string query);
|
||||||
@ -51,15 +62,31 @@ namespace Kyoo.Controllers
|
|||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
return ApplyFilters(_database.Set<T>(), where, sort, limit);
|
return ApplyFilters(_database.Set<TInternal>(), where, sort, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Task<ICollection<T>> ApplyFilters(IQueryable<T> query,
|
protected async Task<ICollection<T>> ApplyFilters(IQueryable<TInternal> query,
|
||||||
Expression<Func<T, bool>> where = null,
|
Expression<Func<T, bool>> where = null,
|
||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
return ApplyFilters(query, Get, DefaultSort, where, sort, limit);
|
ICollection<TInternal> items = await ApplyFilters(query,
|
||||||
|
_Get,
|
||||||
|
DefaultSort,
|
||||||
|
where.Convert<Func<TInternal, bool>>(),
|
||||||
|
sort.To<TInternal>(),
|
||||||
|
limit);
|
||||||
|
|
||||||
|
return items.ToList<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<ICollection<T>> ApplyFilters(IQueryable<TInternal> query,
|
||||||
|
Expression<Func<TInternal, bool>> where = null,
|
||||||
|
Sort<TInternal> sort = default,
|
||||||
|
Pagination limit = default)
|
||||||
|
{
|
||||||
|
ICollection<TInternal> items = await ApplyFilters(query, _Get, DefaultSort, where, sort, limit);
|
||||||
|
return items.ToList<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<ICollection<TValue>> ApplyFilters<TValue>(IQueryable<TValue> query,
|
protected async Task<ICollection<TValue>> ApplyFilters<TValue>(IQueryable<TValue> query,
|
||||||
@ -125,7 +152,7 @@ namespace Kyoo.Controllers
|
|||||||
if (edited == null)
|
if (edited == null)
|
||||||
throw new ArgumentNullException(nameof(edited));
|
throw new ArgumentNullException(nameof(edited));
|
||||||
|
|
||||||
T old = await Get(edited.Slug);
|
TInternal old = (TInternal)await Get(edited.Slug);
|
||||||
|
|
||||||
if (old == null)
|
if (old == null)
|
||||||
throw new ItemNotFound($"No ressource found with the slug {edited.Slug}.");
|
throw new ItemNotFound($"No ressource found with the slug {edited.Slug}.");
|
||||||
@ -138,9 +165,9 @@ namespace Kyoo.Controllers
|
|||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual Task Validate(T ressource)
|
protected virtual Task Validate(TInternal ressource)
|
||||||
{
|
{
|
||||||
foreach (PropertyInfo property in typeof(T).GetProperties()
|
foreach (PropertyInfo property in typeof(TInternal).GetProperties()
|
||||||
.Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType)
|
.Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType)
|
||||||
&& !typeof(string).IsAssignableFrom(x.PropertyType)))
|
&& !typeof(string).IsAssignableFrom(x.PropertyType)))
|
||||||
{
|
{
|
||||||
|
@ -93,7 +93,7 @@ namespace Kyoo.Controllers
|
|||||||
show.Slug = Utility.ToSlug(showName);
|
show.Slug = Utility.ToSlug(showName);
|
||||||
show.Title ??= showName;
|
show.Title ??= showName;
|
||||||
show.IsMovie = isMovie;
|
show.IsMovie = isMovie;
|
||||||
show.GenreLinks = show.GenreLinks?.GroupBy(x => x.Genre.Slug).Select(x => x.First()).ToList();
|
show.Genres = show.Genres?.GroupBy(x => x.Slug).Select(x => x.First()).ToList();
|
||||||
show.People = show.People?.GroupBy(x => x.Slug).Select(x => x.First()).ToList();
|
show.People = show.People?.GroupBy(x => x.Slug).Select(x => x.First()).ToList();
|
||||||
return show;
|
return show;
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,12 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class CollectionRepository : LocalRepository<Collection>, ICollectionRepository
|
public class CollectionRepository : LocalRepository<Collection, CollectionDE>, ICollectionRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly Lazy<IShowRepository> _shows;
|
private readonly Lazy<IShowRepository> _shows;
|
||||||
private readonly Lazy<ILibraryRepository> _libraries;
|
private readonly Lazy<ILibraryRepository> _libraries;
|
||||||
protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name;
|
protected override Expression<Func<CollectionDE, object>> DefaultSort => x => x.Name;
|
||||||
|
|
||||||
public CollectionRepository(DatabaseContext database, IServiceProvider services) : base(database)
|
public CollectionRepository(DatabaseContext database, IServiceProvider services) : base(database)
|
||||||
{
|
{
|
||||||
@ -47,7 +47,7 @@ namespace Kyoo.Controllers
|
|||||||
return await _database.Collections
|
return await _database.Collections
|
||||||
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync<Collection>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<Collection> Create(Collection obj)
|
public override async Task<Collection> Create(Collection obj)
|
||||||
@ -60,10 +60,11 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Delete(Collection obj)
|
public override async Task Delete(Collection item)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (item == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
CollectionDE obj = new CollectionDE(item);
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
if (obj.Links != null)
|
if (obj.Links != null)
|
||||||
@ -82,7 +83,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Collection> collections = await ApplyFilters(_database.CollectionLinks
|
ICollection<Collection> collections = await ApplyFilters(_database.CollectionLinks
|
||||||
.Where(x => x.ShowID == showID)
|
.Where(x => x.ShowID == showID)
|
||||||
.Select(x => x.Collection),
|
.Select(x => x.Collection as CollectionDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -98,7 +99,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Collection> collections = await ApplyFilters(_database.CollectionLinks
|
ICollection<Collection> collections = await ApplyFilters(_database.CollectionLinks
|
||||||
.Where(x => x.Show.Slug == showSlug)
|
.Where(x => x.Show.Slug == showSlug)
|
||||||
.Select(x => x.Collection),
|
.Select(x => x.Collection as CollectionDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -114,7 +115,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Collection> collections = await ApplyFilters(_database.LibraryLinks
|
ICollection<Collection> collections = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.LibraryID == id && x.CollectionID != null)
|
.Where(x => x.LibraryID == id && x.CollectionID != null)
|
||||||
.Select(x => x.Collection),
|
.Select(x => x.Collection as CollectionDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -130,7 +131,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Collection> collections = await ApplyFilters(_database.LibraryLinks
|
ICollection<Collection> collections = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.Library.Slug == slug && x.CollectionID != null)
|
.Where(x => x.Library.Slug == slug && x.CollectionID != null)
|
||||||
.Select(x => x.Collection),
|
.Select(x => x.Collection as CollectionDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
|
@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class EpisodeRepository : LocalRepository<Episode>, IEpisodeRepository
|
public class EpisodeRepository : LocalRepository<Episode, Episode>, IEpisodeRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
@ -133,7 +133,7 @@ namespace Kyoo.Controllers
|
|||||||
Sort<Episode> sort = default,
|
Sort<Episode> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<Episode> episodes = await ApplyFilters(_database.Episodes.Where(x => x.ShowID == showID),
|
ICollection<Episode> episodes = await ApplyFilters<Episode>(_database.Episodes.Where(x => x.ShowID == showID),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
|
@ -10,12 +10,12 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class LibraryRepository : LocalRepository<Library>, ILibraryRepository
|
public class LibraryRepository : LocalRepository<Library, LibraryDE>, ILibraryRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
private readonly Lazy<IShowRepository> _shows;
|
private readonly Lazy<IShowRepository> _shows;
|
||||||
protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
|
protected override Expression<Func<LibraryDE, object>> DefaultSort => x => x.ID;
|
||||||
|
|
||||||
|
|
||||||
public LibraryRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services)
|
public LibraryRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services)
|
||||||
@ -47,13 +47,14 @@ namespace Kyoo.Controllers
|
|||||||
return await _database.Libraries
|
return await _database.Libraries
|
||||||
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync<Library>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<Library> Create(Library obj)
|
public override async Task<Library> Create(Library item)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (item == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
LibraryDE obj = new LibraryDE(item);
|
||||||
|
|
||||||
await Validate(obj);
|
await Validate(obj);
|
||||||
_database.Entry(obj).State = EntityState.Added;
|
_database.Entry(obj).State = EntityState.Added;
|
||||||
@ -65,7 +66,7 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task Validate(Library obj)
|
protected override async Task Validate(LibraryDE obj)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(obj.Slug))
|
if (string.IsNullOrEmpty(obj.Slug))
|
||||||
throw new ArgumentException("The library's slug must be set and not empty");
|
throw new ArgumentException("The library's slug must be set and not empty");
|
||||||
@ -81,10 +82,11 @@ namespace Kyoo.Controllers
|
|||||||
link.Provider = await _providers.CreateIfNotExists(link.Provider);
|
link.Provider = await _providers.CreateIfNotExists(link.Provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Delete(Library obj)
|
public override async Task Delete(Library item)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (item == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
LibraryDE obj = new LibraryDE(item);
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
if (obj.ProviderLinks != null)
|
if (obj.ProviderLinks != null)
|
||||||
@ -103,7 +105,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.ShowID == showID)
|
.Where(x => x.ShowID == showID)
|
||||||
.Select(x => x.Library),
|
.Select(x => x.Library as LibraryDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -119,7 +121,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.Show.Slug == showSlug)
|
.Where(x => x.Show.Slug == showSlug)
|
||||||
.Select(x => x.Library),
|
.Select(x => x.Library as LibraryDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -135,7 +137,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.CollectionID == id)
|
.Where(x => x.CollectionID == id)
|
||||||
.Select(x => x.Library),
|
.Select(x => x.Library as LibraryDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -151,7 +153,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.Collection.Slug == slug)
|
.Where(x => x.Collection.Slug == slug)
|
||||||
.Select(x => x.Library),
|
.Select(x => x.Library as LibraryDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
|
@ -10,7 +10,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class ShowRepository : LocalRepository<Show>, IShowRepository
|
public class ShowRepository : LocalRepository<Show, ShowDE>, IShowRepository
|
||||||
{
|
{
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
private readonly IStudioRepository _studios;
|
private readonly IStudioRepository _studios;
|
||||||
@ -21,7 +21,7 @@ namespace Kyoo.Controllers
|
|||||||
private readonly Lazy<IEpisodeRepository> _episodes;
|
private readonly Lazy<IEpisodeRepository> _episodes;
|
||||||
private readonly Lazy<ILibraryRepository> _libraries;
|
private readonly Lazy<ILibraryRepository> _libraries;
|
||||||
private readonly Lazy<ICollectionRepository> _collections;
|
private readonly Lazy<ICollectionRepository> _collections;
|
||||||
protected override Expression<Func<Show, object>> DefaultSort => x => x.Title;
|
protected override Expression<Func<ShowDE, object>> DefaultSort => x => x.Title;
|
||||||
|
|
||||||
public ShowRepository(DatabaseContext database,
|
public ShowRepository(DatabaseContext database,
|
||||||
IStudioRepository studios,
|
IStudioRepository studios,
|
||||||
@ -83,13 +83,14 @@ namespace Kyoo.Controllers
|
|||||||
.Where(x => EF.Functions.ILike(x.Title, query)
|
.Where(x => EF.Functions.ILike(x.Title, query)
|
||||||
/*|| x.Aliases.Any(y => EF.Functions.ILike(y, query))*/) // NOT TRANSLATABLE.
|
/*|| x.Aliases.Any(y => EF.Functions.ILike(y, query))*/) // NOT TRANSLATABLE.
|
||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync<Show>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<Show> Create(Show obj)
|
public override async Task<Show> Create(Show item)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (item == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
ShowDE obj = new ShowDE(item);
|
||||||
|
|
||||||
await Validate(obj);
|
await Validate(obj);
|
||||||
_database.Entry(obj).State = EntityState.Added;
|
_database.Entry(obj).State = EntityState.Added;
|
||||||
@ -107,7 +108,7 @@ namespace Kyoo.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task Validate(Show obj)
|
protected override async Task Validate(ShowDE obj)
|
||||||
{
|
{
|
||||||
await base.Validate(obj);
|
await base.Validate(obj);
|
||||||
|
|
||||||
@ -147,10 +148,11 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Delete(Show obj)
|
public override async Task Delete(Show item)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (item == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
ShowDE obj = new ShowDE(item);
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
|
|
||||||
@ -190,7 +192,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Show> shows = await ApplyFilters(_database.LibraryLinks
|
ICollection<Show> shows = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.LibraryID == id && x.ShowID != null)
|
.Where(x => x.LibraryID == id && x.ShowID != null)
|
||||||
.Select(x => x.Show),
|
.Select(x => x.Show as ShowDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -206,7 +208,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Show> shows = await ApplyFilters(_database.LibraryLinks
|
ICollection<Show> shows = await ApplyFilters(_database.LibraryLinks
|
||||||
.Where(x => x.Library.Slug == slug && x.ShowID != null)
|
.Where(x => x.Library.Slug == slug && x.ShowID != null)
|
||||||
.Select(x => x.Show),
|
.Select(x => x.Show as ShowDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -222,7 +224,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Show> shows = await ApplyFilters(_database.CollectionLinks
|
ICollection<Show> shows = await ApplyFilters(_database.CollectionLinks
|
||||||
.Where(x => x.CollectionID== id)
|
.Where(x => x.CollectionID== id)
|
||||||
.Select(x => x.Show),
|
.Select(x => x.Show as ShowDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -238,7 +240,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
ICollection<Show> shows = await ApplyFilters(_database.CollectionLinks
|
ICollection<Show> shows = await ApplyFilters(_database.CollectionLinks
|
||||||
.Where(x => x.Collection.Slug == slug)
|
.Where(x => x.Collection.Slug == slug)
|
||||||
.Select(x => x.Show),
|
.Select(x => x.Show as ShowDE),
|
||||||
where,
|
where,
|
||||||
sort,
|
sort,
|
||||||
limit);
|
limit);
|
||||||
@ -249,12 +251,16 @@ namespace Kyoo.Controllers
|
|||||||
|
|
||||||
public Task<Show> GetFromSeason(int seasonID)
|
public Task<Show> GetFromSeason(int seasonID)
|
||||||
{
|
{
|
||||||
return _database.Shows.FirstOrDefaultAsync(x => x.Seasons.Any(y => y.ID == seasonID));
|
return _database.Shows
|
||||||
|
.FirstOrDefaultAsync(x => x.Seasons.Any(y => y.ID == seasonID))
|
||||||
|
.Cast<Show>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Show> GetFromEpisode(int episodeID)
|
public Task<Show> GetFromEpisode(int episodeID)
|
||||||
{
|
{
|
||||||
return _database.Shows.FirstOrDefaultAsync(x => x.Episodes.Any(y => y.ID == episodeID));
|
return _database.Shows
|
||||||
|
.FirstOrDefaultAsync(x => x.Episodes.Any(y => y.ID == episodeID))
|
||||||
|
.Cast<Show>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -96,11 +96,11 @@ namespace Kyoo.Controllers
|
|||||||
if (episode?.Path == null)
|
if (episode?.Path == null)
|
||||||
return default;
|
return default;
|
||||||
|
|
||||||
if (episode.ImgPrimary != null)
|
if (episode.Poster != null)
|
||||||
{
|
{
|
||||||
string localPath = Path.ChangeExtension(episode.Path, "jpg");
|
string localPath = Path.ChangeExtension(episode.Path, "jpg");
|
||||||
if (alwaysDownload || !File.Exists(localPath))
|
if (alwaysDownload || !File.Exists(localPath))
|
||||||
await DownloadImage(episode.ImgPrimary, localPath, $"The thumbnail of {episode.Show.Title}");
|
await DownloadImage(episode.Poster, localPath, $"The thumbnail of {episode.Show.Title}");
|
||||||
}
|
}
|
||||||
return episode;
|
return episode;
|
||||||
}
|
}
|
||||||
|
@ -1,69 +1,27 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using IdentityServer4.EntityFramework.Entities;
|
|
||||||
using IdentityServer4.EntityFramework.Extensions;
|
|
||||||
using IdentityServer4.EntityFramework.Interfaces;
|
|
||||||
using IdentityServer4.EntityFramework.Options;
|
|
||||||
using Kyoo.Models;
|
using Kyoo.Models;
|
||||||
using Kyoo.Models.Exceptions;
|
using Kyoo.Models.Exceptions;
|
||||||
using Kyoo.Models.Watch;
|
using Kyoo.Models.Watch;
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Npgsql;
|
using Npgsql;
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
{
|
{
|
||||||
public class IdentityDatabase : IdentityDbContext<User>, IPersistedGrantDbContext
|
|
||||||
{
|
|
||||||
private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;
|
|
||||||
|
|
||||||
public IdentityDatabase(DbContextOptions<IdentityDatabase> options, IOptions<OperationalStoreOptions> operationalStoreOptions)
|
|
||||||
: base(options)
|
|
||||||
{
|
|
||||||
_operationalStoreOptions = operationalStoreOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbSet<User> Accounts { get; set; }
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
base.OnModelCreating(modelBuilder);
|
|
||||||
modelBuilder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
|
|
||||||
|
|
||||||
modelBuilder.Entity<User>().ToTable("User");
|
|
||||||
modelBuilder.Entity<IdentityUserRole<string>>().ToTable("UserRole");
|
|
||||||
modelBuilder.Entity<IdentityUserLogin<string>>().ToTable("UserLogin");
|
|
||||||
modelBuilder.Entity<IdentityUserClaim<string>>().ToTable("UserClaim");
|
|
||||||
modelBuilder.Entity<IdentityRole>().ToTable("UserRoles");
|
|
||||||
modelBuilder.Entity<IdentityRoleClaim<string>>().ToTable("UserRoleClaim");
|
|
||||||
modelBuilder.Entity<IdentityUserToken<string>>().ToTable("UserToken");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<int> SaveChangesAsync() => base.SaveChangesAsync();
|
|
||||||
|
|
||||||
public DbSet<PersistedGrant> PersistedGrants { get; set; }
|
|
||||||
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DatabaseContext : DbContext
|
public class DatabaseContext : DbContext
|
||||||
{
|
{
|
||||||
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
|
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
|
||||||
|
|
||||||
public DbSet<Library> Libraries { get; set; }
|
public DbSet<LibraryDE> Libraries { get; set; }
|
||||||
public DbSet<Collection> Collections { get; set; }
|
public DbSet<CollectionDE> Collections { get; set; }
|
||||||
public DbSet<Show> Shows { get; set; }
|
public DbSet<ShowDE> Shows { get; set; }
|
||||||
public DbSet<Season> Seasons { get; set; }
|
public DbSet<Season> Seasons { get; set; }
|
||||||
public DbSet<Episode> Episodes { get; set; }
|
public DbSet<Episode> Episodes { get; set; }
|
||||||
public DbSet<Track> Tracks { get; set; }
|
public DbSet<Track> Tracks { get; set; }
|
||||||
public DbSet<Genre> Genres { get; set; }
|
public DbSet<GenreDE> Genres { get; set; }
|
||||||
public DbSet<People> People { get; set; }
|
public DbSet<People> People { get; set; }
|
||||||
public DbSet<Studio> Studios { get; set; }
|
public DbSet<Studio> Studios { get; set; }
|
||||||
public DbSet<ProviderID> Providers { get; set; }
|
public DbSet<ProviderID> Providers { get; set; }
|
||||||
@ -72,7 +30,6 @@ namespace Kyoo
|
|||||||
public DbSet<PeopleRole> PeopleRoles { get; set; }
|
public DbSet<PeopleRole> PeopleRoles { get; set; }
|
||||||
|
|
||||||
|
|
||||||
// This is used because EF doesn't support Many-To-Many relationships so for now we need to override the getter/setters to store this.
|
|
||||||
public DbSet<LibraryLink> LibraryLinks { get; set; }
|
public DbSet<LibraryLink> LibraryLinks { get; set; }
|
||||||
public DbSet<CollectionLink> CollectionLinks { get; set; }
|
public DbSet<CollectionLink> CollectionLinks { get; set; }
|
||||||
public DbSet<GenreLink> GenreLinks { get; set; }
|
public DbSet<GenreLink> GenreLinks { get; set; }
|
||||||
|
46
Kyoo/Models/IdentityDatabase.cs
Normal file
46
Kyoo/Models/IdentityDatabase.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using IdentityServer4.EntityFramework.Entities;
|
||||||
|
using IdentityServer4.EntityFramework.Extensions;
|
||||||
|
using IdentityServer4.EntityFramework.Interfaces;
|
||||||
|
using IdentityServer4.EntityFramework.Options;
|
||||||
|
using Kyoo.Models;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Kyoo
|
||||||
|
{
|
||||||
|
public class IdentityDatabase : IdentityDbContext<User>, IPersistedGrantDbContext
|
||||||
|
{
|
||||||
|
private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;
|
||||||
|
|
||||||
|
public IdentityDatabase(DbContextOptions<IdentityDatabase> options, IOptions<OperationalStoreOptions> operationalStoreOptions)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
_operationalStoreOptions = operationalStoreOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<User> Accounts { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
modelBuilder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
|
||||||
|
|
||||||
|
modelBuilder.Entity<User>().ToTable("User");
|
||||||
|
modelBuilder.Entity<IdentityUserRole<string>>().ToTable("UserRole");
|
||||||
|
modelBuilder.Entity<IdentityUserLogin<string>>().ToTable("UserLogin");
|
||||||
|
modelBuilder.Entity<IdentityUserClaim<string>>().ToTable("UserClaim");
|
||||||
|
modelBuilder.Entity<IdentityRole>().ToTable("UserRoles");
|
||||||
|
modelBuilder.Entity<IdentityRoleClaim<string>>().ToTable("UserRoleClaim");
|
||||||
|
modelBuilder.Entity<IdentityUserToken<string>>().ToTable("UserToken");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> SaveChangesAsync() => base.SaveChangesAsync();
|
||||||
|
|
||||||
|
public DbSet<PersistedGrant> PersistedGrants { get; set; }
|
||||||
|
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
30
Kyoo/Models/Resources/CollectionDE.cs
Normal file
30
Kyoo/Models/Resources/CollectionDE.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
|
namespace Kyoo.Models
|
||||||
|
{
|
||||||
|
public class CollectionDE : Collection
|
||||||
|
{
|
||||||
|
[NotMergable] public virtual IEnumerable<CollectionLink> Links { get; set; }
|
||||||
|
public override IEnumerable<Show> Shows
|
||||||
|
{
|
||||||
|
get => Links.Select(x => x.Show);
|
||||||
|
set => Links = value.Select(x => new CollectionLink(this, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotMergable] public virtual IEnumerable<LibraryLink> LibraryLinks { get; set; }
|
||||||
|
public override IEnumerable<Library> Libraries
|
||||||
|
{
|
||||||
|
get => LibraryLinks?.Select(x => x.Library);
|
||||||
|
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CollectionDE() {}
|
||||||
|
|
||||||
|
public CollectionDE(Collection collection)
|
||||||
|
{
|
||||||
|
Utility.Assign(this, collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
Kyoo/Models/Resources/GenreDE.cs
Normal file
24
Kyoo/Models/Resources/GenreDE.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
|
namespace Kyoo.Models
|
||||||
|
{
|
||||||
|
public class GenreDE : Genre
|
||||||
|
{
|
||||||
|
[NotMergable] public virtual IEnumerable<GenreLink> Links { get; set; }
|
||||||
|
|
||||||
|
[NotMergable] public override IEnumerable<Show> Shows
|
||||||
|
{
|
||||||
|
get => Links.Select(x => x.Show);
|
||||||
|
set => Links = value?.Select(x => new GenreLink(x, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenreDE() {}
|
||||||
|
|
||||||
|
public GenreDE(Genre item)
|
||||||
|
{
|
||||||
|
Utility.Assign(this, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
Kyoo/Models/Resources/LibraryDE.cs
Normal file
39
Kyoo/Models/Resources/LibraryDE.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
|
namespace Kyoo.Models
|
||||||
|
{
|
||||||
|
public class LibraryDE : Library
|
||||||
|
{
|
||||||
|
[NotMergable] public virtual IEnumerable<ProviderLink> ProviderLinks { get; set; }
|
||||||
|
public override IEnumerable<ProviderID> Providers
|
||||||
|
{
|
||||||
|
get => ProviderLinks?.Select(x => x.Provider);
|
||||||
|
set => ProviderLinks = value.Select(x => new ProviderLink(x, this)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotMergable] public virtual IEnumerable<LibraryLink> Links { get; set; }
|
||||||
|
public override IEnumerable<Show> Shows
|
||||||
|
{
|
||||||
|
get => Links?.Where(x => x.Show != null).Select(x => x.Show);
|
||||||
|
set => Links = Utility.MergeLists(
|
||||||
|
value?.Select(x => new LibraryLink(this, x)),
|
||||||
|
Links?.Where(x => x.Show == null));
|
||||||
|
}
|
||||||
|
public override IEnumerable<Collection> Collections
|
||||||
|
{
|
||||||
|
get => Links?.Where(x => x.Collection != null).Select(x => x.Collection);
|
||||||
|
set => Links = Utility.MergeLists(
|
||||||
|
value?.Select(x => new LibraryLink(this, x)),
|
||||||
|
Links?.Where(x => x.Collection == null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryDE() {}
|
||||||
|
|
||||||
|
public LibraryDE(Library item)
|
||||||
|
{
|
||||||
|
Utility.Assign(this, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
Kyoo/Models/Resources/ShowDE.cs
Normal file
47
Kyoo/Models/Resources/ShowDE.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Kyoo.Models.Attributes;
|
||||||
|
|
||||||
|
namespace Kyoo.Models
|
||||||
|
{
|
||||||
|
public class ShowDE : Show
|
||||||
|
{
|
||||||
|
[NotMergable] public virtual IEnumerable<GenreLink> GenreLinks { get; set; }
|
||||||
|
public override IEnumerable<Genre> Genres
|
||||||
|
{
|
||||||
|
get => GenreLinks?.Select(x => x.Genre);
|
||||||
|
set => GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotMergable] public virtual IEnumerable<LibraryLink> LibraryLinks { get; set; }
|
||||||
|
public override IEnumerable<Library> Libraries
|
||||||
|
{
|
||||||
|
get => LibraryLinks?.Select(x => x.Library);
|
||||||
|
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotMergable] public virtual IEnumerable<CollectionLink> CollectionLinks { get; set; }
|
||||||
|
|
||||||
|
public override IEnumerable<Collection> Collections
|
||||||
|
{
|
||||||
|
get => CollectionLinks?.Select(x => x.Collection);
|
||||||
|
set => CollectionLinks = value?.Select(x => new CollectionLink(x, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnMerge(object merged)
|
||||||
|
{
|
||||||
|
base.OnMerge(merged);
|
||||||
|
|
||||||
|
if (GenreLinks != null)
|
||||||
|
foreach (GenreLink genre in GenreLinks)
|
||||||
|
genre.Show = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShowDE() {}
|
||||||
|
|
||||||
|
public ShowDE(Show show)
|
||||||
|
{
|
||||||
|
Utility.Assign(this, show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
Subproject commit d4202623007f0cefb22aa64e3c638142ba7d7831
|
Subproject commit 2e44a86c4b9004012c10d259ae90925adcd66aa7
|
Loading…
x
Reference in New Issue
Block a user