mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-02 21:24:20 -04:00
CodingStlye: Fixing whitespaces
This commit is contained in:
parent
8ff2fe3965
commit
d3a03771dd
@ -7,6 +7,7 @@ trim_trailing_whitespace = true
|
|||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = tab
|
indent_size = tab
|
||||||
|
smart_tab = true
|
||||||
|
|
||||||
[{*.yaml,*.yml}]
|
[{*.yaml,*.yml}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
@ -6,12 +6,15 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.354" />
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.354" PrivateAssets="All" />
|
||||||
|
|
||||||
<None Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" Visible="false" />
|
<None Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" Visible="false" />
|
||||||
<None Include="$(MSBuildThisFileDirectory).editorconfig" Link="stylecop.json" Visible="false" />
|
<None Include="$(MSBuildThisFileDirectory).editorconfig" Link=".editorconfig" Visible="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)Kyoo.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)Kyoo.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<!-- <AnalysisMode>AllEnabledByDefault</AnalysisMode>-->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@ -26,62 +26,62 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// The repository that handle libraries.
|
/// The repository that handle libraries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ILibraryRepository LibraryRepository { get; }
|
ILibraryRepository LibraryRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle libraries's items (a wrapper arround shows & collections).
|
/// The repository that handle libraries's items (a wrapper arround shows & collections).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ILibraryItemRepository LibraryItemRepository { get; }
|
ILibraryItemRepository LibraryItemRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle collections.
|
/// The repository that handle collections.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ICollectionRepository CollectionRepository { get; }
|
ICollectionRepository CollectionRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle shows.
|
/// The repository that handle shows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IShowRepository ShowRepository { get; }
|
IShowRepository ShowRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle seasons.
|
/// The repository that handle seasons.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISeasonRepository SeasonRepository { get; }
|
ISeasonRepository SeasonRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle episodes.
|
/// The repository that handle episodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IEpisodeRepository EpisodeRepository { get; }
|
IEpisodeRepository EpisodeRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle tracks.
|
/// The repository that handle tracks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ITrackRepository TrackRepository { get; }
|
ITrackRepository TrackRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle people.
|
/// The repository that handle people.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IPeopleRepository PeopleRepository { get; }
|
IPeopleRepository PeopleRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle studios.
|
/// The repository that handle studios.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IStudioRepository StudioRepository { get; }
|
IStudioRepository StudioRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle genres.
|
/// The repository that handle genres.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IGenreRepository GenreRepository { get; }
|
IGenreRepository GenreRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle providers.
|
/// The repository that handle providers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IProviderRepository ProviderRepository { get; }
|
IProviderRepository ProviderRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository that handle users.
|
/// The repository that handle users.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IUserRepository UserRepository { get; }
|
IUserRepository UserRepository { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the resource by it's ID
|
/// Get the resource by it's ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -91,7 +91,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource found</returns>
|
/// <returns>The resource found</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<T> Get<T>(int id) where T : class, IResource;
|
Task<T> Get<T>(int id) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the resource by it's slug
|
/// Get the resource by it's slug
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -101,7 +101,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource found</returns>
|
/// <returns>The resource found</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<T> Get<T>(string slug) where T : class, IResource;
|
Task<T> Get<T>(string slug) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the resource by a filter function.
|
/// Get the resource by a filter function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -121,7 +121,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<Season> Get(int showID, int seasonNumber);
|
Task<Season> Get(int showID, int seasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a season from it's show slug and it's seasonNumber
|
/// Get a season from it's show slug and it's seasonNumber
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -131,7 +131,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<Season> Get(string showSlug, int seasonNumber);
|
Task<Season> Get(string showSlug, int seasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a episode from it's showID, it's seasonNumber and it's episode number.
|
/// Get a episode from it's showID, it's seasonNumber and it's episode number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -142,7 +142,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The episode found</returns>
|
/// <returns>The episode found</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<Episode> Get(int showID, int seasonNumber, int episodeNumber);
|
Task<Episode> Get(int showID, int seasonNumber, int episodeNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a episode from it's show slug, it's seasonNumber and it's episode number.
|
/// Get a episode from it's show slug, it's seasonNumber and it's episode number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -162,7 +162,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource found</returns>
|
/// <returns>The resource found</returns>
|
||||||
[ItemCanBeNull]
|
[ItemCanBeNull]
|
||||||
Task<T> GetOrDefault<T>(int id) where T : class, IResource;
|
Task<T> GetOrDefault<T>(int id) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the resource by it's slug or null if it is not found.
|
/// Get the resource by it's slug or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -171,7 +171,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource found</returns>
|
/// <returns>The resource found</returns>
|
||||||
[ItemCanBeNull]
|
[ItemCanBeNull]
|
||||||
Task<T> GetOrDefault<T>(string slug) where T : class, IResource;
|
Task<T> GetOrDefault<T>(string slug) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the resource by a filter function or null if it is not found.
|
/// Get the resource by a filter function or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -189,7 +189,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
[ItemCanBeNull]
|
[ItemCanBeNull]
|
||||||
Task<Season> GetOrDefault(int showID, int seasonNumber);
|
Task<Season> GetOrDefault(int showID, int seasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a season from it's show slug and it's seasonNumber or null if it is not found.
|
/// Get a season from it's show slug and it's seasonNumber or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -198,7 +198,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
[ItemCanBeNull]
|
[ItemCanBeNull]
|
||||||
Task<Season> GetOrDefault(string showSlug, int seasonNumber);
|
Task<Season> GetOrDefault(string showSlug, int seasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a episode from it's showID, it's seasonNumber and it's episode number or null if it is not found.
|
/// Get a episode from it's showID, it's seasonNumber and it's episode number or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -208,7 +208,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The episode found</returns>
|
/// <returns>The episode found</returns>
|
||||||
[ItemCanBeNull]
|
[ItemCanBeNull]
|
||||||
Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber);
|
Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found.
|
/// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -284,7 +284,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
/// <seealso cref="Load{T,T2}(T, System.Linq.Expressions.Expression{System.Func{T,System.Collections.Generic.ICollection{T2}}}, bool)"/>
|
||||||
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
/// <seealso cref="Load{T}(T, System.String, bool)"/>
|
||||||
Task Load([NotNull] IResource obj, string memberName, bool force = false);
|
Task Load([NotNull] IResource obj, string memberName, bool force = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get items (A wrapper arround shows or collections) from a library.
|
/// Get items (A wrapper arround shows or collections) from a library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -297,7 +297,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<LibraryItem, bool>> where = null,
|
Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get items (A wrapper arround shows or collections) from a library.
|
/// Get items (A wrapper arround shows or collections) from a library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -311,7 +311,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<LibraryItem, object>> sort,
|
Expression<Func<LibraryItem, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetItemsFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
) => GetItemsFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get items (A wrapper arround shows or collections) from a library.
|
/// Get items (A wrapper arround shows or collections) from a library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -324,7 +324,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<LibraryItem, bool>> where = null,
|
Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get items (A wrapper arround shows or collections) from a library.
|
/// Get items (A wrapper arround shows or collections) from a library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -338,8 +338,8 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<LibraryItem, object>> sort,
|
Expression<Func<LibraryItem, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetItemsFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
) => GetItemsFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -349,10 +349,10 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID,
|
Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -366,7 +366,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<PeopleRole, object>> sort,
|
Expression<Func<PeopleRole, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetPeopleFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
) => GetPeopleFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -376,10 +376,10 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug,
|
Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -393,8 +393,8 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<PeopleRole, object>> sort,
|
Expression<Func<PeopleRole, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetPeopleFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
) => GetPeopleFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -404,10 +404,10 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetRolesFromPeople(int id,
|
Task<ICollection<PeopleRole>> GetRolesFromPeople(int id,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -421,7 +421,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<PeopleRole, object>> sort,
|
Expression<Func<PeopleRole, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetRolesFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
) => GetRolesFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -431,10 +431,10 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetRolesFromPeople(string slug,
|
Task<ICollection<PeopleRole>> GetRolesFromPeople(string slug,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -449,7 +449,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetRolesFromPeople(slug, where, new Sort<PeopleRole>(sort), limit);
|
) => GetRolesFromPeople(slug, where, new Sort<PeopleRole>(sort), limit);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Setup relations between a show, a library and a collection
|
/// Setup relations between a show, a library and a collection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -457,7 +457,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="libraryID">The library's ID to setup relations with (optional)</param>
|
/// <param name="libraryID">The library's ID to setup relations with (optional)</param>
|
||||||
/// <param name="collectionID">The collection's ID to setup relations with (optional)</param>
|
/// <param name="collectionID">The collection's ID to setup relations with (optional)</param>
|
||||||
Task AddShowLink(int showID, int? libraryID, int? collectionID);
|
Task AddShowLink(int showID, int? libraryID, int? collectionID);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Setup relations between a show, a library and a collection
|
/// Setup relations between a show, a library and a collection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -477,7 +477,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Task<ICollection<T>> GetAll<T>(Expression<Func<T, bool>> where = null,
|
Task<ICollection<T>> GetAll<T>(Expression<Func<T, bool>> where = null,
|
||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
Pagination limit = default) where T : class, IResource;
|
Pagination limit = default) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all resources with filters
|
/// Get all resources with filters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -516,7 +516,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <typeparam name="T">The type of resource</typeparam>
|
/// <typeparam name="T">The type of resource</typeparam>
|
||||||
/// <returns>The resource registers and completed by database's informations (related items & so on)</returns>
|
/// <returns>The resource registers and completed by database's informations (related items & so on)</returns>
|
||||||
Task<T> Create<T>([NotNull] T item) where T : class, IResource;
|
Task<T> Create<T>([NotNull] T item) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
|
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -524,7 +524,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <typeparam name="T">The type of resource</typeparam>
|
/// <typeparam name="T">The type of resource</typeparam>
|
||||||
/// <returns>The newly created item or the existing value if it existed.</returns>
|
/// <returns>The newly created item or the existing value if it existed.</returns>
|
||||||
Task<T> CreateIfNotExists<T>([NotNull] T item) where T : class, IResource;
|
Task<T> CreateIfNotExists<T>([NotNull] T item) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Edit a resource
|
/// Edit a resource
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -542,7 +542,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <typeparam name="T">The type of resource to delete</typeparam>
|
/// <typeparam name="T">The type of resource to delete</typeparam>
|
||||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||||
Task Delete<T>(T item) where T : class, IResource;
|
Task Delete<T>(T item) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a resource by it's ID.
|
/// Delete a resource by it's ID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -550,7 +550,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <typeparam name="T">The type of resource to delete</typeparam>
|
/// <typeparam name="T">The type of resource to delete</typeparam>
|
||||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||||
Task Delete<T>(int id) where T : class, IResource;
|
Task Delete<T>(int id) where T : class, IResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a resource by it's slug.
|
/// Delete a resource by it's slug.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -20,17 +20,17 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// A slug to identify this plugin in queries.
|
/// A slug to identify this plugin in queries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Slug { get; }
|
string Slug { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the plugin
|
/// The name of the plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The description of this plugin. This will be displayed on the "installed plugins" page.
|
/// The description of this plugin. This will be displayed on the "installed plugins" page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Description { get; }
|
string Description { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <c>true</c> if the plugin should be enabled, <c>false</c> otherwise.
|
/// <c>true</c> if the plugin should be enabled, <c>false</c> otherwise.
|
||||||
/// If a plugin is not enabled, no configure method will be called.
|
/// If a plugin is not enabled, no configure method will be called.
|
||||||
@ -41,7 +41,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// By default, a plugin is always enabled. This method can be overriden to change this behavior.
|
/// By default, a plugin is always enabled. This method can be overriden to change this behavior.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
virtual bool Enabled => true;
|
virtual bool Enabled => true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of types that will be available via the IOptions interfaces and will be listed inside
|
/// A list of types that will be available via the IOptions interfaces and will be listed inside
|
||||||
/// an IConfiguration.
|
/// an IConfiguration.
|
||||||
@ -64,7 +64,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <seealso cref="SA"/>
|
/// <seealso cref="SA"/>
|
||||||
virtual IEnumerable<IStartupAction> ConfigureSteps => ArraySegment<IStartupAction>.Empty;
|
virtual IEnumerable<IStartupAction> ConfigureSteps => ArraySegment<IStartupAction>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A configure method that will be run on plugin's startup.
|
/// A configure method that will be run on plugin's startup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">The autofac service container to register services.</param>
|
/// <param name="builder">The autofac service container to register services.</param>
|
||||||
@ -72,7 +72,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
{
|
{
|
||||||
// Skipped
|
// Skipped
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A configure method that will be run on plugin's startup.
|
/// A configure method that will be run on plugin's startup.
|
||||||
/// This is available for libraries that build upon a <see cref="IServiceCollection"/>, for more precise
|
/// This is available for libraries that build upon a <see cref="IServiceCollection"/>, for more precise
|
||||||
@ -94,4 +94,4 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
// Skipped
|
// Skipped
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,14 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <exception cref="ItemNotFoundException">If no plugins match the query</exception>
|
/// <exception cref="ItemNotFoundException">If no plugins match the query</exception>
|
||||||
/// <returns>A plugin that match the queries</returns>
|
/// <returns>A plugin that match the queries</returns>
|
||||||
public T GetPlugin<T>(string name);
|
public T GetPlugin<T>(string name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all plugins of the given type.
|
/// Get all plugins of the given type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of plugins to get</typeparam>
|
/// <typeparam name="T">The type of plugins to get</typeparam>
|
||||||
/// <returns>A list of plugins matching the given type or an empty list of none match.</returns>
|
/// <returns>A list of plugins matching the given type or an empty list of none match.</returns>
|
||||||
public ICollection<T> GetPlugins<T>();
|
public ICollection<T> GetPlugins<T>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all plugins currently running on Kyoo. This also includes deleted plugins if the app as not been restarted.
|
/// Get all plugins currently running on Kyoo. This also includes deleted plugins if the app as not been restarted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -39,7 +39,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// You should not try to put plugins from the plugins directory here as they will get automatically loaded.
|
/// You should not try to put plugins from the plugins directory here as they will get automatically loaded.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void LoadPlugins(ICollection<IPlugin> plugins);
|
public void LoadPlugins(ICollection<IPlugin> plugins);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load plugins and their dependencies from the plugin directory.
|
/// Load plugins and their dependencies from the plugin directory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -49,4 +49,4 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// </param>
|
/// </param>
|
||||||
public void LoadPlugins(params Type[] plugins);
|
public void LoadPlugins(params Type[] plugins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Count = count;
|
Count = count;
|
||||||
AfterID = afterID;
|
AfterID = afterID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implicitly create a new pagination from a limit number.
|
/// Implicitly create a new pagination from a limit number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -57,7 +57,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Descendant { get; }
|
public bool Descendant { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="Sort{T}"/> instance.
|
/// Create a new <see cref="Sort{T}"/> instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -68,7 +68,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
{
|
{
|
||||||
Key = key;
|
Key = key;
|
||||||
Descendant = descendant;
|
Descendant = descendant;
|
||||||
|
|
||||||
if (!Utility.IsPropertyExpression(Key))
|
if (!Utility.IsPropertyExpression(Key))
|
||||||
throw new ArgumentException("The given sort key is not valid.");
|
throw new ArgumentException("The given sort key is not valid.");
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Descendant = false;
|
Descendant = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string key = sortBy.Contains(':') ? sortBy[..sortBy.IndexOf(':')] : sortBy;
|
string key = sortBy.Contains(':') ? sortBy[..sortBy.IndexOf(':')] : sortBy;
|
||||||
string order = sortBy.Contains(':') ? sortBy[(sortBy.IndexOf(':') + 1)..] : null;
|
string order = sortBy.Contains(':') ? sortBy[(sortBy.IndexOf(':') + 1)..] : null;
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Type RepositoryType { get; }
|
Type RepositoryType { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A common repository for every resources.
|
/// A common repository for every resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -147,7 +147,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource found</returns>
|
/// <returns>The resource found</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<T> Get(Expression<Func<T, bool>> where);
|
Task<T> Get(Expression<Func<T, bool>> where);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a resource from it's ID or null if it is not found.
|
/// Get a resource from it's ID or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -169,7 +169,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource found</returns>
|
/// <returns>The resource found</returns>
|
||||||
[ItemCanBeNull]
|
[ItemCanBeNull]
|
||||||
Task<T> GetOrDefault(Expression<Func<T, bool>> where);
|
Task<T> GetOrDefault(Expression<Func<T, bool>> where);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Search for resources.
|
/// Search for resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -177,7 +177,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>A list of resources found</returns>
|
/// <returns>A list of resources found</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<ICollection<T>> Search(string query);
|
Task<ICollection<T>> Search(string query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get every resources that match all filters
|
/// Get every resources that match all filters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -186,7 +186,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How pagination should be done (where to start and how many to return)</param>
|
/// <param name="limit">How pagination should be done (where to start and how many to return)</param>
|
||||||
/// <returns>A list of resources that match every filters</returns>
|
/// <returns>A list of resources that match every filters</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -208,8 +208,8 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="where">A filter predicate</param>
|
/// <param name="where">A filter predicate</param>
|
||||||
/// <returns>How many resources matched that filter</returns>
|
/// <returns>How many resources matched that filter</returns>
|
||||||
Task<int> GetCount(Expression<Func<T, bool>> where = null);
|
Task<int> GetCount(Expression<Func<T, bool>> where = null);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new resource.
|
/// Create a new resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -217,7 +217,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource registers and completed by database's information (related items & so on)</returns>
|
/// <returns>The resource registers and completed by database's information (related items & so on)</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<T> Create([NotNull] T obj);
|
Task<T> Create([NotNull] T obj);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
|
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -225,7 +225,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The newly created item or the existing value if it existed.</returns>
|
/// <returns>The newly created item or the existing value if it existed.</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<T> CreateIfNotExists([NotNull] T obj);
|
Task<T> CreateIfNotExists([NotNull] T obj);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Edit a resource
|
/// Edit a resource
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -235,7 +235,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The resource edited and completed by database's information (related items & so on)</returns>
|
/// <returns>The resource edited and completed by database's information (related items & so on)</returns>
|
||||||
[ItemNotNull]
|
[ItemNotNull]
|
||||||
Task<T> Edit([NotNull] T edited, bool resetOld);
|
Task<T> Edit([NotNull] T edited, bool resetOld);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a resource by it's ID
|
/// Delete a resource by it's ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -254,7 +254,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="obj">The resource to delete</param>
|
/// <param name="obj">The resource to delete</param>
|
||||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||||
Task Delete([NotNull] T obj);
|
Task Delete([NotNull] T obj);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete all resources that match the predicate.
|
/// Delete all resources that match the predicate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -299,7 +299,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
Task<Season> Get(int showID, int seasonNumber);
|
Task<Season> Get(int showID, int seasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a season from it's show slug and it's seasonNumber
|
/// Get a season from it's show slug and it's seasonNumber
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -308,7 +308,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
Task<Season> Get(string showSlug, int seasonNumber);
|
Task<Season> Get(string showSlug, int seasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a season from it's showID and it's seasonNumber or null if it is not found.
|
/// Get a season from it's showID and it's seasonNumber or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -316,7 +316,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="seasonNumber">The season's number</param>
|
/// <param name="seasonNumber">The season's number</param>
|
||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
Task<Season> GetOrDefault(int showID, int seasonNumber);
|
Task<Season> GetOrDefault(int showID, int seasonNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a season from it's show slug and it's seasonNumber or null if it is not found.
|
/// Get a season from it's show slug and it's seasonNumber or null if it is not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -325,7 +325,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>The season found</returns>
|
/// <returns>The season found</returns>
|
||||||
Task<Season> GetOrDefault(string showSlug, int seasonNumber);
|
Task<Season> GetOrDefault(string showSlug, int seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The repository to handle episodes
|
/// The repository to handle episodes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -366,7 +366,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="episodeNumber">The episode's number</param>
|
/// <param name="episodeNumber">The episode's number</param>
|
||||||
/// <returns>The episode found</returns>
|
/// <returns>The episode found</returns>
|
||||||
Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber);
|
Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a episode from it's showID and it's absolute number.
|
/// Get a episode from it's showID and it's absolute number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -389,7 +389,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// A repository to handle tracks
|
/// A repository to handle tracks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITrackRepository : IRepository<Track> { }
|
public interface ITrackRepository : IRepository<Track> { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A repository to handle libraries.
|
/// A repository to handle libraries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -425,7 +425,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<LibraryItem, object>> sort,
|
Expression<Func<LibraryItem, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
) => GetFromLibrary(id, where, new Sort<LibraryItem>(sort), limit);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get items (A wrapper around shows or collections) from a library.
|
/// Get items (A wrapper around shows or collections) from a library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -451,18 +451,18 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<LibraryItem, object>> sort,
|
Expression<Func<LibraryItem, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
) => GetFromLibrary(slug, where, new Sort<LibraryItem>(sort), limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A repository for collections
|
/// A repository for collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ICollectionRepository : IRepository<Collection> { }
|
public interface ICollectionRepository : IRepository<Collection> { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A repository for genres.
|
/// A repository for genres.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IGenreRepository : IRepository<Genre> { }
|
public interface IGenreRepository : IRepository<Genre> { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A repository for studios.
|
/// A repository for studios.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -482,7 +482,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetFromShow(int showID,
|
Task<ICollection<PeopleRole>> GetFromShow(int showID,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -498,7 +498,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<PeopleRole, object>> sort,
|
Expression<Func<PeopleRole, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
) => GetFromShow(showID, where, new Sort<PeopleRole>(sort), limit);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a show.
|
/// Get people's roles from a show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -508,7 +508,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
|
Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -524,7 +524,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<PeopleRole, object>> sort,
|
Expression<Func<PeopleRole, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
) => GetFromShow(showSlug, where, new Sort<PeopleRole>(sort), limit);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -534,7 +534,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetFromPeople(int id,
|
Task<ICollection<PeopleRole>> GetFromPeople(int id,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -550,7 +550,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Expression<Func<PeopleRole, object>> sort,
|
Expression<Func<PeopleRole, object>> sort,
|
||||||
Pagination limit = default
|
Pagination limit = default
|
||||||
) => GetFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
) => GetFromPeople(id, where, new Sort<PeopleRole>(sort), limit);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get people's roles from a person.
|
/// Get people's roles from a person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -560,7 +560,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">How many items to return and where to start</param>
|
/// <param name="limit">How many items to return and where to start</param>
|
||||||
/// <returns>A list of items that match every filters</returns>
|
/// <returns>A list of items that match every filters</returns>
|
||||||
Task<ICollection<PeopleRole>> GetFromPeople(string slug,
|
Task<ICollection<PeopleRole>> GetFromPeople(string slug,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default);
|
Pagination limit = default);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -591,7 +591,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="limit">Pagination information (where to start and how many to get)</param>
|
/// <param name="limit">Pagination information (where to start and how many to get)</param>
|
||||||
/// <typeparam name="T">The type of metadata to retrieve</typeparam>
|
/// <typeparam name="T">The type of metadata to retrieve</typeparam>
|
||||||
/// <returns>A filtered list of external ids.</returns>
|
/// <returns>A filtered list of external ids.</returns>
|
||||||
Task<ICollection<MetadataID>> GetMetadataID<T>(Expression<Func<MetadataID, bool>> where = null,
|
Task<ICollection<MetadataID>> GetMetadataID<T>(Expression<Func<MetadataID, bool>> where = null,
|
||||||
Sort<MetadataID> sort = default,
|
Sort<MetadataID> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
where T : class, IMetadata;
|
where T : class, IMetadata;
|
||||||
@ -609,9 +609,9 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
) where T : class, IMetadata
|
) where T : class, IMetadata
|
||||||
=> GetMetadataID<T>(where, new Sort<MetadataID>(sort), limit);
|
=> GetMetadataID<T>(where, new Sort<MetadataID>(sort), limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A repository to handle users.
|
/// A repository to handle users.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IUserRepository : IRepository<User> {}
|
public interface IUserRepository : IRepository<User> { }
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,22 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// The name of this parameter.
|
/// The name of this parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; init; }
|
public string Name { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The description of this parameter.
|
/// The description of this parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Description { get; init; }
|
public string Description { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of this parameter.
|
/// The type of this parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Type Type { get; init; }
|
public Type Type { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this parameter required or can it be ignored?
|
/// Is this parameter required or can it be ignored?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsRequired { get; init; }
|
public bool IsRequired { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default value of this object.
|
/// The default value of this object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,7 +44,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// The value of the parameter.
|
/// The value of the parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object Value { get; init; }
|
private object Value { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new task parameter.
|
/// Create a new task parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -61,7 +61,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Type = typeof(T)
|
Type = typeof(T)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new required task parameter.
|
/// Create a new required task parameter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -79,7 +79,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
IsRequired = true
|
IsRequired = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a parameter's value to give to a task.
|
/// Create a parameter's value to give to a task.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -104,9 +104,9 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <returns>A new parameter's value for this current parameter</returns>
|
/// <returns>A new parameter's value for this current parameter</returns>
|
||||||
public TaskParameter CreateValue(object value)
|
public TaskParameter CreateValue(object value)
|
||||||
{
|
{
|
||||||
return this with {Value = value};
|
return this with { Value = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the value of this parameter. If the value is of the wrong type, it will be converted.
|
/// Get the value of this parameter. If the value is of the wrong type, it will be converted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -140,12 +140,12 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="name">The name of the task (case sensitive)</param>
|
/// <param name="name">The name of the task (case sensitive)</param>
|
||||||
public TaskParameter this[string name] => this.FirstOrDefault(x => x.Name == name);
|
public TaskParameter this[string name] => this.FirstOrDefault(x => x.Name == name);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new, empty, <see cref="TaskParameters"/>
|
/// Create a new, empty, <see cref="TaskParameters"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TaskParameters() {}
|
public TaskParameters() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a <see cref="TaskParameters"/> with an initial parameters content
|
/// Create a <see cref="TaskParameters"/> with an initial parameters content
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -155,7 +155,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
AddRange(parameters);
|
AddRange(parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A common interface that tasks should implement.
|
/// A common interface that tasks should implement.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -168,7 +168,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// All parameters that this task as. Every one of them will be given to the run function with a value.
|
/// All parameters that this task as. Every one of them will be given to the run function with a value.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public TaskParameters GetParameters();
|
public TaskParameters GetParameters();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start this task.
|
/// Start this task.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -191,4 +191,4 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
[NotNull] IProgress<float> progress,
|
[NotNull] IProgress<float> progress,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <exception cref="ItemNotFoundException">
|
/// <exception cref="ItemNotFoundException">
|
||||||
/// The task could not be found.
|
/// The task could not be found.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
void StartTask(string taskSlug,
|
void StartTask(string taskSlug,
|
||||||
[NotNull] IProgress<float> progress,
|
[NotNull] IProgress<float> progress,
|
||||||
Dictionary<string, object> arguments = null,
|
Dictionary<string, object> arguments = null,
|
||||||
CancellationToken? cancellationToken = null);
|
CancellationToken? cancellationToken = null);
|
||||||
@ -66,13 +66,13 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
Dictionary<string, object> arguments = null,
|
Dictionary<string, object> arguments = null,
|
||||||
CancellationToken? cancellationToken = null)
|
CancellationToken? cancellationToken = null)
|
||||||
where T : ITask;
|
where T : ITask;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all currently running tasks
|
/// Get all currently running tasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A list of currently running tasks.</returns>
|
/// <returns>A list of currently running tasks.</returns>
|
||||||
ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks();
|
ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all available tasks
|
/// Get all available tasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using Kyoo.Abstractions.Models;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Kyoo.Abstractions.Models;
|
||||||
|
|
||||||
namespace Kyoo.Abstractions.Controllers
|
namespace Kyoo.Abstractions.Controllers
|
||||||
{
|
{
|
||||||
|
@ -23,9 +23,9 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="action">The action to run</param>
|
/// <param name="action">The action to run</param>
|
||||||
/// <param name="priority">The priority of the new action</param>
|
/// <param name="priority">The priority of the new action</param>
|
||||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||||
public static StartupAction New(Action action, int priority)
|
public static StartupAction New(Action action, int priority)
|
||||||
=> new(action, priority);
|
=> new(action, priority);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="StartupAction"/>.
|
/// Create a new <see cref="StartupAction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,9 +33,9 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="priority">The priority of the new action</param>
|
/// <param name="priority">The priority of the new action</param>
|
||||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||||
public static StartupAction<T> New<T>(Action<T> action, int priority)
|
public static StartupAction<T> New<T>(Action<T> action, int priority)
|
||||||
=> new(action, priority);
|
=> new(action, priority);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="StartupAction"/>.
|
/// Create a new <see cref="StartupAction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,9 +44,9 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
/// <typeparam name="T">A dependency that this action will use.</typeparam>
|
||||||
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
||||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||||
public static StartupAction<T, T2> New<T, T2>(Action<T, T2> action, int priority)
|
public static StartupAction<T, T2> New<T, T2>(Action<T, T2> action, int priority)
|
||||||
=> new(action, priority);
|
=> new(action, priority);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="StartupAction"/>.
|
/// Create a new <see cref="StartupAction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -56,11 +56,11 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
/// <typeparam name="T2">A second dependency that this action will use.</typeparam>
|
||||||
/// <typeparam name="T3">A third dependency that this action will use.</typeparam>
|
/// <typeparam name="T3">A third dependency that this action will use.</typeparam>
|
||||||
/// <returns>A new <see cref="StartupAction"/></returns>
|
/// <returns>A new <see cref="StartupAction"/></returns>
|
||||||
public static StartupAction<T, T2, T3> New<T, T2, T3>(Action<T, T2, T3> action, int priority)
|
public static StartupAction<T, T2, T3> New<T, T2, T3>(Action<T, T2, T3> action, int priority)
|
||||||
=> new(action, priority);
|
=> new(action, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An action executed on kyoo's startup to initialize the asp-net container.
|
/// An action executed on kyoo's startup to initialize the asp-net container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -81,7 +81,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
/// <param name="provider">The service provider containing all services can be used.</param>
|
/// <param name="provider">The service provider containing all services can be used.</param>
|
||||||
void Run(IServiceProvider provider);
|
void Run(IServiceProvider provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="IStartupAction"/> with no dependencies.
|
/// A <see cref="IStartupAction"/> with no dependencies.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -94,7 +94,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int Priority { get; }
|
public int Priority { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="StartupAction"/>.
|
/// Create a new <see cref="StartupAction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -126,7 +126,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int Priority { get; }
|
public int Priority { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="StartupAction{T}"/>.
|
/// Create a new <see cref="StartupAction{T}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -144,7 +144,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
_action.Invoke(provider.GetRequiredService<T>());
|
_action.Invoke(provider.GetRequiredService<T>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="IStartupAction"/> with two dependencies.
|
/// A <see cref="IStartupAction"/> with two dependencies.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -180,7 +180,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="IStartupAction"/> with three dependencies.
|
/// A <see cref="IStartupAction"/> with three dependencies.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -196,7 +196,7 @@ namespace Kyoo.Abstractions.Controllers
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int Priority { get; }
|
public int Priority { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="StartupAction{T, T2, T3}"/>.
|
/// Create a new <see cref="StartupAction{T, T2, T3}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -20,13 +20,13 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
/// If multiples files with the same schemes exists, an exception will be thrown.
|
/// If multiples files with the same schemes exists, an exception will be thrown.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public string[] Scheme { get; }
|
public string[] Scheme { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <c>true</c> if the scheme should be removed from the path before calling
|
/// <c>true</c> if the scheme should be removed from the path before calling
|
||||||
/// methods of this <see cref="IFileSystem"/>, <c>false</c> otherwise.
|
/// methods of this <see cref="IFileSystem"/>, <c>false</c> otherwise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StripScheme { get; set; }
|
public bool StripScheme { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="FileSystemMetadataAttribute"/> using the specified schemes.
|
/// Create a new <see cref="FileSystemMetadataAttribute"/> using the specified schemes.
|
||||||
@ -36,7 +36,7 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
{
|
{
|
||||||
Scheme = schemes;
|
Scheme = schemes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="FileSystemMetadataAttribute"/> using a dictionary of metadata.
|
/// Create a new <see cref="FileSystemMetadataAttribute"/> using a dictionary of metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -23,7 +23,7 @@ namespace Kyoo.Abstractions.Models.Permissions
|
|||||||
Overall,
|
Overall,
|
||||||
Admin
|
Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specify permissions needed for the API.
|
/// Specify permissions needed for the API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -63,7 +63,7 @@ namespace Kyoo.Abstractions.Models.Permissions
|
|||||||
Kind = permission;
|
Kind = permission;
|
||||||
Group = group;
|
Group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ namespace Kyoo.Abstractions.Models.Permissions
|
|||||||
/// The needed permission kind.
|
/// The needed permission kind.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Kind Kind { get; }
|
public Kind Kind { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ask a permission to run an action.
|
/// Ask a permission to run an action.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -118,7 +118,7 @@ namespace Kyoo.Abstractions.Models.Permissions
|
|||||||
type = type[..^3];
|
type = type[..^3];
|
||||||
Type = type.ToLower();
|
Type = type.ToLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ask a permission to run an action.
|
/// Ask a permission to run an action.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -134,7 +134,7 @@ namespace Kyoo.Abstractions.Models.Permissions
|
|||||||
{
|
{
|
||||||
Kind = permission;
|
Kind = permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
@ -158,7 +158,7 @@ namespace Kyoo.Abstractions.Models.Permissions
|
|||||||
/// <param name="attribute">The permission attribute to validate</param>
|
/// <param name="attribute">The permission attribute to validate</param>
|
||||||
/// <returns>An authorization filter used to validate the permission</returns>
|
/// <returns>An authorization filter used to validate the permission</returns>
|
||||||
IFilterMetadata Create(PermissionAttribute attribute);
|
IFilterMetadata Create(PermissionAttribute attribute);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create an IAuthorizationFilter that will be used to validate permissions.
|
/// Create an IAuthorizationFilter that will be used to validate permissions.
|
||||||
/// This can registered with any lifetime.
|
/// This can registered with any lifetime.
|
||||||
|
@ -19,11 +19,11 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
/// The name of the field containing the related resource's ID.
|
/// The name of the field containing the related resource's ID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string RelationID { get; }
|
public string RelationID { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="LoadableRelationAttribute"/>.
|
/// Create a new <see cref="LoadableRelationAttribute"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LoadableRelationAttribute() {}
|
public LoadableRelationAttribute() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="LoadableRelationAttribute"/> with a baking relationID field.
|
/// Create a new <see cref="LoadableRelationAttribute"/> with a baking relationID field.
|
||||||
|
@ -6,13 +6,13 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
/// Remove an property from the serialization pipeline. It will simply be skipped.
|
/// Remove an property from the serialization pipeline. It will simply be skipped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||||
public class SerializeIgnoreAttribute : Attribute {}
|
public class SerializeIgnoreAttribute : Attribute { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove a property from the deserialization pipeline. The user can't input value for this property.
|
/// Remove a property from the deserialization pipeline. The user can't input value for this property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||||
public class DeserializeIgnoreAttribute : Attribute {}
|
public class DeserializeIgnoreAttribute : Attribute { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change the way the field is serialized. It allow one to use a string format like formatting instead of the default value.
|
/// Change the way the field is serialized. It allow one to use a string format like formatting instead of the default value.
|
||||||
@ -25,7 +25,7 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
/// The format string to use.
|
/// The format string to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Format { get; }
|
public string Format { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="SerializeAsAttribute"/> with the selected format.
|
/// Create a new <see cref="SerializeAsAttribute"/> with the selected format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -16,12 +16,12 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
/// The slug of the task, used to start it.
|
/// The slug of the task, used to start it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Slug { get; }
|
public string Slug { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the task that will be displayed to the user.
|
/// The name of the task that will be displayed to the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A quick description of what this task will do.
|
/// A quick description of what this task will do.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -31,18 +31,18 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
/// Should this task be automatically run at app startup?
|
/// Should this task be automatically run at app startup?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool RunOnStartup { get; set; }
|
public bool RunOnStartup { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The priority of this task. Only used if <see cref="RunOnStartup"/> is true.
|
/// The priority of this task. Only used if <see cref="RunOnStartup"/> is true.
|
||||||
/// It allow one to specify witch task will be started first as tasked are run on a Priority's descending order.
|
/// It allow one to specify witch task will be started first as tasked are run on a Priority's descending order.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Priority { get; set; }
|
public int Priority { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <c>true</c> if this task should not be displayed to the user, <c>false</c> otherwise.
|
/// <c>true</c> if this task should not be displayed to the user, <c>false</c> otherwise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsHidden { get; set; }
|
public bool IsHidden { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="TaskMetadataAttribute"/> with the given slug, name and description.
|
/// Create a new <see cref="TaskMetadataAttribute"/> with the given slug, name and description.
|
||||||
@ -56,7 +56,7 @@ namespace Kyoo.Abstractions.Models.Attributes
|
|||||||
Name = name;
|
Name = name;
|
||||||
Description = description;
|
Description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="TaskMetadataAttribute"/> using a dictionary of metadata.
|
/// Create a new <see cref="TaskMetadataAttribute"/> using a dictionary of metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,16 +9,16 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The start time of the chapter (in second from the start of the episode).
|
/// The start time of the chapter (in second from the start of the episode).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float StartTime { get; set; }
|
public float StartTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The end time of the chapter (in second from the start of the episode)&.
|
/// The end time of the chapter (in second from the start of the episode).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float EndTime { get; set; }
|
public float EndTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this chapter. This should be a human-readable name that could be presented to the user.
|
/// The name of this chapter. This should be a human-readable name that could be presented to the user.
|
||||||
/// There should be well-known chapters name for commonly used chapters.
|
/// There should be well-known chapters name for commonly used chapters.
|
||||||
/// For example, use "Opening" for the introduction-song and "Credits" for the end chapter with credits.
|
/// For example, use "Opening" for the introduction-song and "Credits" for the end chapter with credits.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
@ -35,4 +35,4 @@ namespace Kyoo.Abstractions.Models
|
|||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Type Type { get; }
|
public Type Type { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="ConfigurationReference"/> using a given path and type.
|
/// Create a new <see cref="ConfigurationReference"/> using a given path and type.
|
||||||
/// This method does not create sub configuration resources. Please see <see cref="CreateReference"/>
|
/// This method does not create sub configuration resources. Please see <see cref="CreateReference"/>
|
||||||
@ -75,7 +75,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the list of configuration reference a type has.
|
/// Return the list of configuration reference a type has.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,7 +15,7 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
|||||||
public DuplicatedItemException()
|
public DuplicatedItemException()
|
||||||
: base("Already exists in the database.")
|
: base("Already exists in the database.")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="DuplicatedItemException"/> with a custom message.
|
/// Create a new <see cref="DuplicatedItemException"/> with a custom message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -23,7 +23,7 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
|||||||
public DuplicatedItemException(string message)
|
public DuplicatedItemException(string message)
|
||||||
: base(message)
|
: base(message)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The serialization constructor
|
/// The serialization constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,24 +15,24 @@ namespace Kyoo.Abstractions.Models.Exceptions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public TaskFailedException()
|
public TaskFailedException()
|
||||||
: base("A task failed.")
|
: base("A task failed.")
|
||||||
{}
|
{ }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="TaskFailedException"/> with a custom message.
|
/// Create a new <see cref="TaskFailedException"/> with a custom message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The message to use.</param>
|
/// <param name="message">The message to use.</param>
|
||||||
public TaskFailedException(string message)
|
public TaskFailedException(string message)
|
||||||
: base(message)
|
: base(message)
|
||||||
{}
|
{ }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="TaskFailedException"/> wrapping another exception.
|
/// Create a new <see cref="TaskFailedException"/> wrapping another exception.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exception">The exception to wrap.</param>
|
/// <param name="exception">The exception to wrap.</param>
|
||||||
public TaskFailedException(Exception exception)
|
public TaskFailedException(Exception exception)
|
||||||
: base(exception)
|
: base(exception)
|
||||||
{}
|
{ }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The serialization constructor
|
/// The serialization constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,7 +14,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
Movie,
|
Movie,
|
||||||
Collection
|
Collection
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A type union between <see cref="Show"/> and <see cref="Collection"/>.
|
/// A type union between <see cref="Show"/> and <see cref="Collection"/>.
|
||||||
/// This is used to list content put inside a library.
|
/// This is used to list content put inside a library.
|
||||||
@ -23,30 +23,30 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The title of the show or collection.
|
/// The title of the show or collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The summary of the show or collection.
|
/// The summary of the show or collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this show airing, not aired yet or finished? This is only applicable for shows.
|
/// Is this show airing, not aired yet or finished? This is only applicable for shows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Status? Status { get; set; }
|
public Status? Status { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date this show or collection started airing. It can be null if this is unknown.
|
/// The date this show or collection started airing. It can be null if this is unknown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? StartAir { get; set; }
|
public DateTime? StartAir { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date this show or collection finished airing.
|
/// The date this show or collection finished airing.
|
||||||
/// It must be after the <see cref="StartAir"/> but can be the same (example: for movies).
|
/// It must be after the <see cref="StartAir"/> but can be the same (example: for movies).
|
||||||
@ -64,17 +64,17 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeAs("{HOST}/api/{Type:l}/{Slug}/poster")]
|
[SerializeAs("{HOST}/api/{Type:l}/{Slug}/poster")]
|
||||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of this item (ether a collection, a show or a movie).
|
/// The type of this item (ether a collection, a show or a movie).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemType Type { get; set; }
|
public ItemType Type { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new, empty <see cref="LibraryItem"/>.
|
/// Create a new, empty <see cref="LibraryItem"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LibraryItem() {}
|
public LibraryItem() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a <see cref="LibraryItem"/> from a show.
|
/// Create a <see cref="LibraryItem"/> from a show.
|
||||||
@ -92,7 +92,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
Images = show.Images;
|
Images = show.Images;
|
||||||
Type = show.IsMovie ? ItemType.Movie : ItemType.Show;
|
Type = show.IsMovie ? ItemType.Movie : ItemType.Show;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a <see cref="LibraryItem"/> from a collection
|
/// Create a <see cref="LibraryItem"/> from a collection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -125,7 +125,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
Images = x.Images,
|
Images = x.Images,
|
||||||
Type = x.IsMovie ? ItemType.Movie : ItemType.Show
|
Type = x.IsMovie ? ItemType.Movie : ItemType.Show
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An expression to create a <see cref="LibraryItem"/> representing a collection.
|
/// An expression to create a <see cref="LibraryItem"/> representing a collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,12 +15,12 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The link of the current page.
|
/// The link of the current page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Uri This { get; }
|
public Uri This { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The link of the first page.
|
/// The link of the first page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Uri First { get; }
|
public Uri First { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The link of the next page.
|
/// The link of the next page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -30,13 +30,13 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The number of items in the current page.
|
/// The number of items in the current page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Count => Items.Count;
|
public int Count => Items.Count;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of items in the page.
|
/// The list of items in the page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<T> Items { get; }
|
public ICollection<T> Items { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="Page{T}"/>.
|
/// Create a new <see cref="Page{T}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -72,7 +72,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
query["afterID"] = items.Last().ID.ToString();
|
query["afterID"] = items.Last().ID.ToString();
|
||||||
Next = new Uri(url + query.ToQueryString());
|
Next = new Uri(url + query.ToQueryString());
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Remove("afterID");
|
query.Remove("afterID");
|
||||||
First = new Uri(url + query.ToQueryString());
|
First = new Uri(url + query.ToQueryString());
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug => ForPeople ? Show.Slug : People.Slug;
|
public string Slug => ForPeople ? Show.Slug : People.Slug;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should this role be used as a Show substitute (the value is <c>true</c>) or
|
/// Should this role be used as a Show substitute (the value is <c>true</c>) or
|
||||||
/// as a People substitute (the value is <c>false</c>).
|
/// as a People substitute (the value is <c>false</c>).
|
||||||
@ -30,7 +30,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The people that played this role.
|
/// The people that played this role.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public People People { get; set; }
|
public People People { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the Show where the People playing in.
|
/// The ID of the Show where the People playing in.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -39,13 +39,13 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The show where the People played in.
|
/// The show where the People played in.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Show Show { get; set; }
|
public Show Show { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of work the person has done for the show.
|
/// The type of work the person has done for the show.
|
||||||
/// That can be something like "Actor", "Writer", "Music", "Voice Actor"...
|
/// That can be something like "Actor", "Writer", "Music", "Voice Actor"...
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The role the People played.
|
/// The role the People played.
|
||||||
/// This is mostly used to inform witch character was played for actor and voice actors.
|
/// This is mostly used to inform witch character was played for actor and voice actors.
|
||||||
|
@ -12,10 +12,10 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this collection.
|
/// The name of this collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -23,7 +23,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Dictionary<int, string> Images { get; set; }
|
public Dictionary<int, string> Images { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of this poster.
|
/// The path of this poster.
|
||||||
/// By default, the http path for this poster is returned from the public API.
|
/// By default, the http path for this poster is returned from the public API.
|
||||||
@ -37,17 +37,17 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The description of this collection.
|
/// The description of this collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of shows contained in this collection.
|
/// The list of shows contained in this collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] public ICollection<Show> Shows { get; set; }
|
[LoadableRelation] public ICollection<Show> Shows { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of libraries that contains this collection.
|
/// The list of libraries that contains this collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] public ICollection<Library> Libraries { get; set; }
|
[LoadableRelation] public ICollection<Library> Libraries { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@ -22,15 +22,15 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
if (ShowSlug != null || Show != null)
|
if (ShowSlug != null || Show != null)
|
||||||
return GetSlug(ShowSlug ?? Show.Slug, SeasonNumber, EpisodeNumber, AbsoluteNumber);
|
return GetSlug(ShowSlug ?? Show.Slug, SeasonNumber, EpisodeNumber, AbsoluteNumber);
|
||||||
return ShowID != 0
|
return ShowID != 0
|
||||||
? GetSlug(ShowID.ToString(), SeasonNumber, EpisodeNumber, AbsoluteNumber)
|
? GetSlug(ShowID.ToString(), SeasonNumber, EpisodeNumber, AbsoluteNumber)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
[UsedImplicitly] [NotNull] private set
|
[UsedImplicitly] [NotNull] private set
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
throw new ArgumentNullException(nameof(value));
|
throw new ArgumentNullException(nameof(value));
|
||||||
|
|
||||||
Match match = Regex.Match(value, @"(?<show>.+)-s(?<season>\d+)e(?<episode>\d+)");
|
Match match = Regex.Match(value, @"(?<show>.+)-s(?<season>\d+)e(?<episode>\d+)");
|
||||||
|
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
@ -59,7 +59,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The slug of the Show that contain this episode. If this is not set, this episode is ill-formed.
|
/// The slug of the Show that contain this episode. If this is not set, this episode is ill-formed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string ShowSlug { private get; set; }
|
[SerializeIgnore] public string ShowSlug { private get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the Show containing this episode.
|
/// The ID of the Show containing this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -68,7 +68,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The show that contains this episode. This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
/// The show that contains this episode. This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation(nameof(ShowID))] public Show Show { get; set; }
|
[LoadableRelation(nameof(ShowID))] public Show Show { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the Season containing this episode.
|
/// The ID of the Season containing this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -87,22 +87,22 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The season in witch this episode is in.
|
/// The season in witch this episode is in.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? SeasonNumber { get; set; }
|
public int? SeasonNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of this episode in it's season.
|
/// The number of this episode in it's season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? EpisodeNumber { get; set; }
|
public int? EpisodeNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season.
|
/// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? AbsoluteNumber { get; set; }
|
public int? AbsoluteNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed.
|
/// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string Path { get; set; }
|
[SerializeIgnore] public string Path { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Dictionary<int, string> Images { get; set; }
|
public Dictionary<int, string> Images { get; set; }
|
||||||
|
|
||||||
@ -114,17 +114,17 @@ namespace Kyoo.Abstractions.Models
|
|||||||
[SerializeAs("{HOST}/api/episodes/{Slug}/thumbnail")]
|
[SerializeAs("{HOST}/api/episodes/{Slug}/thumbnail")]
|
||||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||||
public string Thumb => Images?.GetValueOrDefault(Models.Images.Thumbnail);
|
public string Thumb => Images?.GetValueOrDefault(Models.Images.Thumbnail);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The title of this episode.
|
/// The title of this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The overview of this episode.
|
/// The overview of this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The release date of this episode. It can be null if unknown.
|
/// The release date of this episode. It can be null if unknown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -137,7 +137,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The list of tracks this episode has. This lists video, audio and subtitles available.
|
/// The list of tracks this episode has. This lists video, audio and subtitles available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditableRelation] [LoadableRelation] public ICollection<Track> Tracks { get; set; }
|
[EditableRelation] [LoadableRelation] public ICollection<Track> Tracks { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the slug of an episode.
|
/// Get the slug of an episode.
|
||||||
@ -157,8 +157,8 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The slug corresponding to the given arguments</returns>
|
/// <returns>The slug corresponding to the given arguments</returns>
|
||||||
/// <exception cref="ArgumentNullException">The given show slug was null.</exception>
|
/// <exception cref="ArgumentNullException">The given show slug was null.</exception>
|
||||||
public static string GetSlug([NotNull] string showSlug,
|
public static string GetSlug([NotNull] string showSlug,
|
||||||
int? seasonNumber,
|
int? seasonNumber,
|
||||||
int? episodeNumber,
|
int? episodeNumber,
|
||||||
int? absoluteNumber = null)
|
int? absoluteNumber = null)
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,15 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this genre.
|
/// The name of this genre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of shows that have this genre.
|
/// The list of shows that have this genre.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -28,8 +28,8 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new, empty <see cref="Genre"/>.
|
/// Create a new, empty <see cref="Genre"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Genre() {}
|
public Genre() { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="Genre"/> and specify it's <see cref="Name"/>.
|
/// Create a new <see cref="Genre"/> and specify it's <see cref="Name"/>.
|
||||||
/// The <see cref="Slug"/> is automatically calculated from it's name.
|
/// The <see cref="Slug"/> is automatically calculated from it's name.
|
||||||
|
@ -14,7 +14,8 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The link to metadata providers that this show has. See <see cref="MetadataID"/> for more information.
|
/// The link to metadata providers that this show has. See <see cref="MetadataID"/> for more information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditableRelation] [LoadableRelation]
|
[EditableRelation]
|
||||||
|
[LoadableRelation]
|
||||||
public ICollection<MetadataID> ExternalIDs { get; set; }
|
public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// this field is automatically assigned by the <see cref="IRepository{T}"/>.
|
/// this field is automatically assigned by the <see cref="IRepository{T}"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A human-readable identifier that can be used instead of an ID.
|
/// A human-readable identifier that can be used instead of an ID.
|
||||||
/// A slug must be unique for a type of resource but it can be changed.
|
/// A slug must be unique for a type of resource but it can be changed.
|
||||||
@ -24,6 +24,6 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// There is no setter for a slug since it can be computed from other fields.
|
/// There is no setter for a slug since it can be computed from other fields.
|
||||||
/// For example, a season slug is {ShowSlug}-s{SeasonNumber}.
|
/// For example, a season slug is {ShowSlug}-s{SeasonNumber}.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public string Slug { get; }
|
public string Slug { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,7 +16,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// An arbitrary index should not be used, instead use indexes from <see cref="Models.Images"/>
|
/// An arbitrary index should not be used, instead use indexes from <see cref="Models.Images"/>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public Dictionary<int, string> Images { get; set; }
|
public Dictionary<int, string> Images { get; set; }
|
||||||
|
|
||||||
// TODO remove Posters properties add them via the json serializer for every IThumbnails
|
// TODO remove Posters properties add them via the json serializer for every IThumbnails
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,15 +10,15 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this library.
|
/// The name of this library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of paths that this library is responsible for. This is mainly used by the Scan task.
|
/// The list of paths that this library is responsible for. This is mainly used by the Scan task.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,7 +33,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The list of shows in this library.
|
/// The list of shows in this library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] public ICollection<Show> Shows { get; set; }
|
[LoadableRelation] public ICollection<Show> Shows { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of collections in this library.
|
/// The list of collections in this library.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -11,15 +11,15 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this person.
|
/// The name of this person.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Dictionary<int, string> Images { get; set; }
|
public Dictionary<int, string> Images { get; set; }
|
||||||
|
|
||||||
@ -31,10 +31,10 @@ namespace Kyoo.Abstractions.Models
|
|||||||
[SerializeAs("{HOST}/api/people/{Slug}/poster")]
|
[SerializeAs("{HOST}/api/people/{Slug}/poster")]
|
||||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of roles this person has played in. See <see cref="PeopleRole"/> for more information.
|
/// The list of roles this person has played in. See <see cref="PeopleRole"/> for more information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,15 +14,15 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this provider.
|
/// The name of this provider.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Dictionary<int, string> Images { get; set; }
|
public Dictionary<int, string> Images { get; set; }
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@ -13,7 +13,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
public class Season : IResource, IMetadata, IThumbnails
|
public class Season : IResource, IMetadata, IThumbnails
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Computed] public string Slug
|
[Computed] public string Slug
|
||||||
@ -27,7 +27,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
[UsedImplicitly] [NotNull] private set
|
[UsedImplicitly] [NotNull] private set
|
||||||
{
|
{
|
||||||
Match match = Regex.Match(value ?? "", @"(?<show>.+)-s(?<season>\d+)");
|
Match match = Regex.Match(value ?? "", @"(?<show>.+)-s(?<season>\d+)");
|
||||||
|
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
throw new ArgumentException("Invalid season slug. Format: {showSlug}-s{seasonNumber}");
|
throw new ArgumentException("Invalid season slug. Format: {showSlug}-s{seasonNumber}");
|
||||||
ShowSlug = match.Groups["show"].Value;
|
ShowSlug = match.Groups["show"].Value;
|
||||||
@ -39,7 +39,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The slug of the Show that contain this episode. If this is not set, this season is ill-formed.
|
/// The slug of the Show that contain this episode. If this is not set, this season is ill-formed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string ShowSlug { private get; set; }
|
[SerializeIgnore] public string ShowSlug { private get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the Show containing this season.
|
/// The ID of the Show containing this season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -59,17 +59,17 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The title of this season.
|
/// The title of this season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A quick overview of this season.
|
/// A quick overview of this season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The starting air date of this season.
|
/// The starting air date of this season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? StartDate { get; set; }
|
public DateTime? StartDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ending date of this season.
|
/// The ending date of this season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -86,7 +86,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
[SerializeAs("{HOST}/api/seasons/{Slug}/thumb")]
|
[SerializeAs("{HOST}/api/seasons/{Slug}/thumb")]
|
||||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||||
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
public string Poster => Images?.GetValueOrDefault(Models.Images.Poster);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||||
|
|
||||||
|
@ -12,31 +12,31 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The title of this show.
|
/// The title of this show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of alternative titles of this show.
|
/// The list of alternative titles of this show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditableRelation] public string[] Aliases { get; set; }
|
[EditableRelation] public string[] Aliases { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the root directory of this show.
|
/// The path of the root directory of this show.
|
||||||
/// This can be any kind of path supported by <see cref="IFileSystem"/>
|
/// This can be any kind of path supported by <see cref="IFileSystem"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string Path { get; set; }
|
[SerializeIgnore] public string Path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The summary of this show.
|
/// The summary of this show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this show airing, not aired yet or finished?
|
/// Is this show airing, not aired yet or finished?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -48,12 +48,12 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// TODO for now, this is set to a youtube url. It should be cached and converted to a local file.
|
/// TODO for now, this is set to a youtube url. It should be cached and converted to a local file.
|
||||||
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
[Obsolete("Use Images instead of this, this is only kept for the API response.")]
|
||||||
public string TrailerUrl => Images?.GetValueOrDefault(Models.Images.Trailer);
|
public string TrailerUrl => Images?.GetValueOrDefault(Models.Images.Trailer);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date this show started airing. It can be null if this is unknown.
|
/// The date this show started airing. It can be null if this is unknown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? StartAir { get; set; }
|
public DateTime? StartAir { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date this show finished airing.
|
/// The date this show finished airing.
|
||||||
/// It must be after the <see cref="StartAir"/> but can be the same (example: for movies).
|
/// It must be after the <see cref="StartAir"/> but can be the same (example: for movies).
|
||||||
@ -108,39 +108,39 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
/// This must be explicitly loaded via a call to <see cref="ILibraryManager.Load"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation(nameof(StudioID))] [EditableRelation] public Studio Studio { get; set; }
|
[LoadableRelation(nameof(StudioID))] [EditableRelation] public Studio Studio { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of genres (themes) this show has.
|
/// The list of genres (themes) this show has.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] [EditableRelation] public ICollection<Genre> Genres { get; set; }
|
[LoadableRelation] [EditableRelation] public ICollection<Genre> Genres { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of people that made this show.
|
/// The list of people that made this show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] [EditableRelation] public ICollection<PeopleRole> People { get; set; }
|
[LoadableRelation] [EditableRelation] public ICollection<PeopleRole> People { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The different seasons in this show. If this is a movie, this list is always null or empty.
|
/// The different seasons in this show. If this is a movie, this list is always null or empty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] public ICollection<Season> Seasons { get; set; }
|
[LoadableRelation] public ICollection<Season> Seasons { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of episodes in this show.
|
/// The list of episodes in this show.
|
||||||
/// If this is a movie, there will be a unique episode (with the seasonNumber and episodeNumber set to null).
|
/// If this is a movie, there will be a unique episode (with the seasonNumber and episodeNumber set to null).
|
||||||
/// Having an episode is necessary to store metadata and tracks.
|
/// Having an episode is necessary to store metadata and tracks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] public ICollection<Episode> Episodes { get; set; }
|
[LoadableRelation] public ICollection<Episode> Episodes { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of libraries that contains this show.
|
/// The list of libraries that contains this show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] public ICollection<Library> Libraries { get; set; }
|
[LoadableRelation] public ICollection<Library> Libraries { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of collections that contains this show.
|
/// The list of collections that contains this show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[LoadableRelation] public ICollection<Collection> Collections { get; set; }
|
[LoadableRelation] public ICollection<Collection> Collections { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void OnMerge(object merged)
|
public void OnMerge(object merged)
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,15 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this studio.
|
/// The name of this studio.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of shows that are made by this studio.
|
/// The list of shows that are made by this studio.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -27,7 +27,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new, empty, <see cref="Studio"/>.
|
/// Create a new, empty, <see cref="Studio"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@ -27,7 +27,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[Computed] public string Slug
|
[Computed] public string Slug
|
||||||
{
|
{
|
||||||
@ -42,12 +42,14 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
throw new ArgumentNullException(nameof(value));
|
throw new ArgumentNullException(nameof(value));
|
||||||
Match match = Regex.Match(value,
|
Match match = Regex.Match(value,
|
||||||
@"(?<ep>[^\.]+)\.(?<lang>\w{0,3})(-(?<index>\d+))?(\.(?<forced>forced))?\.(?<type>\w+)(\.\w*)?");
|
@"(?<ep>[^\.]+)\.(?<lang>\w{0,3})(-(?<index>\d+))?(\.(?<forced>forced))?\.(?<type>\w+)(\.\w*)?");
|
||||||
|
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
|
{
|
||||||
throw new ArgumentException("Invalid track slug. " +
|
throw new ArgumentException("Invalid track slug. " +
|
||||||
"Format: {episodeSlug}.{language}[-{index}][.forced].{type}[.{extension}]");
|
"Format: {episodeSlug}.{language}[-{index}][.forced].{type}[.{extension}]");
|
||||||
|
}
|
||||||
|
|
||||||
EpisodeSlug = match.Groups["ep"].Value;
|
EpisodeSlug = match.Groups["ep"].Value;
|
||||||
Language = match.Groups["lang"].Value;
|
Language = match.Groups["lang"].Value;
|
||||||
@ -58,53 +60,53 @@ namespace Kyoo.Abstractions.Models
|
|||||||
Type = Enum.Parse<StreamType>(match.Groups["type"].Value, true);
|
Type = Enum.Parse<StreamType>(match.Groups["type"].Value, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The slug of the episode that contain this track. If this is not set, this track is ill-formed.
|
/// The slug of the episode that contain this track. If this is not set, this track is ill-formed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string EpisodeSlug { private get; set; }
|
[SerializeIgnore] public string EpisodeSlug { private get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The title of the stream.
|
/// The title of the stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The language of this stream (as a ISO-639-2 language code)
|
/// The language of this stream (as a ISO-639-2 language code)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Language { get; set; }
|
public string Language { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The codec of this stream.
|
/// The codec of this stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Codec { get; set; }
|
public string Codec { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this stream the default one of it's type?
|
/// Is this stream the default one of it's type?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDefault { get; set; }
|
public bool IsDefault { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this stream tagged as forced?
|
/// Is this stream tagged as forced?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsForced { get; set; }
|
public bool IsForced { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this track extern to the episode's file?
|
/// Is this track extern to the episode's file?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsExternal { get; set; }
|
public bool IsExternal { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of this track.
|
/// The path of this track.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string Path { get; set; }
|
[SerializeIgnore] public string Path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of this stream.
|
/// The type of this stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public StreamType Type { get; set; }
|
[SerializeIgnore] public StreamType Type { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the episode that uses this track.
|
/// The ID of the episode that uses this track.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -137,7 +139,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
name += " Forced";
|
name += " Forced";
|
||||||
if (IsExternal)
|
if (IsExternal)
|
||||||
name += " (External)";
|
name += " (External)";
|
||||||
if (Title is {Length: > 1})
|
if (Title is { Length: > 1 })
|
||||||
name += " - " + Title;
|
name += " - " + Title;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -164,8 +166,8 @@ namespace Kyoo.Abstractions.Models
|
|||||||
public static string BuildSlug(string baseSlug,
|
public static string BuildSlug(string baseSlug,
|
||||||
StreamType type)
|
StreamType type)
|
||||||
{
|
{
|
||||||
return baseSlug.EndsWith($".{type}", StringComparison.InvariantCultureIgnoreCase)
|
return baseSlug.EndsWith($".{type}", StringComparison.InvariantCultureIgnoreCase)
|
||||||
? baseSlug
|
? baseSlug
|
||||||
: $"{baseSlug}.{type.ToString().ToLowerInvariant()}";
|
: $"{baseSlug}.{type.ToString().ToLowerInvariant()}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,30 +9,30 @@ namespace Kyoo.Abstractions.Models
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A username displayed to the user.
|
/// A username displayed to the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user email address.
|
/// The user email address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user password (hashed, it can't be read like that). The hashing format is implementation defined.
|
/// The user password (hashed, it can't be read like that). The hashing format is implementation defined.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of permissions of the user. The format of this is implementation dependent.
|
/// The list of permissions of the user. The format of this is implementation dependent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] Permissions { get; set; }
|
public string[] Permissions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Arbitrary extra data that can be used by specific authentication implementations.
|
/// Arbitrary extra data that can be used by specific authentication implementations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -45,13 +45,13 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The list of shows the user has finished.
|
/// The list of shows the user has finished.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Show> Watched { get; set; }
|
public ICollection<Show> Watched { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of episodes the user is watching (stopped in progress or the next episode of the show)
|
/// The list of episodes the user is watching (stopped in progress or the next episode of the show)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<WatchedEpisode> CurrentlyWatching { get; set; }
|
public ICollection<WatchedEpisode> CurrentlyWatching { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Metadata of episode currently watching by an user
|
/// Metadata of episode currently watching by an user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -61,17 +61,17 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The ID of the user that started watching this episode.
|
/// The ID of the user that started watching this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int UserID { get; set; }
|
public int UserID { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the episode started.
|
/// The ID of the episode started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int EpisodeID { get; set; }
|
public int EpisodeID { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="Episode"/> started.
|
/// The <see cref="Episode"/> started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Episode Episode { get; set; }
|
public Episode Episode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Where the player has stopped watching the episode (between 0 and 100).
|
/// Where the player has stopped watching the episode (between 0 and 100).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -11,32 +11,32 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The query of the search request.
|
/// The query of the search request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Query { get; init; }
|
public string Query { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The collections that matched the search.
|
/// The collections that matched the search.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Collection> Collections { get; init; }
|
public ICollection<Collection> Collections { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The shows that matched the search.
|
/// The shows that matched the search.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Show> Shows { get; init; }
|
public ICollection<Show> Shows { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The episodes that matched the search.
|
/// The episodes that matched the search.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Episode> Episodes { get; init; }
|
public ICollection<Episode> Episodes { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The people that matched the search.
|
/// The people that matched the search.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<People> People { get; init; }
|
public ICollection<People> People { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The genres that matched the search.
|
/// The genres that matched the search.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Genre> Genres { get; init; }
|
public ICollection<Genre> Genres { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The studios that matched the search.
|
/// The studios that matched the search.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -20,7 +20,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The ID of the episode associated with this item.
|
/// The ID of the episode associated with this item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int EpisodeID { get; set; }
|
public int EpisodeID { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The slug of this episode.
|
/// The slug of this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -30,54 +30,54 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// The title of the show containing this episode.
|
/// The title of the show containing this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ShowTitle { get; set; }
|
public string ShowTitle { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The slug of the show containing this episode
|
/// The slug of the show containing this episode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ShowSlug { get; set; }
|
public string ShowSlug { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The season in witch this episode is in.
|
/// The season in witch this episode is in.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? SeasonNumber { get; set; }
|
public int? SeasonNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of this episode is it's season.
|
/// The number of this episode is it's season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? EpisodeNumber { get; set; }
|
public int? EpisodeNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season.
|
/// The absolute number of this episode. It's an episode number that is not reset to 1 after a new season.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? AbsoluteNumber { get; set; }
|
public int? AbsoluteNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The title of this episode.
|
/// The title of this episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The release date of this episode. It can be null if unknown.
|
/// The release date of this episode. It can be null if unknown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? ReleaseDate { get; set; }
|
public DateTime? ReleaseDate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed.
|
/// The path of the video file for this episode. Any format supported by a <see cref="IFileSystem"/> is allowed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string Path { get; set; }
|
[SerializeIgnore] public string Path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The episode that come before this one if you follow usual watch orders.
|
/// The episode that come before this one if you follow usual watch orders.
|
||||||
/// If this is the first episode or this is a movie, it will be null.
|
/// If this is the first episode or this is a movie, it will be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Episode PreviousEpisode { get; set; }
|
public Episode PreviousEpisode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The episode that come after this one if you follow usual watch orders.
|
/// The episode that come after this one if you follow usual watch orders.
|
||||||
/// If this is the last aired episode or this is a movie, it will be null.
|
/// If this is the last aired episode or this is a movie, it will be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Episode NextEpisode { get; set; }
|
public Episode NextEpisode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <c>true</c> if this is a movie, <c>false</c> otherwise.
|
/// <c>true</c> if this is a movie, <c>false</c> otherwise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -89,14 +89,14 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// This can be disabled using the internal query flag.
|
/// This can be disabled using the internal query flag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeAs("{HOST}/api/show/{ShowSlug}/poster")] public string Poster { get; set; }
|
[SerializeAs("{HOST}/api/show/{ShowSlug}/poster")] public string Poster { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of this item's logo.
|
/// The path of this item's logo.
|
||||||
/// By default, the http path for the logo is returned from the public API.
|
/// By default, the http path for the logo is returned from the public API.
|
||||||
/// This can be disabled using the internal query flag.
|
/// This can be disabled using the internal query flag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeAs("{HOST}/api/show/{ShowSlug}/logo")] public string Logo { get; set; }
|
[SerializeAs("{HOST}/api/show/{ShowSlug}/logo")] public string Logo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of this item's backdrop.
|
/// The path of this item's backdrop.
|
||||||
/// By default, the http path for the backdrop is returned from the public API.
|
/// By default, the http path for the backdrop is returned from the public API.
|
||||||
@ -109,27 +109,27 @@ namespace Kyoo.Abstractions.Models
|
|||||||
/// Common containers are mp4, mkv, avi and so on.
|
/// Common containers are mp4, mkv, avi and so on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The video track. See <see cref="Track"/> for more information.
|
/// The video track. See <see cref="Track"/> for more information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Track Video { get; set; }
|
public Track Video { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of audio tracks. See <see cref="Track"/> for more information.
|
/// The list of audio tracks. See <see cref="Track"/> for more information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Track> Audios { get; set; }
|
public ICollection<Track> Audios { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of subtitles tracks. See <see cref="Track"/> for more information.
|
/// The list of subtitles tracks. See <see cref="Track"/> for more information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Track> Subtitles { get; set; }
|
public ICollection<Track> Subtitles { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of chapters. See <see cref="Chapter"/> for more information.
|
/// The list of chapters. See <see cref="Chapter"/> for more information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<Chapter> Chapters { get; set; }
|
public ICollection<Chapter> Chapters { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a <see cref="WatchItem"/> from an <see cref="Episode"/>.
|
/// Create a <see cref="WatchItem"/> from an <see cref="Episode"/>.
|
||||||
@ -146,15 +146,15 @@ namespace Kyoo.Abstractions.Models
|
|||||||
|
|
||||||
await library.Load(ep, x => x.Show);
|
await library.Load(ep, x => x.Show);
|
||||||
await library.Load(ep, x => x.Tracks);
|
await library.Load(ep, x => x.Tracks);
|
||||||
|
|
||||||
if (!ep.Show.IsMovie && ep.SeasonNumber != null && ep.EpisodeNumber != null)
|
if (!ep.Show.IsMovie && ep.SeasonNumber != null && ep.EpisodeNumber != null)
|
||||||
{
|
{
|
||||||
if (ep.EpisodeNumber > 1)
|
if (ep.EpisodeNumber > 1)
|
||||||
previous = await library.GetOrDefault(ep.ShowID, ep.SeasonNumber.Value, ep.EpisodeNumber.Value - 1);
|
previous = await library.GetOrDefault(ep.ShowID, ep.SeasonNumber.Value, ep.EpisodeNumber.Value - 1);
|
||||||
else if (ep.SeasonNumber > 1)
|
else if (ep.SeasonNumber > 1)
|
||||||
{
|
{
|
||||||
previous = (await library.GetAll(x => x.ShowID == ep.ShowID
|
previous = (await library.GetAll(x => x.ShowID == ep.ShowID
|
||||||
&& x.SeasonNumber == ep.SeasonNumber.Value - 1,
|
&& x.SeasonNumber == ep.SeasonNumber.Value - 1,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
sort: new Sort<Episode>(x => x.EpisodeNumber, true))
|
sort: new Sort<Episode>(x => x.EpisodeNumber, true))
|
||||||
).FirstOrDefault();
|
).FirstOrDefault();
|
||||||
@ -167,12 +167,12 @@ namespace Kyoo.Abstractions.Models
|
|||||||
}
|
}
|
||||||
else if (!ep.Show.IsMovie && ep.AbsoluteNumber != null)
|
else if (!ep.Show.IsMovie && ep.AbsoluteNumber != null)
|
||||||
{
|
{
|
||||||
previous = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
previous = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
||||||
&& x.AbsoluteNumber == ep.EpisodeNumber + 1);
|
&& x.AbsoluteNumber == ep.EpisodeNumber + 1);
|
||||||
next = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
next = await library.GetOrDefault<Episode>(x => x.ShowID == ep.ShowID
|
||||||
&& x.AbsoluteNumber == ep.AbsoluteNumber + 1);
|
&& x.AbsoluteNumber == ep.AbsoluteNumber + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WatchItem
|
return new WatchItem
|
||||||
{
|
{
|
||||||
EpisodeID = ep.ID,
|
EpisodeID = ep.ID,
|
||||||
@ -188,7 +188,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
Container = PathIO.GetExtension(ep.Path)![1..],
|
Container = PathIO.GetExtension(ep.Path)![1..],
|
||||||
Video = ep.Tracks.FirstOrDefault(x => x.Type == StreamType.Video),
|
Video = ep.Tracks.FirstOrDefault(x => x.Type == StreamType.Video),
|
||||||
Audios = ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(),
|
Audios = ep.Tracks.Where(x => x.Type == StreamType.Audio).ToArray(),
|
||||||
Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(),
|
Subtitles = ep.Tracks.Where(x => x.Type == StreamType.Subtitle).ToArray(),
|
||||||
PreviousEpisode = previous,
|
PreviousEpisode = previous,
|
||||||
NextEpisode = next,
|
NextEpisode = next,
|
||||||
Chapters = await GetChapters(ep.Path)
|
Chapters = await GetChapters(ep.Path)
|
||||||
@ -200,7 +200,7 @@ namespace Kyoo.Abstractions.Models
|
|||||||
private static async Task<ICollection<Chapter>> GetChapters(string episodePath)
|
private static async Task<ICollection<Chapter>> GetChapters(string episodePath)
|
||||||
{
|
{
|
||||||
string path = PathIO.Combine(
|
string path = PathIO.Combine(
|
||||||
PathIO.GetDirectoryName(episodePath)!,
|
PathIO.GetDirectoryName(episodePath)!,
|
||||||
"Chapters",
|
"Chapters",
|
||||||
PathIO.GetFileNameWithoutExtension(episodePath) + ".txt"
|
PathIO.GetFileNameWithoutExtension(episodePath) + ".txt"
|
||||||
);
|
);
|
||||||
|
@ -30,7 +30,7 @@ namespace Kyoo.Abstractions
|
|||||||
/// <param name="builder">The container</param>
|
/// <param name="builder">The container</param>
|
||||||
/// <typeparam name="T">The type of the task</typeparam>
|
/// <typeparam name="T">The type of the task</typeparam>
|
||||||
/// <returns>The registration builder of this new provider. That can be used to edit the registration.</returns>
|
/// <returns>The registration builder of this new provider. That can be used to edit the registration.</returns>
|
||||||
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
||||||
RegisterProvider<T>(this ContainerBuilder builder)
|
RegisterProvider<T>(this ContainerBuilder builder)
|
||||||
where T : class, IMetadataProvider
|
where T : class, IMetadataProvider
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ namespace Kyoo.Abstractions
|
|||||||
/// If your repository implements a special interface, please use <see cref="RegisterRepository{T,T2}"/>
|
/// If your repository implements a special interface, please use <see cref="RegisterRepository{T,T2}"/>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <returns>The initial container.</returns>
|
/// <returns>The initial container.</returns>
|
||||||
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
public static IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle>
|
||||||
RegisterRepository<T>(this ContainerBuilder builder)
|
RegisterRepository<T>(this ContainerBuilder builder)
|
||||||
where T : IBaseRepository
|
where T : IBaseRepository
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@ namespace Kyoo.Utils
|
|||||||
}
|
}
|
||||||
return Generator(self, mapper);
|
return Generator(self, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A map where the mapping function is asynchronous.
|
/// A map where the mapping function is asynchronous.
|
||||||
/// Note: <see cref="SelectAsync{T,T2}"/> might interest you.
|
/// Note: <see cref="SelectAsync{T,T2}"/> might interest you.
|
||||||
@ -54,7 +54,7 @@ namespace Kyoo.Utils
|
|||||||
/// <returns>The list mapped as an AsyncEnumerable</returns>
|
/// <returns>The list mapped as an AsyncEnumerable</returns>
|
||||||
/// <exception cref="ArgumentNullException">The list or the mapper can't be null</exception>
|
/// <exception cref="ArgumentNullException">The list or the mapper can't be null</exception>
|
||||||
[LinqTunnel]
|
[LinqTunnel]
|
||||||
public static IAsyncEnumerable<T2> MapAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
public static IAsyncEnumerable<T2> MapAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
||||||
[NotNull] Func<T, int, Task<T2>> mapper)
|
[NotNull] Func<T, int, Task<T2>> mapper)
|
||||||
{
|
{
|
||||||
if (self == null)
|
if (self == null)
|
||||||
@ -76,7 +76,7 @@ namespace Kyoo.Utils
|
|||||||
|
|
||||||
return Generator(self, mapper);
|
return Generator(self, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An asynchronous version of Select.
|
/// An asynchronous version of Select.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -87,7 +87,7 @@ namespace Kyoo.Utils
|
|||||||
/// <returns>The list mapped as an AsyncEnumerable</returns>
|
/// <returns>The list mapped as an AsyncEnumerable</returns>
|
||||||
/// <exception cref="ArgumentNullException">The list or the mapper can't be null</exception>
|
/// <exception cref="ArgumentNullException">The list or the mapper can't be null</exception>
|
||||||
[LinqTunnel]
|
[LinqTunnel]
|
||||||
public static IAsyncEnumerable<T2> SelectAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
public static IAsyncEnumerable<T2> SelectAsync<T, T2>([NotNull] this IEnumerable<T> self,
|
||||||
[NotNull] Func<T, Task<T2>> mapper)
|
[NotNull] Func<T, Task<T2>> mapper)
|
||||||
{
|
{
|
||||||
if (self == null)
|
if (self == null)
|
||||||
@ -159,7 +159,7 @@ namespace Kyoo.Utils
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
yield return enumerator.Current;
|
yield return enumerator.Current;
|
||||||
}
|
}
|
||||||
while (enumerator.MoveNext());
|
while (enumerator.MoveNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ namespace Kyoo.Utils
|
|||||||
foreach (T i in self)
|
foreach (T i in self)
|
||||||
action(i);
|
action(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A foreach used as a function with a little specificity: the list can be null.
|
/// A foreach used as a function with a little specificity: the list can be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -192,7 +192,7 @@ namespace Kyoo.Utils
|
|||||||
foreach (object i in self)
|
foreach (object i in self)
|
||||||
action(i);
|
action(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A foreach used as a function with a little specificity: the list can be null.
|
/// A foreach used as a function with a little specificity: the list can be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -205,7 +205,7 @@ namespace Kyoo.Utils
|
|||||||
foreach (object i in self)
|
foreach (object i in self)
|
||||||
await action(i);
|
await action(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A foreach used as a function with a little specificity: the list can be null.
|
/// A foreach used as a function with a little specificity: the list can be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -219,7 +219,7 @@ namespace Kyoo.Utils
|
|||||||
foreach (T i in self)
|
foreach (T i in self)
|
||||||
await action(i);
|
await action(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A foreach used as a function with a little specificity: the list can be null.
|
/// A foreach used as a function with a little specificity: the list can be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -233,7 +233,7 @@ namespace Kyoo.Utils
|
|||||||
await foreach (T i in self)
|
await foreach (T i in self)
|
||||||
action(i);
|
action(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Split a list in a small chunk of data.
|
/// Split a list in a small chunk of data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -247,7 +247,7 @@ namespace Kyoo.Utils
|
|||||||
for (int i = 0; i < list.Count; i += countPerList)
|
for (int i = 0; i < list.Count; i += countPerList)
|
||||||
yield return list.GetRange(i, Math.Min(list.Count - i, countPerList));
|
yield return list.GetRange(i, Math.Min(list.Count - i, countPerList));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Split a list in a small chunk of data.
|
/// Split a list in a small chunk of data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -260,7 +260,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
T[] ret = new T[countPerList];
|
T[] ret = new T[countPerList];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
using IEnumerator<T> enumerator = list.GetEnumerator();
|
using IEnumerator<T> enumerator = list.GetEnumerator();
|
||||||
while (enumerator.MoveNext())
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,7 @@ namespace Kyoo.Utils
|
|||||||
/// <returns>The two list merged as an array</returns>
|
/// <returns>The two list merged as an array</returns>
|
||||||
[ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)]
|
[ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)]
|
||||||
public static T[] MergeLists<T>([CanBeNull] IEnumerable<T> first,
|
public static T[] MergeLists<T>([CanBeNull] IEnumerable<T> first,
|
||||||
[CanBeNull] IEnumerable<T> second,
|
[CanBeNull] IEnumerable<T> second,
|
||||||
[CanBeNull] Func<T, T, bool> isEqual = null)
|
[CanBeNull] Func<T, T, bool> isEqual = null)
|
||||||
{
|
{
|
||||||
if (first == null)
|
if (first == null)
|
||||||
@ -82,7 +82,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
bool success = first.TryAdd(key, value);
|
bool success = first.TryAdd(key, value);
|
||||||
hasChanged |= success;
|
hasChanged |= success;
|
||||||
|
|
||||||
if (success || first[key]?.Equals(default) == false || value?.Equals(default) != false)
|
if (success || first[key]?.Equals(default) == false || value?.Equals(default) != false)
|
||||||
continue;
|
continue;
|
||||||
first[key] = value;
|
first[key] = value;
|
||||||
@ -150,9 +150,9 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
||||||
.Where(x => x.CanRead && x.CanWrite
|
.Where(x => x.CanRead && x.CanWrite
|
||||||
&& Attribute.GetCustomAttribute(x, typeof(NotMergeableAttribute)) == null);
|
&& Attribute.GetCustomAttribute(x, typeof(NotMergeableAttribute)) == null);
|
||||||
|
|
||||||
foreach (PropertyInfo property in properties)
|
foreach (PropertyInfo property in properties)
|
||||||
{
|
{
|
||||||
object value = property.GetValue(second);
|
object value = property.GetValue(second);
|
||||||
@ -163,7 +163,7 @@ namespace Kyoo.Utils
|
|||||||
merge.OnMerge(second);
|
merge.OnMerge(second);
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set every non-default values of seconds to the corresponding property of second.
|
/// Set every non-default values of seconds to the corresponding property of second.
|
||||||
/// Dictionaries are handled like anonymous objects with a property per key/pair value
|
/// Dictionaries are handled like anonymous objects with a property per key/pair value
|
||||||
@ -190,15 +190,15 @@ namespace Kyoo.Utils
|
|||||||
/// <typeparam name="T">Fields of T will be completed</typeparam>
|
/// <typeparam name="T">Fields of T will be completed</typeparam>
|
||||||
/// <returns><see cref="first"/></returns>
|
/// <returns><see cref="first"/></returns>
|
||||||
/// <exception cref="ArgumentNullException">If first is null</exception>
|
/// <exception cref="ArgumentNullException">If first is null</exception>
|
||||||
public static T Complete<T>([NotNull] T first,
|
public static T Complete<T>([NotNull] T first,
|
||||||
[CanBeNull] T second,
|
[CanBeNull] T second,
|
||||||
[InstantHandle] Func<PropertyInfo, bool> where = null)
|
[InstantHandle] Func<PropertyInfo, bool> where = null)
|
||||||
{
|
{
|
||||||
if (first == null)
|
if (first == null)
|
||||||
throw new ArgumentNullException(nameof(first));
|
throw new ArgumentNullException(nameof(first));
|
||||||
if (second == null)
|
if (second == null)
|
||||||
return first;
|
return first;
|
||||||
|
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
||||||
.Where(x => x.CanRead && x.CanWrite
|
.Where(x => x.CanRead && x.CanWrite
|
||||||
@ -206,7 +206,7 @@ namespace Kyoo.Utils
|
|||||||
|
|
||||||
if (where != null)
|
if (where != null)
|
||||||
properties = properties.Where(where);
|
properties = properties.Where(where);
|
||||||
|
|
||||||
foreach (PropertyInfo property in properties)
|
foreach (PropertyInfo property in properties)
|
||||||
{
|
{
|
||||||
object value = property.GetValue(second);
|
object value = property.GetValue(second);
|
||||||
@ -261,7 +261,7 @@ namespace Kyoo.Utils
|
|||||||
/// <typeparam name="T">Fields of T will be merged</typeparam>
|
/// <typeparam name="T">Fields of T will be merged</typeparam>
|
||||||
/// <returns><see cref="first"/></returns>
|
/// <returns><see cref="first"/></returns>
|
||||||
[ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)]
|
[ContractAnnotation("first:notnull => notnull; second:notnull => notnull", true)]
|
||||||
public static T Merge<T>([CanBeNull] T first,
|
public static T Merge<T>([CanBeNull] T first,
|
||||||
[CanBeNull] T second,
|
[CanBeNull] T second,
|
||||||
[InstantHandle] Func<PropertyInfo, bool> where = null)
|
[InstantHandle] Func<PropertyInfo, bool> where = null)
|
||||||
{
|
{
|
||||||
@ -269,21 +269,21 @@ namespace Kyoo.Utils
|
|||||||
return second;
|
return second;
|
||||||
if (second == null)
|
if (second == null)
|
||||||
return first;
|
return first;
|
||||||
|
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
||||||
.Where(x => x.CanRead && x.CanWrite
|
.Where(x => x.CanRead && x.CanWrite
|
||||||
&& Attribute.GetCustomAttribute(x, typeof(NotMergeableAttribute)) == null);
|
&& Attribute.GetCustomAttribute(x, typeof(NotMergeableAttribute)) == null);
|
||||||
|
|
||||||
if (where != null)
|
if (where != null)
|
||||||
properties = properties.Where(where);
|
properties = properties.Where(where);
|
||||||
|
|
||||||
foreach (PropertyInfo property in properties)
|
foreach (PropertyInfo property in properties)
|
||||||
{
|
{
|
||||||
object oldValue = property.GetValue(first);
|
object oldValue = property.GetValue(first);
|
||||||
object newValue = property.GetValue(second);
|
object newValue = property.GetValue(second);
|
||||||
object defaultValue = property.PropertyType.GetClrDefault();
|
object defaultValue = property.PropertyType.GetClrDefault();
|
||||||
|
|
||||||
if (oldValue?.Equals(defaultValue) != false)
|
if (oldValue?.Equals(defaultValue) != false)
|
||||||
property.SetValue(first, newValue);
|
property.SetValue(first, newValue);
|
||||||
else if (Utility.IsOfGenericType(property.PropertyType, typeof(IDictionary<,>)))
|
else if (Utility.IsOfGenericType(property.PropertyType, typeof(IDictionary<,>)))
|
||||||
@ -310,7 +310,7 @@ namespace Kyoo.Utils
|
|||||||
.GenericTypeArguments
|
.GenericTypeArguments
|
||||||
.First();
|
.First();
|
||||||
Func<IResource, IResource, bool> equalityComparer = enumerableType.IsAssignableTo(typeof(IResource))
|
Func<IResource, IResource, bool> equalityComparer = enumerableType.IsAssignableTo(typeof(IResource))
|
||||||
? (x, y) => x.Slug == y.Slug
|
? (x, y) => x.Slug == y.Slug
|
||||||
: null;
|
: null;
|
||||||
property.SetValue(first, Utility.RunGenericMethod<object>(
|
property.SetValue(first, Utility.RunGenericMethod<object>(
|
||||||
typeof(Merger),
|
typeof(Merger),
|
||||||
@ -344,4 +344,4 @@ namespace Kyoo.Utils
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
return action.Method;
|
return action.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a MethodInfo from a direct method.
|
/// Get a MethodInfo from a direct method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -27,7 +27,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
return action.Method;
|
return action.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a MethodInfo from a direct method.
|
/// Get a MethodInfo from a direct method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -37,7 +37,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
return action.Method;
|
return action.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a MethodInfo from a direct method.
|
/// Get a MethodInfo from a direct method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -47,7 +47,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
return action.Method;
|
return action.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a MethodInfo from a direct method.
|
/// Get a MethodInfo from a direct method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -57,7 +57,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
return action.Method;
|
return action.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a MethodInfo from a direct method.
|
/// Get a MethodInfo from a direct method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -67,7 +67,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
return action.Method;
|
return action.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a MethodInfo from a direct method.
|
/// Get a MethodInfo from a direct method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -77,7 +77,7 @@ namespace Kyoo.Utils
|
|||||||
{
|
{
|
||||||
return action.Method;
|
return action.Method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a MethodInfo from a direct method.
|
/// Get a MethodInfo from a direct method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -28,7 +28,7 @@ namespace Kyoo.Utils
|
|||||||
return ex.Body is MemberExpression ||
|
return ex.Body is MemberExpression ||
|
||||||
ex.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)ex.Body).Operand is MemberExpression;
|
ex.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)ex.Body).Operand is MemberExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the name of a property. Useful for selectors as members ex: Load(x => x.Shows)
|
/// Get the name of a property. Useful for selectors as members ex: Load(x => x.Shows)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -66,7 +66,7 @@ namespace Kyoo.Utils
|
|||||||
_ => throw new ArgumentException($"Can't get value of a non property/field (member: {member}).")
|
_ => throw new ArgumentException($"Can't get value of a non property/field (member: {member}).")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Slugify a string (Replace spaces by -, Uniformize accents é -> e)
|
/// Slugify a string (Replace spaces by -, Uniformize accents é -> e)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -78,7 +78,7 @@ namespace Kyoo.Utils
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
str = str.ToLowerInvariant();
|
str = str.ToLowerInvariant();
|
||||||
|
|
||||||
string normalizedString = str.Normalize(NormalizationForm.FormD);
|
string normalizedString = str.Normalize(NormalizationForm.FormD);
|
||||||
StringBuilder stringBuilder = new();
|
StringBuilder stringBuilder = new();
|
||||||
foreach (char c in normalizedString)
|
foreach (char c in normalizedString)
|
||||||
@ -104,7 +104,7 @@ namespace Kyoo.Utils
|
|||||||
public static object GetClrDefault(this Type type)
|
public static object GetClrDefault(this Type type)
|
||||||
{
|
{
|
||||||
return type.IsValueType
|
return type.IsValueType
|
||||||
? Activator.CreateInstance(type)
|
? Activator.CreateInstance(type)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ namespace Kyoo.Utils
|
|||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
return IsOfGenericType(obj.GetType(), genericType);
|
return IsOfGenericType(obj.GetType(), genericType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if <see cref="type"/> inherit from a generic type <see cref="genericType"/>.
|
/// Check if <see cref="type"/> inherit from a generic type <see cref="genericType"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -201,15 +201,15 @@ namespace Kyoo.Utils
|
|||||||
/// The list of generic parameters.
|
/// The list of generic parameters.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="args">
|
/// <param name="args">
|
||||||
/// The list of parameters.
|
/// The list of parameters.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <exception cref="ArgumentException">No method match the given constraints.</exception>
|
/// <exception cref="ArgumentException">No method match the given constraints.</exception>
|
||||||
/// <returns>The method handle of the matching method.</returns>
|
/// <returns>The method handle of the matching method.</returns>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
[NotNull]
|
[NotNull]
|
||||||
public static MethodInfo GetMethod([NotNull] Type type,
|
public static MethodInfo GetMethod([NotNull] Type type,
|
||||||
BindingFlags flag,
|
BindingFlags flag,
|
||||||
string name,
|
string name,
|
||||||
[NotNull] Type[] generics,
|
[NotNull] Type[] generics,
|
||||||
[NotNull] object[] args)
|
[NotNull] object[] args)
|
||||||
{
|
{
|
||||||
@ -219,7 +219,7 @@ namespace Kyoo.Utils
|
|||||||
throw new ArgumentNullException(nameof(generics));
|
throw new ArgumentNullException(nameof(generics));
|
||||||
if (args == null)
|
if (args == null)
|
||||||
throw new ArgumentNullException(nameof(args));
|
throw new ArgumentNullException(nameof(args));
|
||||||
|
|
||||||
MethodInfo[] methods = type.GetMethods(flag | BindingFlags.Public)
|
MethodInfo[] methods = type.GetMethods(flag | BindingFlags.Public)
|
||||||
.Where(x => x.Name == name)
|
.Where(x => x.Name == name)
|
||||||
.Where(x => x.GetGenericArguments().Length == generics.Length)
|
.Where(x => x.GetGenericArguments().Length == generics.Length)
|
||||||
@ -234,7 +234,7 @@ namespace Kyoo.Utils
|
|||||||
// return x.GetGenericArguments().All(y => y.IsAssignableFrom(generics[i++]));
|
// return x.GetGenericArguments().All(y => y.IsAssignableFrom(generics[i++]));
|
||||||
// })
|
// })
|
||||||
// .IfEmpty(() => throw new NullReferenceException($"No method {name} match the generics specified."))
|
// .IfEmpty(() => throw new NullReferenceException($"No method {name} match the generics specified."))
|
||||||
|
|
||||||
// TODO this won't work for Type<T> because T is specified in arguments but not in the parameters type.
|
// TODO this won't work for Type<T> because T is specified in arguments but not in the parameters type.
|
||||||
// .Where(x =>
|
// .Where(x =>
|
||||||
// {
|
// {
|
||||||
@ -249,7 +249,7 @@ namespace Kyoo.Utils
|
|||||||
return methods[0];
|
return methods[0];
|
||||||
throw new ArgumentException($"Multiple methods named {name} match the generics and parameters constraints.");
|
throw new ArgumentException($"Multiple methods named {name} match the generics and parameters constraints.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run a generic static method for a runtime <see cref="Type"/>.
|
/// Run a generic static method for a runtime <see cref="Type"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -276,14 +276,14 @@ namespace Kyoo.Utils
|
|||||||
/// <seealso cref="RunGenericMethod{T}(object,string,System.Type,object[])"/>
|
/// <seealso cref="RunGenericMethod{T}(object,string,System.Type,object[])"/>
|
||||||
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type[],object[])"/>
|
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type[],object[])"/>
|
||||||
public static T RunGenericMethod<T>(
|
public static T RunGenericMethod<T>(
|
||||||
[NotNull] Type owner,
|
[NotNull] Type owner,
|
||||||
[NotNull] string methodName,
|
[NotNull] string methodName,
|
||||||
[NotNull] Type type,
|
[NotNull] Type type,
|
||||||
params object[] args)
|
params object[] args)
|
||||||
{
|
{
|
||||||
return RunGenericMethod<T>(owner, methodName, new[] {type}, args);
|
return RunGenericMethod<T>(owner, methodName, new[] { type }, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run a generic static method for a multiple runtime <see cref="Type"/>.
|
/// Run a generic static method for a multiple runtime <see cref="Type"/>.
|
||||||
/// If your generic method only needs one type, see
|
/// If your generic method only needs one type, see
|
||||||
@ -313,7 +313,7 @@ namespace Kyoo.Utils
|
|||||||
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type,object[])"/>
|
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type,object[])"/>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static T RunGenericMethod<T>(
|
public static T RunGenericMethod<T>(
|
||||||
[NotNull] Type owner,
|
[NotNull] Type owner,
|
||||||
[NotNull] string methodName,
|
[NotNull] string methodName,
|
||||||
[NotNull] Type[] types,
|
[NotNull] Type[] types,
|
||||||
params object[] args)
|
params object[] args)
|
||||||
@ -361,7 +361,7 @@ namespace Kyoo.Utils
|
|||||||
[NotNull] Type type,
|
[NotNull] Type type,
|
||||||
params object[] args)
|
params object[] args)
|
||||||
{
|
{
|
||||||
return RunGenericMethod<T>(instance, methodName, new[] {type}, args);
|
return RunGenericMethod<T>(instance, methodName, new[] { type }, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -392,7 +392,7 @@ namespace Kyoo.Utils
|
|||||||
/// <seealso cref="RunGenericMethod{T}(object,string,System.Type[],object[])"/>
|
/// <seealso cref="RunGenericMethod{T}(object,string,System.Type[],object[])"/>
|
||||||
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type,object[])"/>
|
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type,object[])"/>
|
||||||
public static T RunGenericMethod<T>(
|
public static T RunGenericMethod<T>(
|
||||||
[NotNull] object instance,
|
[NotNull] object instance,
|
||||||
[NotNull] string methodName,
|
[NotNull] string methodName,
|
||||||
[NotNull] Type[] types,
|
[NotNull] Type[] types,
|
||||||
params object[] args)
|
params object[] args)
|
||||||
@ -436,4 +436,4 @@ namespace Kyoo.Utils
|
|||||||
return $"{type.Name[..type.Name.IndexOf('`')]}<{generics}>";
|
return $"{type.Name[..type.Name.IndexOf('`')]}<{generics}>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -32,10 +33,10 @@ namespace Kyoo.Authentication
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug => "auth";
|
public string Slug => "auth";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Name => "Authentication";
|
public string Name => "Authentication";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Description => "Enable OpenID authentication for Kyoo.";
|
public string Description => "Enable OpenID authentication for Kyoo.";
|
||||||
|
|
||||||
@ -70,8 +71,10 @@ namespace Kyoo.Authentication
|
|||||||
/// <param name="configuration">The configuration to use</param>
|
/// <param name="configuration">The configuration to use</param>
|
||||||
/// <param name="logger">The logger used to allow IdentityServer to log things</param>
|
/// <param name="logger">The logger used to allow IdentityServer to log things</param>
|
||||||
/// <param name="environment">The environment information to check if the app runs in debug mode</param>
|
/// <param name="environment">The environment information to check if the app runs in debug mode</param>
|
||||||
|
[SuppressMessage("ReSharper", "ContextualLoggerProblem",
|
||||||
|
Justification = "The logger is used for a dependency that is not created via the container.")]
|
||||||
public AuthenticationModule(IConfiguration configuration,
|
public AuthenticationModule(IConfiguration configuration,
|
||||||
ILogger<DefaultCorsPolicyService> logger,
|
ILogger<DefaultCorsPolicyService> logger,
|
||||||
IWebHostEnvironment environment)
|
IWebHostEnvironment environment)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
@ -100,16 +103,16 @@ namespace Kyoo.Authentication
|
|||||||
IdentityModelEventSource.ShowPII = true;
|
IdentityModelEventSource.ShowPII = true;
|
||||||
|
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
|
|
||||||
// TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos)
|
// TODO handle direct-videos with bearers (probably add a cookie and a app.Use to translate that for videos)
|
||||||
|
|
||||||
// TODO Check if tokens should be stored.
|
// TODO Check if tokens should be stored.
|
||||||
|
|
||||||
List<Client> clients = new();
|
List<Client> clients = new();
|
||||||
_configuration.GetSection("authentication:clients").Bind(clients);
|
_configuration.GetSection("authentication:clients").Bind(clients);
|
||||||
CertificateOption certificateOptions = new();
|
CertificateOption certificateOptions = new();
|
||||||
_configuration.GetSection(CertificateOption.Path).Bind(certificateOptions);
|
_configuration.GetSection(CertificateOption.Path).Bind(certificateOptions);
|
||||||
|
|
||||||
clients.AddRange(IdentityContext.GetClients());
|
clients.AddRange(IdentityContext.GetClients());
|
||||||
foreach (Client client in clients)
|
foreach (Client client in clients)
|
||||||
{
|
{
|
||||||
@ -131,7 +134,7 @@ namespace Kyoo.Authentication
|
|||||||
.AddInMemoryClients(clients)
|
.AddInMemoryClients(clients)
|
||||||
.AddProfileService<AccountApi>()
|
.AddProfileService<AccountApi>()
|
||||||
.AddSigninKeys(certificateOptions);
|
.AddSigninKeys(certificateOptions);
|
||||||
|
|
||||||
services.AddAuthentication()
|
services.AddAuthentication()
|
||||||
.AddJwtBearer(options =>
|
.AddJwtBearer(options =>
|
||||||
{
|
{
|
||||||
@ -181,4 +184,4 @@ namespace Kyoo.Authentication
|
|||||||
SA.New<IApplicationBuilder>(app => app.UseAuthorization(), SA.Authorization)
|
SA.New<IApplicationBuilder>(app => app.UseAuthorization(), SA.Authorization)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ namespace Kyoo.Authentication
|
|||||||
/// <param name="builder">The identity server that will be modified.</param>
|
/// <param name="builder">The identity server that will be modified.</param>
|
||||||
/// <param name="options">The certificate options</param>
|
/// <param name="options">The certificate options</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IIdentityServerBuilder AddSigninKeys(this IIdentityServerBuilder builder,
|
public static IIdentityServerBuilder AddSigninKeys(this IIdentityServerBuilder builder,
|
||||||
CertificateOption options)
|
CertificateOption options)
|
||||||
{
|
{
|
||||||
X509Certificate2 certificate = GetCertificate(options);
|
X509Certificate2 certificate = GetCertificate(options);
|
||||||
builder.AddSigningCredential(certificate);
|
builder.AddSigningCredential(certificate);
|
||||||
|
|
||||||
if (certificate.NotAfter.AddDays(-7) <= DateTime.UtcNow)
|
if (certificate.NotAfter.AddDays(-7) <= DateTime.UtcNow)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Signin certificate will expire soon, renewing it.");
|
Console.WriteLine("Signin certificate will expire soon, renewing it.");
|
||||||
@ -54,8 +54,8 @@ namespace Kyoo.Authentication
|
|||||||
/// <returns>A valid certificate</returns>
|
/// <returns>A valid certificate</returns>
|
||||||
private static X509Certificate2 GetCertificate(CertificateOption options)
|
private static X509Certificate2 GetCertificate(CertificateOption options)
|
||||||
{
|
{
|
||||||
return File.Exists(options.File)
|
return File.Exists(options.File)
|
||||||
? GetExistingCredential(options.File, options.Password)
|
? GetExistingCredential(options.File, options.Password)
|
||||||
: GenerateCertificate(options.File, options.Password);
|
: GenerateCertificate(options.File, options.Password);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,19 +83,19 @@ namespace Kyoo.Authentication
|
|||||||
private static X509Certificate2 GenerateCertificate(string file, string password)
|
private static X509Certificate2 GenerateCertificate(string file, string password)
|
||||||
{
|
{
|
||||||
SecureRandom random = new();
|
SecureRandom random = new();
|
||||||
|
|
||||||
X509V3CertificateGenerator certificateGenerator = new();
|
X509V3CertificateGenerator certificateGenerator = new();
|
||||||
certificateGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One,
|
certificateGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One,
|
||||||
BigInteger.ValueOf(long.MaxValue), random));
|
BigInteger.ValueOf(long.MaxValue), random));
|
||||||
certificateGenerator.SetIssuerDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
|
certificateGenerator.SetIssuerDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
|
||||||
certificateGenerator.SetSubjectDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
|
certificateGenerator.SetSubjectDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
|
||||||
certificateGenerator.SetNotBefore(DateTime.UtcNow.Date);
|
certificateGenerator.SetNotBefore(DateTime.UtcNow.Date);
|
||||||
certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddMonths(3));
|
certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddMonths(3));
|
||||||
|
|
||||||
KeyGenerationParameters keyGenerationParameters = new(random, 2048);
|
KeyGenerationParameters keyGenerationParameters = new(random, 2048);
|
||||||
RsaKeyPairGenerator keyPairGenerator = new();
|
RsaKeyPairGenerator keyPairGenerator = new();
|
||||||
keyPairGenerator.Init(keyGenerationParameters);
|
keyPairGenerator.Init(keyGenerationParameters);
|
||||||
|
|
||||||
AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
|
AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
|
||||||
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
|
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ namespace Kyoo.Authentication
|
|||||||
X509Certificate bouncyCert = certificateGenerator.Generate(signatureFactory);
|
X509Certificate bouncyCert = certificateGenerator.Generate(signatureFactory);
|
||||||
|
|
||||||
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
|
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
|
||||||
store.SetKeyEntry("Kyoo_key", new AsymmetricKeyEntry(subjectKeyPair.Private), new []
|
store.SetKeyEntry("Kyoo_key", new AsymmetricKeyEntry(subjectKeyPair.Private), new[]
|
||||||
{
|
{
|
||||||
new X509CertificateEntry(bouncyCert)
|
new X509CertificateEntry(bouncyCert)
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@ namespace Kyoo.Authentication
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A permission validator to validate permission with user Permission array
|
/// A permission validator to validate permission with user Permission array
|
||||||
/// or the default array from the configurations if the user is not logged.
|
/// or the default array from the configurations if the user is not logged.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PermissionValidatorFactory : IPermissionValidator
|
public class PermissionValidatorFactory : IPermissionValidator
|
||||||
{
|
{
|
||||||
@ -38,7 +38,7 @@ namespace Kyoo.Authentication
|
|||||||
{
|
{
|
||||||
return new PermissionValidator(attribute.Type, attribute.Kind, attribute.Group, _options);
|
return new PermissionValidator(attribute.Type, attribute.Kind, attribute.Group, _options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IFilterMetadata Create(PartialPermissionAttribute attribute)
|
public IFilterMetadata Create(PartialPermissionAttribute attribute)
|
||||||
{
|
{
|
||||||
@ -149,4 +149,4 @@ namespace Kyoo.Authentication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ namespace Kyoo.Authentication
|
|||||||
return new(user.ID.ToString())
|
return new(user.ID.ToString())
|
||||||
{
|
{
|
||||||
DisplayName = user.Username,
|
DisplayName = user.Username,
|
||||||
AdditionalClaims = new[] {new Claim("permissions", string.Join(',', user.Permissions))}
|
AdditionalClaims = new[] { new Claim("permissions", string.Join(',', user.Permissions)) }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@ namespace Kyoo.Authentication.Models.DTO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[EmailAddress(ErrorMessage = "The email is invalid.")]
|
[EmailAddress(ErrorMessage = "The email is invalid.")]
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The new username of the user.
|
/// The new username of the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MinLength(4, ErrorMessage = "The username must have at least 4 characters")]
|
[MinLength(4, ErrorMessage = "The username must have at least 4 characters")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The picture icon.
|
/// The picture icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,17 +9,17 @@ namespace Kyoo.Authentication.Models.DTO
|
|||||||
/// The user's username.
|
/// The user's username.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user's password.
|
/// The user's password.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should the user stay logged in? If true a cookie will be put.
|
/// Should the user stay logged in? If true a cookie will be put.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StayLoggedIn { get; set; }
|
public bool StayLoggedIn { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The return url of the login flow.
|
/// The return url of the login flow.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,7 +9,7 @@ namespace Kyoo.Authentication.Models.DTO
|
|||||||
/// The One Time Access Code
|
/// The One Time Access Code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Otac { get; set; }
|
public string Otac { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Should the user stay logged
|
/// Should the user stay logged
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,13 +15,13 @@ namespace Kyoo.Authentication.Models.DTO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[EmailAddress(ErrorMessage = "The email must be a valid email address")]
|
[EmailAddress(ErrorMessage = "The email must be a valid email address")]
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user's username.
|
/// The user's username.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MinLength(4, ErrorMessage = "The username must have at least {1} characters")]
|
[MinLength(4, ErrorMessage = "The username must have at least {1} characters")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user's password.
|
/// The user's password.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,5 +44,5 @@ namespace Kyoo.Authentication.Models.DTO
|
|||||||
ExtraData = new Dictionary<string, string>()
|
ExtraData = new Dictionary<string, string>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,11 +42,11 @@ namespace Kyoo.Authentication
|
|||||||
AllowedGrantTypes = GrantTypes.Code,
|
AllowedGrantTypes = GrantTypes.Code,
|
||||||
RequirePkce = true,
|
RequirePkce = true,
|
||||||
RequireClientSecret = false,
|
RequireClientSecret = false,
|
||||||
|
|
||||||
AllowAccessTokensViaBrowser = true,
|
AllowAccessTokensViaBrowser = true,
|
||||||
AllowOfflineAccess = true,
|
AllowOfflineAccess = true,
|
||||||
RequireConsent = false,
|
RequireConsent = false,
|
||||||
|
|
||||||
AllowedScopes = { "openid", "profile", "kyoo.read", "kyoo.write", "kyoo.play", "kyoo.admin" },
|
AllowedScopes = { "openid", "profile", "kyoo.read", "kyoo.write", "kyoo.play", "kyoo.admin" },
|
||||||
RedirectUris = { "/", "/silent.html" },
|
RedirectUris = { "/", "/silent.html" },
|
||||||
PostLogoutRedirectUris = { "/logout" }
|
PostLogoutRedirectUris = { "/logout" }
|
||||||
@ -84,7 +84,7 @@ namespace Kyoo.Authentication
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of APIs (this is used to create Audiences)
|
/// The list of APIs (this is used to create Audiences)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,12 +14,12 @@ namespace Kyoo.Authentication.Models
|
|||||||
/// The options for certificates
|
/// The options for certificates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CertificateOption Certificate { get; set; }
|
public CertificateOption Certificate { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for permissions
|
/// Options for permissions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PermissionOption Permissions { get; set; }
|
public PermissionOption Permissions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Root path of user's profile pictures.
|
/// Root path of user's profile pictures.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,7 +9,7 @@ namespace Kyoo.Authentication.Models
|
|||||||
/// The path to get this option from the root configuration.
|
/// The path to get this option from the root configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string Path = "authentication:certificate";
|
public const string Path = "authentication:certificate";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of the certificate file.
|
/// The path of the certificate file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,7 +14,7 @@ namespace Kyoo.Authentication.Models
|
|||||||
/// The default permissions that will be given to a non-connected user.
|
/// The default permissions that will be given to a non-connected user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] Default { get; set; }
|
public string[] Default { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Permissions applied to a new user.
|
/// Permissions applied to a new user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -57,8 +57,8 @@ namespace Kyoo.Authentication.Views
|
|||||||
_files = files;
|
_files = files;
|
||||||
_options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register a new user and return a OTAC to connect to it.
|
/// Register a new user and return a OTAC to connect to it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -78,10 +78,10 @@ namespace Kyoo.Authentication.Views
|
|||||||
}
|
}
|
||||||
catch (DuplicatedItemException)
|
catch (DuplicatedItemException)
|
||||||
{
|
{
|
||||||
return Conflict(new {Errors = new {Duplicate = new[] {"A user with this name already exists"}}});
|
return Conflict(new { Errors = new { Duplicate = new[] { "A user with this name already exists" } } });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(new {Otac = user.ExtraData["otac"]});
|
return Ok(new { Otac = user.ExtraData["otac"] });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -99,7 +99,7 @@ namespace Kyoo.Authentication.Views
|
|||||||
ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(1)
|
ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(1)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Login the user.
|
/// Login the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -117,7 +117,7 @@ namespace Kyoo.Authentication.Views
|
|||||||
await HttpContext.SignInAsync(user.ToIdentityUser(), StayLogged(login.StayLoggedIn));
|
await HttpContext.SignInAsync(user.ToIdentityUser(), StayLogged(login.StayLoggedIn));
|
||||||
return Ok(new { RedirectUrl = login.ReturnURL, IsOk = true });
|
return Ok(new { RedirectUrl = login.ReturnURL, IsOk = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use a OTAC to login a user.
|
/// Use a OTAC to login a user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -127,22 +127,23 @@ namespace Kyoo.Authentication.Views
|
|||||||
{
|
{
|
||||||
// TODO once hstore (Dictionary<string, string> accessor) are supported, use them.
|
// TODO once hstore (Dictionary<string, string> accessor) are supported, use them.
|
||||||
// We retrieve all users, this is inefficient.
|
// We retrieve all users, this is inefficient.
|
||||||
User user = (await _users.GetAll()).FirstOrDefault(x => x.ExtraData.GetValueOrDefault("otac") == otac.Otac);
|
User user = (await _users.GetAll()).FirstOrDefault(x => x.ExtraData.GetValueOrDefault("otac") == otac.Otac);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
if (DateTime.ParseExact(user.ExtraData["otac-expire"], "s", CultureInfo.InvariantCulture) <=
|
if (DateTime.ParseExact(user.ExtraData["otac-expire"], "s", CultureInfo.InvariantCulture) <=
|
||||||
DateTime.UtcNow)
|
DateTime.UtcNow)
|
||||||
{
|
{
|
||||||
return BadRequest(new
|
return BadRequest(new
|
||||||
{
|
{
|
||||||
code = "ExpiredOTAC", description = "The OTAC has expired. Try to login with your password."
|
code = "ExpiredOTAC",
|
||||||
|
description = "The OTAC has expired. Try to login with your password."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await HttpContext.SignInAsync(user.ToIdentityUser(), StayLogged(otac.StayLoggedIn));
|
await HttpContext.SignInAsync(user.ToIdentityUser(), StayLogged(otac.StayLoggedIn));
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sign out an user
|
/// Sign out an user
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -170,7 +171,7 @@ namespace Kyoo.Authentication.Views
|
|||||||
User user = await _users.GetOrDefault(int.Parse(context.Subject.GetSubjectId()));
|
User user = await _users.GetOrDefault(int.Parse(context.Subject.GetSubjectId()));
|
||||||
context.IsActive = user != null;
|
context.IsActive = user != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the user's profile picture.
|
/// Get the user's profile picture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -185,7 +186,7 @@ namespace Kyoo.Authentication.Views
|
|||||||
string path = Path.Combine(_options.Value.ProfilePicturePath, user.ID.ToString());
|
string path = Path.Combine(_options.Value.ProfilePicturePath, user.ID.ToString());
|
||||||
return _files.FileResult(path);
|
return _files.FileResult(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update profile information (email, username, profile picture...)
|
/// Update profile information (email, username, profile picture...)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -32,7 +32,7 @@ namespace Kyoo.Core
|
|||||||
/// Should the application restart after a shutdown?
|
/// Should the application restart after a shutdown?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _shouldRestart;
|
private bool _shouldRestart;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The cancellation token source used to allow the app to be shutdown or restarted.
|
/// The cancellation token source used to allow the app to be shutdown or restarted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -48,7 +48,7 @@ namespace Kyoo.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private ILogger _logger;
|
private ILogger _logger;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="Application"/> that will use the specified environment.
|
/// Create a new <see cref="Application"/> that will use the specified environment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -80,28 +80,28 @@ namespace Kyoo.Core
|
|||||||
public async Task Start(string[] args, Action<ContainerBuilder> configure)
|
public async Task Start(string[] args, Action<ContainerBuilder> configure)
|
||||||
{
|
{
|
||||||
_dataDir = _SetupDataDir(args);
|
_dataDir = _SetupDataDir(args);
|
||||||
|
|
||||||
LoggerConfiguration config = new();
|
LoggerConfiguration config = new();
|
||||||
_ConfigureLogging(config, null, null);
|
_ConfigureLogging(config, null, null);
|
||||||
Log.Logger = config.CreateBootstrapLogger();
|
Log.Logger = config.CreateBootstrapLogger();
|
||||||
_logger = Log.Logger.ForContext<Application>();
|
_logger = Log.Logger.ForContext<Application>();
|
||||||
|
|
||||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => Log.CloseAndFlush();
|
AppDomain.CurrentDomain.ProcessExit += (_, _) => Log.CloseAndFlush();
|
||||||
AppDomain.CurrentDomain.UnhandledException += (_, ex)
|
AppDomain.CurrentDomain.UnhandledException += (_, ex)
|
||||||
=> Log.Fatal(ex.ExceptionObject as Exception, "Unhandled exception");
|
=> Log.Fatal(ex.ExceptionObject as Exception, "Unhandled exception");
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
IHost host = _CreateWebHostBuilder(args)
|
IHost host = _CreateWebHostBuilder(args)
|
||||||
.ConfigureContainer(configure)
|
.ConfigureContainer(configure)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_tokenSource = new CancellationTokenSource();
|
_tokenSource = new CancellationTokenSource();
|
||||||
await _StartWithHost(host, _tokenSource.Token);
|
await _StartWithHost(host, _tokenSource.Token);
|
||||||
}
|
}
|
||||||
while (_shouldRestart);
|
while (_shouldRestart);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Shutdown()
|
public void Shutdown()
|
||||||
{
|
{
|
||||||
@ -155,7 +155,7 @@ namespace Kyoo.Core
|
|||||||
.AddCommandLine(args)
|
.AddCommandLine(args)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
string path = parsed.GetValue<string>("datadir")
|
string path = parsed.GetValue<string>("datadir")
|
||||||
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kyoo");
|
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kyoo");
|
||||||
|
|
||||||
if (!Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
@ -165,7 +165,7 @@ namespace Kyoo.Core
|
|||||||
if (!File.Exists(GetConfigFile()))
|
if (!File.Exists(GetConfigFile()))
|
||||||
File.Copy(Path.Join(AppDomain.CurrentDomain.BaseDirectory, GetConfigFile()),
|
File.Copy(Path.Join(AppDomain.CurrentDomain.BaseDirectory, GetConfigFile()),
|
||||||
GetConfigFile());
|
GetConfigFile());
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ namespace Kyoo.Core
|
|||||||
.UseStartup(host => PluginsStartup.FromWebHost(host, new LoggerFactory().AddSerilog()))
|
.UseStartup(host => PluginsStartup.FromWebHost(host, new LoggerFactory().AddSerilog()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register settings.json, environment variables and command lines arguments as configuration.
|
/// Register settings.json, environment variables and command lines arguments as configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -17,7 +17,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
public class ConfigurationManager : IConfigurationManager
|
public class ConfigurationManager : IConfigurationManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration to retrieve and edit.
|
/// The configuration to retrieve and edit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
ConfigurationReference config = ConfigurationReference.CreateUntyped(path);
|
ConfigurationReference config = ConfigurationReference.CreateUntyped(path);
|
||||||
_references.Add(config.Path, config.Type);
|
_references.Add(config.Path, config.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Register(string path, Type type)
|
public void Register(string path, Type type)
|
||||||
{
|
{
|
||||||
@ -98,7 +98,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
throw new ArgumentException($"The configuration at {path} is not editable or readable.");
|
throw new ArgumentException($"The configuration at {path} is not editable or readable.");
|
||||||
throw new ItemNotFoundException($"No configuration exists for the name: {path}");
|
throw new ItemNotFoundException($"No configuration exists for the name: {path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public object GetValue(string path)
|
public object GetValue(string path)
|
||||||
{
|
{
|
||||||
@ -124,7 +124,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
$"a resource of type {type.Name}.");
|
$"a resource of type {type.Name}.");
|
||||||
return (T)GetValue(path);
|
return (T)GetValue(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task EditValue(string path, object value)
|
public async Task EditValue(string path, object value)
|
||||||
{
|
{
|
||||||
@ -133,7 +133,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
value = JObject.FromObject(value).ToObject(type);
|
value = JObject.FromObject(value).ToObject(type);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
throw new ArgumentException("Invalid value format.");
|
throw new ArgumentException("Invalid value format.");
|
||||||
|
|
||||||
ExpandoObject config = _ToObject(_configuration);
|
ExpandoObject config = _ToObject(_configuration);
|
||||||
IDictionary<string, object> configDic = config;
|
IDictionary<string, object> configDic = config;
|
||||||
configDic[path] = value;
|
configDic[path] = value;
|
||||||
@ -141,7 +141,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
await using StreamWriter writer = new(_application.GetConfigFile());
|
await using StreamWriter writer = new(_application.GetConfigFile());
|
||||||
await writer.WriteAsync(obj.ToString());
|
await writer.WriteAsync(obj.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transform a configuration to a strongly typed object (the root configuration is an <see cref="ExpandoObject"/>
|
/// Transform a configuration to a strongly typed object (the root configuration is an <see cref="ExpandoObject"/>
|
||||||
/// but child elements are using strong types.
|
/// but child elements are using strong types.
|
||||||
@ -169,7 +169,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,4 +192,4 @@ namespace Kyoo.Core.Controllers
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// (only if the option is set to metadata in show)
|
/// (only if the option is set to metadata in show)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options to check if the metadata should be kept in the show directory or in a kyoo's directory.
|
/// Options to check if the metadata should be kept in the show directory or in a kyoo's directory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IOptionsMonitor<BasicOptions> _options;
|
private readonly IOptionsMonitor<BasicOptions> _options;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="FileSystemComposite"/> from a list of <see cref="IFileSystem"/> mapped to their
|
/// Create a new <see cref="FileSystemComposite"/> from a list of <see cref="IFileSystem"/> mapped to their
|
||||||
/// metadata.
|
/// metadata.
|
||||||
@ -45,7 +45,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <param name="libraryManager">The library manager used to load shows to retrieve their path.</param>
|
/// <param name="libraryManager">The library manager used to load shows to retrieve their path.</param>
|
||||||
/// <param name="options">The options to use.</param>
|
/// <param name="options">The options to use.</param>
|
||||||
public FileSystemComposite(ICollection<Meta<Func<IFileSystem>, FileSystemMetadataAttribute>> fileSystems,
|
public FileSystemComposite(ICollection<Meta<Func<IFileSystem>, FileSystemMetadataAttribute>> fileSystems,
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IOptionsMonitor<BasicOptions> options)
|
IOptionsMonitor<BasicOptions> options)
|
||||||
{
|
{
|
||||||
_fileSystems = fileSystems;
|
_fileSystems = fileSystems;
|
||||||
@ -53,7 +53,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
_options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieve the file system that should be used for a given path.
|
/// Retrieve the file system that should be used for a given path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -159,7 +159,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
return _GetFileSystemForPath(path, out string relativePath)
|
return _GetFileSystemForPath(path, out string relativePath)
|
||||||
.Exists(relativePath);
|
.Exists(relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<string> GetExtraDirectory<T>(T resource)
|
public async Task<string> GetExtraDirectory<T>(T resource)
|
||||||
{
|
{
|
||||||
@ -191,7 +191,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
Season season => await GetExtraDirectory(season.Show),
|
Season season => await GetExtraDirectory(season.Show),
|
||||||
Episode episode => await GetExtraDirectory(episode.Show),
|
Episode episode => await GetExtraDirectory(episode.Show),
|
||||||
Track track => await GetExtraDirectory(track.Episode),
|
Track track => await GetExtraDirectory(track.Episode),
|
||||||
IResource res => Combine(_options.CurrentValue.MetadataPath,
|
IResource res => Combine(_options.CurrentValue.MetadataPath,
|
||||||
typeof(T).Name.ToLowerInvariant(), res.Slug),
|
typeof(T).Name.ToLowerInvariant(), res.Slug),
|
||||||
_ => Combine(_options.CurrentValue.MetadataPath, typeof(T).Name.ToLowerInvariant())
|
_ => Combine(_options.CurrentValue.MetadataPath, typeof(T).Name.ToLowerInvariant())
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="IFileSystem"/> for http/https links.
|
/// A <see cref="IFileSystem"/> for http/https links.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FileSystemMetadata(new [] {"http", "https"})]
|
[FileSystemMetadata(new[] { "http", "https" })]
|
||||||
public class HttpFileSystem : IFileSystem
|
public class HttpFileSystem : IFileSystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -30,8 +30,8 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
_clientFactory = factory;
|
_clientFactory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IActionResult FileResult(string path, bool rangeSupport = false, string type = null)
|
public IActionResult FileResult(string path, bool rangeSupport = false, string type = null)
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
HttpClient client = _clientFactory.CreateClient();
|
HttpClient client = _clientFactory.CreateClient();
|
||||||
return client.GetStreamAsync(path);
|
return client.GetStreamAsync(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<Stream> GetReader(string path, AsyncRef<string> mime)
|
public async Task<Stream> GetReader(string path, AsyncRef<string> mime)
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A <see cref="IFileSystem"/> for the local filesystem (using System.IO).
|
/// A <see cref="IFileSystem"/> for the local filesystem (using System.IO).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FileSystemMetadata(new [] {"", "file"}, StripScheme = true)]
|
[FileSystemMetadata(new[] { "", "file" }, StripScheme = true)]
|
||||||
public class LocalFileSystem : IFileSystem
|
public class LocalFileSystem : IFileSystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -51,7 +51,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
return contentType;
|
return contentType;
|
||||||
throw new NotImplementedException($"Can't get the content type of the file at: {path}");
|
throw new NotImplementedException($"Can't get the content type of the file at: {path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IActionResult FileResult(string path, bool rangeSupport = false, string type = null)
|
public IActionResult FileResult(string path, bool rangeSupport = false, string type = null)
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
throw new ArgumentNullException(nameof(path));
|
throw new ArgumentNullException(nameof(path));
|
||||||
return Task.FromResult<Stream>(File.OpenRead(path));
|
return Task.FromResult<Stream>(File.OpenRead(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<Stream> GetReader(string path, AsyncRef<string> mime)
|
public Task<Stream> GetReader(string path, AsyncRef<string> mime)
|
||||||
{
|
{
|
||||||
@ -99,19 +99,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
return Task.FromResult(path);
|
return Task.FromResult(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Combine(params string[] paths)
|
public string Combine(params string[] paths)
|
||||||
{
|
{
|
||||||
return Path.Combine(paths);
|
return Path.Combine(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<string>> ListFiles(string path, SearchOption options = SearchOption.TopDirectoryOnly)
|
public Task<ICollection<string>> ListFiles(string path, SearchOption options = SearchOption.TopDirectoryOnly)
|
||||||
{
|
{
|
||||||
if (path == null)
|
if (path == null)
|
||||||
throw new ArgumentNullException(nameof(path));
|
throw new ArgumentNullException(nameof(path));
|
||||||
string[] ret = Directory.Exists(path)
|
string[] ret = Directory.Exists(path)
|
||||||
? Directory.GetFiles(path, "*", options)
|
? Directory.GetFiles(path, "*", options)
|
||||||
: Array.Empty<string>();
|
: Array.Empty<string>();
|
||||||
return Task.FromResult<ICollection<string>>(ret);
|
return Task.FromResult<ICollection<string>>(ret);
|
||||||
@ -122,7 +122,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
return Task.FromResult(File.Exists(path) || Directory.Exists(path));
|
return Task.FromResult(File.Exists(path) || Directory.Exists(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<string> GetExtraDirectory<T>(T resource)
|
public Task<string> GetExtraDirectory<T>(T resource)
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The list of repositories
|
/// The list of repositories
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IBaseRepository[] _repositories;
|
private readonly IBaseRepository[] _repositories;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ILibraryRepository LibraryRepository { get; }
|
public ILibraryRepository LibraryRepository { get; }
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -41,8 +41,8 @@ namespace Kyoo.Core.Controllers
|
|||||||
public IProviderRepository ProviderRepository { get; }
|
public IProviderRepository ProviderRepository { get; }
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IUserRepository UserRepository { get; }
|
public IUserRepository UserRepository { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="LibraryManager"/> instance with every repository available.
|
/// Create a new <see cref="LibraryManager"/> instance with every repository available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -82,7 +82,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<T> Get<T>(string slug)
|
public Task<T> Get<T>(string slug)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return GetRepository<T>().Get(slug);
|
return GetRepository<T>().Get(slug);
|
||||||
@ -120,19 +120,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<T> GetOrDefault<T>(int id)
|
public async Task<T> GetOrDefault<T>(int id)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return await GetRepository<T>().GetOrDefault(id);
|
return await GetRepository<T>().GetOrDefault(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<T> GetOrDefault<T>(string slug)
|
public async Task<T> GetOrDefault<T>(string slug)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return await GetRepository<T>().GetOrDefault(slug);
|
return await GetRepository<T>().GetOrDefault(slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<T> GetOrDefault<T>(Expression<Func<T, bool>> where)
|
public async Task<T> GetOrDefault<T>(Expression<Func<T, bool>> where)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
@ -145,19 +145,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
return await SeasonRepository.GetOrDefault(showID, seasonNumber);
|
return await SeasonRepository.GetOrDefault(showID, seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<Season> GetOrDefault(string showSlug, int seasonNumber)
|
public async Task<Season> GetOrDefault(string showSlug, int seasonNumber)
|
||||||
{
|
{
|
||||||
return await SeasonRepository.GetOrDefault(showSlug, seasonNumber);
|
return await SeasonRepository.GetOrDefault(showSlug, seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber)
|
public async Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber)
|
||||||
{
|
{
|
||||||
return await EpisodeRepository.GetOrDefault(showID, seasonNumber, episodeNumber);
|
return await EpisodeRepository.GetOrDefault(showID, seasonNumber, episodeNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber)
|
public async Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber)
|
||||||
{
|
{
|
||||||
@ -173,9 +173,9 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <param name="inverse">A setter function to store the owner of a releated object loaded</param>
|
/// <param name="inverse">A setter function to store the owner of a releated object loaded</param>
|
||||||
/// <typeparam name="T1">The type of the owner object</typeparam>
|
/// <typeparam name="T1">The type of the owner object</typeparam>
|
||||||
/// <typeparam name="T2">The type of the related object</typeparam>
|
/// <typeparam name="T2">The type of the related object</typeparam>
|
||||||
private static async Task SetRelation<T1, T2>(T1 obj,
|
private static async Task SetRelation<T1, T2>(T1 obj,
|
||||||
Task<ICollection<T2>> loader,
|
Task<ICollection<T2>> loader,
|
||||||
Action<T1, ICollection<T2>> setter,
|
Action<T1, ICollection<T2>> setter,
|
||||||
Action<T2, T1> inverse)
|
Action<T2, T1> inverse)
|
||||||
{
|
{
|
||||||
ICollection<T2> loaded = await loader;
|
ICollection<T2> loaded = await loader;
|
||||||
@ -230,61 +230,61 @@ namespace Kyoo.Core.Controllers
|
|||||||
(Library l, nameof(Library.Providers)) => ProviderRepository
|
(Library l, nameof(Library.Providers)) => ProviderRepository
|
||||||
.GetAll(x => x.Libraries.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Libraries.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => l.Providers = x),
|
.Then(x => l.Providers = x),
|
||||||
|
|
||||||
(Library l, nameof(Library.Shows)) => ShowRepository
|
(Library l, nameof(Library.Shows)) => ShowRepository
|
||||||
.GetAll(x => x.Libraries.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Libraries.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => l.Shows = x),
|
.Then(x => l.Shows = x),
|
||||||
|
|
||||||
(Library l, nameof(Library.Collections)) => CollectionRepository
|
(Library l, nameof(Library.Collections)) => CollectionRepository
|
||||||
.GetAll(x => x.Libraries.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Libraries.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => l.Collections = x),
|
.Then(x => l.Collections = x),
|
||||||
|
|
||||||
|
|
||||||
(Collection c, nameof(Collection.ExternalIDs)) => SetRelation(c,
|
(Collection c, nameof(Collection.ExternalIDs)) => SetRelation(c,
|
||||||
ProviderRepository.GetMetadataID<Collection>(x => x.ResourceID == obj.ID),
|
ProviderRepository.GetMetadataID<Collection>(x => x.ResourceID == obj.ID),
|
||||||
(x, y) => x.ExternalIDs = y,
|
(x, y) => x.ExternalIDs = y,
|
||||||
(x, y) => { x.ResourceID = y.ID; }),
|
(x, y) => { x.ResourceID = y.ID; }),
|
||||||
|
|
||||||
(Collection c, nameof(Collection.Shows)) => ShowRepository
|
(Collection c, nameof(Collection.Shows)) => ShowRepository
|
||||||
.GetAll(x => x.Collections.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Collections.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => c.Shows = x),
|
.Then(x => c.Shows = x),
|
||||||
|
|
||||||
(Collection c, nameof(Collection.Libraries)) => LibraryRepository
|
(Collection c, nameof(Collection.Libraries)) => LibraryRepository
|
||||||
.GetAll(x => x.Collections.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Collections.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => c.Libraries = x),
|
.Then(x => c.Libraries = x),
|
||||||
|
|
||||||
|
|
||||||
(Show s, nameof(Show.ExternalIDs)) => SetRelation(s,
|
(Show s, nameof(Show.ExternalIDs)) => SetRelation(s,
|
||||||
ProviderRepository.GetMetadataID<Show>(x => x.ResourceID == obj.ID),
|
ProviderRepository.GetMetadataID<Show>(x => x.ResourceID == obj.ID),
|
||||||
(x, y) => x.ExternalIDs = y,
|
(x, y) => x.ExternalIDs = y,
|
||||||
(x, y) => { x.ResourceID = y.ID; }),
|
(x, y) => { x.ResourceID = y.ID; }),
|
||||||
|
|
||||||
(Show s, nameof(Show.Genres)) => GenreRepository
|
(Show s, nameof(Show.Genres)) => GenreRepository
|
||||||
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => s.Genres = x),
|
.Then(x => s.Genres = x),
|
||||||
|
|
||||||
(Show s, nameof(Show.People)) => PeopleRepository
|
(Show s, nameof(Show.People)) => PeopleRepository
|
||||||
.GetFromShow(obj.ID)
|
.GetFromShow(obj.ID)
|
||||||
.Then(x => s.People = x),
|
.Then(x => s.People = x),
|
||||||
|
|
||||||
(Show s, nameof(Show.Seasons)) => SetRelation(s,
|
(Show s, nameof(Show.Seasons)) => SetRelation(s,
|
||||||
SeasonRepository.GetAll(x => x.Show.ID == obj.ID),
|
SeasonRepository.GetAll(x => x.Show.ID == obj.ID),
|
||||||
(x, y) => x.Seasons = y,
|
(x, y) => x.Seasons = y,
|
||||||
(x, y) => { x.Show = y; x.ShowID = y.ID; }),
|
(x, y) => { x.Show = y; x.ShowID = y.ID; }),
|
||||||
|
|
||||||
(Show s, nameof(Show.Episodes)) => SetRelation(s,
|
(Show s, nameof(Show.Episodes)) => SetRelation(s,
|
||||||
EpisodeRepository.GetAll(x => x.Show.ID == obj.ID),
|
EpisodeRepository.GetAll(x => x.Show.ID == obj.ID),
|
||||||
(x, y) => x.Episodes = y,
|
(x, y) => x.Episodes = y,
|
||||||
(x, y) => { x.Show = y; x.ShowID = y.ID; }),
|
(x, y) => { x.Show = y; x.ShowID = y.ID; }),
|
||||||
|
|
||||||
(Show s, nameof(Show.Libraries)) => LibraryRepository
|
(Show s, nameof(Show.Libraries)) => LibraryRepository
|
||||||
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => s.Libraries = x),
|
.Then(x => s.Libraries = x),
|
||||||
|
|
||||||
(Show s, nameof(Show.Collections)) => CollectionRepository
|
(Show s, nameof(Show.Collections)) => CollectionRepository
|
||||||
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => s.Collections = x),
|
.Then(x => s.Collections = x),
|
||||||
|
|
||||||
(Show s, nameof(Show.Studio)) => StudioRepository
|
(Show s, nameof(Show.Studio)) => StudioRepository
|
||||||
.GetOrDefault(x => x.Shows.Any(y => y.ID == obj.ID))
|
.GetOrDefault(x => x.Shows.Any(y => y.ID == obj.ID))
|
||||||
.Then(x =>
|
.Then(x =>
|
||||||
@ -292,18 +292,18 @@ namespace Kyoo.Core.Controllers
|
|||||||
s.Studio = x;
|
s.Studio = x;
|
||||||
s.StudioID = x?.ID ?? 0;
|
s.StudioID = x?.ID ?? 0;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
(Season s, nameof(Season.ExternalIDs)) => SetRelation(s,
|
(Season s, nameof(Season.ExternalIDs)) => SetRelation(s,
|
||||||
ProviderRepository.GetMetadataID<Season>(x => x.ResourceID == obj.ID),
|
ProviderRepository.GetMetadataID<Season>(x => x.ResourceID == obj.ID),
|
||||||
(x, y) => x.ExternalIDs = y,
|
(x, y) => x.ExternalIDs = y,
|
||||||
(x, y) => { x.ResourceID = y.ID; }),
|
(x, y) => { x.ResourceID = y.ID; }),
|
||||||
|
|
||||||
(Season s, nameof(Season.Episodes)) => SetRelation(s,
|
(Season s, nameof(Season.Episodes)) => SetRelation(s,
|
||||||
EpisodeRepository.GetAll(x => x.Season.ID == obj.ID),
|
EpisodeRepository.GetAll(x => x.Season.ID == obj.ID),
|
||||||
(x, y) => x.Episodes = y,
|
(x, y) => x.Episodes = y,
|
||||||
(x, y) => { x.Season = y; x.SeasonID = y.ID; }),
|
(x, y) => { x.Season = y; x.SeasonID = y.ID; }),
|
||||||
|
|
||||||
(Season s, nameof(Season.Show)) => ShowRepository
|
(Season s, nameof(Season.Show)) => ShowRepository
|
||||||
.GetOrDefault(x => x.Seasons.Any(y => y.ID == obj.ID))
|
.GetOrDefault(x => x.Seasons.Any(y => y.ID == obj.ID))
|
||||||
.Then(x =>
|
.Then(x =>
|
||||||
@ -311,18 +311,18 @@ namespace Kyoo.Core.Controllers
|
|||||||
s.Show = x;
|
s.Show = x;
|
||||||
s.ShowID = x?.ID ?? 0;
|
s.ShowID = x?.ID ?? 0;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
(Episode e, nameof(Episode.ExternalIDs)) => SetRelation(e,
|
(Episode e, nameof(Episode.ExternalIDs)) => SetRelation(e,
|
||||||
ProviderRepository.GetMetadataID<Episode>(x => x.ResourceID == obj.ID),
|
ProviderRepository.GetMetadataID<Episode>(x => x.ResourceID == obj.ID),
|
||||||
(x, y) => x.ExternalIDs = y,
|
(x, y) => x.ExternalIDs = y,
|
||||||
(x, y) => { x.ResourceID = y.ID; }),
|
(x, y) => { x.ResourceID = y.ID; }),
|
||||||
|
|
||||||
(Episode e, nameof(Episode.Tracks)) => SetRelation(e,
|
(Episode e, nameof(Episode.Tracks)) => SetRelation(e,
|
||||||
TrackRepository.GetAll(x => x.Episode.ID == obj.ID),
|
TrackRepository.GetAll(x => x.Episode.ID == obj.ID),
|
||||||
(x, y) => x.Tracks = y,
|
(x, y) => x.Tracks = y,
|
||||||
(x, y) => { x.Episode = y; x.EpisodeID = y.ID; }),
|
(x, y) => { x.Episode = y; x.EpisodeID = y.ID; }),
|
||||||
|
|
||||||
(Episode e, nameof(Episode.Show)) => ShowRepository
|
(Episode e, nameof(Episode.Show)) => ShowRepository
|
||||||
.GetOrDefault(x => x.Episodes.Any(y => y.ID == obj.ID))
|
.GetOrDefault(x => x.Episodes.Any(y => y.ID == obj.ID))
|
||||||
.Then(x =>
|
.Then(x =>
|
||||||
@ -330,7 +330,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
e.Show = x;
|
e.Show = x;
|
||||||
e.ShowID = x?.ID ?? 0;
|
e.ShowID = x?.ID ?? 0;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
(Episode e, nameof(Episode.Season)) => SeasonRepository
|
(Episode e, nameof(Episode.Season)) => SeasonRepository
|
||||||
.GetOrDefault(x => x.Episodes.Any(y => y.ID == e.ID))
|
.GetOrDefault(x => x.Episodes.Any(y => y.ID == e.ID))
|
||||||
.Then(x =>
|
.Then(x =>
|
||||||
@ -338,8 +338,8 @@ namespace Kyoo.Core.Controllers
|
|||||||
e.Season = x;
|
e.Season = x;
|
||||||
e.SeasonID = x?.ID ?? 0;
|
e.SeasonID = x?.ID ?? 0;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
(Track t, nameof(Track.Episode)) => EpisodeRepository
|
(Track t, nameof(Track.Episode)) => EpisodeRepository
|
||||||
.GetOrDefault(x => x.Tracks.Any(y => y.ID == obj.ID))
|
.GetOrDefault(x => x.Tracks.Any(y => y.ID == obj.ID))
|
||||||
.Then(x =>
|
.Then(x =>
|
||||||
@ -347,62 +347,62 @@ namespace Kyoo.Core.Controllers
|
|||||||
t.Episode = x;
|
t.Episode = x;
|
||||||
t.EpisodeID = x?.ID ?? 0;
|
t.EpisodeID = x?.ID ?? 0;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
(Genre g, nameof(Genre.Shows)) => ShowRepository
|
(Genre g, nameof(Genre.Shows)) => ShowRepository
|
||||||
.GetAll(x => x.Genres.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Genres.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => g.Shows = x),
|
.Then(x => g.Shows = x),
|
||||||
|
|
||||||
|
|
||||||
(Studio s, nameof(Studio.Shows)) => ShowRepository
|
(Studio s, nameof(Studio.Shows)) => ShowRepository
|
||||||
.GetAll(x => x.Studio.ID == obj.ID)
|
.GetAll(x => x.Studio.ID == obj.ID)
|
||||||
.Then(x => s.Shows = x),
|
.Then(x => s.Shows = x),
|
||||||
|
|
||||||
(Studio s, nameof(Studio.ExternalIDs)) => SetRelation(s,
|
(Studio s, nameof(Studio.ExternalIDs)) => SetRelation(s,
|
||||||
ProviderRepository.GetMetadataID<Studio>(x => x.ResourceID == obj.ID),
|
ProviderRepository.GetMetadataID<Studio>(x => x.ResourceID == obj.ID),
|
||||||
(x, y) => x.ExternalIDs = y,
|
(x, y) => x.ExternalIDs = y,
|
||||||
(x, y) => { x.ResourceID = y.ID; }),
|
(x, y) => { x.ResourceID = y.ID; }),
|
||||||
|
|
||||||
|
|
||||||
(People p, nameof(People.ExternalIDs)) => SetRelation(p,
|
(People p, nameof(People.ExternalIDs)) => SetRelation(p,
|
||||||
ProviderRepository.GetMetadataID<People>(x => x.ResourceID == obj.ID),
|
ProviderRepository.GetMetadataID<People>(x => x.ResourceID == obj.ID),
|
||||||
(x, y) => x.ExternalIDs = y,
|
(x, y) => x.ExternalIDs = y,
|
||||||
(x, y) => { x.ResourceID = y.ID; }),
|
(x, y) => { x.ResourceID = y.ID; }),
|
||||||
|
|
||||||
(People p, nameof(People.Roles)) => PeopleRepository
|
(People p, nameof(People.Roles)) => PeopleRepository
|
||||||
.GetFromPeople(obj.ID)
|
.GetFromPeople(obj.ID)
|
||||||
.Then(x => p.Roles = x),
|
.Then(x => p.Roles = x),
|
||||||
|
|
||||||
|
|
||||||
(Provider p, nameof(Provider.Libraries)) => LibraryRepository
|
(Provider p, nameof(Provider.Libraries)) => LibraryRepository
|
||||||
.GetAll(x => x.Providers.Any(y => y.ID == obj.ID))
|
.GetAll(x => x.Providers.Any(y => y.ID == obj.ID))
|
||||||
.Then(x => p.Libraries = x),
|
.Then(x => p.Libraries = x),
|
||||||
|
|
||||||
|
|
||||||
_ => throw new ArgumentException($"Couldn't find a way to load {memberName} of {obj.Slug}.")
|
_ => throw new ArgumentException($"Couldn't find a way to load {memberName} of {obj.Slug}.")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id,
|
public Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id,
|
||||||
Expression<Func<LibraryItem, bool>> where = null,
|
Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
return LibraryItemRepository.GetFromLibrary(id, where, sort, limit);
|
return LibraryItemRepository.GetFromLibrary(id, where, sort, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<LibraryItem>> GetItemsFromLibrary(string slug,
|
public Task<ICollection<LibraryItem>> GetItemsFromLibrary(string slug,
|
||||||
Expression<Func<LibraryItem, bool>> where = null,
|
Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
return LibraryItemRepository.GetFromLibrary(slug, where, sort, limit);
|
return LibraryItemRepository.GetFromLibrary(slug, where, sort, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID,
|
public Task<ICollection<PeopleRole>> GetPeopleFromShow(int showID,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
@ -411,16 +411,16 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug,
|
public Task<ICollection<PeopleRole>> GetPeopleFromShow(string showSlug,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
return PeopleRepository.GetFromShow(showSlug, where, sort, limit);
|
return PeopleRepository.GetFromShow(showSlug, where, sort, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<PeopleRole>> GetRolesFromPeople(int id,
|
public Task<ICollection<PeopleRole>> GetRolesFromPeople(int id,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
@ -454,7 +454,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<T>> GetAll<T>(Expression<Func<T, bool>> where = null,
|
public Task<ICollection<T>> GetAll<T>(Expression<Func<T, bool>> where = null,
|
||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return GetRepository<T>().GetAll(where, sort, limit);
|
return GetRepository<T>().GetAll(where, sort, limit);
|
||||||
@ -468,19 +468,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<ICollection<T>> Search<T>(string query)
|
public Task<ICollection<T>> Search<T>(string query)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return GetRepository<T>().Search(query);
|
return GetRepository<T>().Search(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<T> Create<T>(T item)
|
public Task<T> Create<T>(T item)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return GetRepository<T>().Create(item);
|
return GetRepository<T>().Create(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<T> CreateIfNotExists<T>(T item)
|
public Task<T> CreateIfNotExists<T>(T item)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
@ -496,21 +496,21 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task Delete<T>(T item)
|
public Task Delete<T>(T item)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return GetRepository<T>().Delete(item);
|
return GetRepository<T>().Delete(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task Delete<T>(int id)
|
public Task Delete<T>(int id)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return GetRepository<T>().Delete(id);
|
return GetRepository<T>().Delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task Delete<T>(string slug)
|
public Task Delete<T>(string slug)
|
||||||
where T : class, IResource
|
where T : class, IResource
|
||||||
{
|
{
|
||||||
return GetRepository<T>().Delete(slug);
|
return GetRepository<T>().Delete(slug);
|
||||||
|
@ -14,7 +14,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
logger.LogWarning("No permission validator has been enabled, all users will have all permissions");
|
logger.LogWarning("No permission validator has been enabled, all users will have all permissions");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IFilterMetadata Create(PermissionAttribute attribute)
|
public IFilterMetadata Create(PermissionAttribute attribute)
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The logger used by this class.
|
/// The logger used by this class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILogger<PluginManager> _logger;
|
private readonly ILogger<PluginManager> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of plugins that are currently loaded.
|
/// The list of plugins that are currently loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -93,7 +93,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
return Array.Empty<IPlugin>();
|
return Array.Empty<IPlugin>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void LoadPlugins(ICollection<IPlugin> plugins)
|
public void LoadPlugins(ICollection<IPlugin> plugins)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
_providers = providers.ToArray();
|
_providers = providers.ToArray();
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void UseProviders(IEnumerable<Provider> providers)
|
public override void UseProviders(IEnumerable<Provider> providers)
|
||||||
@ -71,9 +71,9 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
ret = Merger.Merge(ret, await provider.Get(ret));
|
ret = Merger.Merge(ret, await provider.Get(ret));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "The provider {Provider} could not get a {Type}",
|
_logger.LogError(ex, "The provider {Provider} could not get a {Type}",
|
||||||
provider.Provider.Name, typeof(T).Name);
|
provider.Provider.Name, typeof(T).Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,16 +85,16 @@ namespace Kyoo.Core.Controllers
|
|||||||
public override async Task<ICollection<T>> Search<T>(string query)
|
public override async Task<ICollection<T>> Search<T>(string query)
|
||||||
{
|
{
|
||||||
List<T> ret = new();
|
List<T> ret = new();
|
||||||
|
|
||||||
foreach (IMetadataProvider provider in _GetProviders())
|
foreach (IMetadataProvider provider in _GetProviders())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ret.AddRange(await provider.Search<T>(query));
|
ret.AddRange(await provider.Search<T>(query));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "The provider {Provider} could not search for {Type}",
|
_logger.LogError(ex, "The provider {Provider} could not search for {Type}",
|
||||||
provider.Provider.Name, typeof(T).Name);
|
provider.Provider.Name, typeof(T).Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
return path[(libraryPath?.Length ?? 0)..];
|
return path[(libraryPath?.Length ?? 0)..];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<(Collection, Show, Season, Episode)> Identify(string path)
|
public async Task<(Collection, Show, Season, Episode)> Identify(string path)
|
||||||
{
|
{
|
||||||
@ -77,21 +77,21 @@ namespace Kyoo.Core.Controllers
|
|||||||
Slug = Utility.ToSlug(match.Groups["Show"].Value),
|
Slug = Utility.ToSlug(match.Groups["Show"].Value),
|
||||||
Title = match.Groups["Show"].Value,
|
Title = match.Groups["Show"].Value,
|
||||||
Path = Path.GetDirectoryName(path),
|
Path = Path.GetDirectoryName(path),
|
||||||
StartAir = match.Groups["StartYear"].Success
|
StartAir = match.Groups["StartYear"].Success
|
||||||
? new DateTime(int.Parse(match.Groups["StartYear"].Value), 1, 1)
|
? new DateTime(int.Parse(match.Groups["StartYear"].Value), 1, 1)
|
||||||
: null
|
: null
|
||||||
},
|
},
|
||||||
season: null,
|
season: null,
|
||||||
episode: new Episode
|
episode: new Episode
|
||||||
{
|
{
|
||||||
SeasonNumber = match.Groups["Season"].Success
|
SeasonNumber = match.Groups["Season"].Success
|
||||||
? int.Parse(match.Groups["Season"].Value)
|
? int.Parse(match.Groups["Season"].Value)
|
||||||
: null,
|
: null,
|
||||||
EpisodeNumber = match.Groups["Episode"].Success
|
EpisodeNumber = match.Groups["Episode"].Success
|
||||||
? int.Parse(match.Groups["Episode"].Value)
|
? int.Parse(match.Groups["Episode"].Value)
|
||||||
: null,
|
: null,
|
||||||
AbsoluteNumber = match.Groups["Absolute"].Success
|
AbsoluteNumber = match.Groups["Absolute"].Success
|
||||||
? int.Parse(match.Groups["Absolute"].Value)
|
? int.Parse(match.Groups["Absolute"].Value)
|
||||||
: null,
|
: null,
|
||||||
Path = path
|
Path = path
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The database handle
|
/// The database handle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A provider repository to handle externalID creation and deletion
|
/// A provider repository to handle externalID creation and deletion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name;
|
protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name;
|
||||||
|
|
||||||
@ -58,12 +58,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
await _database.SaveChangesAsync($"Trying to insert a duplicated collection (slug {obj.Slug} already exists).");
|
await _database.SaveChangesAsync($"Trying to insert a duplicated collection (slug {obj.Slug} already exists).");
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override async Task Validate(Collection resource)
|
protected override async Task Validate(Collection resource)
|
||||||
{
|
{
|
||||||
await base.Validate(resource);
|
await base.Validate(resource);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(resource.Slug))
|
if (string.IsNullOrEmpty(resource.Slug))
|
||||||
throw new ArgumentException("The collection's slug must be set and not empty");
|
throw new ArgumentException("The collection's slug must be set and not empty");
|
||||||
if (string.IsNullOrEmpty(resource.Name))
|
if (string.IsNullOrEmpty(resource.Name))
|
||||||
@ -72,7 +72,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
if (resource.ExternalIDs != null)
|
if (resource.ExternalIDs != null)
|
||||||
{
|
{
|
||||||
foreach (MetadataID id in resource.ExternalIDs)
|
foreach (MetadataID id in resource.ExternalIDs)
|
||||||
{
|
{
|
||||||
id.Provider = _database.LocalEntity<Provider>(id.Provider.Slug)
|
id.Provider = _database.LocalEntity<Provider>(id.Provider.Slug)
|
||||||
?? await _providers.CreateIfNotExists(id.Provider);
|
?? await _providers.CreateIfNotExists(id.Provider);
|
||||||
id.ProviderID = id.Provider.ID;
|
id.ProviderID = id.Provider.ID;
|
||||||
@ -80,12 +80,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
_database.MetadataIds<Collection>().AttachRange(resource.ExternalIDs);
|
_database.MetadataIds<Collection>().AttachRange(resource.ExternalIDs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override async Task EditRelations(Collection resource, Collection changed, bool resetOld)
|
protected override async Task EditRelations(Collection resource, Collection changed, bool resetOld)
|
||||||
{
|
{
|
||||||
await Validate(changed);
|
await Validate(changed);
|
||||||
|
|
||||||
if (changed.ExternalIDs != null || resetOld)
|
if (changed.ExternalIDs != null || resetOld)
|
||||||
{
|
{
|
||||||
await Database.Entry(resource).Collection(x => x.ExternalIDs).LoadAsync();
|
await Database.Entry(resource).Collection(x => x.ExternalIDs).LoadAsync();
|
||||||
|
@ -29,7 +29,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// A track repository to handle creation and deletion of tracks related to the current episode.
|
/// A track repository to handle creation and deletion of tracks related to the current episode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ITrackRepository _tracks;
|
private readonly ITrackRepository _tracks;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Episode, object>> DefaultSort => x => x.EpisodeNumber;
|
protected override Expression<Func<Episode, object>> DefaultSort => x => x.EpisodeNumber;
|
||||||
|
|
||||||
@ -42,27 +42,27 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <param name="tracks">A track repository</param>
|
/// <param name="tracks">A track repository</param>
|
||||||
public EpisodeRepository(DatabaseContext database,
|
public EpisodeRepository(DatabaseContext database,
|
||||||
IProviderRepository providers,
|
IProviderRepository providers,
|
||||||
ITrackRepository tracks)
|
ITrackRepository tracks)
|
||||||
: base(database)
|
: base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
_tracks = tracks;
|
_tracks = tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber)
|
public Task<Episode> GetOrDefault(int showID, int seasonNumber, int episodeNumber)
|
||||||
{
|
{
|
||||||
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID
|
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID
|
||||||
&& x.SeasonNumber == seasonNumber
|
&& x.SeasonNumber == seasonNumber
|
||||||
&& x.EpisodeNumber == episodeNumber);
|
&& x.EpisodeNumber == episodeNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber)
|
public Task<Episode> GetOrDefault(string showSlug, int seasonNumber, int episodeNumber)
|
||||||
{
|
{
|
||||||
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
|
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
|
||||||
&& x.SeasonNumber == seasonNumber
|
&& x.SeasonNumber == seasonNumber
|
||||||
&& x.EpisodeNumber == episodeNumber);
|
&& x.EpisodeNumber == episodeNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,14 +87,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<Episode> GetAbsolute(int showID, int absoluteNumber)
|
public Task<Episode> GetAbsolute(int showID, int absoluteNumber)
|
||||||
{
|
{
|
||||||
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID
|
return _database.Episodes.FirstOrDefaultAsync(x => x.ShowID == showID
|
||||||
&& x.AbsoluteNumber == absoluteNumber);
|
&& x.AbsoluteNumber == absoluteNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<Episode> GetAbsolute(string showSlug, int absoluteNumber)
|
public Task<Episode> GetAbsolute(string showSlug, int absoluteNumber)
|
||||||
{
|
{
|
||||||
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
|
return _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
|
||||||
&& x.AbsoluteNumber == absoluteNumber);
|
&& x.AbsoluteNumber == absoluteNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<Episode> Create(Episode obj)
|
public override async Task<Episode> Create(Episode obj)
|
||||||
{
|
{
|
||||||
@ -146,7 +146,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (resource.Tracks == null)
|
if (resource.Tracks == null)
|
||||||
return resource;
|
return resource;
|
||||||
|
|
||||||
resource.Tracks = await resource.Tracks.SelectAsync(x =>
|
resource.Tracks = await resource.Tracks.SelectAsync(x =>
|
||||||
{
|
{
|
||||||
x.Episode = resource;
|
x.Episode = resource;
|
||||||
@ -156,7 +156,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
_database.Tracks.AttachRange(resource.Tracks);
|
_database.Tracks.AttachRange(resource.Tracks);
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override async Task Validate(Episode resource)
|
protected override async Task Validate(Episode resource)
|
||||||
{
|
{
|
||||||
@ -180,17 +180,17 @@ namespace Kyoo.Core.Controllers
|
|||||||
_database.MetadataIds<Episode>().AttachRange(resource.ExternalIDs);
|
_database.MetadataIds<Episode>().AttachRange(resource.ExternalIDs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task Delete(Episode obj)
|
public override async Task Delete(Episode obj)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
await obj.Tracks.ForEachAsync(x => _tracks.Delete(x));
|
await obj.Tracks.ForEachAsync(x => _tracks.Delete(x));
|
||||||
obj.ExternalIDs.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
|
obj.ExternalIDs.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The database handle
|
/// The database handle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Genre, object>> DefaultSort => x => x.Slug;
|
protected override Expression<Func<Genre, object>> DefaultSort => x => x.Slug;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="GenreRepository"/>.
|
/// Create a new <see cref="GenreRepository"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -34,7 +34,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="database">The database instance</param>
|
/// <param name="database">The database instance</param>
|
||||||
/// <param name="libraries">A lazy loaded library repository</param>
|
/// <param name="libraries">A lazy loaded library repository</param>
|
||||||
public LibraryItemRepository(DatabaseContext database,
|
public LibraryItemRepository(DatabaseContext database,
|
||||||
Lazy<ILibraryRepository> libraries)
|
Lazy<ILibraryRepository> libraries)
|
||||||
: base(database)
|
: base(database)
|
||||||
{
|
{
|
||||||
@ -42,13 +42,13 @@ namespace Kyoo.Core.Controllers
|
|||||||
_libraries = libraries;
|
_libraries = libraries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> GetOrDefault(int id)
|
public override Task<LibraryItem> GetOrDefault(int id)
|
||||||
{
|
{
|
||||||
return _database.LibraryItems.FirstOrDefaultAsync(x => x.ID == id);
|
return _database.LibraryItems.FirstOrDefaultAsync(x => x.ID == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> GetOrDefault(string slug)
|
public override Task<LibraryItem> GetOrDefault(string slug)
|
||||||
{
|
{
|
||||||
@ -83,27 +83,27 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> Create(LibraryItem obj)
|
public override Task<LibraryItem> Create(LibraryItem obj)
|
||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> CreateIfNotExists(LibraryItem obj)
|
public override Task<LibraryItem> CreateIfNotExists(LibraryItem obj)
|
||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task<LibraryItem> Edit(LibraryItem obj, bool resetOld)
|
public override Task<LibraryItem> Edit(LibraryItem obj, bool resetOld)
|
||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task Delete(int id)
|
public override Task Delete(int id)
|
||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task Delete(string slug)
|
public override Task Delete(string slug)
|
||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task Delete(LibraryItem obj)
|
public override Task Delete(LibraryItem obj)
|
||||||
=> throw new InvalidOperationException();
|
=> throw new InvalidOperationException();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -125,8 +125,8 @@ namespace Kyoo.Core.Controllers
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ICollection<LibraryItem>> GetFromLibrary(int id,
|
public async Task<ICollection<LibraryItem>> GetFromLibrary(int id,
|
||||||
Expression<Func<LibraryItem, bool>> where = null,
|
Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<LibraryItem> items = await ApplyFilters(LibraryRelatedQuery(x => x.ID == id),
|
ICollection<LibraryItem> items = await ApplyFilters(LibraryRelatedQuery(x => x.ID == id),
|
||||||
@ -137,11 +137,11 @@ namespace Kyoo.Core.Controllers
|
|||||||
throw new ItemNotFoundException();
|
throw new ItemNotFoundException();
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ICollection<LibraryItem>> GetFromLibrary(string slug,
|
public async Task<ICollection<LibraryItem>> GetFromLibrary(string slug,
|
||||||
Expression<Func<LibraryItem, bool>> where = null,
|
Expression<Func<LibraryItem, bool>> where = null,
|
||||||
Sort<LibraryItem> sort = default,
|
Sort<LibraryItem> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<LibraryItem> items = await ApplyFilters(LibraryRelatedQuery(x => x.Slug == slug),
|
ICollection<LibraryItem> items = await ApplyFilters(LibraryRelatedQuery(x => x.Slug == slug),
|
||||||
|
@ -24,7 +24,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// A provider repository to handle externalID creation and deletion
|
/// A provider repository to handle externalID creation and deletion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
|
protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
_providers = providers;
|
_providers = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Library>> Search(string query)
|
public override async Task<ICollection<Library>> Search(string query)
|
||||||
{
|
{
|
||||||
@ -65,14 +65,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
protected override async Task Validate(Library resource)
|
protected override async Task Validate(Library resource)
|
||||||
{
|
{
|
||||||
await base.Validate(resource);
|
await base.Validate(resource);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(resource.Slug))
|
if (string.IsNullOrEmpty(resource.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");
|
||||||
if (string.IsNullOrEmpty(resource.Name))
|
if (string.IsNullOrEmpty(resource.Name))
|
||||||
throw new ArgumentException("The library's name must be set and not empty");
|
throw new ArgumentException("The library's name must be set and not empty");
|
||||||
if (resource.Paths == null || !resource.Paths.Any())
|
if (resource.Paths == null || !resource.Paths.Any())
|
||||||
throw new ArgumentException("The library should have a least one path.");
|
throw new ArgumentException("The library should have a least one path.");
|
||||||
|
|
||||||
if (resource.Providers != null)
|
if (resource.Providers != null)
|
||||||
{
|
{
|
||||||
resource.Providers = await resource.Providers
|
resource.Providers = await resource.Providers
|
||||||
@ -99,7 +99,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The default sort order that will be used for this resource's type.
|
/// The default sort order that will be used for this resource's type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract Expression<Func<T, object>> DefaultSort { get; }
|
protected abstract Expression<Func<T, object>> DefaultSort { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new base <see cref="LocalRepository{T}"/> with the given database handle.
|
/// Create a new base <see cref="LocalRepository{T}"/> with the given database handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -57,7 +57,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
throw new ItemNotFoundException($"No {typeof(T).Name} found with the id {id}");
|
throw new ItemNotFoundException($"No {typeof(T).Name} found with the id {id}");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<T> Get(int id)
|
public virtual async Task<T> Get(int id)
|
||||||
{
|
{
|
||||||
@ -84,19 +84,19 @@ namespace Kyoo.Core.Controllers
|
|||||||
throw new ItemNotFoundException($"No {typeof(T).Name} found with the given predicate.");
|
throw new ItemNotFoundException($"No {typeof(T).Name} found with the given predicate.");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Task<T> GetOrDefault(int id)
|
public virtual Task<T> GetOrDefault(int id)
|
||||||
{
|
{
|
||||||
return Database.Set<T>().FirstOrDefaultAsync(x => x.ID == id);
|
return Database.Set<T>().FirstOrDefaultAsync(x => x.ID == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Task<T> GetOrDefault(string slug)
|
public virtual Task<T> GetOrDefault(string slug)
|
||||||
{
|
{
|
||||||
return Database.Set<T>().FirstOrDefaultAsync(x => x.Slug == slug);
|
return Database.Set<T>().FirstOrDefaultAsync(x => x.Slug == slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Task<T> GetOrDefault(Expression<Func<T, bool>> where)
|
public virtual Task<T> GetOrDefault(Expression<Func<T, bool>> where)
|
||||||
{
|
{
|
||||||
@ -105,7 +105,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public abstract Task<ICollection<T>> Search(string query);
|
public abstract Task<ICollection<T>> Search(string query);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
|
||||||
Sort<T> sort = default,
|
Sort<T> sort = default,
|
||||||
@ -113,7 +113,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
return ApplyFilters(Database.Set<T>(), where, sort, limit);
|
return ApplyFilters(Database.Set<T>(), where, sort, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply filters to a query to ease sort, pagination & where queries for resources of this repository
|
/// Apply filters to a query to ease sort, pagination & where queries for resources of this repository
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -124,12 +124,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <returns>The filtered query</returns>
|
/// <returns>The filtered query</returns>
|
||||||
protected Task<ICollection<T>> ApplyFilters(IQueryable<T> query,
|
protected Task<ICollection<T>> ApplyFilters(IQueryable<T> 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, GetOrDefault, DefaultSort, where, sort, limit);
|
return ApplyFilters(query, GetOrDefault, DefaultSort, where, sort, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apply filters to a query to ease sort, pagination & where queries for any resources types.
|
/// Apply filters to a query to ease sort, pagination & where queries for any resources types.
|
||||||
/// For resources of type <see cref="T"/>, see <see cref="ApplyFilters"/>
|
/// For resources of type <see cref="T"/>, see <see cref="ApplyFilters"/>
|
||||||
@ -145,17 +145,17 @@ namespace Kyoo.Core.Controllers
|
|||||||
Func<int, Task<TValue>> get,
|
Func<int, Task<TValue>> get,
|
||||||
Expression<Func<TValue, object>> defaultSort,
|
Expression<Func<TValue, object>> defaultSort,
|
||||||
Expression<Func<TValue, bool>> where = null,
|
Expression<Func<TValue, bool>> where = null,
|
||||||
Sort<TValue> sort = default,
|
Sort<TValue> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
if (where != null)
|
if (where != null)
|
||||||
query = query.Where(where);
|
query = query.Where(where);
|
||||||
|
|
||||||
Expression<Func<TValue, object>> sortKey = sort.Key ?? defaultSort;
|
Expression<Func<TValue, object>> sortKey = sort.Key ?? defaultSort;
|
||||||
Expression sortExpression = sortKey.Body.NodeType == ExpressionType.Convert
|
Expression sortExpression = sortKey.Body.NodeType == ExpressionType.Convert
|
||||||
? ((UnaryExpression)sortKey.Body).Operand
|
? ((UnaryExpression)sortKey.Body).Operand
|
||||||
: sortKey.Body;
|
: sortKey.Body;
|
||||||
|
|
||||||
if (typeof(Enum).IsAssignableFrom(sortExpression.Type))
|
if (typeof(Enum).IsAssignableFrom(sortExpression.Type))
|
||||||
throw new ArgumentException("Invalid sort key.");
|
throw new ArgumentException("Invalid sort key.");
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
T old = await GetOrDefault(obj.Slug);
|
T old = await GetOrDefault(obj.Slug);
|
||||||
if (old != null)
|
if (old != null)
|
||||||
return old;
|
return old;
|
||||||
|
|
||||||
return await Create(obj);
|
return await Create(obj);
|
||||||
}
|
}
|
||||||
catch (DuplicatedItemException)
|
catch (DuplicatedItemException)
|
||||||
@ -225,7 +225,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
T old = await GetWithTracking(edited.ID);
|
T old = await GetWithTracking(edited.ID);
|
||||||
|
|
||||||
if (resetOld)
|
if (resetOld)
|
||||||
old = Merger.Nullify(old);
|
old = Merger.Nullify(old);
|
||||||
Merger.Complete(old, edited, x => x.GetCustomAttribute<LoadableRelationAttribute>() == null);
|
Merger.Complete(old, edited, x => x.GetCustomAttribute<LoadableRelationAttribute>() == null);
|
||||||
@ -239,7 +239,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
Database.ChangeTracker.Clear();
|
Database.ChangeTracker.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An overridable method to edit relation of a resource.
|
/// An overridable method to edit relation of a resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -257,7 +257,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
return Validate(resource);
|
return Validate(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A method called just before saving a new resource to the database.
|
/// A method called just before saving a new resource to the database.
|
||||||
/// It is also called on the default implementation of <see cref="EditRelations"/>
|
/// It is also called on the default implementation of <see cref="EditRelations"/>
|
||||||
@ -278,7 +278,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
MethodInfo setter = typeof(T).GetProperty(nameof(resource.Slug))!.GetSetMethod();
|
MethodInfo setter = typeof(T).GetProperty(nameof(resource.Slug))!.GetSetMethod();
|
||||||
if (setter != null)
|
if (setter != null)
|
||||||
setter.Invoke(resource, new object[] {resource.Slug + '!'});
|
setter.Invoke(resource, new object[] { resource.Slug + '!' });
|
||||||
else
|
else
|
||||||
throw new ArgumentException("Resources slug can't be number only.");
|
throw new ArgumentException("Resources slug can't be number only.");
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public abstract Task Delete(T obj);
|
public abstract Task Delete(T obj);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task DeleteAll(Expression<Func<T, bool>> where)
|
public async Task DeleteAll(Expression<Func<T, bool>> where)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// A lazy loaded show repository to validate requests from shows.
|
/// A lazy loaded show repository to validate requests from shows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Lazy<IShowRepository> _shows;
|
private readonly Lazy<IShowRepository> _shows;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<People, object>> DefaultSort => x => x.Name;
|
protected override Expression<Func<People, object>> DefaultSort => x => x.Name;
|
||||||
|
|
||||||
@ -41,14 +41,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <param name="shows">A lazy loaded show repository</param>
|
/// <param name="shows">A lazy loaded show repository</param>
|
||||||
public PeopleRepository(DatabaseContext database,
|
public PeopleRepository(DatabaseContext database,
|
||||||
IProviderRepository providers,
|
IProviderRepository providers,
|
||||||
Lazy<IShowRepository> shows)
|
Lazy<IShowRepository> shows)
|
||||||
: base(database)
|
: base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
_shows = shows;
|
_shows = shows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<People>> Search(string query)
|
public override async Task<ICollection<People>> Search(string query)
|
||||||
@ -89,7 +89,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
foreach (PeopleRole role in resource.Roles)
|
foreach (PeopleRole role in resource.Roles)
|
||||||
{
|
{
|
||||||
role.Show = _database.LocalEntity<Show>(role.Show.Slug)
|
role.Show = _database.LocalEntity<Show>(role.Show.Slug)
|
||||||
?? await _shows.Value.CreateIfNotExists(role.Show);
|
?? await _shows.Value.CreateIfNotExists(role.Show);
|
||||||
role.ShowID = role.Show.ID;
|
role.ShowID = role.Show.ID;
|
||||||
_database.Entry(role).State = EntityState.Added;
|
_database.Entry(role).State = EntityState.Added;
|
||||||
@ -101,7 +101,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
protected override async Task EditRelations(People resource, People changed, bool resetOld)
|
protected override async Task EditRelations(People resource, People changed, bool resetOld)
|
||||||
{
|
{
|
||||||
await Validate(changed);
|
await Validate(changed);
|
||||||
|
|
||||||
if (changed.Roles != null || resetOld)
|
if (changed.Roles != null || resetOld)
|
||||||
{
|
{
|
||||||
await Database.Entry(resource).Collection(x => x.Roles).LoadAsync();
|
await Database.Entry(resource).Collection(x => x.Roles).LoadAsync();
|
||||||
@ -120,7 +120,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
obj.ExternalIDs.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
|
obj.ExternalIDs.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
|
||||||
obj.Roles.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
|
obj.Roles.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
|
||||||
@ -128,9 +128,9 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ICollection<PeopleRole>> GetFromShow(int showID,
|
public async Task<ICollection<PeopleRole>> GetFromShow(int showID,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||||
@ -151,7 +151,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
|
public async Task<ICollection<PeopleRole>> GetFromShow(string showSlug,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles
|
||||||
@ -169,11 +169,11 @@ namespace Kyoo.Core.Controllers
|
|||||||
role.ForPeople = true;
|
role.ForPeople = true;
|
||||||
return people;
|
return people;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ICollection<PeopleRole>> GetFromPeople(int id,
|
public async Task<ICollection<PeopleRole>> GetFromPeople(int id,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||||
@ -188,11 +188,11 @@ namespace Kyoo.Core.Controllers
|
|||||||
throw new ItemNotFoundException();
|
throw new ItemNotFoundException();
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<ICollection<PeopleRole>> GetFromPeople(string slug,
|
public async Task<ICollection<PeopleRole>> GetFromPeople(string slug,
|
||||||
Expression<Func<PeopleRole, bool>> where = null,
|
Expression<Func<PeopleRole, bool>> where = null,
|
||||||
Sort<PeopleRole> sort = default,
|
Sort<PeopleRole> sort = default,
|
||||||
Pagination limit = default)
|
Pagination limit = default)
|
||||||
{
|
{
|
||||||
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
ICollection<PeopleRole> roles = await ApplyFilters(_database.PeopleRoles
|
||||||
|
@ -50,7 +50,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
throw new ItemNotFoundException($"No season {seasonNumber} found for the show {showID}");
|
throw new ItemNotFoundException($"No season {seasonNumber} found for the show {showID}");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task<Season> Get(string showSlug, int seasonNumber)
|
public async Task<Season> Get(string showSlug, int seasonNumber)
|
||||||
{
|
{
|
||||||
@ -63,14 +63,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Task<Season> GetOrDefault(int showID, int seasonNumber)
|
public Task<Season> GetOrDefault(int showID, int seasonNumber)
|
||||||
{
|
{
|
||||||
return _database.Seasons.FirstOrDefaultAsync(x => x.ShowID == showID
|
return _database.Seasons.FirstOrDefaultAsync(x => x.ShowID == showID
|
||||||
&& x.SeasonNumber == seasonNumber);
|
&& x.SeasonNumber == seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Task<Season> GetOrDefault(string showSlug, int seasonNumber)
|
public Task<Season> GetOrDefault(string showSlug, int seasonNumber)
|
||||||
{
|
{
|
||||||
return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
|
return _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug
|
||||||
&& x.SeasonNumber == seasonNumber);
|
&& x.SeasonNumber == seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,14 +121,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
protected override async Task EditRelations(Season resource, Season changed, bool resetOld)
|
protected override async Task EditRelations(Season resource, Season changed, bool resetOld)
|
||||||
{
|
{
|
||||||
await Validate(changed);
|
await Validate(changed);
|
||||||
|
|
||||||
if (changed.ExternalIDs != null || resetOld)
|
if (changed.ExternalIDs != null || resetOld)
|
||||||
{
|
{
|
||||||
await Database.Entry(resource).Collection(x => x.ExternalIDs).LoadAsync();
|
await Database.Entry(resource).Collection(x => x.ExternalIDs).LoadAsync();
|
||||||
resource.ExternalIDs = changed.ExternalIDs;
|
resource.ExternalIDs = changed.ExternalIDs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override async Task Delete(Season obj)
|
public override async Task Delete(Season obj)
|
||||||
{
|
{
|
||||||
@ -139,4 +139,4 @@ namespace Kyoo.Core.Controllers
|
|||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,8 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// <param name="providers">A provider repository</param>
|
/// <param name="providers">A provider repository</param>
|
||||||
public ShowRepository(DatabaseContext database,
|
public ShowRepository(DatabaseContext database,
|
||||||
IStudioRepository studios,
|
IStudioRepository studios,
|
||||||
IPeopleRepository people,
|
IPeopleRepository people,
|
||||||
IGenreRepository genres,
|
IGenreRepository genres,
|
||||||
IProviderRepository providers)
|
IProviderRepository providers)
|
||||||
: base(database)
|
: base(database)
|
||||||
{
|
{
|
||||||
@ -61,7 +61,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
_genres = genres;
|
_genres = genres;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Show>> Search(string query)
|
public override async Task<ICollection<Show>> Search(string query)
|
||||||
@ -82,7 +82,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
await _database.SaveChangesAsync($"Trying to insert a duplicated show (slug {obj.Slug} already exists).");
|
await _database.SaveChangesAsync($"Trying to insert a duplicated show (slug {obj.Slug} already exists).");
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override async Task Validate(Show resource)
|
protected override async Task Validate(Show resource)
|
||||||
{
|
{
|
||||||
@ -128,7 +128,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
protected override async Task EditRelations(Show resource, Show changed, bool resetOld)
|
protected override async Task EditRelations(Show resource, Show changed, bool resetOld)
|
||||||
{
|
{
|
||||||
await Validate(changed);
|
await Validate(changed);
|
||||||
|
|
||||||
if (changed.Aliases != null || resetOld)
|
if (changed.Aliases != null || resetOld)
|
||||||
resource.Aliases = changed.Aliases;
|
resource.Aliases = changed.Aliases;
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
await Database.Entry(resource).Reference(x => x.Studio).LoadAsync();
|
await Database.Entry(resource).Reference(x => x.Studio).LoadAsync();
|
||||||
resource.Studio = changed.Studio;
|
resource.Studio = changed.Studio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed.Genres != null || resetOld)
|
if (changed.Genres != null || resetOld)
|
||||||
{
|
{
|
||||||
await Database.Entry(resource).Collection(x => x.Genres).LoadAsync();
|
await Database.Entry(resource).Collection(x => x.Genres).LoadAsync();
|
||||||
@ -177,7 +177,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
await _database.SaveIfNoDuplicates();
|
await _database.SaveIfNoDuplicates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<string> GetSlug(int showID)
|
public Task<string> GetSlug(int showID)
|
||||||
{
|
{
|
||||||
@ -185,7 +185,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
.Select(x => x.Slug)
|
.Select(x => x.Slug)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task Delete(Show obj)
|
public override async Task Delete(Show obj)
|
||||||
{
|
{
|
||||||
|
@ -19,12 +19,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The database handle
|
/// The database handle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A provider repository to handle externalID creation and deletion
|
/// A provider repository to handle externalID creation and deletion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IProviderRepository _providers;
|
private readonly IProviderRepository _providers;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Studio, object>> DefaultSort => x => x.Name;
|
protected override Expression<Func<Studio, object>> DefaultSort => x => x.Name;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
_database = database;
|
_database = database;
|
||||||
_providers = providers;
|
_providers = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<Studio>> Search(string query)
|
public override async Task<ICollection<Studio>> Search(string query)
|
||||||
{
|
{
|
||||||
@ -59,7 +59,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
await _database.SaveChangesAsync($"Trying to insert a duplicated studio (slug {obj.Slug} already exists).");
|
await _database.SaveChangesAsync($"Trying to insert a duplicated studio (slug {obj.Slug} already exists).");
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override async Task Validate(Studio resource)
|
protected override async Task Validate(Studio resource)
|
||||||
{
|
{
|
||||||
@ -75,7 +75,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
_database.MetadataIds<Studio>().AttachRange(resource.ExternalIDs);
|
_database.MetadataIds<Studio>().AttachRange(resource.ExternalIDs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override async Task EditRelations(Studio resource, Studio changed, bool resetOld)
|
protected override async Task EditRelations(Studio resource, Studio changed, bool resetOld)
|
||||||
{
|
{
|
||||||
@ -93,7 +93,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The database handle
|
/// The database handle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<Track, object>> DefaultSort => x => x.TrackIndex;
|
protected override Expression<Func<Track, object>> DefaultSort => x => x.TrackIndex;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// Create a new <see cref="TrackRepository"/>.
|
/// Create a new <see cref="TrackRepository"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="database">The database handle</param>
|
/// <param name="database">The database handle</param>
|
||||||
public TrackRepository(DatabaseContext database)
|
public TrackRepository(DatabaseContext database)
|
||||||
: base(database)
|
: base(database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
@ -69,7 +69,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The database handle
|
/// The database handle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly DatabaseContext _database;
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Expression<Func<User, object>> DefaultSort => x => x.Username;
|
protected override Expression<Func<User, object>> DefaultSort => x => x.Username;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="UserRepository"/>
|
/// Create a new <see cref="UserRepository"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,7 +33,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<ICollection<User>> Search(string query)
|
public override async Task<ICollection<User>> Search(string query)
|
||||||
{
|
{
|
||||||
@ -43,7 +43,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
.Take(20)
|
.Take(20)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task<User> Create(User obj)
|
public override async Task<User> Create(User obj)
|
||||||
{
|
{
|
||||||
@ -58,7 +58,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
|
||||||
_database.Entry(obj).State = EntityState.Deleted;
|
_database.Entry(obj).State = EntityState.Deleted;
|
||||||
await _database.SaveChangesAsync();
|
await _database.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The metadata for this task (the slug, and other useful information).
|
/// The metadata for this task (the slug, and other useful information).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TaskMetadataAttribute Metadata { get; set; }
|
public TaskMetadataAttribute Metadata { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The function used to create the task object.
|
/// The function used to create the task object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -53,23 +53,23 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// The task currently queued.
|
/// The task currently queued.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ManagedTask Task { get; init; }
|
public ManagedTask Task { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The progress reporter that this task should use.
|
/// The progress reporter that this task should use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IProgress<float> ProgressReporter { get; init; }
|
public IProgress<float> ProgressReporter { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The arguments to give to run the task with.
|
/// The arguments to give to run the task with.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, object> Arguments { get; init; }
|
public Dictionary<string, object> Arguments { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A token informing the task that it should be cancelled or not.
|
/// A token informing the task that it should be cancelled or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CancellationToken? CancellationToken { get; init; }
|
public CancellationToken? CancellationToken { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration instance used to get schedule information
|
/// The configuration instance used to get schedule information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -115,14 +115,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
Metadata = x.Metadata,
|
Metadata = x.Metadata,
|
||||||
ScheduledDate = GetNextTaskDate(x.Metadata.Slug)
|
ScheduledDate = GetNextTaskDate(x.Metadata.Slug)
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
if (_tasks.Any())
|
if (_tasks.Any())
|
||||||
_logger.LogTrace("Task manager initiated with: {Tasks}", _tasks.Select(x => x.Metadata.Name));
|
_logger.LogTrace("Task manager initiated with: {Tasks}", _tasks.Select(x => x.Metadata.Name));
|
||||||
else
|
else
|
||||||
_logger.LogInformation("Task manager initiated without any tasks");
|
_logger.LogInformation("Task manager initiated without any tasks");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered when the application host is ready to start the service.
|
/// Triggered when the application host is ready to start the service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -133,7 +133,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
Task.Run(() => base.StartAsync(cancellationToken), CancellationToken.None);
|
Task.Run(() => base.StartAsync(cancellationToken), CancellationToken.None);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task StopAsync(CancellationToken cancellationToken)
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@ -148,7 +148,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_EnqueueStartupTasks();
|
_EnqueueStartupTasks();
|
||||||
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
if (_queuedTasks.Any())
|
if (_queuedTasks.Any())
|
||||||
@ -160,12 +160,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
catch (TaskFailedException ex)
|
catch (TaskFailedException ex)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("The task \"{Task}\" failed: {Message}",
|
_logger.LogWarning("The task \"{Task}\" failed: {Message}",
|
||||||
task.Task.Metadata.Name, ex.Message);
|
task.Task.Metadata.Name, ex.Message);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.LogError(e, "An unhandled exception occured while running the task {Task}",
|
_logger.LogError(e, "An unhandled exception occured while running the task {Task}",
|
||||||
task.Task.Metadata.Name);
|
task.Task.Metadata.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// If the number of arguments is invalid, if an argument can't be converted or if the task finds the argument
|
/// If the number of arguments is invalid, if an argument can't be converted or if the task finds the argument
|
||||||
/// invalid.
|
/// invalid.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
private async Task _RunTask(ManagedTask task,
|
private async Task _RunTask(ManagedTask task,
|
||||||
[NotNull] IProgress<float> progress,
|
[NotNull] IProgress<float> progress,
|
||||||
Dictionary<string, object> arguments,
|
Dictionary<string, object> arguments,
|
||||||
CancellationToken? cancellationToken = null)
|
CancellationToken? cancellationToken = null)
|
||||||
@ -220,14 +220,14 @@ namespace Kyoo.Core.Controllers
|
|||||||
return x.CreateValue(value ?? x.DefaultValue);
|
return x.CreateValue(value ?? x.DefaultValue);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
_logger.LogInformation("Task starting: {Task} ({Parameters})",
|
_logger.LogInformation("Task starting: {Task} ({Parameters})",
|
||||||
task.Metadata.Name, args.ToDictionary(x => x.Name, x => x.As<object>()));
|
task.Metadata.Name, args.ToDictionary(x => x.Name, x => x.As<object>()));
|
||||||
|
|
||||||
CancellationToken token = cancellationToken != null
|
CancellationToken token = cancellationToken != null
|
||||||
? CancellationTokenSource.CreateLinkedTokenSource(_taskToken.Token, cancellationToken.Value).Token
|
? CancellationTokenSource.CreateLinkedTokenSource(_taskToken.Token, cancellationToken.Value).Token
|
||||||
: _taskToken.Token;
|
: _taskToken.Token;
|
||||||
await taskObj.Value.Run(args, progress, token);
|
await taskObj.Value.Run(args, progress, token);
|
||||||
|
|
||||||
_logger.LogInformation("Task finished: {Task}", task.Metadata.Name);
|
_logger.LogInformation("Task finished: {Task}", task.Metadata.Name);
|
||||||
_runningTask = null;
|
_runningTask = null;
|
||||||
}
|
}
|
||||||
@ -261,13 +261,13 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void StartTask(string taskSlug,
|
public void StartTask(string taskSlug,
|
||||||
IProgress<float> progress,
|
IProgress<float> progress,
|
||||||
Dictionary<string, object> arguments = null,
|
Dictionary<string, object> arguments = null,
|
||||||
CancellationToken? cancellationToken = null)
|
CancellationToken? cancellationToken = null)
|
||||||
{
|
{
|
||||||
arguments ??= new Dictionary<string, object>();
|
arguments ??= new Dictionary<string, object>();
|
||||||
|
|
||||||
int index = _tasks.FindIndex(x => x.Metadata.Slug == taskSlug);
|
int index = _tasks.FindIndex(x => x.Metadata.Slug == taskSlug);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
throw new ItemNotFoundException($"No task found with the slug {taskSlug}");
|
throw new ItemNotFoundException($"No task found with the slug {taskSlug}");
|
||||||
@ -276,13 +276,13 @@ namespace Kyoo.Core.Controllers
|
|||||||
Task = _tasks[index],
|
Task = _tasks[index],
|
||||||
ProgressReporter = progress,
|
ProgressReporter = progress,
|
||||||
Arguments = arguments,
|
Arguments = arguments,
|
||||||
CancellationToken = cancellationToken
|
CancellationToken = cancellationToken
|
||||||
});
|
});
|
||||||
_tasks[index].ScheduledDate = GetNextTaskDate(taskSlug);
|
_tasks[index].ScheduledDate = GetNextTaskDate(taskSlug);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void StartTask<T>(IProgress<float> progress,
|
public void StartTask<T>(IProgress<float> progress,
|
||||||
Dictionary<string, object> arguments = null,
|
Dictionary<string, object> arguments = null,
|
||||||
CancellationToken? cancellationToken = null)
|
CancellationToken? cancellationToken = null)
|
||||||
where T : ITask
|
where T : ITask
|
||||||
@ -304,12 +304,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
return DateTime.Now + delay;
|
return DateTime.Now + delay;
|
||||||
return DateTime.MaxValue;
|
return DateTime.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks()
|
public ICollection<(TaskMetadataAttribute, ITask)> GetRunningTasks()
|
||||||
{
|
{
|
||||||
return _runningTask == null
|
return _runningTask == null
|
||||||
? ArraySegment<(TaskMetadataAttribute, ITask)>.Empty
|
? ArraySegment<(TaskMetadataAttribute, ITask)>.Empty
|
||||||
: new[] { _runningTask.Value };
|
: new[] { _runningTask.Value };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="files">The file manager to use.</param>
|
/// <param name="files">The file manager to use.</param>
|
||||||
/// <param name="logger">A logger to report errors</param>
|
/// <param name="logger">A logger to report errors</param>
|
||||||
public ThumbnailsManager(IFileSystem files,
|
public ThumbnailsManager(IFileSystem files,
|
||||||
ILogger<ThumbnailsManager> logger)
|
ILogger<ThumbnailsManager> logger)
|
||||||
{
|
{
|
||||||
_files = files;
|
_files = files;
|
||||||
@ -66,7 +66,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<bool> DownloadImages<T>(T item, bool alwaysDownload = false)
|
public async Task<bool> DownloadImages<T>(T item, bool alwaysDownload = false)
|
||||||
where T : IThumbnails
|
where T : IThumbnails
|
||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
@ -84,7 +84,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
if (alwaysDownload || !await _files.Exists(localPath))
|
if (alwaysDownload || !await _files.Exists(localPath))
|
||||||
ret |= await _DownloadImage(image, localPath, $"The image n°{id} of {name}");
|
ret |= await _DownloadImage(image, localPath, $"The image n°{id} of {name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
throw new ArgumentNullException(nameof(item));
|
throw new ArgumentNullException(nameof(item));
|
||||||
|
|
||||||
string directory = await _files.GetExtraDirectory(item);
|
string directory = await _files.GetExtraDirectory(item);
|
||||||
string imageName = imageID switch
|
string imageName = imageID switch
|
||||||
{
|
{
|
||||||
@ -109,7 +109,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
Images.Trailer => "trailer",
|
Images.Trailer => "trailer",
|
||||||
_ => $"{imageID}"
|
_ => $"{imageID}"
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (item)
|
switch (item)
|
||||||
{
|
{
|
||||||
case Season season:
|
case Season season:
|
||||||
@ -123,7 +123,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
|
|
||||||
return _files.Combine(directory, imageName);
|
return _files.Combine(directory, imageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<string> GetImagePath<T>(T item, int imageID)
|
public async Task<string> GetImagePath<T>(T item, int imageID)
|
||||||
where T : IThumbnails
|
where T : IThumbnails
|
||||||
|
@ -13,8 +13,8 @@ using Stream = Kyoo.Core.Models.Watch.Stream;
|
|||||||
|
|
||||||
namespace Kyoo.Core.Controllers
|
namespace Kyoo.Core.Controllers
|
||||||
{
|
{
|
||||||
public class BadTranscoderException : Exception {}
|
public class BadTranscoderException : Exception { }
|
||||||
|
|
||||||
public class Transcoder : ITranscoder
|
public class Transcoder : ITranscoder
|
||||||
{
|
{
|
||||||
private static class TranscoderAPI
|
private static class TranscoderAPI
|
||||||
@ -26,7 +26,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
|
|
||||||
public static int Init() => init();
|
public static int Init() => init();
|
||||||
|
|
||||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl,
|
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl,
|
||||||
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||||
private static extern int transmux(string path, string outpath, out float playableDuration);
|
private static extern int transmux(string path, string outpath, out float playableDuration);
|
||||||
|
|
||||||
@ -37,9 +37,9 @@ namespace Kyoo.Core.Controllers
|
|||||||
return transmux(path, outPath, out playableDuration);
|
return transmux(path, outPath, out playableDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl,
|
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl,
|
||||||
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
|
||||||
private static extern IntPtr extract_infos(string path,
|
private static extern IntPtr extract_infos(string path,
|
||||||
string outpath,
|
string outpath,
|
||||||
out uint length,
|
out uint length,
|
||||||
out uint trackCount,
|
out uint trackCount,
|
||||||
@ -53,12 +53,12 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
path = path.Replace('\\', '/');
|
path = path.Replace('\\', '/');
|
||||||
outPath = outPath.Replace('\\', '/');
|
outPath = outPath.Replace('\\', '/');
|
||||||
|
|
||||||
int size = Marshal.SizeOf<Models.Watch.Stream>();
|
int size = Marshal.SizeOf<Models.Watch.Stream>();
|
||||||
IntPtr ptr = extract_infos(path, outPath, out uint arrayLength, out uint trackCount, reextract);
|
IntPtr ptr = extract_infos(path, outPath, out uint arrayLength, out uint trackCount, reextract);
|
||||||
IntPtr streamsPtr = ptr;
|
IntPtr streamsPtr = ptr;
|
||||||
Track[] tracks;
|
Track[] tracks;
|
||||||
|
|
||||||
if (trackCount > 0 && ptr != IntPtr.Zero)
|
if (trackCount > 0 && ptr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
tracks = new Track[trackCount];
|
tracks = new Track[trackCount];
|
||||||
@ -113,7 +113,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
{
|
{
|
||||||
if (!File.Exists(episode.Path))
|
if (!File.Exists(episode.Path))
|
||||||
throw new ArgumentException("Path does not exists. Can't transcode.");
|
throw new ArgumentException("Path does not exists. Can't transcode.");
|
||||||
|
|
||||||
string folder = Path.Combine(_options.Value.TransmuxPath, episode.Slug);
|
string folder = Path.Combine(_options.Value.TransmuxPath, episode.Slug);
|
||||||
string manifest = Path.Combine(folder, episode.Slug + ".m3u8");
|
string manifest = Path.Combine(folder, episode.Slug + ".m3u8");
|
||||||
float playableDuration = 0;
|
float playableDuration = 0;
|
||||||
@ -130,7 +130,7 @@ namespace Kyoo.Core.Controllers
|
|||||||
await Console.Error.WriteLineAsync($"Access to the path {manifest} is denied. Please change your transmux path in the config.");
|
await Console.Error.WriteLineAsync($"Access to the path {manifest} is denied. Please change your transmux path in the config.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
transmuxFailed = TranscoderAPI.Transmux(episode.Path, manifest, out playableDuration) != 0;
|
transmuxFailed = TranscoderAPI.Transmux(episode.Path, manifest, out playableDuration) != 0;
|
||||||
|
@ -29,10 +29,10 @@ namespace Kyoo.Core
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Slug => "core";
|
public string Slug => "core";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Name => "Core";
|
public string Name => "Core";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Description => "The core module containing default implementations.";
|
public string Description => "The core module containing default implementations.";
|
||||||
|
|
||||||
@ -66,11 +66,11 @@ namespace Kyoo.Core
|
|||||||
public void Configure(ContainerBuilder builder)
|
public void Configure(ContainerBuilder builder)
|
||||||
{
|
{
|
||||||
builder.RegisterModule<AttributedMetadataModule>();
|
builder.RegisterModule<AttributedMetadataModule>();
|
||||||
|
|
||||||
builder.RegisterComposite<FileSystemComposite, IFileSystem>().InstancePerLifetimeScope();
|
builder.RegisterComposite<FileSystemComposite, IFileSystem>().InstancePerLifetimeScope();
|
||||||
builder.RegisterType<LocalFileSystem>().As<IFileSystem>().SingleInstance();
|
builder.RegisterType<LocalFileSystem>().As<IFileSystem>().SingleInstance();
|
||||||
builder.RegisterType<HttpFileSystem>().As<IFileSystem>().SingleInstance();
|
builder.RegisterType<HttpFileSystem>().As<IFileSystem>().SingleInstance();
|
||||||
|
|
||||||
builder.RegisterType<TaskManager>().As<ITaskManager>().As<IHostedService>().SingleInstance();
|
builder.RegisterType<TaskManager>().As<ITaskManager>().As<IHostedService>().SingleInstance();
|
||||||
|
|
||||||
builder.RegisterType<ConfigurationManager>().As<IConfigurationManager>().SingleInstance();
|
builder.RegisterType<ConfigurationManager>().As<IConfigurationManager>().SingleInstance();
|
||||||
@ -78,7 +78,7 @@ namespace Kyoo.Core
|
|||||||
builder.RegisterType<ThumbnailsManager>().As<IThumbnailsManager>().InstancePerLifetimeScope();
|
builder.RegisterType<ThumbnailsManager>().As<IThumbnailsManager>().InstancePerLifetimeScope();
|
||||||
builder.RegisterType<LibraryManager>().As<ILibraryManager>().InstancePerLifetimeScope();
|
builder.RegisterType<LibraryManager>().As<ILibraryManager>().InstancePerLifetimeScope();
|
||||||
builder.RegisterType<RegexIdentifier>().As<IIdentifier>().SingleInstance();
|
builder.RegisterType<RegexIdentifier>().As<IIdentifier>().SingleInstance();
|
||||||
|
|
||||||
builder.RegisterComposite<ProviderComposite, IMetadataProvider>();
|
builder.RegisterComposite<ProviderComposite, IMetadataProvider>();
|
||||||
builder.Register(x => (AProviderComposite)x.Resolve<IMetadataProvider>());
|
builder.Register(x => (AProviderComposite)x.Resolve<IMetadataProvider>());
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ namespace Kyoo.Core
|
|||||||
|
|
||||||
builder.RegisterType<PassthroughPermissionValidator>().As<IPermissionValidator>()
|
builder.RegisterType<PassthroughPermissionValidator>().As<IPermissionValidator>()
|
||||||
.IfNotRegistered(typeof(IPermissionValidator));
|
.IfNotRegistered(typeof(IPermissionValidator));
|
||||||
|
|
||||||
builder.RegisterType<FileExtensionContentTypeProvider>().As<IContentTypeProvider>().SingleInstance()
|
builder.RegisterType<FileExtensionContentTypeProvider>().As<IContentTypeProvider>().SingleInstance()
|
||||||
.OnActivating(x =>
|
.OnActivating(x =>
|
||||||
{
|
{
|
||||||
@ -117,7 +117,7 @@ namespace Kyoo.Core
|
|||||||
x.Instance.Mappings[".m3u8"] = "application/x-mpegurl";
|
x.Instance.Mappings[".m3u8"] = "application/x-mpegurl";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Configure(IServiceCollection services)
|
public void Configure(IServiceCollection services)
|
||||||
{
|
{
|
||||||
@ -130,12 +130,12 @@ namespace Kyoo.Core
|
|||||||
x.SerializerSettings.ContractResolver = new JsonPropertyIgnorer(publicUrl);
|
x.SerializerSettings.ContractResolver = new JsonPropertyIgnorer(publicUrl);
|
||||||
x.SerializerSettings.Converters.Add(new PeopleRoleConverter());
|
x.SerializerSettings.Converters.Add(new PeopleRoleConverter());
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddResponseCompression(x =>
|
services.AddResponseCompression(x =>
|
||||||
{
|
{
|
||||||
x.EnableForHttps = true;
|
x.EnableForHttps = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddHttpClient();
|
services.AddHttpClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ namespace Kyoo.Core.Models.Watch
|
|||||||
".mkv",
|
".mkv",
|
||||||
".flv",
|
".flv",
|
||||||
".vob",
|
".vob",
|
||||||
".ogg",
|
".ogg",
|
||||||
".ogv",
|
".ogv",
|
||||||
".avi",
|
".avi",
|
||||||
".mts",
|
".mts",
|
||||||
@ -25,7 +25,7 @@ namespace Kyoo.Core.Models.Watch
|
|||||||
".ts",
|
".ts",
|
||||||
".mov",
|
".mov",
|
||||||
".qt",
|
".qt",
|
||||||
".asf",
|
".asf",
|
||||||
".mp4",
|
".mp4",
|
||||||
".m4p",
|
".m4p",
|
||||||
".m4v",
|
".m4v",
|
||||||
@ -48,11 +48,11 @@ namespace Kyoo.Core.Models.Watch
|
|||||||
{
|
{
|
||||||
return VideoExtensions.Contains(Path.GetExtension(filePath));
|
return VideoExtensions.Contains(Path.GetExtension(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The dictionary of known subtitles extensions and the name of the subtitle codec.
|
/// The dictionary of known subtitles extensions and the name of the subtitle codec.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly ImmutableDictionary<string, string> SubtitleExtensions = new Dictionary<string, string>
|
public static readonly ImmutableDictionary<string, string> SubtitleExtensions = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{".ass", "ass"},
|
{".ass", "ass"},
|
||||||
{".str", "subrip"}
|
{".str", "subrip"}
|
||||||
|
@ -32,7 +32,7 @@ namespace Kyoo.Core.Models.Options
|
|||||||
/// The temporary folder to cache transmuxed file.
|
/// The temporary folder to cache transmuxed file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TransmuxPath { get; set; } = "cached/transmux";
|
public string TransmuxPath { get; set; } = "cached/transmux";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The temporary folder to cache transcoded file.
|
/// The temporary folder to cache transcoded file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,12 +9,12 @@ namespace Kyoo.Core.Models.Options
|
|||||||
/// The path of this options
|
/// The path of this options
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string Path = "Media";
|
public const string Path = "Media";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A regex for episodes
|
/// A regex for episodes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] Regex { get; set; }
|
public string[] Regex { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A regex for subtitles
|
/// A regex for subtitles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -13,7 +13,7 @@ namespace Kyoo.Core.Models.Options
|
|||||||
/// The path of this options
|
/// The path of this options
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string Path = "Tasks";
|
public const string Path = "Tasks";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of tasks that can be run concurrently.
|
/// The number of tasks that can be run concurrently.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -14,17 +14,17 @@ namespace Kyoo.Core.Models.Watch
|
|||||||
/// The title of the stream.
|
/// The title of the stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The language of this stream (as a ISO-639-2 language code)
|
/// The language of this stream (as a ISO-639-2 language code)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Language { get; set; }
|
public string Language { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The codec of this stream.
|
/// The codec of this stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Codec { get; set; }
|
public string Codec { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this stream the default one of it's type?
|
/// Is this stream the default one of it's type?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -34,12 +34,12 @@ namespace Kyoo.Core.Models.Watch
|
|||||||
/// Is this stream tagged as forced?
|
/// Is this stream tagged as forced?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MarshalAs(UnmanagedType.I1)] public bool IsForced;
|
[MarshalAs(UnmanagedType.I1)] public bool IsForced;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The path of this track.
|
/// The path of this track.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeIgnore] public string Path { get; set; }
|
[SerializeIgnore] public string Path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of this stream.
|
/// The type of this stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -69,7 +69,7 @@ namespace Kyoo.Core
|
|||||||
{
|
{
|
||||||
foreach (IPlugin plugin in _plugins.GetAllPlugins())
|
foreach (IPlugin plugin in _plugins.GetAllPlugins())
|
||||||
plugin.Configure(services);
|
plugin.Configure(services);
|
||||||
|
|
||||||
IEnumerable<KeyValuePair<string, Type>> configTypes = _plugins.GetAllPlugins()
|
IEnumerable<KeyValuePair<string, Type>> configTypes = _plugins.GetAllPlugins()
|
||||||
.SelectMany(x => x.Configuration)
|
.SelectMany(x => x.Configuration)
|
||||||
.Where(x => x.Value != null);
|
.Where(x => x.Value != null);
|
||||||
@ -92,7 +92,7 @@ namespace Kyoo.Core
|
|||||||
{
|
{
|
||||||
builder.RegisterInstance(_plugins).As<IPluginManager>().ExternallyOwned();
|
builder.RegisterInstance(_plugins).As<IPluginManager>().ExternallyOwned();
|
||||||
builder.RegisterTask<PluginInitializer>();
|
builder.RegisterTask<PluginInitializer>();
|
||||||
|
|
||||||
foreach (IPlugin plugin in _plugins.GetAllPlugins())
|
foreach (IPlugin plugin in _plugins.GetAllPlugins())
|
||||||
plugin.Configure(builder);
|
plugin.Configure(builder);
|
||||||
}
|
}
|
||||||
@ -125,8 +125,8 @@ namespace Kyoo.Core
|
|||||||
foreach ((string path, Type type) in pluginConfig)
|
foreach ((string path, Type type) in pluginConfig)
|
||||||
config.Register(path, type);
|
config.Register(path, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="PluginsStartup"/> from a webhost.
|
/// Create a new <see cref="PluginsStartup"/> from a webhost.
|
||||||
/// This is meant to be used from <see cref="WebHostBuilderExtensions.UseStartup"/>.
|
/// This is meant to be used from <see cref="WebHostBuilderExtensions.UseStartup"/>.
|
||||||
@ -136,7 +136,7 @@ namespace Kyoo.Core
|
|||||||
/// The logger factory used to log while the application is setting itself up.
|
/// The logger factory used to log while the application is setting itself up.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>A new <see cref="PluginsStartup"/>.</returns>
|
/// <returns>A new <see cref="PluginsStartup"/>.</returns>
|
||||||
public static PluginsStartup FromWebHost(WebHostBuilderContext host,
|
public static PluginsStartup FromWebHost(WebHostBuilderContext host,
|
||||||
ILoggerFactory logger)
|
ILoggerFactory logger)
|
||||||
{
|
{
|
||||||
HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger);
|
HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger);
|
||||||
@ -147,7 +147,7 @@ namespace Kyoo.Core
|
|||||||
);
|
);
|
||||||
return new PluginsStartup(plugins, host.Configuration);
|
return new PluginsStartup(plugins, host.Configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A simple host service provider used to activate plugins instance.
|
/// A simple host service provider used to activate plugins instance.
|
||||||
/// The same services as a generic host are available and an <see cref="ILoggerFactory"/> has been added.
|
/// The same services as a generic host are available and an <see cref="ILoggerFactory"/> has been added.
|
||||||
@ -158,18 +158,18 @@ namespace Kyoo.Core
|
|||||||
/// The host environment that could be used by plugins to configure themself.
|
/// The host environment that could be used by plugins to configure themself.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IWebHostEnvironment _hostEnvironment;
|
private readonly IWebHostEnvironment _hostEnvironment;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration context.
|
/// The configuration context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A logger factory used to create a logger for the plugin manager.
|
/// A logger factory used to create a logger for the plugin manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new <see cref="HostServiceProvider"/> that will return given services when asked.
|
/// Create a new <see cref="HostServiceProvider"/> that will return given services when asked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -52,8 +52,8 @@ namespace Kyoo.Core.Tasks
|
|||||||
_taskManager = taskManager;
|
_taskManager = taskManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TaskParameters GetParameters()
|
public TaskParameters GetParameters()
|
||||||
{
|
{
|
||||||
@ -67,9 +67,9 @@ namespace Kyoo.Core.Tasks
|
|||||||
public async Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
public async Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
string argument = arguments["slug"].As<string>();
|
string argument = arguments["slug"].As<string>();
|
||||||
ICollection<Library> libraries = argument == null
|
ICollection<Library> libraries = argument == null
|
||||||
? await _libraryManager.GetAll<Library>()
|
? await _libraryManager.GetAll<Library>()
|
||||||
: new [] { await _libraryManager.GetOrDefault<Library>(argument)};
|
: new[] { await _libraryManager.GetOrDefault<Library>(argument) };
|
||||||
|
|
||||||
if (argument != null && libraries.First() == null)
|
if (argument != null && libraries.First() == null)
|
||||||
throw new ArgumentException($"No library found with the name {argument}");
|
throw new ArgumentException($"No library found with the name {argument}");
|
||||||
@ -79,7 +79,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
|
|
||||||
progress.Report(0);
|
progress.Report(0);
|
||||||
float percent = 0;
|
float percent = 0;
|
||||||
|
|
||||||
ICollection<Episode> episodes = await _libraryManager.GetAll<Episode>();
|
ICollection<Episode> episodes = await _libraryManager.GetAll<Episode>();
|
||||||
ICollection<Track> tracks = await _libraryManager.GetAll<Track>();
|
ICollection<Track> tracks = await _libraryManager.GetAll<Track>();
|
||||||
foreach (Library library in libraries)
|
foreach (Library library in libraries)
|
||||||
@ -91,15 +91,15 @@ namespace Kyoo.Core.Tasks
|
|||||||
});
|
});
|
||||||
await Scan(library, episodes, tracks, reporter, cancellationToken);
|
await Scan(library, episodes, tracks, reporter, cancellationToken);
|
||||||
percent += 100f / libraries.Count;
|
percent += 100f / libraries.Count;
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Scan(Library library,
|
private async Task Scan(Library library,
|
||||||
IEnumerable<Episode> episodes,
|
IEnumerable<Episode> episodes,
|
||||||
IEnumerable<Track> tracks,
|
IEnumerable<Track> tracks,
|
||||||
IProgress<float> progress,
|
IProgress<float> progress,
|
||||||
@ -109,7 +109,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
foreach (string path in library.Paths)
|
foreach (string path in library.Paths)
|
||||||
{
|
{
|
||||||
ICollection<string> files = await _fileSystem.ListFiles(path, SearchOption.AllDirectories);
|
ICollection<string> files = await _fileSystem.ListFiles(path, SearchOption.AllDirectories);
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -121,8 +121,8 @@ namespace Kyoo.Core.Tasks
|
|||||||
.Where(x => episodes.All(y => y.Path != x))
|
.Where(x => episodes.All(y => y.Path != x))
|
||||||
.GroupBy(Path.GetDirectoryName)
|
.GroupBy(Path.GetDirectoryName)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|
||||||
string[] paths = shows.Select(x => x.First())
|
string[] paths = shows.Select(x => x.First())
|
||||||
.Concat(shows.SelectMany(x => x.Skip(1)))
|
.Concat(shows.SelectMany(x => x.Skip(1)))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@ -132,7 +132,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
// ReSharper disable once AccessToModifiedClosure
|
// ReSharper disable once AccessToModifiedClosure
|
||||||
progress.Report((percent + x / paths.Length - 10) / library.Paths.Length);
|
progress.Report((percent + x / paths.Length - 10) / library.Paths.Length);
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (string episodePath in paths)
|
foreach (string episodePath in paths)
|
||||||
{
|
{
|
||||||
_taskManager.StartTask<RegisterEpisode>(reporter, new Dictionary<string, object>
|
_taskManager.StartTask<RegisterEpisode>(reporter, new Dictionary<string, object>
|
||||||
@ -143,7 +143,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
percent += 100f / paths.Length;
|
percent += 100f / paths.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string[] subtitles = files
|
string[] subtitles = files
|
||||||
.Where(FileExtensions.IsSubtitle)
|
.Where(FileExtensions.IsSubtitle)
|
||||||
.Where(x => !x.Contains("Extra"))
|
.Where(x => !x.Contains("Extra"))
|
||||||
@ -155,7 +155,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
// ReSharper disable once AccessToModifiedClosure
|
// ReSharper disable once AccessToModifiedClosure
|
||||||
progress.Report((90 + (percent + x / subtitles.Length)) / library.Paths.Length);
|
progress.Report((90 + (percent + x / subtitles.Length)) / library.Paths.Length);
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (string trackPath in subtitles)
|
foreach (string trackPath in subtitles)
|
||||||
{
|
{
|
||||||
_taskManager.StartTask<RegisterSubtitle>(reporter, new Dictionary<string, object>
|
_taskManager.StartTask<RegisterSubtitle>(reporter, new Dictionary<string, object>
|
||||||
|
@ -57,10 +57,10 @@ namespace Kyoo.Core.Tasks
|
|||||||
{
|
{
|
||||||
progress.Report(count / delCount * 100);
|
progress.Report(count / delCount * 100);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (await _fileSystem.Exists(show.Path))
|
if (await _fileSystem.Exists(show.Path))
|
||||||
continue;
|
continue;
|
||||||
_logger.LogWarning("Show {Name}'s folder has been deleted (was {Path}), removing it from kyoo",
|
_logger.LogWarning("Show {Name}'s folder has been deleted (was {Path}), removing it from kyoo",
|
||||||
show.Title, show.Path);
|
show.Title, show.Path);
|
||||||
await _libraryManager.Delete(show);
|
await _libraryManager.Delete(show);
|
||||||
}
|
}
|
||||||
@ -69,14 +69,14 @@ namespace Kyoo.Core.Tasks
|
|||||||
{
|
{
|
||||||
progress.Report(count / delCount * 100);
|
progress.Report(count / delCount * 100);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (await _fileSystem.Exists(episode.Path))
|
if (await _fileSystem.Exists(episode.Path))
|
||||||
continue;
|
continue;
|
||||||
_logger.LogWarning("Episode {Slug}'s file has been deleted (was {Path}), removing it from kyoo",
|
_logger.LogWarning("Episode {Slug}'s file has been deleted (was {Path}), removing it from kyoo",
|
||||||
episode.Slug, episode.Path);
|
episode.Slug, episode.Path);
|
||||||
await _libraryManager.Delete(episode);
|
await _libraryManager.Delete(episode);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
/// <param name="metadataProviders">
|
/// <param name="metadataProviders">
|
||||||
/// The list of metadata providers to register.
|
/// The list of metadata providers to register.
|
||||||
/// </param>
|
/// </param>
|
||||||
public MetadataProviderLoader(IProviderRepository providers,
|
public MetadataProviderLoader(IProviderRepository providers,
|
||||||
IThumbnailsManager thumbnails,
|
IThumbnailsManager thumbnails,
|
||||||
ICollection<IMetadataProvider> metadataProviders)
|
ICollection<IMetadataProvider> metadataProviders)
|
||||||
{
|
{
|
||||||
@ -61,7 +61,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
{
|
{
|
||||||
float percent = 0;
|
float percent = 0;
|
||||||
progress.Report(0);
|
progress.Report(0);
|
||||||
|
|
||||||
foreach (IMetadataProvider provider in _metadataProviders)
|
foreach (IMetadataProvider provider in _metadataProviders)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(provider.Provider.Slug))
|
if (string.IsNullOrEmpty(provider.Provider.Slug))
|
||||||
|
@ -10,7 +10,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A task run on Kyoo's startup to initialize plugins
|
/// A task run on Kyoo's startup to initialize plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TaskMetadata("plugin-init", "Plugin Initializer", "A task to initialize plugins.",
|
[TaskMetadata("plugin-init", "Plugin Initializer", "A task to initialize plugins.",
|
||||||
RunOnStartup = true, Priority = int.MaxValue, IsHidden = true)]
|
RunOnStartup = true, Priority = int.MaxValue, IsHidden = true)]
|
||||||
public class PluginInitializer : ITask
|
public class PluginInitializer : ITask
|
||||||
{
|
{
|
||||||
@ -33,14 +33,14 @@ namespace Kyoo.Core.Tasks
|
|||||||
_pluginManager = pluginManager;
|
_pluginManager = pluginManager;
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TaskParameters GetParameters()
|
public TaskParameters GetParameters()
|
||||||
{
|
{
|
||||||
return new();
|
return new();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
public Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@ -51,11 +51,11 @@ namespace Kyoo.Core.Tasks
|
|||||||
foreach (IPlugin plugin in plugins)
|
foreach (IPlugin plugin in plugins)
|
||||||
{
|
{
|
||||||
plugin.Initialize(_provider);
|
plugin.Initialize(_provider);
|
||||||
|
|
||||||
progress.Report(count / plugins.Count * 100);
|
progress.Report(count / plugins.Count * 100);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
TaskParameter.CreateRequired<Library>("library", "The library in witch the episode is")
|
TaskParameter.CreateRequired<Library>("library", "The library in witch the episode is")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
public async Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@ -148,7 +148,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
throw new TaskFailedException(ex);
|
throw new TaskFailedException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieve the equivalent item if it already exists in the database,
|
/// Retrieve the equivalent item if it already exists in the database,
|
||||||
/// if it does not, fill metadata using the metadata provider, download images and register the item to the
|
/// if it does not, fill metadata using the metadata provider, download images and register the item to the
|
||||||
@ -172,7 +172,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
|
|
||||||
item = await _metadataProvider.Get(item);
|
item = await _metadataProvider.Get(item);
|
||||||
await _thumbnailsManager.DownloadImages(item);
|
await _thumbnailsManager.DownloadImages(item);
|
||||||
|
|
||||||
switch (item)
|
switch (item)
|
||||||
{
|
{
|
||||||
case Show show when show.People != null:
|
case Show show when show.People != null:
|
||||||
|
@ -42,7 +42,7 @@ namespace Kyoo.Core.Tasks
|
|||||||
TaskParameter.CreateRequired<string>("path", "The path of the subtitle file")
|
TaskParameter.CreateRequired<string>("path", "The path of the subtitle file")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
public async Task Run(TaskParameters arguments, IProgress<float> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -22,17 +22,17 @@ namespace Kyoo.Core.Api
|
|||||||
private readonly IFileSystem _files;
|
private readonly IFileSystem _files;
|
||||||
private readonly IThumbnailsManager _thumbs;
|
private readonly IThumbnailsManager _thumbs;
|
||||||
|
|
||||||
public CollectionApi(ILibraryManager libraryManager,
|
public CollectionApi(ILibraryManager libraryManager,
|
||||||
IFileSystem files,
|
IFileSystem files,
|
||||||
IThumbnailsManager thumbs,
|
IThumbnailsManager thumbs,
|
||||||
IOptions<BasicOptions> options)
|
IOptions<BasicOptions> options)
|
||||||
: base(libraryManager.CollectionRepository, options.Value.PublicUrl)
|
: base(libraryManager.CollectionRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_files = files;
|
_files = files;
|
||||||
_thumbs = thumbs;
|
_thumbs = thumbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id:int}/show")]
|
[HttpGet("{id:int}/show")]
|
||||||
[HttpGet("{id:int}/shows")]
|
[HttpGet("{id:int}/shows")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -55,10 +55,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}/show")]
|
[HttpGet("{slug}/show")]
|
||||||
[HttpGet("{slug}/shows")]
|
[HttpGet("{slug}/shows")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -81,10 +81,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id:int}/library")]
|
[HttpGet("{id:int}/library")]
|
||||||
[HttpGet("{id:int}/libraries")]
|
[HttpGet("{id:int}/libraries")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -107,10 +107,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}/library")]
|
[HttpGet("{slug}/library")]
|
||||||
[HttpGet("{slug}/libraries")]
|
[HttpGet("{slug}/libraries")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -133,10 +133,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}/poster")]
|
[HttpGet("{slug}/poster")]
|
||||||
public async Task<IActionResult> GetPoster(string slug)
|
public async Task<IActionResult> GetPoster(string slug)
|
||||||
{
|
{
|
||||||
@ -150,7 +150,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}/logo")]
|
[HttpGet("{slug}/logo")]
|
||||||
public async Task<IActionResult> GetLogo(string slug)
|
public async Task<IActionResult> GetLogo(string slug)
|
||||||
{
|
{
|
||||||
@ -164,7 +164,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}/backdrop")]
|
[HttpGet("{slug}/backdrop")]
|
||||||
[HttpGet("{slug}/thumbnail")]
|
[HttpGet("{slug}/thumbnail")]
|
||||||
public async Task<IActionResult> GetBackdrop(string slug)
|
public async Task<IActionResult> GetBackdrop(string slug)
|
||||||
|
@ -25,7 +25,7 @@ namespace Kyoo.Core.Api
|
|||||||
public EpisodeApi(ILibraryManager libraryManager,
|
public EpisodeApi(ILibraryManager libraryManager,
|
||||||
IOptions<BasicOptions> options,
|
IOptions<BasicOptions> options,
|
||||||
IFileSystem files,
|
IFileSystem files,
|
||||||
IThumbnailsManager thumbnails)
|
IThumbnailsManager thumbnails)
|
||||||
: base(libraryManager.EpisodeRepository, options.Value.PublicUrl)
|
: base(libraryManager.EpisodeRepository, options.Value.PublicUrl)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
@ -37,12 +37,12 @@ namespace Kyoo.Core.Api
|
|||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
public async Task<ActionResult<Show>> GetShow(int episodeID)
|
public async Task<ActionResult<Show>> GetShow(int episodeID)
|
||||||
{
|
{
|
||||||
Show ret = await _libraryManager.GetOrDefault<Show>(x => x.Episodes.Any(y => y.ID == episodeID));
|
Show ret = await _libraryManager.GetOrDefault<Show>(x => x.Episodes.Any(y => y.ID == episodeID));
|
||||||
if (ret == null)
|
if (ret == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}/show")]
|
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}/show")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
public async Task<ActionResult<Show>> GetShow(string showSlug, int seasonNumber, int episodeNumber)
|
public async Task<ActionResult<Show>> GetShow(string showSlug, int seasonNumber, int episodeNumber)
|
||||||
@ -52,7 +52,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{showID:int}-{seasonNumber:int}e{episodeNumber:int}/show")]
|
[HttpGet("{showID:int}-{seasonNumber:int}e{episodeNumber:int}/show")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
public async Task<ActionResult<Show>> GetShow(int showID, int seasonNumber, int episodeNumber)
|
public async Task<ActionResult<Show>> GetShow(int showID, int seasonNumber, int episodeNumber)
|
||||||
@ -62,7 +62,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{episodeID:int}/season")]
|
[HttpGet("{episodeID:int}/season")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
public async Task<ActionResult<Season>> GetSeason(int episodeID)
|
public async Task<ActionResult<Season>> GetSeason(int episodeID)
|
||||||
@ -72,7 +72,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}/season")]
|
[HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}/season")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
public async Task<ActionResult<Season>> GetSeason(string showSlug, int seasonNumber, int episodeNumber)
|
public async Task<ActionResult<Season>> GetSeason(string showSlug, int seasonNumber, int episodeNumber)
|
||||||
@ -86,7 +86,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{showID:int}-{seasonNumber:int}e{episodeNumber:int}/season")]
|
[HttpGet("{showID:int}-{seasonNumber:int}e{episodeNumber:int}/season")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
public async Task<ActionResult<Season>> GetSeason(int showID, int seasonNumber, int episodeNumber)
|
public async Task<ActionResult<Season>> GetSeason(int showID, int seasonNumber, int episodeNumber)
|
||||||
@ -100,7 +100,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{episodeID:int}/track")]
|
[HttpGet("{episodeID:int}/track")]
|
||||||
[HttpGet("{episodeID:int}/tracks")]
|
[HttpGet("{episodeID:int}/tracks")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -123,10 +123,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{showID:int}-s{seasonNumber:int}e{episodeNumber:int}/track")]
|
[HttpGet("{showID:int}-s{seasonNumber:int}e{episodeNumber:int}/track")]
|
||||||
[HttpGet("{showID:int}-s{seasonNumber:int}e{episodeNumber:int}/tracks")]
|
[HttpGet("{showID:int}-s{seasonNumber:int}e{episodeNumber:int}/tracks")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -141,7 +141,7 @@ namespace Kyoo.Core.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ICollection<Track> resources = await _libraryManager.GetAll(
|
ICollection<Track> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere<Track>(where, x => x.Episode.ShowID == showID
|
ApiHelper.ParseWhere<Track>(where, x => x.Episode.ShowID == showID
|
||||||
&& x.Episode.SeasonNumber == seasonNumber
|
&& x.Episode.SeasonNumber == seasonNumber
|
||||||
&& x.Episode.EpisodeNumber == episodeNumber),
|
&& x.Episode.EpisodeNumber == episodeNumber),
|
||||||
new Sort<Track>(sortBy),
|
new Sort<Track>(sortBy),
|
||||||
@ -153,10 +153,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}-s{seasonNumber:int}e{episodeNumber:int}/track")]
|
[HttpGet("{slug}-s{seasonNumber:int}e{episodeNumber:int}/track")]
|
||||||
[HttpGet("{slug}-s{seasonNumber:int}e{episodeNumber:int}/tracks")]
|
[HttpGet("{slug}-s{seasonNumber:int}e{episodeNumber:int}/tracks")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -171,7 +171,7 @@ namespace Kyoo.Core.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ICollection<Track> resources = await _libraryManager.GetAll(
|
ICollection<Track> resources = await _libraryManager.GetAll(
|
||||||
ApiHelper.ParseWhere<Track>(where, x => x.Episode.Show.Slug == slug
|
ApiHelper.ParseWhere<Track>(where, x => x.Episode.Show.Slug == slug
|
||||||
&& x.Episode.SeasonNumber == seasonNumber
|
&& x.Episode.SeasonNumber == seasonNumber
|
||||||
&& x.Episode.EpisodeNumber == episodeNumber),
|
&& x.Episode.EpisodeNumber == episodeNumber),
|
||||||
new Sort<Track>(sortBy),
|
new Sort<Track>(sortBy),
|
||||||
@ -183,10 +183,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id:int}/thumbnail")]
|
[HttpGet("{id:int}/thumbnail")]
|
||||||
[HttpGet("{id:int}/backdrop")]
|
[HttpGet("{id:int}/backdrop")]
|
||||||
public async Task<IActionResult> GetThumb(int id)
|
public async Task<IActionResult> GetThumb(int id)
|
||||||
@ -201,7 +201,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}/thumbnail")]
|
[HttpGet("{slug}/thumbnail")]
|
||||||
[HttpGet("{slug}/backdrop")]
|
[HttpGet("{slug}/backdrop")]
|
||||||
public async Task<IActionResult> GetThumb(string slug)
|
public async Task<IActionResult> GetThumb(string slug)
|
||||||
@ -217,4 +217,4 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id:int}/show")]
|
[HttpGet("{id:int}/show")]
|
||||||
[HttpGet("{id:int}/shows")]
|
[HttpGet("{id:int}/shows")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -47,10 +47,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{slug}/show")]
|
[HttpGet("{slug}/show")]
|
||||||
[HttpGet("{slug}/shows")]
|
[HttpGet("{slug}/shows")]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
@ -73,7 +73,7 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
return operand(left, right);
|
return operand(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Expression<Func<T, bool>> ParseWhere<T>(Dictionary<string, string> where,
|
public static Expression<Func<T, bool>> ParseWhere<T>(Dictionary<string, string> where,
|
||||||
Expression<Func<T, bool>> defaultWhere = null)
|
Expression<Func<T, bool>> defaultWhere = null)
|
||||||
{
|
{
|
||||||
if (where == null || where.Count == 0)
|
if (where == null || where.Count == 0)
|
||||||
@ -35,7 +35,7 @@ namespace Kyoo.Core.Api
|
|||||||
{
|
{
|
||||||
if (key == null || desired == null)
|
if (key == null || desired == null)
|
||||||
throw new ArgumentException("Invalid key/value pair. Can't be null.");
|
throw new ArgumentException("Invalid key/value pair. Can't be null.");
|
||||||
|
|
||||||
string value = desired;
|
string value = desired;
|
||||||
string operand = "eq";
|
string operand = "eq";
|
||||||
if (desired.Contains(':'))
|
if (desired.Contains(':'))
|
||||||
@ -68,15 +68,15 @@ namespace Kyoo.Core.Api
|
|||||||
|
|
||||||
valueExpr = Expression.Constant(val, property.PropertyType);
|
valueExpr = Expression.Constant(val, property.PropertyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression condition = operand switch
|
Expression condition = operand switch
|
||||||
{
|
{
|
||||||
"eq" when isList => ContainsResourceExpression(propertyExpr, value),
|
"eq" when isList => ContainsResourceExpression(propertyExpr, value),
|
||||||
"ctn" => ContainsResourceExpression(propertyExpr, value),
|
"ctn" => ContainsResourceExpression(propertyExpr, value),
|
||||||
|
|
||||||
"eq" when valueExpr == null => ResourceEqual(propertyExpr, value),
|
"eq" when valueExpr == null => ResourceEqual(propertyExpr, value),
|
||||||
"not" when valueExpr == null => ResourceEqual(propertyExpr, value, true),
|
"not" when valueExpr == null => ResourceEqual(propertyExpr, value, true),
|
||||||
|
|
||||||
"eq" => Expression.Equal(propertyExpr, valueExpr),
|
"eq" => Expression.Equal(propertyExpr, valueExpr),
|
||||||
"not" => Expression.NotEqual(propertyExpr, valueExpr!),
|
"not" => Expression.NotEqual(propertyExpr, valueExpr!),
|
||||||
"lt" => StringCompatibleExpression(Expression.LessThan, propertyExpr, valueExpr),
|
"lt" => StringCompatibleExpression(Expression.LessThan, propertyExpr, valueExpr),
|
||||||
@ -110,11 +110,11 @@ namespace Kyoo.Core.Api
|
|||||||
valueConst = Expression.Constant(value);
|
valueConst = Expression.Constant(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return notEqual
|
return notEqual
|
||||||
? Expression.NotEqual(field, valueConst)
|
? Expression.NotEqual(field, valueConst)
|
||||||
: Expression.Equal(field, valueConst);
|
: Expression.Equal(field, valueConst);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Expression ContainsResourceExpression(MemberExpression xProperty, string value)
|
private static Expression ContainsResourceExpression(MemberExpression xProperty, string value)
|
||||||
{
|
{
|
||||||
// x => x.PROPERTY.Any(y => y.Slug == value)
|
// x => x.PROPERTY.Any(y => y.Slug == value)
|
||||||
|
@ -54,10 +54,10 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[PartialPermission(Kind.Read)]
|
[PartialPermission(Kind.Read)]
|
||||||
public virtual async Task<ActionResult<Page<T>>> GetAll([FromQuery] string sortBy,
|
public virtual async Task<ActionResult<Page<T>>> GetAll([FromQuery] string sortBy,
|
||||||
@ -75,7 +75,7 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ namespace Kyoo.Core.Api
|
|||||||
}
|
}
|
||||||
catch (ArgumentException ex)
|
catch (ArgumentException ex)
|
||||||
{
|
{
|
||||||
return BadRequest(new {Error = ex.Message});
|
return BadRequest(new { Error = ex.Message });
|
||||||
}
|
}
|
||||||
catch (DuplicatedItemException)
|
catch (DuplicatedItemException)
|
||||||
{
|
{
|
||||||
@ -106,7 +106,7 @@ namespace Kyoo.Core.Api
|
|||||||
return Conflict(existing);
|
return Conflict(existing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut]
|
[HttpPut]
|
||||||
[PartialPermission(Kind.Write)]
|
[PartialPermission(Kind.Write)]
|
||||||
public virtual async Task<ActionResult<T>> Edit([FromQuery] bool resetOld, [FromBody] T resource)
|
public virtual async Task<ActionResult<T>> Edit([FromQuery] bool resetOld, [FromBody] T resource)
|
||||||
@ -140,7 +140,7 @@ namespace Kyoo.Core.Api
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("{slug}")]
|
[HttpPut("{slug}")]
|
||||||
[PartialPermission(Kind.Write)]
|
[PartialPermission(Kind.Write)]
|
||||||
public virtual async Task<ActionResult<T>> Edit(string slug, [FromQuery] bool resetOld, [FromBody] T resource)
|
public virtual async Task<ActionResult<T>> Edit(string slug, [FromQuery] bool resetOld, [FromBody] T resource)
|
||||||
@ -172,7 +172,7 @@ namespace Kyoo.Core.Api
|
|||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("{slug}")]
|
[HttpDelete("{slug}")]
|
||||||
[PartialPermission(Kind.Delete)]
|
[PartialPermission(Kind.Delete)]
|
||||||
public virtual async Task<IActionResult> Delete(string slug)
|
public virtual async Task<IActionResult> Delete(string slug)
|
||||||
@ -188,7 +188,7 @@ namespace Kyoo.Core.Api
|
|||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[PartialPermission(Kind.Delete)]
|
[PartialPermission(Kind.Delete)]
|
||||||
public virtual async Task<IActionResult> Delete(Dictionary<string, string> where)
|
public virtual async Task<IActionResult> Delete(Dictionary<string, string> where)
|
||||||
{
|
{
|
||||||
|
@ -81,7 +81,7 @@ namespace Kyoo.Core.Api
|
|||||||
value.Show.People = null;
|
value.Show.People = null;
|
||||||
if (value.People != null)
|
if (value.People != null)
|
||||||
value.People.Roles = null;
|
value.People.Roles = null;
|
||||||
|
|
||||||
JObject obj = JObject.FromObject((value.ForPeople ? value.People : value.Show)!, serializer);
|
JObject obj = JObject.FromObject((value.ForPeople ? value.People : value.Show)!, serializer);
|
||||||
obj.Add("role", value.Role);
|
obj.Add("role", value.Role);
|
||||||
obj.Add("type", value.Type);
|
obj.Add("type", value.Type);
|
||||||
@ -93,7 +93,7 @@ namespace Kyoo.Core.Api
|
|||||||
value.People.Roles = oldRoles;
|
value.People.Roles = oldRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override PeopleRole ReadJson(JsonReader reader,
|
public override PeopleRole ReadJson(JsonReader reader,
|
||||||
Type objectType,
|
Type objectType,
|
||||||
PeopleRole existingValue,
|
PeopleRole existingValue,
|
||||||
bool hasExistingValue,
|
bool hasExistingValue,
|
||||||
@ -113,7 +113,7 @@ namespace Kyoo.Core.Api
|
|||||||
_format = format;
|
_format = format;
|
||||||
_host = host.TrimEnd('/');
|
_host = host.TrimEnd('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetValue(object target)
|
public object GetValue(object target)
|
||||||
{
|
{
|
||||||
return Regex.Replace(_format, @"(?<!{){(\w+)(:(\w+))?}", x =>
|
return Regex.Replace(_format, @"(?<!{){(\w+)(:(\w+))?}", x =>
|
||||||
@ -123,7 +123,7 @@ namespace Kyoo.Core.Api
|
|||||||
|
|
||||||
if (value == "HOST")
|
if (value == "HOST")
|
||||||
return _host;
|
return _host;
|
||||||
|
|
||||||
PropertyInfo properties = target.GetType()
|
PropertyInfo properties = target.GetType()
|
||||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||||
.FirstOrDefault(y => y.Name == value);
|
.FirstOrDefault(y => y.Name == value);
|
||||||
@ -147,7 +147,7 @@ namespace Kyoo.Core.Api
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(object target, object value)
|
public void SetValue(object target, object value)
|
||||||
{
|
{
|
||||||
// Values are ignored and should not be editable, except if the internal value is set.
|
// Values are ignored and should not be editable, except if the internal value is set.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user