diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index d4485716..71a6db8b 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -411,91 +411,240 @@ namespace Kyoo.Controllers Task GetAbsolute(string showSlug, int absoluteNumber); } + /// + /// A repository to handle tracks + /// public interface ITrackRepository : IRepository { + /// + /// Get a track from it's slug and it's type. + /// + /// The slug of the track + /// The type (Video, Audio or Subtitle) + /// If the item is not found + /// The tracl found Task Get(string slug, StreamType type = StreamType.Unknown); + + /// + /// Get a track from it's slug and it's type or null if it is not found. + /// + /// The slug of the track + /// The type (Video, Audio or Subtitle) + /// The tracl found + Task GetOrDefault(string slug, StreamType type = StreamType.Unknown); } + /// + /// A repository to handle libraries. + /// public interface ILibraryRepository : IRepository { } + /// + /// A repository to handle library items (A wrapper arround shows and collections). + /// public interface ILibraryItemRepository : IRepository { + /// + /// Get items (A wrapper arround shows or collections) from a library. + /// + /// The ID of the library + /// A filter function + /// Sort informations (sort order & sort by) + /// How many items to return and where to start + /// A list of items that match every filters public Task> GetFromLibrary(int id, Expression> where = null, Sort sort = default, Pagination limit = default); - + /// + /// Get items (A wrapper arround shows or collections) from a library. + /// + /// The ID of the library + /// A filter function + /// A sort by method + /// How many items to return and where to start + /// A list of items that match every filters public Task> GetFromLibrary(int id, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromLibrary(id, where, new Sort(sort), limit); - public Task> GetFromLibrary(string librarySlug, + /// + /// Get items (A wrapper arround shows or collections) from a library. + /// + /// The slug of the library + /// A filter function + /// Sort informations (sort order & sort by) + /// How many items to return and where to start + /// A list of items that match every filters + public Task> GetFromLibrary(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); - - public Task> GetFromLibrary(string librarySlug, + /// + /// Get items (A wrapper arround shows or collections) from a library. + /// + /// The slug of the library + /// A filter function + /// A sort by method + /// How many items to return and where to start + /// A list of items that match every filters + public Task> GetFromLibrary(string slug, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetFromLibrary(librarySlug, where, new Sort(sort), limit); + ) => GetFromLibrary(slug, where, new Sort(sort), limit); } + /// + /// A repository for collections + /// public interface ICollectionRepository : IRepository { } + + /// + /// A repository for genres. + /// public interface IGenreRepository : IRepository { } + + /// + /// A repository for studios. + /// public interface IStudioRepository : IRepository { } + /// + /// A repository for people. + /// public interface IPeopleRepository : IRepository { + /// + /// Get people's roles from a show. + /// + /// The ID of the show + /// A filter function + /// Sort informations (sort order & sort by) + /// How many items to return and where to start + /// A list of items that match every filters Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); + /// + /// Get people's roles from a show. + /// + /// The ID of the show + /// A filter function + /// A sort by method + /// How many items to return and where to start + /// A list of items that match every filters Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); + /// + /// Get people's roles from a show. + /// + /// The slug of the show + /// A filter function + /// Sort informations (sort order & sort by) + /// How many items to return and where to start + /// A list of items that match every filters Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); + /// + /// Get people's roles from a show. + /// + /// The slug of the show + /// A filter function + /// A sort by method + /// How many items to return and where to start + /// A list of items that match every filters Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); - Task> GetFromPeople(int showID, + /// + /// Get people's roles from a person. + /// + /// The id of the person + /// A filter function + /// Sort informations (sort order & sort by) + /// How many items to return and where to start + /// A list of items that match every filters + Task> GetFromPeople(int id, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetFromPeople(int showID, + /// + /// Get people's roles from a person. + /// + /// The id of the person + /// A filter function + /// A sort by method + /// How many items to return and where to start + /// A list of items that match every filters + Task> GetFromPeople(int id, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetFromPeople(showID, where, new Sort(sort), limit); + ) => GetFromPeople(id, where, new Sort(sort), limit); - Task> GetFromPeople(string showSlug, + /// + /// Get people's roles from a person. + /// + /// The slug of the person + /// A filter function + /// Sort informations (sort order & sort by) + /// How many items to return and where to start + /// A list of items that match every filters + Task> GetFromPeople(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); - Task> GetFromPeople(string showSlug, + /// + /// Get people's roles from a person. + /// + /// The slug of the person + /// A filter function + /// A sort by method + /// How many items to return and where to start + /// A list of items that match every filters + Task> GetFromPeople(string slug, [Optional] Expression> where, Expression> sort, Pagination limit = default - ) => GetFromPeople(showSlug, where, new Sort(sort), limit); + ) => GetFromPeople(slug, where, new Sort(sort), limit); } + /// + /// A repository to handle providers. + /// public interface IProviderRepository : IRepository { + /// + /// Get a list of external ids that match all filters + /// + /// A predicate to add arbitrary filter + /// Sort information (sort order & sort by) + /// Paginations information (where to start and how many to get) + /// A filtered list of external ids. Task> GetMetadataID(Expression> where = null, Sort sort = default, Pagination limit = default); + /// + /// Get a list of external ids that match all filters + /// + /// A predicate to add arbitrary filter + /// A sort by expression + /// Paginations information (where to start and how many to get) + /// A filtered list of external ids. Task> GetMetadataID([Optional] Expression> where, Expression> sort, Pagination limit = default diff --git a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs index b1f66291..de35db92 100644 --- a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs +++ b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs @@ -15,66 +15,35 @@ namespace Kyoo.Controllers /// private readonly IBaseRepository[] _repositories; - /// - /// The repository that handle libraries. - /// + /// public ILibraryRepository LibraryRepository { get; } - - /// - /// The repository that handle libraries's items (a wrapper arround shows & collections). - /// + /// public ILibraryItemRepository LibraryItemRepository { get; } - - /// - /// The repository that handle collections. - /// + /// public ICollectionRepository CollectionRepository { get; } - - /// - /// The repository that handle shows. - /// + /// public IShowRepository ShowRepository { get; } - - /// - /// The repository that handle seasons. - /// + /// public ISeasonRepository SeasonRepository { get; } - - /// - /// The repository that handle episodes. - /// + /// public IEpisodeRepository EpisodeRepository { get; } - - /// - /// The repository that handle tracks. - /// + /// public ITrackRepository TrackRepository { get; } - - /// - /// The repository that handle people. - /// + /// public IPeopleRepository PeopleRepository { get; } - - /// - /// The repository that handle studios. - /// + /// public IStudioRepository StudioRepository { get; } - - /// - /// The repository that handle genres. - /// + /// public IGenreRepository GenreRepository { get; } - - /// - /// The repository that handle providers. - /// + /// public IProviderRepository ProviderRepository { get; } /// /// Create a new instancce with every repository available. /// - /// The list of repositories that this library manager should manage. If a repository for every base type is not available, this instance won't be stable. + /// The list of repositories that this library manager should manage. + /// If a repository for every base type is not available, this instance won't be stable. public LibraryManager(IEnumerable repositories) { _repositories = repositories.ToArray(); @@ -91,9 +60,7 @@ namespace Kyoo.Controllers ProviderRepository = GetRepository() as IProviderRepository; } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// + /// public void Dispose() { foreach (IBaseRepository repo in _repositories) @@ -101,21 +68,13 @@ namespace Kyoo.Controllers GC.SuppressFinalize(this); } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously. - /// - /// A task that represents the asynchronous dispose operation. + /// public async ValueTask DisposeAsync() { await Task.WhenAll(_repositories.Select(x => x.DisposeAsync().AsTask())); } - /// - /// Get the repository corresponding to the T item. - /// - /// The type you want - /// If the item is not found - /// The repository corresponding + /// public IRepository GetRepository() where T : class, IResource { @@ -124,208 +83,109 @@ namespace Kyoo.Controllers throw new ItemNotFound(); } - /// - /// Get the resource by it's ID - /// - /// The id of the resource - /// The type of the resource - /// If the item is not found - /// The resource found + /// public Task Get(int id) where T : class, IResource { return GetRepository().Get(id); } - /// - /// Get the resource by it's slug - /// - /// The slug of the resource - /// The type of the resource - /// If the item is not found - /// The resource found + /// public Task Get(string slug) where T : class, IResource { return GetRepository().Get(slug); } - /// - /// Get the resource by a filter function. - /// - /// The filter function. - /// The type of the resource - /// If the item is not found - /// The first resource found that match the where function + /// public Task Get(Expression> where) where T : class, IResource { return GetRepository().Get(where); } - /// - /// Get a season from it's showID and it's seasonNumber - /// - /// The id of the show - /// The season's number - /// If the item is not found - /// The season found + /// public Task Get(int showID, int seasonNumber) { return SeasonRepository.Get(showID, seasonNumber); } - /// - /// Get a season from it's show slug and it's seasonNumber - /// - /// The slug of the show - /// The season's number - /// If the item is not found - /// The season found + /// public Task Get(string showSlug, int seasonNumber) { return SeasonRepository.Get(showSlug, seasonNumber); } - /// - /// Get a episode from it's showID, it's seasonNumber and it's episode number. - /// - /// The id of the show - /// The season's number - /// The episode's number - /// If the item is not found - /// The episode found + /// public Task Get(int showID, int seasonNumber, int episodeNumber) { return EpisodeRepository.Get(showID, seasonNumber, episodeNumber); } - /// - /// Get a episode from it's show slug, it's seasonNumber and it's episode number. - /// - /// The slug of the show - /// The season's number - /// The episode's number - /// If the item is not found - /// The episode found + /// public Task Get(string showSlug, int seasonNumber, int episodeNumber) { return EpisodeRepository.Get(showSlug, seasonNumber, episodeNumber); } - /// - /// Get a tracck from it's slug and it's type. - /// - /// The slug of the track - /// The type (Video, Audio or Subtitle) - /// If the item is not found - /// The tracl found + /// public Task Get(string slug, StreamType type = StreamType.Unknown) { return TrackRepository.Get(slug, type); } - /// - /// Get the resource by it's ID or null if it is not found. - /// - /// The id of the resource - /// The type of the resource - /// The resource found + /// public async Task GetOrDefault(int id) where T : class, IResource { return await GetRepository().GetOrDefault(id); } - /// - /// Get the resource by it's slug or null if it is not found. - /// - /// The slug of the resource - /// The type of the resource - /// The resource found + /// public async Task GetOrDefault(string slug) where T : class, IResource { return await GetRepository().GetOrDefault(slug); } - /// - /// Get the resource by a filter function or null if it is not found. - /// - /// The filter function. - /// The type of the resource - /// The first resource found that match the where function + /// public async Task GetOrDefault(Expression> where) where T : class, IResource { return await GetRepository().GetOrDefault(where); } - /// - /// Get a season from it's showID and it's seasonNumber or null if it is not found. - /// - /// The id of the show - /// The season's number - /// The season found + /// public async Task GetOrDefault(int showID, int seasonNumber) { return await SeasonRepository.GetOrDefault(showID, seasonNumber); } - /// - /// Get a season from it's show slug and it's seasonNumber or null if it is not found. - /// - /// The slug of the show - /// The season's number - /// The season found + /// public async Task GetOrDefault(string showSlug, int seasonNumber) { return await SeasonRepository.GetOrDefault(showSlug, seasonNumber); } - /// - /// Get a episode from it's showID, it's seasonNumber and it's episode number or null if it is not found. - /// - /// The id of the show - /// The season's number - /// The episode's number - /// The episode found + /// public async Task GetOrDefault(int showID, int seasonNumber, int episodeNumber) { return await EpisodeRepository.GetOrDefault(showID, seasonNumber, episodeNumber); } - /// - /// Get a episode from it's show slug, it's seasonNumber and it's episode number or null if it is not found. - /// - /// The slug of the show - /// The season's number - /// The episode's number - /// The episode found + /// public async Task GetOrDefault(string showSlug, int seasonNumber, int episodeNumber) { return await EpisodeRepository.GetOrDefault(showSlug, seasonNumber, episodeNumber); } - /// - /// Get a track from it's slug and it's type or null if it is not found. - /// - /// The slug of the track - /// The type (Video, Audio or Subtitle) - /// The tracl found + /// public async Task GetOrDefault(string slug, StreamType type = StreamType.Unknown) { return await TrackRepository.GetOrDefault(slug, type); } - /// - /// Load a related resource - /// - /// The source object. - /// A getter function for the member to load - /// The type of the source object - /// The related resource's type - /// The param + /// public Task Load(T obj, Expression> member) where T : class, IResource where T2 : class, IResource, new() @@ -335,14 +195,7 @@ namespace Kyoo.Controllers return Load(obj, Utility.GetPropertyName(member)); } - /// - /// Load a collection of related resource - /// - /// The source object. - /// A getter function for the member to load - /// The type of the source object - /// The related resource's type - /// The param + /// public Task Load(T obj, Expression>> member) where T : class, IResource where T2 : class, new() @@ -352,13 +205,7 @@ namespace Kyoo.Controllers return Load(obj, Utility.GetPropertyName(member)); } - /// - /// Load a related resource by it's name - /// - /// The source object. - /// The name of the resource to load (case sensitive) - /// The type of the source object - /// The param + /// public async Task Load(T obj, string memberName) where T : class, IResource { @@ -386,11 +233,7 @@ namespace Kyoo.Controllers inverse(item, obj); } - /// - /// Load a related resource without specifing it's type. - /// - /// The source object. - /// The name of the resource to load (case sensitive) + /// public Task Load(IResource obj, string memberName) { if (obj == null) @@ -544,14 +387,7 @@ namespace Kyoo.Controllers }; } - /// - /// Get items (A wrapper arround shows or collections) from a library. - /// - /// The ID of the library - /// A filter function - /// Sort informations (sort order & sort by) - /// How many items to return and where to start - /// A list of items that match every filters + /// public Task> GetItemsFromLibrary(int id, Expression> where = null, Sort sort = default, @@ -560,14 +396,7 @@ namespace Kyoo.Controllers return LibraryItemRepository.GetFromLibrary(id, where, sort, limit); } - /// - /// Get items (A wrapper arround shows or collections) from a library. - /// - /// The slug of the library - /// A filter function - /// Sort informations (sort order & sort by) - /// How many items to return and where to start - /// A list of items that match every filters + /// public Task> GetItemsFromLibrary(string slug, Expression> where = null, Sort sort = default, @@ -576,14 +405,7 @@ namespace Kyoo.Controllers return LibraryItemRepository.GetFromLibrary(slug, where, sort, limit); } - /// - /// Get people's roles from a show. - /// - /// The ID of the show - /// A filter function - /// Sort informations (sort order & sort by) - /// How many items to return and where to start - /// A list of items that match every filters + /// public Task> GetPeopleFromShow(int showID, Expression> where = null, Sort sort = default, @@ -592,14 +414,7 @@ namespace Kyoo.Controllers return PeopleRepository.GetFromShow(showID, where, sort, limit); } - /// - /// Get people's roles from a show. - /// - /// The slug of the show - /// A filter function - /// Sort informations (sort order & sort by) - /// How many items to return and where to start - /// A list of items that match every filters + /// public Task> GetPeopleFromShow(string showSlug, Expression> where = null, Sort sort = default, @@ -608,14 +423,7 @@ namespace Kyoo.Controllers return PeopleRepository.GetFromShow(showSlug, where, sort, limit); } - /// - /// Get people's roles from a person. - /// - /// The id of the person - /// A filter function - /// Sort informations (sort order & sort by) - /// How many items to return and where to start - /// A list of items that match every filters + /// public Task> GetRolesFromPeople(int id, Expression> where = null, Sort sort = default, @@ -624,14 +432,7 @@ namespace Kyoo.Controllers return PeopleRepository.GetFromPeople(id, where, sort, limit); } - /// - /// Get people's roles from a person. - /// - /// The slug of the person - /// A filter function - /// Sort informations (sort order & sort by) - /// How many items to return and where to start - /// A list of items that match every filters + /// public Task> GetRolesFromPeople(string slug, Expression> where = null, Sort sort = default, @@ -640,23 +441,13 @@ namespace Kyoo.Controllers return PeopleRepository.GetFromPeople(slug, where, sort, limit); } - /// - /// Setup relations between a show, a library and a collection - /// - /// The show's ID to setup relations with - /// The library's ID to setup relations with (optional) - /// The collection's ID to setup relations with (optional) + /// public Task AddShowLink(int showID, int? libraryID, int? collectionID) { return ShowRepository.AddShowLink(showID, libraryID, collectionID); } - /// - /// Setup relations between a show, a library and a collection - /// - /// The show to setup relations with - /// The library to setup relations with (optional) - /// The collection to setup relations with (optional) + /// public Task AddShowLink(Show show, Library library, Collection collection) { if (show == null) @@ -664,14 +455,7 @@ namespace Kyoo.Controllers return ShowRepository.AddShowLink(show.ID, library?.ID, collection?.ID); } - /// - /// Get all resources with filters - /// - /// A filter function - /// Sort informations (sort order & sort by) - /// How many items to return and where to start - /// The type of resources to load - /// A list of resources that match every filters + /// public Task> GetAll(Expression> where = null, Sort sort = default, Pagination limit = default) @@ -680,98 +464,56 @@ namespace Kyoo.Controllers return GetRepository().GetAll(where, sort, limit); } - /// - /// Get the count of resources that match the filter - /// - /// A filter function - /// The type of resources to load - /// A list of resources that match every filters + /// public Task GetCount(Expression> where = null) where T : class, IResource { return GetRepository().GetCount(where); } - /// - /// Search for a resource - /// - /// The search query - /// The type of resources - /// A list of 20 items that match the search query + /// public Task> Search(string query) where T : class, IResource { return GetRepository().Search(query); } - /// - /// Create a new resource. - /// - /// The item to register - /// The type of resource - /// The resource registers and completed by database's informations (related items & so on) + /// public Task Create(T item) where T : class, IResource { return GetRepository().Create(item); } - /// - /// Create a new resource if it does not exist already. If it does, the existing value is returned instead. - /// - /// The object to create - /// The type of resource - /// The newly created item or the existing value if it existed. + /// public Task CreateIfNotExists(T item) where T : class, IResource { return GetRepository().CreateIfNotExists(item); } - /// - /// Edit a resource - /// - /// The resourcce to edit, it's ID can't change. - /// Should old properties of the resource be discarded or should null values considered as not changed? - /// The type of resources - /// If the item is not found - /// The resource edited and completed by database's informations (related items & so on) + /// public Task Edit(T item, bool resetOld) where T : class, IResource { return GetRepository().Edit(item, resetOld); } - /// - /// Delete a resource. - /// - /// The resource to delete - /// The type of resource to delete - /// If the item is not found + /// public Task Delete(T item) where T : class, IResource { return GetRepository().Delete(item); } - /// - /// Delete a resource by it's ID. - /// - /// The id of the resource to delete - /// The type of resource to delete - /// If the item is not found + /// public Task Delete(int id) where T : class, IResource { return GetRepository().Delete(id); } - /// - /// Delete a resource by it's slug. - /// - /// The slug of the resource to delete - /// The type of resource to delete - /// If the item is not found + /// public Task Delete(string slug) where T : class, IResource { diff --git a/Kyoo/Controllers/Repositories/CollectionRepository.cs b/Kyoo/Controllers/Repositories/CollectionRepository.cs index ccebc298..bbef77af 100644 --- a/Kyoo/Controllers/Repositories/CollectionRepository.cs +++ b/Kyoo/Controllers/Repositories/CollectionRepository.cs @@ -8,34 +8,30 @@ using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers { + /// + /// A local repository to handle collections + /// public class CollectionRepository : LocalRepository, ICollectionRepository { - private bool _disposed; + /// + /// The database handle + /// private readonly DatabaseContext _database; + + /// protected override Expression> DefaultSort => x => x.Name; - public CollectionRepository(DatabaseContext database) : base(database) + /// + /// Create a new . + /// + /// The database handle to use + public CollectionRepository(DatabaseContext database) + : base(database) { _database = database; } - public override void Dispose() - { - if (_disposed) - return; - _disposed = true; - _database.Dispose(); - GC.SuppressFinalize(this); - } - - public override async ValueTask DisposeAsync() - { - if (_disposed) - return; - _disposed = true; - await _database.DisposeAsync(); - } - + /// public override async Task> Search(string query) { return await _database.Collections @@ -45,6 +41,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override async Task Create(Collection obj) { await base.Create(obj); @@ -53,6 +50,7 @@ namespace Kyoo.Controllers return obj; } + /// public override async Task Delete(Collection obj) { if (obj == null) diff --git a/Kyoo/Controllers/Repositories/GenreRepository.cs b/Kyoo/Controllers/Repositories/GenreRepository.cs index bfbc1e3c..0ce1a155 100644 --- a/Kyoo/Controllers/Repositories/GenreRepository.cs +++ b/Kyoo/Controllers/Repositories/GenreRepository.cs @@ -8,35 +8,31 @@ using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers { + /// + /// A local repository for genres. + /// public class GenreRepository : LocalRepository, IGenreRepository { - private bool _disposed; + /// + /// The database handle + /// private readonly DatabaseContext _database; + + /// protected override Expression> DefaultSort => x => x.Slug; - public GenreRepository(DatabaseContext database) : base(database) + /// + /// Create a new . + /// + /// The database handle + public GenreRepository(DatabaseContext database) + : base(database) { _database = database; } - public override void Dispose() - { - if (_disposed) - return; - _disposed = true; - _database.Dispose(); - GC.SuppressFinalize(this); - } - - public override async ValueTask DisposeAsync() - { - if (_disposed) - return; - _disposed = true; - await _database.DisposeAsync(); - } - + /// public override async Task> Search(string query) { return await _database.Genres @@ -46,6 +42,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override async Task Create(Genre obj) { await base.Create(obj); @@ -54,6 +51,7 @@ namespace Kyoo.Controllers return obj; } + /// public override async Task Delete(Genre obj) { if (obj == null) diff --git a/Kyoo/Controllers/Repositories/LibraryItemRepository.cs b/Kyoo/Controllers/Repositories/LibraryItemRepository.cs index 57f293b5..9d96b23f 100644 --- a/Kyoo/Controllers/Repositories/LibraryItemRepository.cs +++ b/Kyoo/Controllers/Repositories/LibraryItemRepository.cs @@ -10,18 +10,49 @@ using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { + /// + /// A local repository to handle library items. + /// public class LibraryItemRepository : LocalRepository, ILibraryItemRepository { + /// + /// Has this instance been disposed and should not handle requests? + /// private bool _disposed; + /// + /// The database handle + /// private readonly DatabaseContext _database; + /// + /// A provider repository to handle externalID creation and deletion + /// private readonly IProviderRepository _providers; + /// + /// A lazy loaded library repository to validate queries (check if a library does exist) + /// private readonly Lazy _libraries; + /// + /// A lazy loaded show repository to get a show from it's id. + /// private readonly Lazy _shows; + /// + /// A lazy loaded collection repository to get a collection from it's id. + /// private readonly Lazy _collections; + + /// protected override Expression> DefaultSort => x => x.Title; - public LibraryItemRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services) + /// + /// Create a new . + /// + /// The databse instance + /// A provider repository + /// A service provider to lazilly request a library, show or collection repository. + public LibraryItemRepository(DatabaseContext database, + IProviderRepository providers, + IServiceProvider services) : base(database) { _database = database; @@ -31,6 +62,7 @@ namespace Kyoo.Controllers _collections = new Lazy(services.GetRequiredService); } + /// public override void Dispose() { if (_disposed) @@ -45,6 +77,7 @@ namespace Kyoo.Controllers GC.SuppressFinalize(this); } + /// public override async ValueTask DisposeAsync() { if (_disposed) @@ -58,6 +91,7 @@ namespace Kyoo.Controllers await _collections.Value.DisposeAsync(); } + /// public override async Task Get(int id) { return id > 0 @@ -65,18 +99,24 @@ namespace Kyoo.Controllers : new LibraryItem(await _collections.Value.Get(-id)); } + /// public override Task Get(string slug) { - throw new InvalidOperationException(); + throw new InvalidOperationException("You can't get a library item by a slug."); } - private IQueryable ItemsQuery + /// + /// Get a basic queryable with the right mapping from shows & collections. + /// Shows contained in a collection are excluded. + /// + private IQueryable ItemsQuery => _database.Shows .Where(x => !x.Collections.Any()) .Select(LibraryItem.FromShow) .Concat(_database.Collections .Select(LibraryItem.FromCollection)); + /// public override Task> GetAll(Expression> where = null, Sort sort = default, Pagination limit = default) @@ -84,6 +124,7 @@ namespace Kyoo.Controllers return ApplyFilters(ItemsQuery, where, sort, limit); } + /// public override Task GetCount(Expression> where = null) { IQueryable query = ItemsQuery; @@ -92,6 +133,7 @@ namespace Kyoo.Controllers return query.CountAsync(); } + /// public override async Task> Search(string query) { return await ItemsQuery @@ -101,19 +143,31 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override Task Create(LibraryItem obj) => throw new InvalidOperationException(); + /// public override Task CreateIfNotExists(LibraryItem obj, bool silentFail = false) { if (silentFail) return Task.FromResult(default); throw new InvalidOperationException(); } + /// public override Task Edit(LibraryItem obj, bool reset) => throw new InvalidOperationException(); + /// public override Task Delete(int id) => throw new InvalidOperationException(); + /// public override Task Delete(string slug) => throw new InvalidOperationException(); + /// public override Task Delete(LibraryItem obj) => throw new InvalidOperationException(); + /// + /// Get a basic queryable for a library with the right mapping from shows & collections. + /// Shows contained in a collection are excluded. + /// + /// Only items that are part of a library that match this predicate will be returned. + /// A queryable containing items that are part of a library matching the selector. private IQueryable LibraryRelatedQuery(Expression> selector) => _database.Libraries .Where(selector) @@ -125,7 +179,8 @@ namespace Kyoo.Controllers .SelectMany(x => x.Collections) .Select(LibraryItem.FromCollection)); - public async Task> GetFromLibrary(int id, + /// + public async Task> GetFromLibrary(int id, Expression> where = null, Sort sort = default, Pagination limit = default) @@ -139,7 +194,8 @@ namespace Kyoo.Controllers return items; } - public async Task> GetFromLibrary(string slug, + /// + public async Task> GetFromLibrary(string slug, Expression> where = null, Sort sort = default, Pagination limit = default) diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs index b4d725c1..f61e4445 100644 --- a/Kyoo/Controllers/Repositories/LibraryRepository.cs +++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs @@ -8,14 +8,33 @@ using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers { + /// + /// A local repository to handle libraries. + /// public class LibraryRepository : LocalRepository, ILibraryRepository { + /// + /// Has this instance been disposed and should not handle requests? + /// private bool _disposed; + /// + /// The database handle + /// private readonly DatabaseContext _database; + /// + /// A provider repository to handle externalID creation and deletion + /// private readonly IProviderRepository _providers; + + /// protected override Expression> DefaultSort => x => x.ID; + /// + /// Create a new instance. + /// + /// The database handle + /// The providere repository public LibraryRepository(DatabaseContext database, IProviderRepository providers) : base(database) { @@ -23,6 +42,7 @@ namespace Kyoo.Controllers _providers = providers; } + /// public override void Dispose() { if (_disposed) @@ -33,6 +53,7 @@ namespace Kyoo.Controllers GC.SuppressFinalize(this); } + /// public override async ValueTask DisposeAsync() { if (_disposed) @@ -42,6 +63,7 @@ namespace Kyoo.Controllers await _providers.DisposeAsync(); } + /// public override async Task> Search(string query) { return await _database.Libraries @@ -51,6 +73,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override async Task Create(Library obj) { await base.Create(obj); @@ -61,6 +84,7 @@ namespace Kyoo.Controllers return obj; } + /// protected override async Task Validate(Library resource) { await base.Validate(resource); @@ -69,6 +93,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// protected override async Task EditRelations(Library resource, Library changed, bool resetOld) { if (string.IsNullOrEmpty(resource.Slug)) @@ -86,6 +111,7 @@ namespace Kyoo.Controllers } } + /// public override async Task Delete(Library obj) { if (obj == null) diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs index 9097bea8..7d1c870e 100644 --- a/Kyoo/Controllers/Repositories/PeopleRepository.cs +++ b/Kyoo/Controllers/Repositories/PeopleRepository.cs @@ -10,15 +10,40 @@ using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { + /// + /// A local repository to handle people. + /// public class PeopleRepository : LocalRepository, IPeopleRepository { + /// + /// Has this instance been disposed and should not handle requests? + /// private bool _disposed; + /// + /// The database handle + /// private readonly DatabaseContext _database; + /// + /// A provider repository to handle externalID creation and deletion + /// private readonly IProviderRepository _providers; + /// + /// A lazy loaded show repository to validate requests from shows. + /// private readonly Lazy _shows; + + /// protected override Expression> DefaultSort => x => x.Name; - public PeopleRepository(DatabaseContext database, IProviderRepository providers, IServiceProvider services) + /// + /// Create a new + /// + /// The database handle + /// A provider repository + /// A service provider to lazy load a show repository + public PeopleRepository(DatabaseContext database, + IProviderRepository providers, + IServiceProvider services) : base(database) { _database = database; @@ -27,6 +52,7 @@ namespace Kyoo.Controllers } + /// public override void Dispose() { if (_disposed) @@ -39,6 +65,7 @@ namespace Kyoo.Controllers GC.SuppressFinalize(this); } + /// public override async ValueTask DisposeAsync() { if (_disposed) @@ -50,6 +77,7 @@ namespace Kyoo.Controllers await _shows.Value.DisposeAsync(); } + /// public override async Task> Search(string query) { return await _database.People @@ -59,6 +87,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override async Task Create(People obj) { await base.Create(obj); @@ -68,6 +97,7 @@ namespace Kyoo.Controllers return obj; } + /// protected override async Task Validate(People resource) { await base.Validate(resource); @@ -85,6 +115,7 @@ namespace Kyoo.Controllers }); } + /// protected override async Task EditRelations(People resource, People changed, bool resetOld) { if (changed.Roles != null || resetOld) @@ -102,6 +133,7 @@ namespace Kyoo.Controllers await base.EditRelations(resource, changed, resetOld); } + /// public override async Task Delete(People obj) { if (obj == null) @@ -113,6 +145,7 @@ namespace Kyoo.Controllers await _database.SaveChangesAsync(); } + /// public async Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, @@ -133,6 +166,7 @@ namespace Kyoo.Controllers return people; } + /// public async Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, @@ -154,24 +188,26 @@ namespace Kyoo.Controllers return people; } - public async Task> GetFromPeople(int peopleID, + /// + public async Task> GetFromPeople(int id, Expression> where = null, Sort sort = default, Pagination limit = default) { ICollection roles = await ApplyFilters(_database.PeopleRoles - .Where(x => x.PeopleID == peopleID) + .Where(x => x.PeopleID == id) .Include(x => x.Show), - id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id), + y => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == y), x => x.Show.Title, where, sort, limit); - if (!roles.Any() && await Get(peopleID) == null) + if (!roles.Any() && await Get(id) == null) throw new ItemNotFound(); return roles; } + /// public async Task> GetFromPeople(string slug, Expression> where = null, Sort sort = default, diff --git a/Kyoo/Controllers/Repositories/ProviderRepository.cs b/Kyoo/Controllers/Repositories/ProviderRepository.cs index 2d90b889..31c283d3 100644 --- a/Kyoo/Controllers/Repositories/ProviderRepository.cs +++ b/Kyoo/Controllers/Repositories/ProviderRepository.cs @@ -8,17 +8,31 @@ using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers { + /// + /// A local repository to handle providers. + /// public class ProviderRepository : LocalRepository, IProviderRepository { + /// + /// The database handle + /// private readonly DatabaseContext _database; + + /// protected override Expression> DefaultSort => x => x.Slug; - public ProviderRepository(DatabaseContext database) : base(database) + /// + /// Create a new . + /// + /// The database handle + public ProviderRepository(DatabaseContext database) + : base(database) { _database = database; } + /// public override async Task> Search(string query) { return await _database.Providers @@ -28,6 +42,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override async Task Create(Provider obj) { await base.Create(obj); @@ -36,6 +51,7 @@ namespace Kyoo.Controllers return obj; } + /// public override async Task Delete(Provider obj) { if (obj == null) @@ -46,6 +62,7 @@ namespace Kyoo.Controllers await _database.SaveChangesAsync(); } + /// public Task> GetMetadataID(Expression> where = null, Sort sort = default, Pagination limit = default) diff --git a/Kyoo/Controllers/Repositories/StudioRepository.cs b/Kyoo/Controllers/Repositories/StudioRepository.cs index f8afc757..6c813f65 100644 --- a/Kyoo/Controllers/Repositories/StudioRepository.cs +++ b/Kyoo/Controllers/Repositories/StudioRepository.cs @@ -8,17 +8,31 @@ using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers { + /// + /// A local repository to handle studios + /// public class StudioRepository : LocalRepository, IStudioRepository { + /// + /// The database handle + /// private readonly DatabaseContext _database; + + /// protected override Expression> DefaultSort => x => x.Name; - public StudioRepository(DatabaseContext database) : base(database) + /// + /// Create a new . + /// + /// The database handle + public StudioRepository(DatabaseContext database) + : base(database) { _database = database; } + /// public override async Task> Search(string query) { return await _database.Studios @@ -28,6 +42,7 @@ namespace Kyoo.Controllers .ToListAsync(); } + /// public override async Task Create(Studio obj) { await base.Create(obj); @@ -36,6 +51,7 @@ namespace Kyoo.Controllers return obj; } + /// public override async Task Delete(Studio obj) { if (obj == null) diff --git a/Kyoo/Controllers/Repositories/TrackRepository.cs b/Kyoo/Controllers/Repositories/TrackRepository.cs index d4e04376..4d3c725d 100644 --- a/Kyoo/Controllers/Repositories/TrackRepository.cs +++ b/Kyoo/Controllers/Repositories/TrackRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -9,40 +10,48 @@ using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers { + /// + /// A local repository to handle tracks. + /// public class TrackRepository : LocalRepository, ITrackRepository { - private bool _disposed; + /// + /// The databse handle + /// private readonly DatabaseContext _database; + + /// protected override Expression> DefaultSort => x => x.TrackIndex; - public TrackRepository(DatabaseContext database) : base(database) + /// + /// Create a new . + /// + /// The datatabse handle + public TrackRepository(DatabaseContext database) + : base(database) { _database = database; } + - public override void Dispose() - { - if (_disposed) - return; - _disposed = true; - _database.Dispose(); - } - - public override async ValueTask DisposeAsync() - { - if (_disposed) - return; - _disposed = true; - await _database.DisposeAsync(); - } - + /// public override Task Get(string slug) { return Get(slug, StreamType.Unknown); } + + /// + public async Task Get(string slug, StreamType type) + { + Track ret = await GetOrDefault(slug, type); + if (ret == null) + throw new ItemNotFound($"No track found with the slug {slug} and the type {type}."); + return ret; + } - public Task Get(string slug, StreamType type) + /// + public Task GetOrDefault(string slug, StreamType type) { Match match = Regex.Match(slug, @"(?.*)-s(?\d+)e(?\d+)(\.(?\w*))?\.(?.{0,3})(?-forced)?(\..*)?"); @@ -65,27 +74,23 @@ namespace Kyoo.Controllers if (match.Groups["type"].Success) type = Enum.Parse(match.Groups["type"].Value, true); - if (type == StreamType.Unknown) - { - return _database.Tracks.FirstOrDefaultAsync(x => x.Episode.Show.Slug == showSlug - && x.Episode.SeasonNumber == seasonNumber - && x.Episode.EpisodeNumber == episodeNumber - && x.Language == language - && x.IsForced == forced); - } - return _database.Tracks.FirstOrDefaultAsync(x => x.Episode.Show.Slug == showSlug - && x.Episode.SeasonNumber == seasonNumber - && x.Episode.EpisodeNumber == episodeNumber - && x.Type == type - && x.Language == language - && x.IsForced == forced); + IQueryable query = _database.Tracks.Where(x => x.Episode.Show.Slug == showSlug + && x.Episode.SeasonNumber == seasonNumber + && x.Episode.EpisodeNumber == episodeNumber + && x.Language == language + && x.IsForced == forced); + if (type != StreamType.Unknown) + return query.FirstOrDefaultAsync(x => x.Type == type); + return query.FirstOrDefaultAsync(); } + /// public override Task> Search(string query) { throw new InvalidOperationException("Tracks do not support the search method."); } + /// public override async Task Create(Track obj) { if (obj.EpisodeID <= 0) @@ -107,6 +112,7 @@ namespace Kyoo.Controllers return obj; } + /// public override async Task Delete(Track obj) { if (obj == null)