From bf66f0ca9c276ca48b0e9831dc8a56e87135e676 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 2 Jun 2020 04:01:23 +0200 Subject: [PATCH 01/18] Restarting the library manager to use repositories --- Kyoo.Common/Controllers/ILibraryManager.cs | 47 ++- Kyoo.Common/Controllers/IRepository.cs | 34 ++ Kyoo/Controllers/LibraryManager.cs | 371 +----------------- .../Repositories/ShowRepository.cs | 67 ++++ 4 files changed, 151 insertions(+), 368 deletions(-) create mode 100644 Kyoo.Common/Controllers/IRepository.cs create mode 100644 Kyoo/Controllers/Repositories/ShowRepository.cs diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index 8268cb66..ff239fb1 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -1,9 +1,10 @@ -using Kyoo.Models; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; +using Kyoo.Models; namespace Kyoo.Controllers { + // ReSharper disable once PossibleInterfaceMemberAmbiguity public interface ILibraryManager { // Get by slug @@ -16,21 +17,22 @@ namespace Kyoo.Controllers Genre GetGenre(string slug); Studio GetStudio(string slug); People GetPeople(string slug); - ProviderID GetProvider(string name); // Get all IEnumerable GetLibraries(); IEnumerable GetCollections(); IEnumerable GetShows(); + IEnumerable GetSeasons(); IEnumerable GetEpisodes(); - IEnumerable GetTracks(); IEnumerable GetStudios(); IEnumerable GetPeoples(); IEnumerable GetGenres(); // Search + IEnumerable SearchLibraries(string searchQuery); IEnumerable SearchCollections(string searchQuery); IEnumerable SearchShows(string searchQuery); + IEnumerable SearchSeasons(string searchQuery); IEnumerable SearchEpisodes(string searchQuery); IEnumerable SearchGenres(string searchQuery); IEnumerable SearchStudios(string searchQuery); @@ -42,17 +44,34 @@ namespace Kyoo.Controllers IEnumerable GetEpisodes(string showSlug, long seasonNumber); //Register values - void Register(object obj); - Task Edit(object obj, bool resetOld); - void RegisterShowLinks(Library library, Collection collection, Show show); - Task SaveChanges(); + void RegisterLibrary(Library library); + void RegisterCollection(Collection collection); + void RegisterShow(Show show); + void RegisterSeason(Season season); + void RegisterEpisode(Episode episode); + void RegisterGenre(Genre genre); + void RegisterStudio(Studio studio); + void RegisterPeople(People people); - // Validate values - IEnumerable Validate(IEnumerable id); + // Edit values + void EditLibrary(Library library, bool resetOld); + void EditCollection(Collection collection, bool resetOld); + void EditShow(Show show, bool resetOld); + void EditSeason(Season season, bool resetOld); + void EditEpisode(Episode episode, bool resetOld); + void EditGenre(Genre genre, bool resetOld); + void EditStudio(Studio studio, bool resetOld); + void EditPeople(People people, bool resetOld); + - // Remove values - void RemoveShow(Show show); - void RemoveSeason(Season season); - void RemoveEpisode(Episode episode); + // Delete values + void DelteLibrary(Library library); + void DeleteCollection(Collection collection); + void DeleteShow(Show show); + void DeleteSeason(Season season); + void DeleteEpisode(Episode episode); + void DeleteGenre(Genre genre); + void DeleteStudio(Studio studio); + void DeletePeople(People people); } } diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs new file mode 100644 index 00000000..4ff868e6 --- /dev/null +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using Kyoo.Models; + +namespace Kyoo.Controllers +{ + public interface IRepository + { + T Get(string slug); + IEnumerable Search(string query); + IEnumerable GetAll(); + T Create(T obj); + T CreateIfNotExists(T obj); + void Edit(T edited, bool resetOld); + void Delete(string slug); + } + + public interface IShowRepository : IRepository {} + + public interface ISeasonRepository : IRepository + { + Season Get(string showSlug, int seasonNumber); + } + + public interface IEpisodeRepository : IRepository + { + Episode Get(string showSlug, int seasonNumber, int episodeNumber); + } + + public interface ILibraryRepository : IRepository {} + public interface ICollectionRepository : IRepository {} + public interface IGenreRepository : IRepository {} + public interface IStudioRepository : IRepository {} + public interface IPeopleRepository : IRepository {} +} \ No newline at end of file diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 8d7aaaf2..393ada95 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -12,383 +12,46 @@ namespace Kyoo.Controllers { public class LibraryManager : ILibraryManager { - private const int MaxSaveRetry = 3; - private readonly DatabaseContext _database; + private readonly ILibraryRepository _library; - - public LibraryManager(DatabaseContext database) + public LibraryManager(ILibraryRepository library) { - _database = database; + _library = library; } - #region GetBySlug - public Library GetLibrary(string librarySlug) + public Library Get(string slug) { - return _database.Libraries.FirstOrDefault(library => library.Slug == librarySlug); - } - - public Collection GetCollection(string slug) - { - return _database.Collections.FirstOrDefault(col => col.Slug == slug); + throw new NotImplementedException(); } - public Show GetShow(string slug) + public IEnumerable Search(string query) { - return _database.Shows.FirstOrDefault(show => show.Slug == slug); + throw new NotImplementedException(); } - public Season GetSeason(string showSlug, long seasonNumber) + public IEnumerable GetAll() { - return _database.Seasons.FirstOrDefault(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber); + throw new NotImplementedException(); } - public Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber) + public Library Create(Library obj) { - return _database.Episodes.FirstOrDefault(x => x.EpisodeNumber == episodeNumber - && x.SeasonNumber == seasonNumber - && x.Show.Slug == showSlug); - } - - public Episode GetMovieEpisode(string movieSlug) - { - return _database.Episodes.FirstOrDefault(x => x.Show.Slug == movieSlug); + throw new NotImplementedException(); } - public Genre GetGenre(string slug) + public Library CreateIfNotExists(Library obj) { - return _database.Genres.FirstOrDefault(genre => genre.Slug == slug); + throw new NotImplementedException(); } - public Studio GetStudio(string slug) + public void Edit(Library edited, bool resetOld) { - return _database.Studios.FirstOrDefault(studio => studio.Slug == slug); + throw new NotImplementedException(); } - public People GetPeople(string slug) + public void Delete(string slug) { - return _database.Peoples.FirstOrDefault(people => people.Slug == slug); + throw new NotImplementedException(); } - - public ProviderID GetProvider(string name) - { - return _database.Providers.FirstOrDefault(x => x.Name == name); - } - - #endregion - - #region GetAll - public IEnumerable GetLibraries() - { - return _database.Libraries; - } - - public IEnumerable GetCollections() - { - return _database.Collections; - } - - public IEnumerable GetShows() - { - return _database.Shows; - } - - public IEnumerable GetEpisodes() - { - return _database.Episodes; - } - - public IEnumerable GetGenres() - { - return _database.Genres; - } - - public IEnumerable GetStudios() - { - return _database.Studios; - } - - public IEnumerable GetPeoples() - { - return _database.Peoples; - } - - public IEnumerable GetTracks() - { - return _database.Tracks; - } - - #endregion - - #region GetHelper - public IEnumerable GetLibrariesPath() - { - IEnumerable paths = new List(); - return Enumerable.Aggregate(_database.Libraries, paths, (current, lib) => current.Concat(lib.Paths)); - } - - public Show GetShowByPath(string path) - { - return _database.Shows.FirstOrDefault(show => show.Path == path); - } - - public IEnumerable GetEpisodes(string showSlug, long seasonNumber) - { - return _database.Episodes.Where(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber); - } - #endregion - - #region Search - public IEnumerable SearchCollections(string searchQuery) - { - return _database.Collections.Where(collection => EF.Functions.Like(collection.Name, $"%{searchQuery}%")) - .Take(20); - } - - public IEnumerable SearchShows(string searchQuery) - { - return _database.Shows.FromSqlInterpolated($@"SELECT * FROM Shows WHERE Shows.Title LIKE {$"%{searchQuery}%"} - OR Shows.Aliases LIKE {$"%{searchQuery}%"}").Take(20); - } - - public IEnumerable SearchEpisodes(string searchQuery) - { - return _database.Episodes.Where(x => EF.Functions.Like(x.Title, $"%{searchQuery}%")).Take(20); - } - - public IEnumerable SearchGenres(string searchQuery) - { - return _database.Genres.Where(genre => EF.Functions.Like(genre.Name, $"%{searchQuery}%")) - .Take(20); - } - - public IEnumerable SearchStudios(string searchQuery) - { - return _database.Studios.Where(studio => EF.Functions.Like(studio.Name, $"%{searchQuery}%")) - .Take(20); - } - - public IEnumerable SearchPeople(string searchQuery) - { - return _database.Peoples.Where(people => EF.Functions.Like(people.Name, $"%{searchQuery}%")) - .OrderBy(x => x.ImgPrimary == null) - .ThenBy(x => x.Name) - .Take(20); - } - #endregion - - #region Register - public void Register(object obj) - { - if (obj == null) - return; - ValidateRootEntry(_database.Entry(obj), entry => - { - if (entry.State != EntityState.Detached) - return false; - - entry.State = EntityState.Added; - return true; - }); - } - - public void RegisterShowLinks(Library library, Collection collection, Show show) - { - if (collection != null) - { - _database.LibraryLinks.AddIfNotExist(new LibraryLink {Library = library, Collection = collection}, - x => x.Library == library && x.Collection == collection && x.ShowID == null); - _database.CollectionLinks.AddIfNotExist(new CollectionLink { Collection = collection, Show = show}, - x => x.Collection == collection && x.Show == show); - } - else - _database.LibraryLinks.AddIfNotExist(new LibraryLink {Library = library, Show = show}, - x => x.Library == library && x.Collection == null && x.Show == show); - } - - public Task SaveChanges() - { - return SaveChanges(0); - } - - private async Task SaveChanges(int retryCount) - { - ValidateChanges(); - try - { - await _database.SaveChangesAsync(); - } - catch (DbUpdateException) - { - if (retryCount < MaxSaveRetry) - await SaveChanges(retryCount + 1); - else - throw; - } - } - - public async Task Edit(object obj, bool resetOld) - { - _database.ChangeTracker.LazyLoadingEnabled = false; - _database.ChangeTracker.AutoDetectChangesEnabled = false; - - try - { - object existing = FindExisting(obj); - - if (existing == null) - throw new ItemNotFound($"No existing object (of type {obj.GetType().Name}) found on the databse."); - - if (resetOld) - Utility.Nullify(existing); - Utility.Merge(existing, obj); - - ValidateRootEntry(_database.Entry(existing), entry => entry.State != EntityState.Added); - - _database.ChangeTracker.DetectChanges(); - await _database.SaveChangesAsync(); - } - finally - { - _database.ChangeTracker.LazyLoadingEnabled = true; - _database.ChangeTracker.AutoDetectChangesEnabled = true; - } - } - #endregion - - #region ValidateValue - private void ValidateChanges() - { - _database.ChangeTracker.AutoDetectChangesEnabled = false; - try - { - foreach (EntityEntry sourceEntry in _database.ChangeTracker.Entries()) - { - if (sourceEntry.State != EntityState.Added && sourceEntry.State != EntityState.Modified) - continue; - - foreach (NavigationEntry navigation in sourceEntry.Navigations) - ValidateNavigation(navigation); - } - } - finally - { - _database.ChangeTracker.AutoDetectChangesEnabled = true; - _database.ChangeTracker.DetectChanges(); - } - } - - private void ValidateRootEntry(EntityEntry entry, Func shouldRun) - { - if (!shouldRun.Invoke(entry)) - return; - foreach (NavigationEntry navigation in entry.Navigations) - { - ValidateNavigation(navigation); - if (navigation.CurrentValue == null) - continue; - if (navigation.Metadata.IsCollection()) - { - IEnumerable entities = (IEnumerable)navigation.CurrentValue; - foreach (object childEntry in entities) - ValidateRootEntry(_database.Entry(childEntry), shouldRun); - } - else - ValidateRootEntry(_database.Entry(navigation.CurrentValue), shouldRun); - } - } - - private void ValidateNavigation(NavigationEntry navigation) - { - object oldValue = navigation.CurrentValue; - if (oldValue == null) - return; - object newValue = Validate(oldValue); - if (ReferenceEquals(oldValue, newValue)) - return; - navigation.CurrentValue = newValue; - if (!navigation.Metadata.IsCollection()) - _database.Entry(oldValue).State = EntityState.Detached; - } - - private T Validate(T obj) where T : class - { - switch (obj) - { - case null: - return null; - case IEnumerable enumerable: - return (T)Utility.RunGenericMethod( - this, - "ValidateList", - Utility.GetEnumerableType(enumerable), new [] {obj}); - } - - EntityState state = _database.Entry(obj).State; - if (state != EntityState.Added && state != EntityState.Detached) - return obj; - - return (T)(FindExisting(obj) ?? obj); - } - - public IEnumerable ValidateList(IEnumerable list) where T : class - { - return list.Select(x => - { - T tmp = Validate(x); - if (tmp != x) - _database.Entry(x).State = EntityState.Detached; - return tmp ?? x; - })/*.GroupBy(GetSlug).Select(x => x.First()).Where(x => x != null)*/.ToList(); - } - - private object FindExisting(object obj) - { - return obj switch - { - Library library => GetLibrary(library.Slug), - Collection collection => GetCollection(collection.Slug), - Show show => GetShow(show.Slug), - Season season => GetSeason(season.Show.Slug, season.SeasonNumber), - Episode episode => GetEpisode(episode.Show.Slug, episode.SeasonNumber, episode.EpisodeNumber), - Studio studio => GetStudio(studio.Slug), - People people => GetPeople(people.Slug), - Genre genre => GetGenre(genre.Slug), - ProviderID provider => GetProvider(provider.Name), - _ => null - }; - } - - public IEnumerable Validate(IEnumerable ids) - { - return ids?.Select(x => - { - x.Provider = _database.Providers.FirstOrDefault(y => y.Name == x.Provider.Name) ?? x.Provider; - return x; - }).GroupBy(x => x.Provider.Name).Select(x => x.First()).ToList(); - } - #endregion - - #region Remove - public void RemoveShow(Show show) - { - if (_database.Entry(show).State == EntityState.Detached) - _database.Shows.Attach(show); - _database.Shows.Remove(show); - } - - public void RemoveSeason(Season season) - { - if (_database.Entry(season).State == EntityState.Detached) - _database.Seasons.Attach(season); - _database.Seasons.Remove(season); - } - - public void RemoveEpisode(Episode episode) - { - if (_database.Entry(episode).State == EntityState.Detached) - _database.Episodes.Attach(episode); - _database.Episodes.Remove(episode); - } - #endregion } } diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs new file mode 100644 index 00000000..51aacad2 --- /dev/null +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Kyoo.Models; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class ShowRepository : IShowRepository + { + private readonly DatabaseContext _database; + private readonly ILibraryManager _library; + + public ShowRepository(DatabaseContext database, ILibraryManager library) + { + _database = database; + _library = library; + } + + public Show Get(string slug) + { + return _database.Shows.FirstOrDefault(x => x.Slug == slug); + } + + public IEnumerable Search(string query) + { + return _database.Shows.FromSqlInterpolated($@"SELECT * FROM Shows WHERE Shows.Title LIKE {$"%{query}%"} + OR Shows.Aliases LIKE {$"%{query}%"}").Take(20); + } + + public IEnumerable GetAll() + { + return _database.Shows.ToList(); + } + + public Show Create(Show obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + obj.Genres = obj.Genres.Select(_library.CreateIfNotExists).ToList(); + + + _database.Shows.Add(obj); + _database.SaveChanges(); + return obj; + } + + public Show CreateIfNotExists(Show obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + return Get(obj.Slug) ?? Create(obj); + } + + public void Edit(Show edited, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void Delete(string slug) + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file From b59f208781107c0cb5a0883bcdd1543c06750cbe Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 2 Jun 2020 23:34:37 +0200 Subject: [PATCH 02/18] Using ids of entities instead of the whole entity in create responeses --- Kyoo.Common/Controllers/ILibraryManager.cs | 14 +- Kyoo.Common/Controllers/IRepository.cs | 22 +- Kyoo.Common/Models/Show.cs | 1 + Kyoo/Controllers/LibraryManager.cs | 303 ++++++++++++++++-- .../Repositories/ShowRepository.cs | 91 ++++-- 5 files changed, 365 insertions(+), 66 deletions(-) diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index ff239fb1..906c5e32 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -1,19 +1,18 @@ using System.Collections.Generic; -using System.Threading.Tasks; using Kyoo.Models; namespace Kyoo.Controllers { - // ReSharper disable once PossibleInterfaceMemberAmbiguity public interface ILibraryManager { // Get by slug - Library GetLibrary(string librarySlug); + Library GetLibrary(string slug); Collection GetCollection(string slug); Show GetShow(string slug); Season GetSeason(string showSlug, long seasonNumber); Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber); Episode GetMovieEpisode(string movieSlug); + Track GetTrack(string slug); Genre GetGenre(string slug); Studio GetStudio(string slug); People GetPeople(string slug); @@ -24,6 +23,7 @@ namespace Kyoo.Controllers IEnumerable GetShows(); IEnumerable GetSeasons(); IEnumerable GetEpisodes(); + IEnumerable GetTracks(); IEnumerable GetStudios(); IEnumerable GetPeoples(); IEnumerable GetGenres(); @@ -38,17 +38,13 @@ namespace Kyoo.Controllers IEnumerable SearchStudios(string searchQuery); IEnumerable SearchPeople(string searchQuery); - // Other get helpers - Show GetShowByPath(string path); - IEnumerable GetLibrariesPath(); - IEnumerable GetEpisodes(string showSlug, long seasonNumber); - //Register values void RegisterLibrary(Library library); void RegisterCollection(Collection collection); void RegisterShow(Show show); void RegisterSeason(Season season); void RegisterEpisode(Episode episode); + void RegisterTrack(Track track); void RegisterGenre(Genre genre); void RegisterStudio(Studio studio); void RegisterPeople(People people); @@ -59,6 +55,7 @@ namespace Kyoo.Controllers void EditShow(Show show, bool resetOld); void EditSeason(Season season, bool resetOld); void EditEpisode(Episode episode, bool resetOld); + void EditTrack(Track track, bool resetOld); void EditGenre(Genre genre, bool resetOld); void EditStudio(Studio studio, bool resetOld); void EditPeople(People people, bool resetOld); @@ -70,6 +67,7 @@ namespace Kyoo.Controllers void DeleteShow(Show show); void DeleteSeason(Season season); void DeleteEpisode(Episode episode); + void DeleteTrack(Track track); void DeleteGenre(Genre genre); void DeleteStudio(Studio studio); void DeletePeople(People people); diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index 4ff868e6..cddb3805 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -1,31 +1,35 @@ using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; using Kyoo.Models; namespace Kyoo.Controllers { public interface IRepository { - T Get(string slug); - IEnumerable Search(string query); - IEnumerable GetAll(); - T Create(T obj); - T CreateIfNotExists(T obj); - void Edit(T edited, bool resetOld); - void Delete(string slug); + Task Get(long id); + Task Get(string slug); + Task> Search(string query); + Task> GetAll(); + Task Create([NotNull] T obj); + Task CreateIfNotExists([NotNull] T obj); + Task Edit([NotNull] T edited, bool resetOld); + Task Delete(T obj); } public interface IShowRepository : IRepository {} public interface ISeasonRepository : IRepository { - Season Get(string showSlug, int seasonNumber); + Season Get(string showSlug, long seasonNumber); } public interface IEpisodeRepository : IRepository { - Episode Get(string showSlug, int seasonNumber, int episodeNumber); + Episode Get(string showSlug, long seasonNumber, long episodeNumber); } + public interface ITrackRepository : IRepository {} public interface ILibraryRepository : IRepository {} public interface ICollectionRepository : IRepository {} public interface IGenreRepository : IRepository {} diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index 4801fb35..684b5305 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -36,6 +36,7 @@ namespace Kyoo.Models set => GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList(); } [NotMergable] [JsonIgnore] public virtual IEnumerable GenreLinks { get; set; } + [JsonIgnore] public long StudioID { get; set; } public virtual Studio Studio { get; set; } [JsonIgnore] public virtual IEnumerable People { get; set; } [JsonIgnore] public virtual IEnumerable Seasons { get; set; } diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 393ada95..3eecf500 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -1,57 +1,310 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; using Kyoo.Models; -using Kyoo.Models.Exceptions; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; namespace Kyoo.Controllers { public class LibraryManager : ILibraryManager { - private readonly ILibraryRepository _library; + private readonly ILibraryRepository _libraries; + private readonly ICollectionRepository _collections; + private readonly IShowRepository _shows; + private readonly ISeasonRepository _seasons; + private readonly IEpisodeRepository _episodes; + private readonly ITrackRepository _tracks; + private readonly IGenreRepository _genres; + private readonly IStudioRepository _studios; + private readonly IPeopleRepository _people; - public LibraryManager(ILibraryRepository library) + public LibraryManager(ILibraryRepository libraries, + ICollectionRepository collections, + IShowRepository shows, + ISeasonRepository seasons, + IEpisodeRepository episodes, + ITrackRepository tracks, + IGenreRepository genres, + IStudioRepository studios, + IPeopleRepository people) { - _library = library; + _libraries = libraries; + _collections = collections; + _shows = shows; + _seasons = seasons; + _episodes = episodes; + _tracks = tracks; + _genres = genres; + _studios = studios; + _people = people; } - public Library Get(string slug) + public Library GetLibrary(string slug) { - throw new NotImplementedException(); + return _libraries.Get(slug); } - public IEnumerable Search(string query) + public Collection GetCollection(string slug) { - throw new NotImplementedException(); + return _collections.Get(slug); } - public IEnumerable GetAll() + public Show GetShow(string slug) { - throw new NotImplementedException(); + return _shows.Get(slug); } - public Library Create(Library obj) + public Season GetSeason(string showSlug, long seasonNumber) { - throw new NotImplementedException(); + return _seasons.Get(showSlug, seasonNumber); } - public Library CreateIfNotExists(Library obj) + public Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber) { - throw new NotImplementedException(); + return _episodes.Get(showSlug, seasonNumber, episodeNumber); } - public void Edit(Library edited, bool resetOld) + public Episode GetMovieEpisode(string movieSlug) { - throw new NotImplementedException(); + return _episodes.Get(movieSlug); } - public void Delete(string slug) + public Track GetTrack(string slug) { - throw new NotImplementedException(); + return _tracks.Get(slug); + } + + public Genre GetGenre(string slug) + { + return _genres.Get(slug); + } + + public Studio GetStudio(string slug) + { + return _studios.Get(slug); + } + + public People GetPeople(string slug) + { + return _people.Get(slug); + } + + public IEnumerable GetLibraries() + { + return _libraries.GetAll(); + } + + public IEnumerable GetCollections() + { + return _collections.GetAll(); + } + + public IEnumerable GetShows() + { + return _shows.GetAll(); + } + + public IEnumerable GetSeasons() + { + return _seasons.GetAll(); + } + + public IEnumerable GetEpisodes() + { + return _episodes.GetAll(); + } + + public IEnumerable GetTracks() + { + return _tracks.GetAll(); + } + + public IEnumerable GetStudios() + { + return _studios.GetAll(); + } + + public IEnumerable GetPeoples() + { + return _people.GetAll(); + } + + public IEnumerable GetGenres() + { + return _genres.GetAll(); + } + + public IEnumerable SearchLibraries(string searchQuery) + { + return _libraries.Search(searchQuery); + } + + public IEnumerable SearchCollections(string searchQuery) + { + return _collections.Search(searchQuery); + } + + public IEnumerable SearchShows(string searchQuery) + { + return _shows.Search(searchQuery); + } + + public IEnumerable SearchSeasons(string searchQuery) + { + return _seasons.Search(searchQuery); + } + + public IEnumerable SearchEpisodes(string searchQuery) + { + return _episodes.Search(searchQuery); + } + + public IEnumerable SearchGenres(string searchQuery) + { + return _genres.Search(searchQuery); + } + + public IEnumerable SearchStudios(string searchQuery) + { + return _studios.Search(searchQuery); + } + + public IEnumerable SearchPeople(string searchQuery) + { + return _people.Search(searchQuery); + } + + public void RegisterLibrary(Library library) + { + _libraries.Create(library); + } + + public void RegisterCollection(Collection collection) + { + _collections.Create(collection); + } + + public void RegisterShow(Show show) + { + _shows.Create(show); + } + + public void RegisterSeason(Season season) + { + _seasons.Create(season); + } + + public void RegisterEpisode(Episode episode) + { + _episodes.Create(episode); + } + + public void RegisterTrack(Track track) + { + _tracks.Create(track); + } + + public void RegisterGenre(Genre genre) + { + _genres.Create(genre); + + } + + public void RegisterStudio(Studio studio) + { + _studios.Create(studio); + } + + public void RegisterPeople(People people) + { + _people.Create(people); + } + + public void EditLibrary(Library library, bool resetOld) + { + _libraries.Edit(library, resetOld); + } + + public void EditCollection(Collection collection, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void EditShow(Show show, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void EditSeason(Season season, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void EditEpisode(Episode episode, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void EditTrack(Track track, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void EditGenre(Genre genre, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void EditStudio(Studio studio, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void EditPeople(People people, bool resetOld) + { + throw new System.NotImplementedException(); + } + + public void DelteLibrary(Library library) + { + throw new System.NotImplementedException(); + } + + public void DeleteCollection(Collection collection) + { + throw new System.NotImplementedException(); + } + + public void DeleteShow(Show show) + { + throw new System.NotImplementedException(); + } + + public void DeleteSeason(Season season) + { + throw new System.NotImplementedException(); + } + + public void DeleteEpisode(Episode episode) + { + throw new System.NotImplementedException(); + } + + public void DeleteTrack(Track track) + { + throw new System.NotImplementedException(); + } + + public void DeleteGenre(Genre genre) + { + throw new System.NotImplementedException(); + } + + public void DeleteStudio(Studio studio) + { + throw new System.NotImplementedException(); + } + + public void DeletePeople(People people) + { + throw new System.NotImplementedException(); } } } diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index 51aacad2..2382ba04 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Kyoo.Models; +using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; namespace Kyoo.Controllers @@ -9,59 +11,100 @@ namespace Kyoo.Controllers public class ShowRepository : IShowRepository { private readonly DatabaseContext _database; - private readonly ILibraryManager _library; + private readonly IGenreRepository _genres; + private readonly IPeopleRepository _people; + private readonly IStudioRepository _studio; - public ShowRepository(DatabaseContext database, ILibraryManager library) + public ShowRepository(DatabaseContext database, + IGenreRepository genres, + IPeopleRepository people, + IStudioRepository studio) { _database = database; - _library = library; + _genres = genres; + _people = people; + _studio = studio; } - public Show Get(string slug) + public Task Get(long id) { - return _database.Shows.FirstOrDefault(x => x.Slug == slug); + return Task.FromResult(_database.Shows.FirstOrDefault(x => x.ID == id)); + } + + public Task Get(string slug) + { + return Task.FromResult(_database.Shows.FirstOrDefault(x => x.Slug == slug)); } - public IEnumerable Search(string query) + public Task> Search(string query) { - return _database.Shows.FromSqlInterpolated($@"SELECT * FROM Shows WHERE Shows.Title LIKE {$"%{query}%"} - OR Shows.Aliases LIKE {$"%{query}%"}").Take(20); + return Task.FromResult>( + _database.Shows.FromSqlInterpolated($@"SELECT * FROM Shows WHERE Shows.Title LIKE {$"%{query}%"} + OR Shows.Aliases LIKE {$"%{query}%"}").Take(20).ToList()); } - public IEnumerable GetAll() + public Task> GetAll() { - return _database.Shows.ToList(); + return Task.FromResult>(_database.Shows.ToList()); } - public Show Create(Show obj) + public async Task Create(Show obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); - obj.Genres = obj.Genres.Select(_library.CreateIfNotExists).ToList(); + // TODO handle ExternalIDs. + obj.StudioID = await _studio.CreateIfNotExists(obj.Studio); + obj.GenreLinks = (await Task.WhenAll(obj.GenreLinks.Select(async x => + { + x.GenreID = await _genres.CreateIfNotExists(x.Genre); + return x; + }))).ToList(); + obj.People = (await Task.WhenAll(obj.People.Select(async x => + { + x.PeopleID = await _people.CreateIfNotExists(x.People); + return x; + }))).ToList(); + obj.Seasons = null; + obj.Episodes = null; - _database.Shows.Add(obj); - _database.SaveChanges(); - return obj; + await _database.Shows.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; } - public Show CreateIfNotExists(Show obj) + public async Task CreateIfNotExists(Show obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); + + Show old = await Get(obj.Slug); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(Show edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); - return Get(obj.Slug) ?? Create(obj); + Show old = await Get(edited.Slug); + + if (old == null) + throw new ItemNotFound($"No show found with the slug {edited.Slug}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await _database.SaveChangesAsync(); } - public void Edit(Show edited, bool resetOld) + public async Task Delete(Show show) { - throw new System.NotImplementedException(); - } - - public void Delete(string slug) - { - throw new System.NotImplementedException(); + _database.Shows.Remove(show); + await _database.SaveChangesAsync(); } } } \ No newline at end of file From 4414d94c7e9aca7bedd51ad2a8be7814d0b385dc Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Jun 2020 01:51:53 +0200 Subject: [PATCH 03/18] Handling external ids --- Kyoo.Common/Controllers/IRepository.cs | 1 + Kyoo/Controllers/Repositories/ShowRepository.cs | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index cddb3805..4a691ee9 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -35,4 +35,5 @@ namespace Kyoo.Controllers public interface IGenreRepository : IRepository {} public interface IStudioRepository : IRepository {} public interface IPeopleRepository : IRepository {} + public interface IProviderRepository : IRepository {} } \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index 2382ba04..120af32c 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -14,16 +14,19 @@ namespace Kyoo.Controllers private readonly IGenreRepository _genres; private readonly IPeopleRepository _people; private readonly IStudioRepository _studio; + private readonly IProviderRepository _providers; public ShowRepository(DatabaseContext database, IGenreRepository genres, IPeopleRepository people, - IStudioRepository studio) + IStudioRepository studio, + IProviderRepository providers) { _database = database; _genres = genres; _people = people; _studio = studio; + _providers = providers; } public Task Get(long id) @@ -52,8 +55,7 @@ namespace Kyoo.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - - // TODO handle ExternalIDs. + obj.StudioID = await _studio.CreateIfNotExists(obj.Studio); obj.GenreLinks = (await Task.WhenAll(obj.GenreLinks.Select(async x => { @@ -65,6 +67,11 @@ namespace Kyoo.Controllers x.PeopleID = await _people.CreateIfNotExists(x.People); return x; }))).ToList(); + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); obj.Seasons = null; obj.Episodes = null; From bd1ef0e15beb1b95e9c0cec38ea3d7d2678a46f2 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Jun 2020 02:08:17 +0200 Subject: [PATCH 04/18] Creating the genre repository --- .../Repositories/GenreRepository.cs | 87 +++++++++++++++++++ .../Repositories/ShowRepository.cs | 62 +++++++------ 2 files changed, 122 insertions(+), 27 deletions(-) create mode 100644 Kyoo/Controllers/Repositories/GenreRepository.cs diff --git a/Kyoo/Controllers/Repositories/GenreRepository.cs b/Kyoo/Controllers/Repositories/GenreRepository.cs new file mode 100644 index 00000000..5544c07b --- /dev/null +++ b/Kyoo/Controllers/Repositories/GenreRepository.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class GenreRepository : IGenreRepository + { + private readonly DatabaseContext _database; + + + public GenreRepository(DatabaseContext database) + { + _database = database; + } + + public async Task Get(long id) + { + return await _database.Genres.FirstOrDefaultAsync(x => x.ID == id); + } + + public async Task Get(string slug) + { + return await _database.Genres.FirstOrDefaultAsync(x => x.Slug == slug); + } + + public async Task> Search(string query) + { + return await _database.Genres + .Where(genre => EF.Functions.Like(genre.Name, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Genres.ToListAsync(); + } + + public async Task Create(Genre obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + await _database.Genres.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(Genre obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + Genre old = await Get(obj.Slug); + if (old != null) + return obj.ID; + return await Create(obj); + } + + public async Task Edit(Genre edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + Genre old = await Get(edited.Slug); + + if (old == null) + throw new ItemNotFound($"No genre found with the slug {edited.Slug}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await _database.SaveChangesAsync(); + } + + public async Task Delete(Genre obj) + { + _database.Genres.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index 120af32c..e0901cfc 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -29,49 +29,36 @@ namespace Kyoo.Controllers _providers = providers; } - public Task Get(long id) + public async Task Get(long id) { - return Task.FromResult(_database.Shows.FirstOrDefault(x => x.ID == id)); + return await _database.Shows.FirstOrDefaultAsync(x => x.ID == id); } - public Task Get(string slug) + public async Task Get(string slug) { - return Task.FromResult(_database.Shows.FirstOrDefault(x => x.Slug == slug)); + return await _database.Shows.FirstOrDefaultAsync(x => x.Slug == slug); } - public Task> Search(string query) + public async Task> Search(string query) { - return Task.FromResult>( - _database.Shows.FromSqlInterpolated($@"SELECT * FROM Shows WHERE Shows.Title LIKE {$"%{query}%"} - OR Shows.Aliases LIKE {$"%{query}%"}").Take(20).ToList()); + return await _database.Shows + .FromSqlInterpolated($@"SELECT * FROM Shows WHERE Shows.Title LIKE {$"%{query}%"} + OR Shows.Aliases LIKE {$"%{query}%"}") + .Take(20) + .ToListAsync(); } - public Task> GetAll() + public async Task> GetAll() { - return Task.FromResult>(_database.Shows.ToList()); + return await _database.Shows.ToListAsync(); } public async Task Create(Show obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); - - obj.StudioID = await _studio.CreateIfNotExists(obj.Studio); - obj.GenreLinks = (await Task.WhenAll(obj.GenreLinks.Select(async x => - { - x.GenreID = await _genres.CreateIfNotExists(x.Genre); - return x; - }))).ToList(); - obj.People = (await Task.WhenAll(obj.People.Select(async x => - { - x.PeopleID = await _people.CreateIfNotExists(x.People); - return x; - }))).ToList(); - obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => - { - x.ProviderID = await _providers.CreateIfNotExists(x.Provider); - return x; - }))).ToList(); + + await Validate(obj); obj.Seasons = null; obj.Episodes = null; @@ -105,9 +92,30 @@ namespace Kyoo.Controllers if (resetOld) Utility.Nullify(old); Utility.Merge(old, edited); + await Validate(old); await _database.SaveChangesAsync(); } + private async Task Validate(Show obj) + { + obj.StudioID = await _studio.CreateIfNotExists(obj.Studio); + obj.GenreLinks = (await Task.WhenAll(obj.GenreLinks.Select(async x => + { + x.GenreID = await _genres.CreateIfNotExists(x.Genre); + return x; + }))).ToList(); + obj.People = (await Task.WhenAll(obj.People.Select(async x => + { + x.PeopleID = await _people.CreateIfNotExists(x.People); + return x; + }))).ToList(); + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } + public async Task Delete(Show show) { _database.Shows.Remove(show); From 0bee630f4663f7aa9b10609f29dd94452a648c14 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Jun 2020 03:21:21 +0200 Subject: [PATCH 05/18] Creating the people repository --- .../Repositories/PeopleRepository.cs | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 Kyoo/Controllers/Repositories/PeopleRepository.cs diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs new file mode 100644 index 00000000..f6a85c1a --- /dev/null +++ b/Kyoo/Controllers/Repositories/PeopleRepository.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class PeopleRepository : IPeopleRepository + { + private readonly DatabaseContext _database; + private readonly IProviderRepository _providers; + + public PeopleRepository(DatabaseContext database, IProviderRepository providers) + { + _database = database; + _providers = providers; + } + + public Task Get(long id) + { + return _database.Peoples.FirstOrDefaultAsync(x => x.ID == id); + } + + public Task Get(string slug) + { + return _database.Peoples.FirstOrDefaultAsync(x => x.Slug == slug); + } + + public async Task> Search(string query) + { + return await _database.Peoples + .Where(people => EF.Functions.Like(people.Name, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Peoples.ToListAsync(); + } + + public async Task Create(People obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + await Validate(obj); + obj.Roles = null; + + await _database.Peoples.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(People obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + People old = await Get(obj.Slug); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(People edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + People old = await Get(edited.Slug); + + if (old == null) + throw new ItemNotFound($"No people found with the slug {edited.Slug}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await Validate(old); + await _database.SaveChangesAsync(); + } + + private async Task Validate(People obj) + { + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } + + public async Task Delete(People obj) + { + _database.Peoples.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file From c5c795411687cd3f56c24c69f37c56b655632a7e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Jun 2020 03:29:39 +0200 Subject: [PATCH 06/18] Creating the provider repository --- .../Repositories/ProviderRepository.cs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 Kyoo/Controllers/Repositories/ProviderRepository.cs diff --git a/Kyoo/Controllers/Repositories/ProviderRepository.cs b/Kyoo/Controllers/Repositories/ProviderRepository.cs new file mode 100644 index 00000000..01e2898a --- /dev/null +++ b/Kyoo/Controllers/Repositories/ProviderRepository.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class ProviderRepository : IProviderRepository + { + private readonly DatabaseContext _database; + + + public ProviderRepository(DatabaseContext database) + { + _database = database; + } + + public async Task Get(long id) + { + return await _database.Providers.FirstOrDefaultAsync(x => x.ID == id); + } + + public async Task Get(string slug) + { + return await _database.Providers.FirstOrDefaultAsync(x => x.Name == slug); + } + + public async Task> Search(string query) + { + return await _database.Providers + .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Providers.ToListAsync(); + } + + public async Task Create(ProviderID obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + await _database.Providers.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(ProviderID obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + ProviderID old = await Get(obj.Name); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(ProviderID edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + ProviderID old = await Get(edited.Name); + + if (old == null) + throw new ItemNotFound($"No provider found with the name {edited.Name}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await _database.SaveChangesAsync(); + } + + public async Task Delete(ProviderID obj) + { + _database.Providers.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file From 965fb7ed5b2c988b7d43681da7dc5e692c76931d Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Jun 2020 03:52:27 +0200 Subject: [PATCH 07/18] Creating the season repository --- Kyoo.Common/Controllers/IRepository.cs | 4 +- Kyoo.Common/Models/Season.cs | 2 +- .../Repositories/SeasonRepository.cs | 114 ++++++++++++++++++ 3 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 Kyoo/Controllers/Repositories/SeasonRepository.cs diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index 4a691ee9..baf7e1cc 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -21,12 +21,12 @@ namespace Kyoo.Controllers public interface ISeasonRepository : IRepository { - Season Get(string showSlug, long seasonNumber); + Task Get(string showSlug, long seasonNumber); } public interface IEpisodeRepository : IRepository { - Episode Get(string showSlug, long seasonNumber, long episodeNumber); + Task Get(string showSlug, long seasonNumber, long episodeNumber); } public interface ITrackRepository : IRepository {} diff --git a/Kyoo.Common/Models/Season.cs b/Kyoo.Common/Models/Season.cs index 0f306349..99bbd5cf 100644 --- a/Kyoo.Common/Models/Season.cs +++ b/Kyoo.Common/Models/Season.cs @@ -10,7 +10,7 @@ namespace Kyoo.Models public long SeasonNumber { get; set; } = -1; - public string Slug => $"{Show.Title}-s{SeasonNumber}"; + public string Slug => $"{Show.Slug}-s{SeasonNumber}"; public string Title { get; set; } public string Overview { get; set; } public long? Year { get; set; } diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs new file mode 100644 index 00000000..067e44b0 --- /dev/null +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class SeasonRepository : ISeasonRepository + { + private readonly DatabaseContext _database; + private readonly IProviderRepository _providers; + + + public SeasonRepository(DatabaseContext database, IProviderRepository providers) + { + _database = database; + _providers = providers; + } + + public async Task Get(long id) + { + return await _database.Seasons.FirstOrDefaultAsync(x => x.ID == id); + } + + public Task Get(string slug) + { + int index = slug.IndexOf('-'); + if (index == -1) + throw new InvalidOperationException("Invalid season slug. Format: showSlug-seasonNumber"); + string showSlug = slug.Substring(0, index); + if (!long.TryParse(slug.Substring(index + 1), out long seasonNumber)) + throw new InvalidOperationException("Invalid season slug. Format: showSlug-seasonNumber"); + return Get(showSlug, seasonNumber); + } + + public async Task Get(string showSlug, long seasonNumber) + { + return await _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug + && x.SeasonNumber == seasonNumber); + } + + public async Task> Search(string query) + { + return await _database.Seasons + .Where(x => EF.Functions.Like(x.Title, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Seasons.ToListAsync(); + } + + public async Task Create(Season obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + obj.Show = null; + obj.Episodes = null; + await Validate(obj); + + await _database.Seasons.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(Season obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + Season old = await Get(obj.Slug); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(Season edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + Season old = await Get(edited.Slug); + + if (old == null) + throw new ItemNotFound($"No season found with the slug {edited.Slug}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await _database.SaveChangesAsync(); + } + + private async Task Validate(Season obj) + { + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } + + public async Task Delete(Season obj) + { + _database.Seasons.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file From 5272c75232638b2b47e1bc2b1bbaed91ecbc810a Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 3 Jun 2020 04:08:59 +0200 Subject: [PATCH 08/18] Creating the episode repository --- .../Repositories/EpisodeRepository.cs | 121 ++++++++++++++++++ .../Repositories/SeasonRepository.cs | 10 +- 2 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 Kyoo/Controllers/Repositories/EpisodeRepository.cs diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs new file mode 100644 index 00000000..3f934f35 --- /dev/null +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class EpisodeRepository : IEpisodeRepository + { + private readonly DatabaseContext _database; + private readonly IProviderRepository _providers; + + + public EpisodeRepository(DatabaseContext database, IProviderRepository providers) + { + _database = database; + _providers = providers; + } + + public async Task Get(long id) + { + return await _database.Episodes.FirstOrDefaultAsync(x => x.ID == id); + } + + public Task Get(string slug) + { + int sIndex = slug.IndexOf("-s", StringComparison.Ordinal); + int eIndex = slug.IndexOf("-e", StringComparison.Ordinal); + if (sIndex == -1 || eIndex == -1 || eIndex < sIndex) + throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}"); + string showSlug = slug.Substring(0, sIndex); + if (!long.TryParse(slug.Substring(sIndex + 2), out long seasonNumber)) + throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}"); + if (!long.TryParse(slug.Substring(eIndex + 2), out long episodeNumber)) + throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}"); + return Get(showSlug, seasonNumber, episodeNumber); + } + + public async Task Get(string showSlug, long seasonNumber, long episodeNumber) + { + return await _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug + && x.SeasonNumber == seasonNumber + && x.EpisodeNumber == episodeNumber); + } + + public async Task> Search(string query) + { + return await _database.Episodes + .Where(x => EF.Functions.Like(x.Title, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Episodes.ToListAsync(); + } + + public async Task Create(Episode obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + // TODO initialize ShowID & SeaosnID here. (same for the season repository). OR null check the ID and throw on invalid. + obj.Show = null; + obj.Season = null; + await Validate(obj); + + await _database.Episodes.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(Episode obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + Episode old = await Get(obj.Slug); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(Episode edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + Episode old = await Get(edited.Slug); + + if (old == null) + throw new ItemNotFound($"No episode found with the slug {edited.Slug}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + + await Validate(old); + await _database.SaveChangesAsync(); + } + + private async Task Validate(Episode obj) + { + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } + + public async Task Delete(Episode obj) + { + _database.Episodes.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index 067e44b0..056d64a6 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -27,12 +27,12 @@ namespace Kyoo.Controllers public Task Get(string slug) { - int index = slug.IndexOf('-'); + int index = slug.IndexOf("-s", StringComparison.Ordinal); if (index == -1) - throw new InvalidOperationException("Invalid season slug. Format: showSlug-seasonNumber"); + throw new InvalidOperationException("Invalid season slug. Format: {showSlug}-s{seasonNumber}"); string showSlug = slug.Substring(0, index); - if (!long.TryParse(slug.Substring(index + 1), out long seasonNumber)) - throw new InvalidOperationException("Invalid season slug. Format: showSlug-seasonNumber"); + if (!long.TryParse(slug.Substring(index + 2), out long seasonNumber)) + throw new InvalidOperationException("Invalid season slug. Format: {showSlug}-s{seasonNumber}"); return Get(showSlug, seasonNumber); } @@ -93,6 +93,8 @@ namespace Kyoo.Controllers if (resetOld) Utility.Nullify(old); Utility.Merge(old, edited); + + await Validate(old); await _database.SaveChangesAsync(); } From 3c900039143edfae30a5028b978dee29c25647d7 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 5 Jun 2020 19:48:45 +0200 Subject: [PATCH 09/18] Implementing the track repository --- Kyoo.Common/Controllers/IRepository.cs | 7 +- .../Repositories/EpisodeRepository.cs | 6 +- .../Repositories/SeasonRepository.cs | 3 + .../Repositories/TrackRepository.cs | 88 +++++++++++++++++++ 4 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 Kyoo/Controllers/Repositories/TrackRepository.cs diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index baf7e1cc..07c8043d 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -28,8 +28,11 @@ namespace Kyoo.Controllers { Task Get(string showSlug, long seasonNumber, long episodeNumber); } - - public interface ITrackRepository : IRepository {} + + public interface ITrackRepository : IRepository + { + Task Get(long episodeID, string languageTag, bool isForced); + } public interface ILibraryRepository : IRepository {} public interface ICollectionRepository : IRepository {} public interface IGenreRepository : IRepository {} diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index 3f934f35..bc32b92c 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -63,8 +63,7 @@ namespace Kyoo.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - - // TODO initialize ShowID & SeaosnID here. (same for the season repository). OR null check the ID and throw on invalid. + obj.Show = null; obj.Season = null; await Validate(obj); @@ -105,6 +104,9 @@ namespace Kyoo.Controllers private async Task Validate(Episode obj) { + if (obj.ShowID <= 0) + throw new InvalidOperationException($"Can't store an episode not related to any show (showID: {obj.ShowID})."); + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => { x.ProviderID = await _providers.CreateIfNotExists(x.Provider); diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index 056d64a6..86bd5d6f 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -100,6 +100,9 @@ namespace Kyoo.Controllers private async Task Validate(Season obj) { + if (obj.ShowID <= 0) + throw new InvalidOperationException($"Can't store a season not related to any show (showID: {obj.ShowID})."); + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => { x.ProviderID = await _providers.CreateIfNotExists(x.Provider); diff --git a/Kyoo/Controllers/Repositories/TrackRepository.cs b/Kyoo/Controllers/Repositories/TrackRepository.cs new file mode 100644 index 00000000..a5d58aa0 --- /dev/null +++ b/Kyoo/Controllers/Repositories/TrackRepository.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class TrackRepository : ITrackRepository + { + private readonly DatabaseContext _database; + + + public TrackRepository(DatabaseContext database) + { + _database = database; + } + + public async Task Get(long id) + { + return await _database.Tracks.FirstOrDefaultAsync(x => x.ID == id); + } + + public Task Get(string slug) + { + throw new InvalidOperationException("Tracks do not support the get by slug method."); + } + + public Task Get(long episodeID, string languageTag, bool isForced) + { + return _database.Tracks.FirstOrDefaultAsync(x => x.EpisodeID == episodeID + && x.Language == languageTag + && x.IsForced == isForced); + } + + public Task> Search(string query) + { + throw new InvalidOperationException("Tracks do not support the search method."); + } + + public async Task> GetAll() + { + return await _database.Tracks.ToListAsync(); + } + + public async Task Create(Track obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + if (obj.EpisodeID <= 0) + throw new InvalidOperationException($"Can't store a track not related to any episode (episodeID: {obj.EpisodeID})."); + + obj.Episode = null; + await _database.Tracks.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public Task CreateIfNotExists(Track obj) + { + return Create(obj); + } + + public async Task Edit(Track edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + Track old = await Get(edited.ID); + + if (old == null) + throw new ItemNotFound($"No track found with the ID {edited.ID}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await _database.SaveChangesAsync(); + } + + public async Task Delete(Track obj) + { + _database.Tracks.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file From d2f98096342580d3a11a9dd6627bafe424a1f31a Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 6 Jun 2020 00:50:06 +0200 Subject: [PATCH 10/18] Implementing the library repository --- .../Repositories/LibraryRepository.cs | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 Kyoo/Controllers/Repositories/LibraryRepository.cs diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs new file mode 100644 index 00000000..bac6e6ba --- /dev/null +++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class LibraryRepository : ILibraryRepository + { + private readonly DatabaseContext _database; + private readonly IProviderRepository _providers; + + + public LibraryRepository(DatabaseContext database, IProviderRepository providers) + { + _database = database; + _providers = providers; + } + + public Task Get(long id) + { + return _database.Libraries.FirstOrDefaultAsync(x => x.ID == id); + } + + public Task Get(string slug) + { + return _database.Libraries.FirstOrDefaultAsync(x => x.Name == slug); + } + + public async Task> Search(string query) + { + return await _database.Libraries + .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Libraries.ToListAsync(); + } + + public async Task Create(Library obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + obj.Links = null; + await Validate(obj); + await _database.Libraries.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(Library obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + Library old = await Get(obj.Name); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(Library edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + Library old = await Get(edited.Name); + + if (old == null) + throw new ItemNotFound($"No library found with the name {edited.Name}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await Validate(old); + await _database.SaveChangesAsync(); + } + + private async Task Validate(Library obj) + { + obj.ProviderLinks = (await Task.WhenAll(obj.ProviderLinks.Select(async x => + { + x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } + + public async Task Delete(Library obj) + { + _database.Libraries.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file From b20c7bfe06dea5a749f697f7c2c7b30d47353580 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 6 Jun 2020 01:14:48 +0200 Subject: [PATCH 11/18] Implemnting the studio repository --- .../Repositories/StudioRepository.cs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 Kyoo/Controllers/Repositories/StudioRepository.cs diff --git a/Kyoo/Controllers/Repositories/StudioRepository.cs b/Kyoo/Controllers/Repositories/StudioRepository.cs new file mode 100644 index 00000000..c7d77f18 --- /dev/null +++ b/Kyoo/Controllers/Repositories/StudioRepository.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class StudioRepository : IStudioRepository + { + private readonly DatabaseContext _database; + + + public StudioRepository(DatabaseContext database) + { + _database = database; + } + + public async Task Get(long id) + { + return await _database.Studios.FirstOrDefaultAsync(x => x.ID == id); + } + + public async Task Get(string slug) + { + return await _database.Studios.FirstOrDefaultAsync(x => x.Name == slug); + } + + public async Task> Search(string query) + { + return await _database.Studios + .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Studios.ToListAsync(); + } + + public async Task Create(Studio obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + await _database.Studios.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(Studio obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + Studio old = await Get(obj.Name); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(Studio edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + Studio old = await Get(edited.Name); + + if (old == null) + throw new ItemNotFound($"No studio found with the name {edited.Name}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + await _database.SaveChangesAsync(); + } + + public async Task Delete(Studio obj) + { + _database.Studios.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file From e954af478780b79f07b34bb40e61b612c706f85b Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 6 Jun 2020 01:17:26 +0200 Subject: [PATCH 12/18] Implemnting the collection repository --- .../Repositories/CollectionRepository.cs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Kyoo/Controllers/Repositories/CollectionRepository.cs diff --git a/Kyoo/Controllers/Repositories/CollectionRepository.cs b/Kyoo/Controllers/Repositories/CollectionRepository.cs new file mode 100644 index 00000000..c0b38434 --- /dev/null +++ b/Kyoo/Controllers/Repositories/CollectionRepository.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; +using Microsoft.EntityFrameworkCore; + +namespace Kyoo.Controllers +{ + public class CollectionRepository : ICollectionRepository + { + private readonly DatabaseContext _database; + + + public CollectionRepository(DatabaseContext database) + { + _database = database; + } + + public Task Get(long id) + { + return _database.Collections.FirstOrDefaultAsync(x => x.ID == id); + } + + public Task Get(string slug) + { + return _database.Collections.FirstOrDefaultAsync(x => x.Slug == slug); + } + + public async Task> Search(string query) + { + return await _database.Collections + .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) + .Take(20) + .ToListAsync(); + } + + public async Task> GetAll() + { + return await _database.Collections.ToListAsync(); + } + + public async Task Create(Collection obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + await _database.Collections.AddAsync(obj); + await _database.SaveChangesAsync(); + return obj.ID; + } + + public async Task CreateIfNotExists(Collection obj) + { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); + + Collection old = await Get(obj.Slug); + if (old != null) + return old.ID; + return await Create(obj); + } + + public async Task Edit(Collection edited, bool resetOld) + { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); + + Collection old = await Get(edited.Slug); + + if (old == null) + throw new ItemNotFound($"No collection found with the slug {edited.Slug}."); + + if (resetOld) + Utility.Nullify(old); + Utility.Merge(old, edited); + + await _database.SaveChangesAsync(); + } + + public async Task Delete(Collection obj) + { + _database.Collections.Remove(obj); + await _database.SaveChangesAsync(); + } + } +} \ No newline at end of file From b3847a5bc50e8ba947c571b9795e90c7b6bc045e Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 6 Jun 2020 13:51:53 +0200 Subject: [PATCH 13/18] Finishing the library manager --- Kyoo.Common/Controllers/ILibraryManager.cs | 110 +++++------ Kyoo/Controllers/LibraryManager.cs | 201 ++++++++++----------- 2 files changed, 156 insertions(+), 155 deletions(-) diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index 906c5e32..6a3234f4 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using Kyoo.Models; namespace Kyoo.Controllers @@ -6,70 +7,71 @@ namespace Kyoo.Controllers public interface ILibraryManager { // Get by slug - Library GetLibrary(string slug); - Collection GetCollection(string slug); - Show GetShow(string slug); - Season GetSeason(string showSlug, long seasonNumber); - Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber); - Episode GetMovieEpisode(string movieSlug); - Track GetTrack(string slug); - Genre GetGenre(string slug); - Studio GetStudio(string slug); - People GetPeople(string slug); + Task GetLibrary(string slug); + Task GetCollection(string slug); + Task GetShow(string slug); + Task GetSeason(string showSlug, long seasonNumber); + Task GetEpisode(string showSlug, long seasonNumber, long episodeNumber); + Task GetMovieEpisode(string movieSlug); + Task GetTrack(long episodeID, string language, bool isForced); + Task GetGenre(string slug); + Task GetStudio(string slug); + Task GetPeople(string slug); // Get all - IEnumerable GetLibraries(); - IEnumerable GetCollections(); - IEnumerable GetShows(); - IEnumerable GetSeasons(); - IEnumerable GetEpisodes(); - IEnumerable GetTracks(); - IEnumerable GetStudios(); - IEnumerable GetPeoples(); - IEnumerable GetGenres(); + Task> GetLibraries(); + Task> GetCollections(); + Task> GetShows(); + Task> GetSeasons(); + Task> GetEpisodes(); + Task> GetTracks(); + Task> GetStudios(); + Task> GetPeoples(); + Task> GetGenres(); + Task> GetProviders(); // Search - IEnumerable SearchLibraries(string searchQuery); - IEnumerable SearchCollections(string searchQuery); - IEnumerable SearchShows(string searchQuery); - IEnumerable SearchSeasons(string searchQuery); - IEnumerable SearchEpisodes(string searchQuery); - IEnumerable SearchGenres(string searchQuery); - IEnumerable SearchStudios(string searchQuery); - IEnumerable SearchPeople(string searchQuery); + Task> SearchLibraries(string searchQuery); + Task> SearchCollections(string searchQuery); + Task> SearchShows(string searchQuery); + Task> SearchSeasons(string searchQuery); + Task> SearchEpisodes(string searchQuery); + Task> SearchGenres(string searchQuery); + Task> SearchStudios(string searchQuery); + Task> SearchPeople(string searchQuery); //Register values - void RegisterLibrary(Library library); - void RegisterCollection(Collection collection); - void RegisterShow(Show show); - void RegisterSeason(Season season); - void RegisterEpisode(Episode episode); - void RegisterTrack(Track track); - void RegisterGenre(Genre genre); - void RegisterStudio(Studio studio); - void RegisterPeople(People people); + Task RegisterLibrary(Library library); + Task RegisterCollection(Collection collection); + Task RegisterShow(Show show); + Task RegisterSeason(Season season); + Task RegisterEpisode(Episode episode); + Task RegisterTrack(Track track); + Task RegisterGenre(Genre genre); + Task RegisterStudio(Studio studio); + Task RegisterPeople(People people); // Edit values - void EditLibrary(Library library, bool resetOld); - void EditCollection(Collection collection, bool resetOld); - void EditShow(Show show, bool resetOld); - void EditSeason(Season season, bool resetOld); - void EditEpisode(Episode episode, bool resetOld); - void EditTrack(Track track, bool resetOld); - void EditGenre(Genre genre, bool resetOld); - void EditStudio(Studio studio, bool resetOld); - void EditPeople(People people, bool resetOld); + Task EditLibrary(Library library, bool resetOld); + Task EditCollection(Collection collection, bool resetOld); + Task EditShow(Show show, bool resetOld); + Task EditSeason(Season season, bool resetOld); + Task EditEpisode(Episode episode, bool resetOld); + Task EditTrack(Track track, bool resetOld); + Task EditGenre(Genre genre, bool resetOld); + Task EditStudio(Studio studio, bool resetOld); + Task EditPeople(People people, bool resetOld); // Delete values - void DelteLibrary(Library library); - void DeleteCollection(Collection collection); - void DeleteShow(Show show); - void DeleteSeason(Season season); - void DeleteEpisode(Episode episode); - void DeleteTrack(Track track); - void DeleteGenre(Genre genre); - void DeleteStudio(Studio studio); - void DeletePeople(People people); + Task DelteLibrary(Library library); + Task DeleteCollection(Collection collection); + Task DeleteShow(Show show); + Task DeleteSeason(Season season); + Task DeleteEpisode(Episode episode); + Task DeleteTrack(Track track); + Task DeleteGenre(Genre genre); + Task DeleteStudio(Studio studio); + Task DeletePeople(People people); } } diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 3eecf500..f351fd72 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using Kyoo.Models; namespace Kyoo.Controllers @@ -14,297 +15,295 @@ namespace Kyoo.Controllers private readonly IGenreRepository _genres; private readonly IStudioRepository _studios; private readonly IPeopleRepository _people; + private readonly IProviderRepository _providers; - public LibraryManager(ILibraryRepository libraries, - ICollectionRepository collections, - IShowRepository shows, - ISeasonRepository seasons, - IEpisodeRepository episodes, - ITrackRepository tracks, - IGenreRepository genres, - IStudioRepository studios, - IPeopleRepository people) + public LibraryManager(DatabaseContext database) { - _libraries = libraries; - _collections = collections; - _shows = shows; - _seasons = seasons; - _episodes = episodes; - _tracks = tracks; - _genres = genres; - _studios = studios; - _people = people; + _providers = new ProviderRepository(database); + _libraries = new LibraryRepository(database, _providers); + _collections = new CollectionRepository(database); + _genres = new GenreRepository(database); + _people = new PeopleRepository(database, _providers); + _studios = new StudioRepository(database); + _shows = new ShowRepository(database, _genres, _people, _studios, _providers); + _seasons = new SeasonRepository(database, _providers); + _episodes = new EpisodeRepository(database, _providers); + _tracks = new TrackRepository(database); } - public Library GetLibrary(string slug) + public Task GetLibrary(string slug) { return _libraries.Get(slug); } - public Collection GetCollection(string slug) + public Task GetCollection(string slug) { return _collections.Get(slug); } - public Show GetShow(string slug) + public Task GetShow(string slug) { return _shows.Get(slug); } - public Season GetSeason(string showSlug, long seasonNumber) + public Task GetSeason(string showSlug, long seasonNumber) { return _seasons.Get(showSlug, seasonNumber); } - public Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber) + public Task GetEpisode(string showSlug, long seasonNumber, long episodeNumber) { return _episodes.Get(showSlug, seasonNumber, episodeNumber); } - public Episode GetMovieEpisode(string movieSlug) + public Task GetMovieEpisode(string movieSlug) { return _episodes.Get(movieSlug); } - public Track GetTrack(string slug) + public Task GetTrack(long episodeID, string language, bool isForced) { - return _tracks.Get(slug); + return _tracks.Get(episodeID, language, isForced); } - public Genre GetGenre(string slug) + public Task GetGenre(string slug) { return _genres.Get(slug); } - public Studio GetStudio(string slug) + public Task GetStudio(string slug) { return _studios.Get(slug); } - public People GetPeople(string slug) + public Task GetPeople(string slug) { return _people.Get(slug); } - public IEnumerable GetLibraries() + public Task> GetLibraries() { return _libraries.GetAll(); } - public IEnumerable GetCollections() + public Task> GetCollections() { return _collections.GetAll(); } - public IEnumerable GetShows() + public Task> GetShows() { return _shows.GetAll(); } - public IEnumerable GetSeasons() + public Task> GetSeasons() { return _seasons.GetAll(); } - public IEnumerable GetEpisodes() + public Task> GetEpisodes() { return _episodes.GetAll(); } - public IEnumerable GetTracks() + public Task> GetTracks() { return _tracks.GetAll(); } - public IEnumerable GetStudios() + public Task> GetStudios() { return _studios.GetAll(); } - public IEnumerable GetPeoples() + public Task> GetPeoples() { return _people.GetAll(); } - public IEnumerable GetGenres() + public Task> GetGenres() { return _genres.GetAll(); } - public IEnumerable SearchLibraries(string searchQuery) + public Task> GetProviders() + { + return _providers.GetAll(); + } + + public Task> SearchLibraries(string searchQuery) { return _libraries.Search(searchQuery); } - public IEnumerable SearchCollections(string searchQuery) + public Task> SearchCollections(string searchQuery) { return _collections.Search(searchQuery); } - public IEnumerable SearchShows(string searchQuery) + public Task> SearchShows(string searchQuery) { return _shows.Search(searchQuery); } - public IEnumerable SearchSeasons(string searchQuery) + public Task> SearchSeasons(string searchQuery) { return _seasons.Search(searchQuery); } - public IEnumerable SearchEpisodes(string searchQuery) + public Task> SearchEpisodes(string searchQuery) { return _episodes.Search(searchQuery); } - public IEnumerable SearchGenres(string searchQuery) + public Task> SearchGenres(string searchQuery) { return _genres.Search(searchQuery); } - public IEnumerable SearchStudios(string searchQuery) + public Task> SearchStudios(string searchQuery) { return _studios.Search(searchQuery); } - public IEnumerable SearchPeople(string searchQuery) + public Task> SearchPeople(string searchQuery) { return _people.Search(searchQuery); } - public void RegisterLibrary(Library library) + public Task RegisterLibrary(Library library) { - _libraries.Create(library); + return _libraries.Create(library); } - public void RegisterCollection(Collection collection) + public Task RegisterCollection(Collection collection) { - _collections.Create(collection); + return _collections.Create(collection); } - public void RegisterShow(Show show) + public Task RegisterShow(Show show) { - _shows.Create(show); + return _shows.Create(show); } - public void RegisterSeason(Season season) + public Task RegisterSeason(Season season) { - _seasons.Create(season); + return _seasons.Create(season); } - public void RegisterEpisode(Episode episode) + public Task RegisterEpisode(Episode episode) { - _episodes.Create(episode); + return _episodes.Create(episode); } - public void RegisterTrack(Track track) + public Task RegisterTrack(Track track) { - _tracks.Create(track); + return _tracks.Create(track); } - public void RegisterGenre(Genre genre) + public Task RegisterGenre(Genre genre) { - _genres.Create(genre); - + return _genres.Create(genre); } - public void RegisterStudio(Studio studio) + public Task RegisterStudio(Studio studio) { - _studios.Create(studio); + return _studios.Create(studio); } - public void RegisterPeople(People people) + public Task RegisterPeople(People people) { - _people.Create(people); + return _people.Create(people); } - public void EditLibrary(Library library, bool resetOld) + public Task EditLibrary(Library library, bool resetOld) { - _libraries.Edit(library, resetOld); + return _libraries.Edit(library, resetOld); } - public void EditCollection(Collection collection, bool resetOld) + public Task EditCollection(Collection collection, bool resetOld) { - throw new System.NotImplementedException(); + return _collections.Edit(collection, resetOld); } - public void EditShow(Show show, bool resetOld) + public Task EditShow(Show show, bool resetOld) { - throw new System.NotImplementedException(); + return _shows.Edit(show, resetOld); } - public void EditSeason(Season season, bool resetOld) + public Task EditSeason(Season season, bool resetOld) { - throw new System.NotImplementedException(); + return _seasons.Edit(season, resetOld); } - public void EditEpisode(Episode episode, bool resetOld) + public Task EditEpisode(Episode episode, bool resetOld) { - throw new System.NotImplementedException(); + return _episodes.Edit(episode, resetOld); } - public void EditTrack(Track track, bool resetOld) + public Task EditTrack(Track track, bool resetOld) { - throw new System.NotImplementedException(); + return _tracks.Edit(track, resetOld); } - public void EditGenre(Genre genre, bool resetOld) + public Task EditGenre(Genre genre, bool resetOld) { - throw new System.NotImplementedException(); + return _genres.Edit(genre, resetOld); } - public void EditStudio(Studio studio, bool resetOld) + public Task EditStudio(Studio studio, bool resetOld) { - throw new System.NotImplementedException(); + return _studios.Edit(studio, resetOld); } - public void EditPeople(People people, bool resetOld) + public Task EditPeople(People people, bool resetOld) { - throw new System.NotImplementedException(); + return _people.Edit(people, resetOld); } - public void DelteLibrary(Library library) + public Task DelteLibrary(Library library) { - throw new System.NotImplementedException(); + return _libraries.Delete(library); } - public void DeleteCollection(Collection collection) + public Task DeleteCollection(Collection collection) { - throw new System.NotImplementedException(); + return _collections.Delete(collection); } - public void DeleteShow(Show show) + public Task DeleteShow(Show show) { - throw new System.NotImplementedException(); + return _shows.Delete(show); } - public void DeleteSeason(Season season) + public Task DeleteSeason(Season season) { - throw new System.NotImplementedException(); + return _seasons.Delete(season); } - public void DeleteEpisode(Episode episode) + public Task DeleteEpisode(Episode episode) { - throw new System.NotImplementedException(); + return _episodes.Delete(episode); } - public void DeleteTrack(Track track) + public Task DeleteTrack(Track track) { - throw new System.NotImplementedException(); + return _tracks.Delete(track); } - public void DeleteGenre(Genre genre) + public Task DeleteGenre(Genre genre) { - throw new System.NotImplementedException(); + return _genres.Delete(genre); } - public void DeleteStudio(Studio studio) + public Task DeleteStudio(Studio studio) { - throw new System.NotImplementedException(); + return _studios.Delete(studio); } - public void DeletePeople(People people) + public Task DeletePeople(People people) { - throw new System.NotImplementedException(); + return _people.Delete(people); } } } From c5b0858d4a40f2bf2604be1aa84d91ade8bfeab0 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 6 Jun 2020 17:53:08 +0200 Subject: [PATCH 14/18] Implemnting relational data loading inside the repositories --- Kyoo.Common/Controllers/ILibraryManager.cs | 10 ++ Kyoo.Common/Controllers/IRepository.cs | 7 ++ Kyoo/Controllers/LibraryManager.cs | 30 ++++++ .../Repositories/EpisodeRepository.cs | 19 +++- .../Repositories/SeasonRepository.cs | 10 ++ Kyoo/Tasks/ReScan.cs | 6 +- Kyoo/Views/API/CollectionAPI.cs | 5 +- Kyoo/Views/API/EpisodesAPI.cs | 9 +- Kyoo/Views/API/GenresAPI.cs | 5 +- Kyoo/Views/API/LibrariesAPI.cs | 14 +-- Kyoo/Views/API/PeopleAPI.cs | 5 +- Kyoo/Views/API/SearchAPI.cs | 17 ++-- Kyoo/Views/API/ShowsAPI.cs | 11 +-- Kyoo/Views/API/StudioAPI.cs | 5 +- Kyoo/Views/API/SubtitleAPI.cs | 94 ++++++++++--------- Kyoo/Views/API/ThumbnailAPI.cs | 17 ++-- Kyoo/Views/API/VideoAPI.cs | 16 ++-- Kyoo/Views/API/WatchAPI.cs | 11 ++- 18 files changed, 189 insertions(+), 102 deletions(-) diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index 6a3234f4..133fa7c5 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -13,11 +13,21 @@ namespace Kyoo.Controllers Task GetSeason(string showSlug, long seasonNumber); Task GetEpisode(string showSlug, long seasonNumber, long episodeNumber); Task GetMovieEpisode(string movieSlug); + Task GetTrack(long id); Task GetTrack(long episodeID, string language, bool isForced); Task GetGenre(string slug); Task GetStudio(string slug); Task GetPeople(string slug); + // Get by relations + Task> GetSeasons(long showID); + Task> GetSeasons(string showSlug); + + Task> GetEpisodes(long showID, long seasonNumber); + Task> GetEpisodes(string showSlug, long seasonNumber); + Task> GetEpisodes(long seasonID); + + // Get all Task> GetLibraries(); Task> GetCollections(); diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index 07c8043d..af30eb88 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -22,11 +22,18 @@ namespace Kyoo.Controllers public interface ISeasonRepository : IRepository { Task Get(string showSlug, long seasonNumber); + + Task> GetSeasons(long showID); + Task> GetSeasons(string showSlug); } public interface IEpisodeRepository : IRepository { Task Get(string showSlug, long seasonNumber, long episodeNumber); + + Task> GetEpisodes(long showID, long seasonNumber); + Task> GetEpisodes(string showSlug, long seasonNumber); + Task> GetEpisodes(long seasonID); } public interface ITrackRepository : IRepository diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index f351fd72..60ca9f79 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -61,6 +61,11 @@ namespace Kyoo.Controllers return _episodes.Get(movieSlug); } + public Task GetTrack(long id) + { + return _tracks.Get(id); + } + public Task GetTrack(long episodeID, string language, bool isForced) { return _tracks.Get(episodeID, language, isForced); @@ -131,6 +136,31 @@ namespace Kyoo.Controllers return _providers.GetAll(); } + public Task> GetSeasons(long showID) + { + return _seasons.GetSeasons(showID); + } + + public Task> GetSeasons(string showSlug) + { + return _seasons.GetSeasons(showSlug); + } + + public Task> GetEpisodes(long showID, long seasonNumber) + { + return _episodes.GetEpisodes(showID, seasonNumber); + } + + public Task> GetEpisodes(string showSlug, long seasonNumber) + { + return _episodes.GetEpisodes(showSlug, seasonNumber); + } + + public Task> GetEpisodes(long seasonID) + { + return _episodes.GetEpisodes(seasonID); + } + public Task> SearchLibraries(string searchQuery) { return _libraries.Search(searchQuery); diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index bc32b92c..71fcfebd 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -45,7 +45,7 @@ namespace Kyoo.Controllers && x.SeasonNumber == seasonNumber && x.EpisodeNumber == episodeNumber); } - + public async Task> Search(string query) { return await _database.Episodes @@ -119,5 +119,22 @@ namespace Kyoo.Controllers _database.Episodes.Remove(obj); await _database.SaveChangesAsync(); } + + public async Task> GetEpisodes(long showID, long seasonNumber) + { + return await _database.Episodes.Where(x => x.ShowID == showID + && x.SeasonNumber == seasonNumber).ToListAsync(); + } + + public async Task> GetEpisodes(string showSlug, long seasonNumber) + { + return await _database.Episodes.Where(x => x.Show.Slug == showSlug + && x.SeasonNumber == seasonNumber).ToListAsync(); + } + + public async Task> GetEpisodes(long seasonID) + { + return await _database.Episodes.Where(x => x.SeasonID == seasonID).ToListAsync(); + } } } \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index 86bd5d6f..98d1fe26 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -115,5 +115,15 @@ namespace Kyoo.Controllers _database.Seasons.Remove(obj); await _database.SaveChangesAsync(); } + + public async Task> GetSeasons(long showID) + { + return await _database.Seasons.Where(x => x.ShowID == showID).ToListAsync(); + } + + public async Task> GetSeasons(string showSlug) + { + return await _database.Seasons.Where(x => x.Show.Slug == showSlug).ToListAsync(); + } } } \ No newline at end of file diff --git a/Kyoo/Tasks/ReScan.cs b/Kyoo/Tasks/ReScan.cs index 22c7aeb5..aca39b6d 100644 --- a/Kyoo/Tasks/ReScan.cs +++ b/Kyoo/Tasks/ReScan.cs @@ -62,7 +62,7 @@ namespace Kyoo.Tasks edited.ID = old.ID; edited.Slug = old.Slug; edited.Path = old.Path; - await libraryManager.Edit(edited, true); + await libraryManager.EditShow(edited, true); await _thumbnailsManager.Validate(edited, true); } if (old.Seasons != null) @@ -95,7 +95,7 @@ namespace Kyoo.Tasks Library library = _database.LibraryLinks.First(x => x.Show == show && x.Library != null).Library; Season edited = await _providerManager.GetSeason(show, old.SeasonNumber, library); edited.ID = old.ID; - await libraryManager.Edit(edited, true); + await libraryManager.EditSeason(edited, true); await _thumbnailsManager.Validate(edited, true); } if (old.Episodes != null) @@ -110,7 +110,7 @@ namespace Kyoo.Tasks Library library = _database.LibraryLinks.First(x => x.Show == show && x.Library != null).Library; Episode edited = await _providerManager.GetEpisode(show, old.Path, old.SeasonNumber, old.EpisodeNumber, old.AbsoluteNumber, library); edited.ID = old.ID; - await libraryManager.Edit(edited, true); + await libraryManager.EditEpisode(edited, true); await _thumbnailsManager.Validate(edited, true); } diff --git a/Kyoo/Views/API/CollectionAPI.cs b/Kyoo/Views/API/CollectionAPI.cs index f15ff86d..bd4658fa 100644 --- a/Kyoo/Views/API/CollectionAPI.cs +++ b/Kyoo/Views/API/CollectionAPI.cs @@ -2,6 +2,7 @@ using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; namespace Kyoo.Api @@ -19,9 +20,9 @@ namespace Kyoo.Api [HttpGet("{collectionSlug}")] [Authorize(Policy="Read")] - public ActionResult GetShows(string collectionSlug) + public async Task> GetShows(string collectionSlug) { - Collection collection = _libraryManager.GetCollection(collectionSlug); + Collection collection = await _libraryManager.GetCollection(collectionSlug); if (collection == null) return NotFound(); diff --git a/Kyoo/Views/API/EpisodesAPI.cs b/Kyoo/Views/API/EpisodesAPI.cs index d4fe7bd0..4e0dbb5b 100644 --- a/Kyoo/Views/API/EpisodesAPI.cs +++ b/Kyoo/Views/API/EpisodesAPI.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Kyoo.Controllers; using Microsoft.AspNetCore.Authorization; @@ -20,9 +21,9 @@ namespace Kyoo.Api [HttpGet("{showSlug}/season/{seasonNumber}")] [Authorize(Policy="Read")] - public ActionResult> GetEpisodesForSeason(string showSlug, long seasonNumber) + public async Task>> GetEpisodesForSeason(string showSlug, long seasonNumber) { - IEnumerable episodes = _libraryManager.GetEpisodes(showSlug, seasonNumber); + IEnumerable episodes = await _libraryManager.GetEpisodes(showSlug, seasonNumber); if(episodes == null) return NotFound(); @@ -33,9 +34,9 @@ namespace Kyoo.Api [HttpGet("{showSlug}/season/{seasonNumber}/episode/{episodeNumber}")] [Authorize(Policy="Read")] [JsonDetailed] - public ActionResult GetEpisode(string showSlug, long seasonNumber, long episodeNumber) + public async Task> GetEpisode(string showSlug, long seasonNumber, long episodeNumber) { - Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); + Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); if (episode == null) return NotFound(); diff --git a/Kyoo/Views/API/GenresAPI.cs b/Kyoo/Views/API/GenresAPI.cs index 21dc5643..98d27e7f 100644 --- a/Kyoo/Views/API/GenresAPI.cs +++ b/Kyoo/Views/API/GenresAPI.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; @@ -18,9 +19,9 @@ namespace Kyoo.API _libraryManager = libraryManager; } - public ActionResult> Index() + public async Task>> Index() { - return _libraryManager.GetGenres().ToList(); + return (await _libraryManager.GetGenres()).ToList(); } } } \ No newline at end of file diff --git a/Kyoo/Views/API/LibrariesAPI.cs b/Kyoo/Views/API/LibrariesAPI.cs index 32aa73f6..73a5f907 100644 --- a/Kyoo/Views/API/LibrariesAPI.cs +++ b/Kyoo/Views/API/LibrariesAPI.cs @@ -3,6 +3,7 @@ using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; namespace Kyoo.Api @@ -22,15 +23,15 @@ namespace Kyoo.Api } [HttpGet] - public IEnumerable GetLibraries() + public async Task> GetLibraries() { - return _libraryManager.GetLibraries(); + return await _libraryManager.GetLibraries(); } [Route("/api/library/create")] [HttpPost] [Authorize(Policy="Admin")] - public IActionResult CreateLibrary([FromBody] Library library) + public async Task CreateLibrary([FromBody] Library library) { if (!ModelState.IsValid) return BadRequest(library); @@ -42,17 +43,16 @@ namespace Kyoo.Api return BadRequest(new {error = "The library should have a least one path."}); if (_libraryManager.GetLibrary(library.Slug) != null) return BadRequest(new {error = "Duplicated library slug"}); - _libraryManager.Register(library); - _libraryManager.SaveChanges(); + await _libraryManager.RegisterLibrary(library); _taskManager.StartTask("scan", library.Slug); return Ok(); } [HttpGet("{librarySlug}")] [Authorize(Policy="Read")] - public ActionResult> GetShows(string librarySlug) + public async Task>> GetShows(string librarySlug) { - Library library = _libraryManager.GetLibrary(librarySlug); + Library library = await _libraryManager.GetLibrary(librarySlug); if (library == null) return NotFound(); diff --git a/Kyoo/Views/API/PeopleAPI.cs b/Kyoo/Views/API/PeopleAPI.cs index ca21eb0b..ad27d8b9 100644 --- a/Kyoo/Views/API/PeopleAPI.cs +++ b/Kyoo/Views/API/PeopleAPI.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Threading.Tasks; using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Authorization; @@ -19,9 +20,9 @@ namespace Kyoo.Api [HttpGet("{peopleSlug}")] [Authorize(Policy="Read")] - public ActionResult GetPeople(string peopleSlug) + public async Task> GetPeople(string peopleSlug) { - People people = _libraryManager.GetPeople(peopleSlug); + People people = await _libraryManager.GetPeople(peopleSlug); if (people == null) return NotFound(); diff --git a/Kyoo/Views/API/SearchAPI.cs b/Kyoo/Views/API/SearchAPI.cs index ab0ab3dd..4efcf93a 100644 --- a/Kyoo/Views/API/SearchAPI.cs +++ b/Kyoo/Views/API/SearchAPI.cs @@ -1,4 +1,5 @@ -using Kyoo.Controllers; +using System.Threading.Tasks; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -18,17 +19,17 @@ namespace Kyoo.Api [HttpGet("{query}")] [Authorize(Policy="Read")] - public ActionResult Search(string query) + public async Task> Search(string query) { SearchResult result = new SearchResult { Query = query, - Collections = _libraryManager.SearchCollections(query), - Shows = _libraryManager.SearchShows(query), - Episodes = _libraryManager.SearchEpisodes(query), - People = _libraryManager.SearchPeople(query), - Genres = _libraryManager.SearchGenres(query), - Studios = _libraryManager.SearchStudios(query) + Collections = await _libraryManager.SearchCollections(query), + Shows = await _libraryManager.SearchShows(query), + Episodes = await _libraryManager.SearchEpisodes(query), + People = await _libraryManager.SearchPeople(query), + Genres = await _libraryManager.SearchGenres(query), + Studios = await _libraryManager.SearchStudios(query) }; return result; } diff --git a/Kyoo/Views/API/ShowsAPI.cs b/Kyoo/Views/API/ShowsAPI.cs index d656130c..e92c028a 100644 --- a/Kyoo/Views/API/ShowsAPI.cs +++ b/Kyoo/Views/API/ShowsAPI.cs @@ -43,9 +43,9 @@ namespace Kyoo.Api [HttpGet("{slug}")] [Authorize(Policy="Read")] [JsonDetailed] - public ActionResult GetShow(string slug) + public async Task> GetShow(string slug) { - Show show = _libraryManager.GetShow(slug); + Show show = await _libraryManager.GetShow(slug); if (show == null) return NotFound(); @@ -55,7 +55,7 @@ namespace Kyoo.Api [HttpPost("edit/{slug}")] [Authorize(Policy="Write")] - public IActionResult EditShow(string slug, [FromBody] Show show) + public async Task EditShow(string slug, [FromBody] Show show) { if (!ModelState.IsValid) return BadRequest(show); @@ -66,7 +66,7 @@ namespace Kyoo.Api show.ID = old.ID; show.Slug = slug; show.Path = old.Path; - _libraryManager.Edit(show, false); + await _libraryManager.EditShow(show, false); return Ok(); } @@ -79,7 +79,6 @@ namespace Kyoo.Api Show show = _database.Shows.Include(x => x.ExternalIDs).FirstOrDefault(x => x.Slug == slug); if (show == null) return NotFound(); - show.ExternalIDs = _libraryManager.Validate(externalIDs); _database.SaveChanges(); _taskManager.StartTask("re-scan", $"show/{slug}"); return Ok(); @@ -96,7 +95,7 @@ namespace Kyoo.Api [Authorize(Policy = "Write")] public async Task DownloadImages(string slug) { - Show show = _libraryManager.GetShow(slug); + Show show = await _libraryManager.GetShow(slug); if (show == null) return NotFound(); await _thumbnailsManager.Validate(show, true); diff --git a/Kyoo/Views/API/StudioAPI.cs b/Kyoo/Views/API/StudioAPI.cs index 4437d5ca..59228155 100644 --- a/Kyoo/Views/API/StudioAPI.cs +++ b/Kyoo/Views/API/StudioAPI.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Mvc; @@ -18,9 +19,9 @@ namespace Kyoo.API _libraryManager = libraryManager; } - public ActionResult> Index() + public async Task>> Index() { - return _libraryManager.GetStudios().ToList(); + return (await _libraryManager.GetStudios()).ToList(); } } } \ No newline at end of file diff --git a/Kyoo/Views/API/SubtitleAPI.cs b/Kyoo/Views/API/SubtitleAPI.cs index df875fca..ea0c73e2 100644 --- a/Kyoo/Views/API/SubtitleAPI.cs +++ b/Kyoo/Views/API/SubtitleAPI.cs @@ -14,31 +14,37 @@ namespace Kyoo.Api public class SubtitleController : ControllerBase { private readonly ILibraryManager _libraryManager; - private readonly ITranscoder _transcoder; + //private readonly ITranscoder _transcoder; - public SubtitleController(ILibraryManager libraryManager, ITranscoder transcoder) + public SubtitleController(ILibraryManager libraryManager/*, ITranscoder transcoder*/) { _libraryManager = libraryManager; - _transcoder = transcoder; + // _transcoder = transcoder; } [HttpGet("{showSlug}-s{seasonNumber:int}e{episodeNumber:int}.{identifier}.{extension?}")] [Authorize(Policy="Play")] - public IActionResult GetSubtitle(string showSlug, int seasonNumber, int episodeNumber, string identifier, string extension) + public async Task GetSubtitle(string showSlug, + int seasonNumber, + int episodeNumber, + string identifier, + string extension) { string languageTag = identifier.Length == 3 ? identifier.Substring(0, 3) : null; bool forced = identifier.Length > 4 && identifier.Substring(4) == "forced"; Track subtitle = null; if (languageTag != null) - subtitle = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber)?.Tracks + subtitle = (await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber))?.Tracks .FirstOrDefault(x => x.Language == languageTag && x.IsForced == forced); if (subtitle == null) { - string idString = identifier.IndexOf('-') != -1 ? identifier.Substring(0, identifier.IndexOf('-')) : identifier; + string idString = identifier.IndexOf('-') != -1 + ? identifier.Substring(0, identifier.IndexOf('-')) + : identifier; long.TryParse(idString, out long id); - subtitle = _libraryManager.GetTracks().FirstOrDefault(x => x.ID == id); + subtitle = await _libraryManager.GetTrack(id); } if (subtitle == null) @@ -57,43 +63,43 @@ namespace Kyoo.Api return PhysicalFile(subtitle.Path, mime); } - [HttpGet("extract/{showSlug}-s{seasonNumber}e{episodeNumber}")] - [Authorize(Policy="Admin")] - public async Task ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber) - { - Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); - episode.Tracks = null; - - Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path); - foreach (Track track in tracks) - { - track.EpisodeID = episode.ID; - _libraryManager.Register(track); - } - await _libraryManager.SaveChanges(); - return "Done. " + tracks.Length + " track(s) extracted."; - } - - [HttpGet("extract/{showSlug}")] - [Authorize(Policy="Admin")] - public async Task ExtractSubtitle(string showSlug) - { - IEnumerable episodes = _libraryManager.GetShow(showSlug).Episodes; - foreach (Episode episode in episodes) - { - episode.Tracks = null; - - Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path); - foreach (Track track in tracks) - { - track.EpisodeID = episode.ID; - _libraryManager.Register(track); - } - await _libraryManager.SaveChanges(); - } - - return "Done."; - } + // [HttpGet("extract/{showSlug}-s{seasonNumber}e{episodeNumber}")] + // [Authorize(Policy="Admin")] + // public async Task ExtractSubtitle(string showSlug, long seasonNumber, long episodeNumber) + // { + // Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); + // episode.Tracks = null; + // + // Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path); + // foreach (Track track in tracks) + // { + // track.EpisodeID = episode.ID; + // _libraryManager.Register(track); + // } + // await _libraryManager.SaveChanges(); + // return "Done. " + tracks.Length + " track(s) extracted."; + // } + // + // [HttpGet("extract/{showSlug}")] + // [Authorize(Policy="Admin")] + // public async Task ExtractSubtitle(string showSlug) + // { + // IEnumerable episodes = _libraryManager.GetShow(showSlug).Episodes; + // foreach (Episode episode in episodes) + // { + // episode.Tracks = null; + // + // Track[] tracks = await _transcoder.ExtractSubtitles(episode.Path); + // foreach (Track track in tracks) + // { + // track.EpisodeID = episode.ID; + // _libraryManager.Register(track); + // } + // await _libraryManager.SaveChanges(); + // } + // + // return "Done."; + // } } diff --git a/Kyoo/Views/API/ThumbnailAPI.cs b/Kyoo/Views/API/ThumbnailAPI.cs index 22b376e8..12b8035c 100644 --- a/Kyoo/Views/API/ThumbnailAPI.cs +++ b/Kyoo/Views/API/ThumbnailAPI.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System.IO; +using System.Threading.Tasks; using Kyoo.Controllers; using Microsoft.AspNetCore.Authorization; @@ -20,9 +21,9 @@ namespace Kyoo.Api [HttpGet("poster/{showSlug}")] [Authorize(Policy="Read")] - public IActionResult GetShowThumb(string showSlug) + public async Task GetShowThumb(string showSlug) { - string path = _libraryManager.GetShow(showSlug)?.Path; + string path = (await _libraryManager.GetShow(showSlug))?.Path; if (path == null) return NotFound(); @@ -35,9 +36,9 @@ namespace Kyoo.Api [HttpGet("logo/{showSlug}")] [Authorize(Policy="Read")] - public IActionResult GetShowLogo(string showSlug) + public async Task GetShowLogo(string showSlug) { - string path = _libraryManager.GetShow(showSlug)?.Path; + string path = (await _libraryManager.GetShow(showSlug))?.Path; if (path == null) return NotFound(); @@ -50,9 +51,9 @@ namespace Kyoo.Api [HttpGet("backdrop/{showSlug}")] [Authorize(Policy="Read")] - public IActionResult GetShowBackdrop(string showSlug) + public async Task GetShowBackdrop(string showSlug) { - string path = _libraryManager.GetShow(showSlug)?.Path; + string path = (await _libraryManager.GetShow(showSlug))?.Path; if (path == null) return NotFound(); @@ -76,9 +77,9 @@ namespace Kyoo.Api [HttpGet("thumb/{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Read")] - public IActionResult GetEpisodeThumb(string showSlug, long seasonNumber, long episodeNumber) + public async Task GetEpisodeThumb(string showSlug, long seasonNumber, long episodeNumber) { - string path = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber)?.Path; + string path = (await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber))?.Path; if (path == null) return NotFound(); diff --git a/Kyoo/Views/API/VideoAPI.cs b/Kyoo/Views/API/VideoAPI.cs index 57a77833..c8e6f164 100644 --- a/Kyoo/Views/API/VideoAPI.cs +++ b/Kyoo/Views/API/VideoAPI.cs @@ -27,9 +27,9 @@ namespace Kyoo.Api [HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Play")] - public IActionResult Index(string showSlug, long seasonNumber, long episodeNumber) + public async Task Index(string showSlug, long seasonNumber, long episodeNumber) { - Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); + Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); if (episode != null && System.IO.File.Exists(episode.Path)) return PhysicalFile(episode.Path, "video/x-matroska", true); @@ -40,7 +40,7 @@ namespace Kyoo.Api [Authorize(Policy="Play")] public async Task Transmux(string showSlug, long seasonNumber, long episodeNumber) { - Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); + Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); if (episode == null || !System.IO.File.Exists(episode.Path)) return NotFound(); @@ -63,7 +63,7 @@ namespace Kyoo.Api [Authorize(Policy="Play")] public async Task Transcode(string showSlug, long seasonNumber, long episodeNumber) { - Episode episode = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); + Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); if (episode == null || !System.IO.File.Exists(episode.Path)) return NotFound(); @@ -85,9 +85,9 @@ namespace Kyoo.Api [HttpGet("{movieSlug}")] [Authorize(Policy="Play")] - public IActionResult Index(string movieSlug) + public async Task Index(string movieSlug) { - Episode episode = _libraryManager.GetMovieEpisode(movieSlug); + Episode episode = await _libraryManager.GetMovieEpisode(movieSlug); if (episode != null && System.IO.File.Exists(episode.Path)) return PhysicalFile(episode.Path, "video/webm", true); @@ -98,7 +98,7 @@ namespace Kyoo.Api [Authorize(Policy="Play")] public async Task Transmux(string movieSlug) { - Episode episode = _libraryManager.GetMovieEpisode(movieSlug); + Episode episode = await _libraryManager.GetMovieEpisode(movieSlug); if (episode == null || !System.IO.File.Exists(episode.Path)) return NotFound(); @@ -112,7 +112,7 @@ namespace Kyoo.Api [Authorize(Policy="Play")] public async Task Transcode(string movieSlug) { - Episode episode = _libraryManager.GetMovieEpisode(movieSlug); + Episode episode = await _libraryManager.GetMovieEpisode(movieSlug); if (episode == null || !System.IO.File.Exists(episode.Path)) return NotFound(); diff --git a/Kyoo/Views/API/WatchAPI.cs b/Kyoo/Views/API/WatchAPI.cs index d8cc84c2..3ef292f1 100644 --- a/Kyoo/Views/API/WatchAPI.cs +++ b/Kyoo/Views/API/WatchAPI.cs @@ -1,4 +1,5 @@ -using Kyoo.Controllers; +using System.Threading.Tasks; +using Kyoo.Controllers; using Kyoo.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -18,9 +19,9 @@ namespace Kyoo.Api [HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Read")] - public ActionResult Index(string showSlug, long seasonNumber, long episodeNumber) + public async Task> Index(string showSlug, long seasonNumber, long episodeNumber) { - Episode item = _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); + Episode item = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); if(item == null) return NotFound(); @@ -30,9 +31,9 @@ namespace Kyoo.Api [HttpGet("{movieSlug}")] [Authorize(Policy="Read")] - public ActionResult Index(string movieSlug) + public async Task> Index(string movieSlug) { - Episode item = _libraryManager.GetMovieEpisode(movieSlug); + Episode item = await _libraryManager.GetMovieEpisode(movieSlug); if(item == null) return NotFound(); From 5d96452309c89a1dec125ca76633b0f87997c4f8 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sat, 6 Jun 2020 21:01:46 +0200 Subject: [PATCH 15/18] Reworking the crawler --- Kyoo.Common/Controllers/ILibraryManager.cs | 52 +++++----- Kyoo.Common/Controllers/IRepository.cs | 22 +++-- Kyoo.Common/Models/Task.cs | 2 +- Kyoo/Controllers/LibraryManager.cs | 66 ++++++++----- .../Repositories/CollectionRepository.cs | 4 +- .../Repositories/EpisodeRepository.cs | 13 +-- .../Repositories/GenreRepository.cs | 4 +- .../Repositories/LibraryRepository.cs | 4 +- .../Repositories/PeopleRepository.cs | 4 +- .../Repositories/ProviderRepository.cs | 4 +- .../Repositories/SeasonRepository.cs | 8 +- .../Repositories/ShowRepository.cs | 32 +++++- .../Repositories/StudioRepository.cs | 4 +- .../Repositories/TrackRepository.cs | 4 +- Kyoo/Tasks/Crawler.cs | 99 +++++++++++-------- Kyoo/Tasks/CreateDatabase.cs | 4 +- Kyoo/Tasks/MetadataLoader.cs | 4 +- Kyoo/Tasks/PluginLoader.cs | 4 +- Kyoo/Tasks/ReScan.cs | 4 +- 19 files changed, 205 insertions(+), 133 deletions(-) diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index 133fa7c5..75e2b53f 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; +using JetBrains.Annotations; using Kyoo.Models; namespace Kyoo.Controllers @@ -20,35 +21,40 @@ namespace Kyoo.Controllers Task GetPeople(string slug); // Get by relations - Task> GetSeasons(long showID); - Task> GetSeasons(string showSlug); + Task> GetSeasons(long showID); + Task> GetSeasons(string showSlug); - Task> GetEpisodes(long showID, long seasonNumber); - Task> GetEpisodes(string showSlug, long seasonNumber); - Task> GetEpisodes(long seasonID); + Task> GetEpisodes(long showID, long seasonNumber); + Task> GetEpisodes(string showSlug, long seasonNumber); + Task> GetEpisodes(long seasonID); + // Helpers + Task GetShowByPath(string path); + Task AddShowLink(long showID, long? libraryID, long? collectionID); + Task AddShowLink([NotNull] Show show, Library library, Collection collection); + // Get all - Task> GetLibraries(); - Task> GetCollections(); - Task> GetShows(); - Task> GetSeasons(); - Task> GetEpisodes(); - Task> GetTracks(); - Task> GetStudios(); - Task> GetPeoples(); - Task> GetGenres(); - Task> GetProviders(); + Task> GetLibraries(); + Task> GetCollections(); + Task> GetShows(); + Task> GetSeasons(); + Task> GetEpisodes(); + Task> GetTracks(); + Task> GetStudios(); + Task> GetPeoples(); + Task> GetGenres(); + Task> GetProviders(); // Search - Task> SearchLibraries(string searchQuery); - Task> SearchCollections(string searchQuery); - Task> SearchShows(string searchQuery); - Task> SearchSeasons(string searchQuery); - Task> SearchEpisodes(string searchQuery); - Task> SearchGenres(string searchQuery); - Task> SearchStudios(string searchQuery); - Task> SearchPeople(string searchQuery); + Task> SearchLibraries(string searchQuery); + Task> SearchCollections(string searchQuery); + Task> SearchShows(string searchQuery); + Task> SearchSeasons(string searchQuery); + Task> SearchEpisodes(string searchQuery); + Task> SearchGenres(string searchQuery); + Task> SearchStudios(string searchQuery); + Task> SearchPeople(string searchQuery); //Register values Task RegisterLibrary(Library library); diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index af30eb88..a63886ea 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -9,31 +9,35 @@ namespace Kyoo.Controllers { Task Get(long id); Task Get(string slug); - Task> Search(string query); - Task> GetAll(); + Task> Search(string query); + Task> GetAll(); Task Create([NotNull] T obj); Task CreateIfNotExists([NotNull] T obj); Task Edit([NotNull] T edited, bool resetOld); Task Delete(T obj); } - - public interface IShowRepository : IRepository {} + + public interface IShowRepository : IRepository + { + Task GetByPath(string path); + Task AddShowLink(long showID, long? libraryID, long? collectionID); + } public interface ISeasonRepository : IRepository { Task Get(string showSlug, long seasonNumber); - Task> GetSeasons(long showID); - Task> GetSeasons(string showSlug); + Task> GetSeasons(long showID); + Task> GetSeasons(string showSlug); } public interface IEpisodeRepository : IRepository { Task Get(string showSlug, long seasonNumber, long episodeNumber); - Task> GetEpisodes(long showID, long seasonNumber); - Task> GetEpisodes(string showSlug, long seasonNumber); - Task> GetEpisodes(long seasonID); + Task> GetEpisodes(long showID, long seasonNumber); + Task> GetEpisodes(string showSlug, long seasonNumber); + Task> GetEpisodes(long seasonID); } public interface ITrackRepository : IRepository diff --git a/Kyoo.Common/Models/Task.cs b/Kyoo.Common/Models/Task.cs index f00b24c2..76cfbc52 100644 --- a/Kyoo.Common/Models/Task.cs +++ b/Kyoo.Common/Models/Task.cs @@ -14,7 +14,7 @@ namespace Kyoo.Models public bool RunOnStartup { get; } public int Priority { get; } public Task Run(IServiceProvider serviceProvider, CancellationToken cancellationToken, string arguments = null); - public IEnumerable GetPossibleParameters(); + public Task> GetPossibleParameters(); public int? Progress(); } } \ No newline at end of file diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 60ca9f79..82f8f5ea 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using Kyoo.Models; @@ -86,117 +87,134 @@ namespace Kyoo.Controllers return _people.Get(slug); } - public Task> GetLibraries() + public Task> GetLibraries() { return _libraries.GetAll(); } - public Task> GetCollections() + public Task> GetCollections() { return _collections.GetAll(); } - public Task> GetShows() + public Task> GetShows() { return _shows.GetAll(); } - public Task> GetSeasons() + public Task> GetSeasons() { return _seasons.GetAll(); } - public Task> GetEpisodes() + public Task> GetEpisodes() { return _episodes.GetAll(); } - public Task> GetTracks() + public Task> GetTracks() { return _tracks.GetAll(); } - public Task> GetStudios() + public Task> GetStudios() { return _studios.GetAll(); } - public Task> GetPeoples() + public Task> GetPeoples() { return _people.GetAll(); } - public Task> GetGenres() + public Task> GetGenres() { return _genres.GetAll(); } - public Task> GetProviders() + public Task> GetProviders() { return _providers.GetAll(); } - public Task> GetSeasons(long showID) + public Task> GetSeasons(long showID) { return _seasons.GetSeasons(showID); } - public Task> GetSeasons(string showSlug) + public Task> GetSeasons(string showSlug) { return _seasons.GetSeasons(showSlug); } - public Task> GetEpisodes(long showID, long seasonNumber) + public Task> GetEpisodes(long showID, long seasonNumber) { return _episodes.GetEpisodes(showID, seasonNumber); } - public Task> GetEpisodes(string showSlug, long seasonNumber) + public Task> GetEpisodes(string showSlug, long seasonNumber) { return _episodes.GetEpisodes(showSlug, seasonNumber); } - public Task> GetEpisodes(long seasonID) + public Task> GetEpisodes(long seasonID) { return _episodes.GetEpisodes(seasonID); } - public Task> SearchLibraries(string searchQuery) + public Task GetShowByPath(string path) + { + return _shows.GetByPath(path); + } + + public Task AddShowLink(long showID, long? libraryID, long? collectionID) + { + return _shows.AddShowLink(showID, libraryID, collectionID); + } + + public Task AddShowLink(Show show, Library library, Collection collection) + { + if (show == null) + throw new ArgumentNullException(nameof(show)); + return AddShowLink(show.ID, library?.ID, collection?.ID); + } + + public Task> SearchLibraries(string searchQuery) { return _libraries.Search(searchQuery); } - public Task> SearchCollections(string searchQuery) + public Task> SearchCollections(string searchQuery) { return _collections.Search(searchQuery); } - public Task> SearchShows(string searchQuery) + public Task> SearchShows(string searchQuery) { return _shows.Search(searchQuery); } - public Task> SearchSeasons(string searchQuery) + public Task> SearchSeasons(string searchQuery) { return _seasons.Search(searchQuery); } - public Task> SearchEpisodes(string searchQuery) + public Task> SearchEpisodes(string searchQuery) { return _episodes.Search(searchQuery); } - public Task> SearchGenres(string searchQuery) + public Task> SearchGenres(string searchQuery) { return _genres.Search(searchQuery); } - public Task> SearchStudios(string searchQuery) + public Task> SearchStudios(string searchQuery) { return _studios.Search(searchQuery); } - public Task> SearchPeople(string searchQuery) + public Task> SearchPeople(string searchQuery) { return _people.Search(searchQuery); } diff --git a/Kyoo/Controllers/Repositories/CollectionRepository.cs b/Kyoo/Controllers/Repositories/CollectionRepository.cs index c0b38434..476ffd67 100644 --- a/Kyoo/Controllers/Repositories/CollectionRepository.cs +++ b/Kyoo/Controllers/Repositories/CollectionRepository.cs @@ -28,7 +28,7 @@ namespace Kyoo.Controllers return _database.Collections.FirstOrDefaultAsync(x => x.Slug == slug); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Collections .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) @@ -36,7 +36,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Collections.ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index 71fcfebd..dd92ad85 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -46,7 +46,7 @@ namespace Kyoo.Controllers && x.EpisodeNumber == episodeNumber); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Episodes .Where(x => EF.Functions.Like(x.Title, $"%{query}%")) @@ -54,7 +54,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Episodes.ToListAsync(); } @@ -64,10 +64,7 @@ namespace Kyoo.Controllers if (obj == null) throw new ArgumentNullException(nameof(obj)); - obj.Show = null; - obj.Season = null; await Validate(obj); - await _database.Episodes.AddAsync(obj); await _database.SaveChangesAsync(); return obj.ID; @@ -120,19 +117,19 @@ namespace Kyoo.Controllers await _database.SaveChangesAsync(); } - public async Task> GetEpisodes(long showID, long seasonNumber) + public async Task> GetEpisodes(long showID, long seasonNumber) { return await _database.Episodes.Where(x => x.ShowID == showID && x.SeasonNumber == seasonNumber).ToListAsync(); } - public async Task> GetEpisodes(string showSlug, long seasonNumber) + public async Task> GetEpisodes(string showSlug, long seasonNumber) { return await _database.Episodes.Where(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber).ToListAsync(); } - public async Task> GetEpisodes(long seasonID) + public async Task> GetEpisodes(long seasonID) { return await _database.Episodes.Where(x => x.SeasonID == seasonID).ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/GenreRepository.cs b/Kyoo/Controllers/Repositories/GenreRepository.cs index 5544c07b..1035e54b 100644 --- a/Kyoo/Controllers/Repositories/GenreRepository.cs +++ b/Kyoo/Controllers/Repositories/GenreRepository.cs @@ -28,7 +28,7 @@ namespace Kyoo.Controllers return await _database.Genres.FirstOrDefaultAsync(x => x.Slug == slug); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Genres .Where(genre => EF.Functions.Like(genre.Name, $"%{query}%")) @@ -36,7 +36,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Genres.ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs index bac6e6ba..c73af246 100644 --- a/Kyoo/Controllers/Repositories/LibraryRepository.cs +++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs @@ -30,7 +30,7 @@ namespace Kyoo.Controllers return _database.Libraries.FirstOrDefaultAsync(x => x.Name == slug); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Libraries .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) @@ -38,7 +38,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Libraries.ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs index f6a85c1a..0b702be5 100644 --- a/Kyoo/Controllers/Repositories/PeopleRepository.cs +++ b/Kyoo/Controllers/Repositories/PeopleRepository.cs @@ -29,7 +29,7 @@ namespace Kyoo.Controllers return _database.Peoples.FirstOrDefaultAsync(x => x.Slug == slug); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Peoples .Where(people => EF.Functions.Like(people.Name, $"%{query}%")) @@ -37,7 +37,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Peoples.ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/ProviderRepository.cs b/Kyoo/Controllers/Repositories/ProviderRepository.cs index 01e2898a..4f9b85aa 100644 --- a/Kyoo/Controllers/Repositories/ProviderRepository.cs +++ b/Kyoo/Controllers/Repositories/ProviderRepository.cs @@ -28,7 +28,7 @@ namespace Kyoo.Controllers return await _database.Providers.FirstOrDefaultAsync(x => x.Name == slug); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Providers .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) @@ -36,7 +36,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Providers.ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index 98d1fe26..686308dc 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -42,7 +42,7 @@ namespace Kyoo.Controllers && x.SeasonNumber == seasonNumber); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Seasons .Where(x => EF.Functions.Like(x.Title, $"%{query}%")) @@ -50,7 +50,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Seasons.ToListAsync(); } @@ -116,12 +116,12 @@ namespace Kyoo.Controllers await _database.SaveChangesAsync(); } - public async Task> GetSeasons(long showID) + public async Task> GetSeasons(long showID) { return await _database.Seasons.Where(x => x.ShowID == showID).ToListAsync(); } - public async Task> GetSeasons(string showSlug) + public async Task> GetSeasons(string showSlug) { return await _database.Seasons.Where(x => x.Show.Slug == showSlug).ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index e0901cfc..21ce741b 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -39,7 +39,12 @@ namespace Kyoo.Controllers return await _database.Shows.FirstOrDefaultAsync(x => x.Slug == slug); } - public async Task> Search(string query) + public async Task GetByPath(string path) + { + return await _database.Shows.FirstOrDefaultAsync(x => x.Path == path); + } + + public async Task> Search(string query) { return await _database.Shows .FromSqlInterpolated($@"SELECT * FROM Shows WHERE Shows.Title LIKE {$"%{query}%"} @@ -48,7 +53,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Shows.ToListAsync(); } @@ -121,5 +126,28 @@ namespace Kyoo.Controllers _database.Shows.Remove(show); await _database.SaveChangesAsync(); } + + public Task AddShowLink(long showID, long? libraryID, long? collectionID) + { + if (collectionID != null) + { + _database.CollectionLinks.AddIfNotExist(new CollectionLink { CollectionID = collectionID, ShowID = showID}, + x => x.CollectionID == collectionID && x.ShowID == showID); + } + if (libraryID != null) + { + _database.LibraryLinks.AddIfNotExist(new LibraryLink {LibraryID = libraryID.Value, ShowID = showID}, + x => x.LibraryID == libraryID.Value && x.CollectionID == null && x.ShowID == showID); + } + + if (libraryID != null && collectionID != null) + { + _database.LibraryLinks.AddIfNotExist( + new LibraryLink {LibraryID = libraryID.Value, CollectionID = collectionID.Value}, + x => x.LibraryID == libraryID && x.CollectionID == collectionID && x.ShowID == null); + } + + return Task.CompletedTask; + } } } \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/StudioRepository.cs b/Kyoo/Controllers/Repositories/StudioRepository.cs index c7d77f18..f531d7c1 100644 --- a/Kyoo/Controllers/Repositories/StudioRepository.cs +++ b/Kyoo/Controllers/Repositories/StudioRepository.cs @@ -28,7 +28,7 @@ namespace Kyoo.Controllers return await _database.Studios.FirstOrDefaultAsync(x => x.Name == slug); } - public async Task> Search(string query) + public async Task> Search(string query) { return await _database.Studios .Where(x => EF.Functions.Like(x.Name, $"%{query}%")) @@ -36,7 +36,7 @@ namespace Kyoo.Controllers .ToListAsync(); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Studios.ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/TrackRepository.cs b/Kyoo/Controllers/Repositories/TrackRepository.cs index a5d58aa0..be67ab2c 100644 --- a/Kyoo/Controllers/Repositories/TrackRepository.cs +++ b/Kyoo/Controllers/Repositories/TrackRepository.cs @@ -34,12 +34,12 @@ namespace Kyoo.Controllers && x.IsForced == isForced); } - public Task> Search(string query) + public Task> Search(string query) { throw new InvalidOperationException("Tracks do not support the search method."); } - public async Task> GetAll() + public async Task> GetAll() { return await _database.Tracks.ToListAsync(); } diff --git a/Kyoo/Tasks/Crawler.cs b/Kyoo/Tasks/Crawler.cs index 065bc613..70a88b6c 100644 --- a/Kyoo/Tasks/Crawler.cs +++ b/Kyoo/Tasks/Crawler.cs @@ -8,7 +8,6 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Kyoo.Models.Watch; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers @@ -28,11 +27,11 @@ namespace Kyoo.Controllers private ITranscoder _transcoder; private IConfiguration _config; - public IEnumerable GetPossibleParameters() + public async Task> GetPossibleParameters() { using IServiceScope serviceScope = _serviceProvider.CreateScope(); ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService(); - return libraryManager.GetLibraries().Select(x => x.Slug); + return (await libraryManager.GetLibraries()).Select(x => x.Slug); } public int? Progress() @@ -53,28 +52,27 @@ namespace Kyoo.Controllers { using IServiceScope serviceScope = _serviceProvider.CreateScope(); ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService(); - IEnumerable episodes = libraryManager.GetEpisodes(); - IEnumerable libraries = argument == null - ? libraryManager.GetLibraries() - : new [] {libraryManager.GetLibrary(argument)}; + ICollection episodes = await libraryManager.GetEpisodes(); + ICollection libraries = argument == null + ? await libraryManager.GetLibraries() + : new [] { await libraryManager.GetLibrary(argument)}; foreach (Episode episode in episodes) { if (!File.Exists(episode.Path)) - libraryManager.RemoveEpisode(episode); + await libraryManager.DeleteEpisode(episode); } - await libraryManager.SaveChanges(); - await Task.WhenAll(libraries.ToList().Select(x => Scan(x, libraryManager, cancellationToken))); + await Task.WhenAll(libraries.Select(x => Scan(x, episodes, cancellationToken))); } catch (Exception ex) { - Console.Error.WriteLine($"Unknown exception thrown durring libraries scan.\nException: {ex.Message}"); + await Console.Error.WriteLineAsync($"Unknown exception thrown durring libraries scan.\nException: {ex.Message}"); } Console.WriteLine("Scan finished!"); } - private Task Scan(Library library, ILibraryManager libraryManager, CancellationToken cancellationToken) + private Task Scan(Library library, ICollection episodes, CancellationToken cancellationToken) { Console.WriteLine($"Scanning library {library.Name} at {string.Join(", ", library.Paths)}."); return Task.WhenAll(library.Paths.Select(async path => @@ -89,29 +87,29 @@ namespace Kyoo.Controllers } catch (DirectoryNotFoundException) { - Console.Error.WriteLine($"The library's directory {path} could not be found (library slug: {library.Slug})"); + await Console.Error.WriteLineAsync($"The library's directory {path} could not be found (library slug: {library.Slug})"); return Task.CompletedTask; } catch (PathTooLongException) { - Console.Error.WriteLine($"The library's directory {path} is too long for this system. (library slug: {library.Slug})"); + await Console.Error.WriteLineAsync($"The library's directory {path} is too long for this system. (library slug: {library.Slug})"); return Task.CompletedTask; } catch (ArgumentException) { - Console.Error.WriteLine($"The library's directory {path} is invalid. (library slug: {library.Slug})"); + await Console.Error.WriteLineAsync($"The library's directory {path} is invalid. (library slug: {library.Slug})"); return Task.CompletedTask; } catch (UnauthorizedAccessException) { - Console.Error.WriteLine($"Permission denied: can't access library's directory at {path}. (library slug: {library.Slug})"); + await Console.Error.WriteLineAsync($"Permission denied: can't access library's directory at {path}. (library slug: {library.Slug})"); return Task.CompletedTask; } // return Task.WhenAll(files.Select(file => foreach (string file in files) { - if (!IsVideo(file) || libraryManager.GetEpisodes().Any(x => x.Path == file)) + if (!IsVideo(file) || episodes.Any(x => x.Path == file)) continue; //return Task.CompletedTask; string relativePath = file.Substring(path.Length); /*return*/ await RegisterFile(file, relativePath, library, cancellationToken); @@ -128,7 +126,6 @@ namespace Kyoo.Controllers using IServiceScope serviceScope = _serviceProvider.CreateScope(); ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService(); - ((DbSet)libraryManager.GetLibraries()).Attach(library); string patern = _config.GetValue("regex"); Regex regex = new Regex(patern, RegexOptions.IgnoreCase); @@ -145,66 +142,88 @@ namespace Kyoo.Controllers bool isMovie = seasonNumber == -1 && episodeNumber == -1 && absoluteNumber == -1; Show show = await GetShow(libraryManager, showName, showPath, isMovie, library); if (isMovie) - libraryManager.Register(await GetMovie(show, path)); + await libraryManager.RegisterEpisode(await GetMovie(show, path)); else { Season season = await GetSeason(libraryManager, show, seasonNumber, library); Episode episode = await GetEpisode(libraryManager, show, season, episodeNumber, absoluteNumber, path, library); - libraryManager.Register(episode); + await libraryManager.RegisterEpisode(episode); } - if (collection != null) - libraryManager.Register(collection); - libraryManager.RegisterShowLinks(library, collection, show); - Console.WriteLine($"Registering episode at: {path}"); - await libraryManager.SaveChanges(); + + await libraryManager.AddShowLink(show, library, collection); + Console.WriteLine($"Episode at {path} registered."); } - private async Task GetCollection(ILibraryManager libraryManager, string collectionName, Library library) + private async Task GetCollection(ILibraryManager libraryManager, + string collectionName, + Library library) { if (string.IsNullOrEmpty(collectionName)) - return await Task.FromResult(null); - Collection name = libraryManager.GetCollection(Utility.ToSlug(collectionName)); - if (name != null) - return name; - return await _metadataProvider.GetCollectionFromName(collectionName, library); + return null; + Collection collection = await libraryManager.GetCollection(Utility.ToSlug(collectionName)); + if (collection != null) + return collection; + collection = await _metadataProvider.GetCollectionFromName(collectionName, library); + await libraryManager.RegisterCollection(collection); + return collection; } - private async Task GetShow(ILibraryManager libraryManager, string showTitle, string showPath, bool isMovie, Library library) + private async Task GetShow(ILibraryManager libraryManager, + string showTitle, + string showPath, + bool isMovie, + Library library) { - Show show = libraryManager.GetShowByPath(showPath); + Show show = await libraryManager.GetShowByPath(showPath); if (show != null) return show; show = await _metadataProvider.SearchShow(showTitle, isMovie, library); show.Path = showPath; show.People = await _metadataProvider.GetPeople(show, library); + await libraryManager.RegisterShow(show); await _thumbnailsManager.Validate(show.People); await _thumbnailsManager.Validate(show); return show; } - private async Task GetSeason(ILibraryManager libraryManager, Show show, long seasonNumber, Library library) + private async Task GetSeason(ILibraryManager libraryManager, + Show show, + long seasonNumber, + Library library) { if (seasonNumber == -1) return default; - Season season = libraryManager.GetSeason(show.Slug, seasonNumber); + Season season = await libraryManager.GetSeason(show.Slug, seasonNumber); if (season == null) { season = await _metadataProvider.GetSeason(show, seasonNumber, library); + await libraryManager.RegisterSeason(season); await _thumbnailsManager.Validate(season); } season.Show = show; return season; } - private async Task GetEpisode(ILibraryManager libraryManager, Show show, Season season, long episodeNumber, long absoluteNumber, string episodePath, Library library) + private async Task GetEpisode(ILibraryManager libraryManager, + Show show, + Season season, + long episodeNumber, + long absoluteNumber, + string episodePath, + Library library) { - Episode episode = await _metadataProvider.GetEpisode(show, episodePath, season?.SeasonNumber ?? -1, episodeNumber, absoluteNumber, library); - if (season == null) - season = await GetSeason(libraryManager, show, episode.SeasonNumber, library); + Episode episode = await _metadataProvider.GetEpisode(show, + episodePath, + season?.SeasonNumber ?? -1, + episodeNumber, + absoluteNumber, + library); + + season ??= await GetSeason(libraryManager, show, episode.SeasonNumber, library); episode.Season = season; if (season == null) { - await Console.Error.WriteLineAsync("\tError: You don't have any provider that support absolute epiode numbering. Install one and try again."); + await Console.Error.WriteLineAsync("Error: You don't have any provider that support absolute epiode numbering. Install one and try again."); return default; } diff --git a/Kyoo/Tasks/CreateDatabase.cs b/Kyoo/Tasks/CreateDatabase.cs index c5345ab4..d4e751dc 100644 --- a/Kyoo/Tasks/CreateDatabase.cs +++ b/Kyoo/Tasks/CreateDatabase.cs @@ -58,9 +58,9 @@ namespace Kyoo.Tasks return Task.CompletedTask; } - public IEnumerable GetPossibleParameters() + public Task> GetPossibleParameters() { - return null; + return Task.FromResult>(null); } public int? Progress() diff --git a/Kyoo/Tasks/MetadataLoader.cs b/Kyoo/Tasks/MetadataLoader.cs index 427eb22e..c66702c5 100644 --- a/Kyoo/Tasks/MetadataLoader.cs +++ b/Kyoo/Tasks/MetadataLoader.cs @@ -28,9 +28,9 @@ namespace Kyoo.Tasks return Task.CompletedTask; } - public IEnumerable GetPossibleParameters() + public Task> GetPossibleParameters() { - return null; + return Task.FromResult>(null); } public int? Progress() diff --git a/Kyoo/Tasks/PluginLoader.cs b/Kyoo/Tasks/PluginLoader.cs index a174caa5..b3f1c064 100644 --- a/Kyoo/Tasks/PluginLoader.cs +++ b/Kyoo/Tasks/PluginLoader.cs @@ -24,9 +24,9 @@ namespace Kyoo.Tasks return Task.CompletedTask; } - public IEnumerable GetPossibleParameters() + public Task> GetPossibleParameters() { - return null; + return Task.FromResult>(null); } public int? Progress() diff --git a/Kyoo/Tasks/ReScan.cs b/Kyoo/Tasks/ReScan.cs index aca39b6d..7ab182a7 100644 --- a/Kyoo/Tasks/ReScan.cs +++ b/Kyoo/Tasks/ReScan.cs @@ -114,9 +114,9 @@ namespace Kyoo.Tasks await _thumbnailsManager.Validate(edited, true); } - public IEnumerable GetPossibleParameters() + public Task> GetPossibleParameters() { - return default; + return Task.FromResult>(null); } public int? Progress() From 2d77ca992b5e85cd5004a631d76912364a221b86 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 7 Jun 2020 17:03:51 +0200 Subject: [PATCH 16/18] Basic crawler working --- Kyoo.Common/Controllers/ILibraryManager.cs | 18 +- Kyoo.Common/Controllers/IMetadataProvider.cs | 4 +- Kyoo.Common/Controllers/IProviderManager.cs | 4 +- Kyoo.Common/Controllers/IRepository.cs | 22 +-- Kyoo.Common/Models/Collection.cs | 2 +- Kyoo.Common/Models/CollectionLink.cs | 6 +- Kyoo.Common/Models/Episode.cs | 36 ++-- Kyoo.Common/Models/Genre.cs | 4 +- Kyoo.Common/Models/GenreLink.cs | 4 +- Kyoo.Common/Models/Library.cs | 5 +- Kyoo.Common/Models/LibraryLink.cs | 8 +- Kyoo.Common/Models/MetadataID.cs | 12 +- Kyoo.Common/Models/People.cs | 2 +- Kyoo.Common/Models/PeopleLink.cs | 6 +- Kyoo.Common/Models/ProviderID.cs | 4 +- Kyoo.Common/Models/ProviderLink.cs | 6 +- Kyoo.Common/Models/Season.cs | 14 +- Kyoo.Common/Models/Show.cs | 16 +- Kyoo.Common/Models/Studio.cs | 2 +- Kyoo.Common/Models/Track.cs | 4 +- Kyoo.Common/Models/WatchItem.cs | 18 +- Kyoo/Controllers/LibraryManager.cs | 49 +++-- Kyoo/Controllers/ProviderManager.cs | 11 +- .../Repositories/CollectionRepository.cs | 6 +- .../Repositories/EpisodeRepository.cs | 39 ++-- .../Repositories/GenreRepository.cs | 6 +- .../Repositories/LibraryRepository.cs | 22 ++- .../Repositories/PeopleRepository.cs | 6 +- .../Repositories/ProviderRepository.cs | 8 +- .../Repositories/SeasonRepository.cs | 35 ++-- .../Repositories/ShowRepository.cs | 83 ++++---- .../Repositories/StudioRepository.cs | 6 +- .../Repositories/TrackRepository.cs | 8 +- ....cs => 20200607010830_Initial.Designer.cs} | 178 +++++++++--------- ...3_Initial.cs => 20200607010830_Initial.cs} | 88 ++++----- .../Internal/DatabaseContextModelSnapshot.cs | 176 ++++++++--------- Kyoo/Startup.cs | 12 ++ Kyoo/Tasks/Crawler.cs | 21 ++- Kyoo/Views/API/EpisodesAPI.cs | 4 +- Kyoo/Views/API/LibrariesAPI.cs | 2 +- Kyoo/Views/API/SubtitleAPI.cs | 2 +- Kyoo/Views/API/ThumbnailAPI.cs | 2 +- Kyoo/Views/API/VideoAPI.cs | 6 +- Kyoo/Views/API/WatchAPI.cs | 2 +- 44 files changed, 515 insertions(+), 454 deletions(-) rename Kyoo/Models/DatabaseMigrations/Internal/{20200526235513_Initial.Designer.cs => 20200607010830_Initial.Designer.cs} (80%) rename Kyoo/Models/DatabaseMigrations/Internal/{20200526235513_Initial.cs => 20200607010830_Initial.cs} (88%) diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs index 75e2b53f..c345bf38 100644 --- a/Kyoo.Common/Controllers/ILibraryManager.cs +++ b/Kyoo.Common/Controllers/ILibraryManager.cs @@ -11,27 +11,27 @@ namespace Kyoo.Controllers Task GetLibrary(string slug); Task GetCollection(string slug); Task GetShow(string slug); - Task GetSeason(string showSlug, long seasonNumber); - Task GetEpisode(string showSlug, long seasonNumber, long episodeNumber); + Task GetSeason(string showSlug, int seasonNumber); + Task GetEpisode(string showSlug, int seasonNumber, int episodeNumber); Task GetMovieEpisode(string movieSlug); - Task GetTrack(long id); - Task GetTrack(long episodeID, string language, bool isForced); + Task GetTrack(int id); + Task GetTrack(int episodeID, string language, bool isForced); Task GetGenre(string slug); Task GetStudio(string slug); Task GetPeople(string slug); // Get by relations - Task> GetSeasons(long showID); + Task> GetSeasons(int showID); Task> GetSeasons(string showSlug); - Task> GetEpisodes(long showID, long seasonNumber); - Task> GetEpisodes(string showSlug, long seasonNumber); - Task> GetEpisodes(long seasonID); + Task> GetEpisodes(int showID, int seasonNumber); + Task> GetEpisodes(string showSlug, int seasonNumber); + Task> GetEpisodes(int seasonID); // Helpers Task GetShowByPath(string path); - Task AddShowLink(long showID, long? libraryID, long? collectionID); + Task AddShowLink(int showID, int? libraryID, int? collectionID); Task AddShowLink([NotNull] Show show, Library library, Collection collection); // Get all diff --git a/Kyoo.Common/Controllers/IMetadataProvider.cs b/Kyoo.Common/Controllers/IMetadataProvider.cs index 3a0472b9..1852739f 100644 --- a/Kyoo.Common/Controllers/IMetadataProvider.cs +++ b/Kyoo.Common/Controllers/IMetadataProvider.cs @@ -14,8 +14,8 @@ namespace Kyoo.Controllers Task> SearchShows(string showName, bool isMovie); Task> GetPeople(Show show); - Task GetSeason(Show show, long seasonNumber); + Task GetSeason(Show show, int seasonNumber); - Task GetEpisode(Show show, long seasonNumber, long episodeNumber, long absoluteNumber); + Task GetEpisode(Show show, int seasonNumber, int episodeNumber, int absoluteNumber); } } diff --git a/Kyoo.Common/Controllers/IProviderManager.cs b/Kyoo.Common/Controllers/IProviderManager.cs index 5690842d..b5c3da50 100644 --- a/Kyoo.Common/Controllers/IProviderManager.cs +++ b/Kyoo.Common/Controllers/IProviderManager.cs @@ -10,8 +10,8 @@ namespace Kyoo.Controllers Task CompleteShow(Show show, Library library); Task SearchShow(string showName, bool isMovie, Library library); Task> SearchShows(string showName, bool isMovie, Library library); - Task GetSeason(Show show, long seasonNumber, Library library); - Task GetEpisode(Show show, string episodePath, long seasonNumber, long episodeNumber, long absoluteNumber, Library library); + Task GetSeason(Show show, int seasonNumber, Library library); + Task GetEpisode(Show show, string episodePath, int seasonNumber, int episodeNumber, int absoluteNumber, Library library); Task> GetPeople(Show show, Library library); } } \ No newline at end of file diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index a63886ea..0993ca69 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -7,12 +7,12 @@ namespace Kyoo.Controllers { public interface IRepository { - Task Get(long id); + Task Get(int id); Task Get(string slug); Task> Search(string query); Task> GetAll(); - Task Create([NotNull] T obj); - Task CreateIfNotExists([NotNull] T obj); + Task Create([NotNull] T obj); + Task CreateIfNotExists([NotNull] T obj); Task Edit([NotNull] T edited, bool resetOld); Task Delete(T obj); } @@ -20,29 +20,29 @@ namespace Kyoo.Controllers public interface IShowRepository : IRepository { Task GetByPath(string path); - Task AddShowLink(long showID, long? libraryID, long? collectionID); + Task AddShowLink(int showID, int? libraryID, int? collectionID); } public interface ISeasonRepository : IRepository { - Task Get(string showSlug, long seasonNumber); + Task Get(string showSlug, int seasonNumber); - Task> GetSeasons(long showID); + Task> GetSeasons(int showID); Task> GetSeasons(string showSlug); } public interface IEpisodeRepository : IRepository { - Task Get(string showSlug, long seasonNumber, long episodeNumber); + Task Get(string showSlug, int seasonNumber, int episodeNumber); - Task> GetEpisodes(long showID, long seasonNumber); - Task> GetEpisodes(string showSlug, long seasonNumber); - Task> GetEpisodes(long seasonID); + Task> GetEpisodes(int showID, int seasonNumber); + Task> GetEpisodes(string showSlug, int seasonNumber); + Task> GetEpisodes(int seasonID); } public interface ITrackRepository : IRepository { - Task Get(long episodeID, string languageTag, bool isForced); + Task Get(int episodeID, string languageTag, bool isForced); } public interface ILibraryRepository : IRepository {} public interface ICollectionRepository : IRepository {} diff --git a/Kyoo.Common/Models/Collection.cs b/Kyoo.Common/Models/Collection.cs index c0297521..98881da2 100644 --- a/Kyoo.Common/Models/Collection.cs +++ b/Kyoo.Common/Models/Collection.cs @@ -7,7 +7,7 @@ namespace Kyoo.Models { public class Collection { - [JsonIgnore] public long ID { get; set; } + [JsonIgnore] public int ID { get; set; } public string Slug { get; set; } public string Name { get; set; } public string Poster { get; set; } diff --git a/Kyoo.Common/Models/CollectionLink.cs b/Kyoo.Common/Models/CollectionLink.cs index 24fb6403..cc8aa040 100644 --- a/Kyoo.Common/Models/CollectionLink.cs +++ b/Kyoo.Common/Models/CollectionLink.cs @@ -2,10 +2,10 @@ namespace Kyoo.Models { public class CollectionLink { - public long ID { get; set; } - public long? CollectionID { get; set; } + public int ID { get; set; } + public int? CollectionID { get; set; } public virtual Collection Collection { get; set; } - public long ShowID { get; set; } + public int ShowID { get; set; } public virtual Show Show { get; set; } public CollectionLink() { } diff --git a/Kyoo.Common/Models/Episode.cs b/Kyoo.Common/Models/Episode.cs index ada5a1ea..a00fa12f 100644 --- a/Kyoo.Common/Models/Episode.cs +++ b/Kyoo.Common/Models/Episode.cs @@ -6,21 +6,21 @@ namespace Kyoo.Models { public class Episode { - [JsonIgnore] public long ID { get; set; } - [JsonIgnore] public long ShowID { get; set; } + [JsonIgnore] public int ID { get; set; } + [JsonIgnore] public int ShowID { get; set; } [JsonIgnore] public virtual Show Show { get; set; } - [JsonIgnore] public long? SeasonID { get; set; } + [JsonIgnore] public int? SeasonID { get; set; } [JsonIgnore] public virtual Season Season { get; set; } - public long SeasonNumber { get; set; } - public long EpisodeNumber { get; set; } - public long AbsoluteNumber { get; set; } + public int SeasonNumber { get; set; } + public int EpisodeNumber { get; set; } + public int AbsoluteNumber { get; set; } [JsonIgnore] public string Path { get; set; } public string Title { get; set; } public string Overview { get; set; } public DateTime? ReleaseDate { get; set; } - public long Runtime { get; set; } //This runtime variable should be in minutes + public int Runtime { get; set; } //This runtime variable should be in minutes [JsonIgnore] public string ImgPrimary { get; set; } public virtual IEnumerable ExternalIDs { get; set; } @@ -42,13 +42,13 @@ namespace Kyoo.Models public Episode() { } - public Episode(long seasonNumber, - long episodeNumber, - long absoluteNumber, + public Episode(int seasonNumber, + int episodeNumber, + int absoluteNumber, string title, string overview, DateTime? releaseDate, - long runtime, + int runtime, string imgPrimary, IEnumerable externalIDs) { @@ -63,16 +63,16 @@ namespace Kyoo.Models ExternalIDs = externalIDs; } - public Episode(long showID, - long seasonID, - long seasonNumber, - long episodeNumber, - long absoluteNumber, + public Episode(int showID, + int seasonID, + int seasonNumber, + int episodeNumber, + int absoluteNumber, string path, string title, string overview, DateTime? releaseDate, - long runtime, + int runtime, string imgPrimary, IEnumerable externalIDs) { @@ -90,7 +90,7 @@ namespace Kyoo.Models ExternalIDs = externalIDs; } - public static string GetSlug(string showSlug, long seasonNumber, long episodeNumber) + public static string GetSlug(string showSlug, int seasonNumber, int episodeNumber) { return showSlug + "-s" + seasonNumber + "e" + episodeNumber; } diff --git a/Kyoo.Common/Models/Genre.cs b/Kyoo.Common/Models/Genre.cs index e57cd286..1935189e 100644 --- a/Kyoo.Common/Models/Genre.cs +++ b/Kyoo.Common/Models/Genre.cs @@ -4,7 +4,7 @@ namespace Kyoo.Models { public class Genre { - [JsonIgnore] public long ID { get; set; } + [JsonIgnore] public int ID { get; set; } public string Slug { get; set; } public string Name { get; set; } @@ -24,7 +24,7 @@ namespace Kyoo.Models Name = name; } - public Genre(long id, string slug, string name) + public Genre(int id, string slug, string name) { ID = id; Slug = slug; diff --git a/Kyoo.Common/Models/GenreLink.cs b/Kyoo.Common/Models/GenreLink.cs index cb85d01a..dce3e1bb 100644 --- a/Kyoo.Common/Models/GenreLink.cs +++ b/Kyoo.Common/Models/GenreLink.cs @@ -2,9 +2,9 @@ namespace Kyoo.Models { public class GenreLink { - public long ShowID { get; set; } + public int ShowID { get; set; } public virtual Show Show { get; set; } - public long GenreID { get; set; } + public int GenreID { get; set; } public virtual Genre Genre { get; set; } public GenreLink() {} diff --git a/Kyoo.Common/Models/Library.cs b/Kyoo.Common/Models/Library.cs index d3324b22..84441297 100644 --- a/Kyoo.Common/Models/Library.cs +++ b/Kyoo.Common/Models/Library.cs @@ -1,5 +1,4 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Kyoo.Models.Attributes; using Newtonsoft.Json; @@ -8,7 +7,7 @@ namespace Kyoo.Models { public class Library { - [JsonIgnore] public long ID { get; set; } + [JsonIgnore] public int ID { get; set; } public string Slug { get; set; } public string Name { get; set; } public IEnumerable Paths { get; set; } diff --git a/Kyoo.Common/Models/LibraryLink.cs b/Kyoo.Common/Models/LibraryLink.cs index 36cfc749..22120348 100644 --- a/Kyoo.Common/Models/LibraryLink.cs +++ b/Kyoo.Common/Models/LibraryLink.cs @@ -2,12 +2,12 @@ namespace Kyoo.Models { public class LibraryLink { - public long ID { get; set; } - public long LibraryID { get; set; } + public int ID { get; set; } + public int LibraryID { get; set; } public virtual Library Library { get; set; } - public long? ShowID { get; set; } + public int? ShowID { get; set; } public virtual Show Show { get; set; } - public long? CollectionID { get; set; } + public int? CollectionID { get; set; } public virtual Collection Collection { get; set; } public LibraryLink() { } diff --git a/Kyoo.Common/Models/MetadataID.cs b/Kyoo.Common/Models/MetadataID.cs index b1bd7a72..649ec157 100644 --- a/Kyoo.Common/Models/MetadataID.cs +++ b/Kyoo.Common/Models/MetadataID.cs @@ -4,20 +4,20 @@ namespace Kyoo.Models { public class MetadataID { - [JsonIgnore] public long ID { get; set; } - [JsonIgnore] public long ProviderID { get; set; } + [JsonIgnore] public int ID { get; set; } + [JsonIgnore] public int ProviderID { get; set; } public virtual ProviderID Provider {get; set; } - [JsonIgnore] public long? ShowID { get; set; } + [JsonIgnore] public int? ShowID { get; set; } [JsonIgnore] public virtual Show Show { get; set; } - [JsonIgnore] public long? EpisodeID { get; set; } + [JsonIgnore] public int? EpisodeID { get; set; } [JsonIgnore] public virtual Episode Episode { get; set; } - [JsonIgnore] public long? SeasonID { get; set; } + [JsonIgnore] public int? SeasonID { get; set; } [JsonIgnore] public virtual Season Season { get; set; } - [JsonIgnore] public long? PeopleID { get; set; } + [JsonIgnore] public int? PeopleID { get; set; } [JsonIgnore] public virtual People People { get; set; } public string DataID { get; set; } diff --git a/Kyoo.Common/Models/People.cs b/Kyoo.Common/Models/People.cs index 8dc17f9d..6514dc9f 100644 --- a/Kyoo.Common/Models/People.cs +++ b/Kyoo.Common/Models/People.cs @@ -6,7 +6,7 @@ namespace Kyoo.Models { public class People { - public long ID { get; set; } + public int ID { get; set; } public string Slug { get; set; } public string Name { get; set; } [JsonIgnore] public string ImgPrimary { get; set; } diff --git a/Kyoo.Common/Models/PeopleLink.cs b/Kyoo.Common/Models/PeopleLink.cs index ef6ef3af..509f2b93 100644 --- a/Kyoo.Common/Models/PeopleLink.cs +++ b/Kyoo.Common/Models/PeopleLink.cs @@ -5,8 +5,8 @@ namespace Kyoo.Models { public class PeopleLink { - [JsonIgnore] public long ID { get; set; } - [JsonIgnore] public long PeopleID { get; set; } + [JsonIgnore] public int ID { get; set; } + [JsonIgnore] public int PeopleID { get; set; } [JsonIgnore] public virtual People People { get; set; } public string Slug @@ -27,7 +27,7 @@ namespace Kyoo.Models set => People.ExternalIDs = value; } - [JsonIgnore] public long ShowID { get; set; } + [JsonIgnore] public int ShowID { get; set; } [JsonIgnore] public virtual Show Show { get; set; } public string Role { get; set; } public string Type { get; set; } diff --git a/Kyoo.Common/Models/ProviderID.cs b/Kyoo.Common/Models/ProviderID.cs index e7d76268..b68785b1 100644 --- a/Kyoo.Common/Models/ProviderID.cs +++ b/Kyoo.Common/Models/ProviderID.cs @@ -4,13 +4,13 @@ namespace Kyoo.Models { public class ProviderID { - [JsonIgnore] public long ID { get; set; } + [JsonIgnore] public int ID { get; set; } public string Name { get; set; } public string Logo { get; set; } public ProviderID() { } - public ProviderID(long id, string name, string logo) + public ProviderID(int id, string name, string logo) { ID = id; Name = name; diff --git a/Kyoo.Common/Models/ProviderLink.cs b/Kyoo.Common/Models/ProviderLink.cs index 088e4f80..6bc50b1a 100644 --- a/Kyoo.Common/Models/ProviderLink.cs +++ b/Kyoo.Common/Models/ProviderLink.cs @@ -4,10 +4,10 @@ namespace Kyoo.Models { public class ProviderLink { - [JsonIgnore] public long ID { get; set; } - [JsonIgnore] public long ProviderID { get; set; } + [JsonIgnore] public int ID { get; set; } + [JsonIgnore] public int ProviderID { get; set; } [JsonIgnore] public virtual ProviderID Provider { get; set; } - [JsonIgnore] public long? LibraryID { get; set; } + [JsonIgnore] public int? LibraryID { get; set; } [JsonIgnore] public virtual Library Library { get; set; } public ProviderLink() { } diff --git a/Kyoo.Common/Models/Season.cs b/Kyoo.Common/Models/Season.cs index 99bbd5cf..8d4d9052 100644 --- a/Kyoo.Common/Models/Season.cs +++ b/Kyoo.Common/Models/Season.cs @@ -5,15 +5,15 @@ namespace Kyoo.Models { public class Season { - [JsonIgnore] public long ID { get; set; } - [JsonIgnore] public long ShowID { get; set; } + [JsonIgnore] public int ID { get; set; } + [JsonIgnore] public int ShowID { get; set; } - public long SeasonNumber { get; set; } = -1; + public int SeasonNumber { get; set; } = -1; public string Slug => $"{Show.Slug}-s{SeasonNumber}"; public string Title { get; set; } public string Overview { get; set; } - public long? Year { get; set; } + public int? Year { get; set; } [JsonIgnore] public string ImgPrimary { get; set; } public virtual IEnumerable ExternalIDs { get; set; } @@ -23,11 +23,11 @@ namespace Kyoo.Models public Season() { } - public Season(long showID, - long seasonNumber, + public Season(int showID, + int seasonNumber, string title, string overview, - long? year, + int? year, string imgPrimary, IEnumerable externalIDs) { diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index 684b5305..a79ef71e 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -7,7 +7,7 @@ namespace Kyoo.Models { public class Show : IOnMerge { - [JsonIgnore] public long ID { get; set; } + [JsonIgnore] public int ID { get; set; } public string Slug { get; set; } public string Title { get; set; } @@ -17,8 +17,8 @@ namespace Kyoo.Models public Status? Status { get; set; } public string TrailerUrl { get; set; } - public long? StartYear { get; set; } - public long? EndYear { get; set; } + public int? StartYear { get; set; } + public int? EndYear { get; set; } public string Poster { get; set; } public string Logo { get; set; } @@ -36,7 +36,7 @@ namespace Kyoo.Models set => GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList(); } [NotMergable] [JsonIgnore] public virtual IEnumerable GenreLinks { get; set; } - [JsonIgnore] public long StudioID { get; set; } + [JsonIgnore] public int? StudioID { get; set; } public virtual Studio Studio { get; set; } [JsonIgnore] public virtual IEnumerable People { get; set; } [JsonIgnore] public virtual IEnumerable Seasons { get; set; } @@ -51,8 +51,8 @@ namespace Kyoo.Models string trailerUrl, IEnumerable genres, Status? status, - long? startYear, - long? endYear, + int? startYear, + int? endYear, IEnumerable externalIDs) { Slug = slug; @@ -76,8 +76,8 @@ namespace Kyoo.Models string overview, string trailerUrl, Status? status, - long? startYear, - long? endYear, + int? startYear, + int? endYear, string poster, string logo, string backdrop, diff --git a/Kyoo.Common/Models/Studio.cs b/Kyoo.Common/Models/Studio.cs index f02637fa..ec37121a 100644 --- a/Kyoo.Common/Models/Studio.cs +++ b/Kyoo.Common/Models/Studio.cs @@ -5,7 +5,7 @@ namespace Kyoo.Models { public class Studio { - [JsonIgnore] public long ID { get; set; } + [JsonIgnore] public int ID { get; set; } public string Slug { get; set; } public string Name { get; set; } diff --git a/Kyoo.Common/Models/Track.cs b/Kyoo.Common/Models/Track.cs index 7dc52ba3..9741330e 100644 --- a/Kyoo.Common/Models/Track.cs +++ b/Kyoo.Common/Models/Track.cs @@ -55,8 +55,8 @@ namespace Kyoo.Models public class Track : Stream { - [JsonIgnore] public long ID { get; set; } - [JsonIgnore] public long EpisodeID { get; set; } + [JsonIgnore] public int ID { get; set; } + [JsonIgnore] public int EpisodeID { get; set; } public bool IsDefault { get => isDefault; diff --git a/Kyoo.Common/Models/WatchItem.cs b/Kyoo.Common/Models/WatchItem.cs index 3278f313..10c91350 100644 --- a/Kyoo.Common/Models/WatchItem.cs +++ b/Kyoo.Common/Models/WatchItem.cs @@ -7,12 +7,12 @@ namespace Kyoo.Models { public class WatchItem { - [JsonIgnore] public readonly long EpisodeID = -1; + [JsonIgnore] public readonly int EpisodeID = -1; public string ShowTitle; public string ShowSlug; - public long SeasonNumber; - public long EpisodeNumber; + public int SeasonNumber; + public int EpisodeNumber; public string Title; public string Link; public DateTime? ReleaseDate; @@ -28,11 +28,11 @@ namespace Kyoo.Models public WatchItem() { } - public WatchItem(long episodeID, + public WatchItem(int episodeID, string showTitle, string showSlug, - long seasonNumber, - long episodeNumber, + int seasonNumber, + int episodeNumber, string title, DateTime? releaseDate, string path) @@ -50,11 +50,11 @@ namespace Kyoo.Models Link = Episode.GetSlug(ShowSlug, seasonNumber, episodeNumber); } - public WatchItem(long episodeID, + public WatchItem(int episodeID, string showTitle, string showSlug, - long seasonNumber, - long episodeNumber, + int seasonNumber, + int episodeNumber, string title, DateTime? releaseDate, string path, diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 82f8f5ea..c4f1432a 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -18,18 +18,27 @@ namespace Kyoo.Controllers private readonly IPeopleRepository _people; private readonly IProviderRepository _providers; - public LibraryManager(DatabaseContext database) + public LibraryManager(ILibraryRepository libraries, + ICollectionRepository collections, + IShowRepository shows, + ISeasonRepository seasons, + IEpisodeRepository episodes, + ITrackRepository tracks, + IGenreRepository genres, + IStudioRepository studios, + IProviderRepository providers, + IPeopleRepository people) { - _providers = new ProviderRepository(database); - _libraries = new LibraryRepository(database, _providers); - _collections = new CollectionRepository(database); - _genres = new GenreRepository(database); - _people = new PeopleRepository(database, _providers); - _studios = new StudioRepository(database); - _shows = new ShowRepository(database, _genres, _people, _studios, _providers); - _seasons = new SeasonRepository(database, _providers); - _episodes = new EpisodeRepository(database, _providers); - _tracks = new TrackRepository(database); + _libraries = libraries; + _collections = collections; + _shows = shows; + _seasons = seasons; + _episodes = episodes; + _tracks = tracks; + _genres = genres; + _studios = studios; + _providers = providers; + _people = people; } public Task GetLibrary(string slug) @@ -47,12 +56,12 @@ namespace Kyoo.Controllers return _shows.Get(slug); } - public Task GetSeason(string showSlug, long seasonNumber) + public Task GetSeason(string showSlug, int seasonNumber) { return _seasons.Get(showSlug, seasonNumber); } - public Task GetEpisode(string showSlug, long seasonNumber, long episodeNumber) + public Task GetEpisode(string showSlug, int seasonNumber, int episodeNumber) { return _episodes.Get(showSlug, seasonNumber, episodeNumber); } @@ -62,12 +71,12 @@ namespace Kyoo.Controllers return _episodes.Get(movieSlug); } - public Task GetTrack(long id) + public Task GetTrack(int id) { return _tracks.Get(id); } - public Task GetTrack(long episodeID, string language, bool isForced) + public Task GetTrack(int episodeID, string language, bool isForced) { return _tracks.Get(episodeID, language, isForced); } @@ -137,7 +146,7 @@ namespace Kyoo.Controllers return _providers.GetAll(); } - public Task> GetSeasons(long showID) + public Task> GetSeasons(int showID) { return _seasons.GetSeasons(showID); } @@ -147,17 +156,17 @@ namespace Kyoo.Controllers return _seasons.GetSeasons(showSlug); } - public Task> GetEpisodes(long showID, long seasonNumber) + public Task> GetEpisodes(int showID, int seasonNumber) { return _episodes.GetEpisodes(showID, seasonNumber); } - public Task> GetEpisodes(string showSlug, long seasonNumber) + public Task> GetEpisodes(string showSlug, int seasonNumber) { return _episodes.GetEpisodes(showSlug, seasonNumber); } - public Task> GetEpisodes(long seasonID) + public Task> GetEpisodes(int seasonID) { return _episodes.GetEpisodes(seasonID); } @@ -167,7 +176,7 @@ namespace Kyoo.Controllers return _shows.GetByPath(path); } - public Task AddShowLink(long showID, long? libraryID, long? collectionID) + public Task AddShowLink(int showID, int? libraryID, int? collectionID) { return _shows.AddShowLink(showID, libraryID, collectionID); } diff --git a/Kyoo/Controllers/ProviderManager.cs b/Kyoo/Controllers/ProviderManager.cs index 5dc6791c..663898d1 100644 --- a/Kyoo/Controllers/ProviderManager.cs +++ b/Kyoo/Controllers/ProviderManager.cs @@ -113,13 +113,14 @@ namespace Kyoo.Controllers }); } - public async Task GetSeason(Show show, long seasonNumber, Library library) + public async Task GetSeason(Show show, int seasonNumber, Library library) { Season season = await GetMetadata( provider => provider.GetSeason(show, seasonNumber), library, $"the season {seasonNumber} of {show.Title}"); season.Show = show; + season.ShowID = show.ID; season.SeasonNumber = season.SeasonNumber == -1 ? seasonNumber : season.SeasonNumber; season.Title ??= $"Season {season.SeasonNumber}"; return season; @@ -127,9 +128,9 @@ namespace Kyoo.Controllers public async Task GetEpisode(Show show, string episodePath, - long seasonNumber, - long episodeNumber, - long absoluteNumber, + int seasonNumber, + int episodeNumber, + int absoluteNumber, Library library) { Episode episode = await GetMetadata( @@ -137,6 +138,7 @@ namespace Kyoo.Controllers library, "an episode"); episode.Show = show; + episode.ShowID = show.ID; episode.Path = episodePath; episode.SeasonNumber = episode.SeasonNumber != -1 ? episode.SeasonNumber : seasonNumber; episode.EpisodeNumber = episode.EpisodeNumber != -1 ? episode.EpisodeNumber : episodeNumber; @@ -155,6 +157,7 @@ namespace Kyoo.Controllers .Select(x => { x.Show = show; + x.ShowID = show.ID; return x; }).ToList(); } diff --git a/Kyoo/Controllers/Repositories/CollectionRepository.cs b/Kyoo/Controllers/Repositories/CollectionRepository.cs index 476ffd67..c09bbc94 100644 --- a/Kyoo/Controllers/Repositories/CollectionRepository.cs +++ b/Kyoo/Controllers/Repositories/CollectionRepository.cs @@ -18,7 +18,7 @@ namespace Kyoo.Controllers _database = database; } - public Task Get(long id) + public Task Get(int id) { return _database.Collections.FirstOrDefaultAsync(x => x.ID == id); } @@ -41,7 +41,7 @@ namespace Kyoo.Controllers return await _database.Collections.ToListAsync(); } - public async Task Create(Collection obj) + public async Task Create(Collection obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -51,7 +51,7 @@ namespace Kyoo.Controllers return obj.ID; } - public async Task CreateIfNotExists(Collection obj) + public async Task CreateIfNotExists(Collection obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index dd92ad85..157a7a80 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -5,22 +5,23 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { public class EpisodeRepository : IEpisodeRepository { private readonly DatabaseContext _database; - private readonly IProviderRepository _providers; + private readonly IServiceProvider _serviceProvider; - public EpisodeRepository(DatabaseContext database, IProviderRepository providers) + public EpisodeRepository(DatabaseContext database, IServiceProvider serviceProvider) { _database = database; - _providers = providers; + _serviceProvider = serviceProvider; } - public async Task Get(long id) + public async Task Get(int id) { return await _database.Episodes.FirstOrDefaultAsync(x => x.ID == id); } @@ -32,14 +33,14 @@ namespace Kyoo.Controllers if (sIndex == -1 || eIndex == -1 || eIndex < sIndex) throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}"); string showSlug = slug.Substring(0, sIndex); - if (!long.TryParse(slug.Substring(sIndex + 2), out long seasonNumber)) + if (!int.TryParse(slug.Substring(sIndex + 2), out int seasonNumber)) throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}"); - if (!long.TryParse(slug.Substring(eIndex + 2), out long episodeNumber)) + if (!int.TryParse(slug.Substring(eIndex + 2), out int episodeNumber)) throw new InvalidOperationException("Invalid episode slug. Format: {showSlug}-s{seasonNumber}-e{episodeNumber}"); return Get(showSlug, seasonNumber, episodeNumber); } - public async Task Get(string showSlug, long seasonNumber, long episodeNumber) + public async Task Get(string showSlug, int seasonNumber, int episodeNumber) { return await _database.Episodes.FirstOrDefaultAsync(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber @@ -59,7 +60,7 @@ namespace Kyoo.Controllers return await _database.Episodes.ToListAsync(); } - public async Task Create(Episode obj) + public async Task Create(Episode obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -70,7 +71,7 @@ namespace Kyoo.Controllers return obj.ID; } - public async Task CreateIfNotExists(Episode obj) + public async Task CreateIfNotExists(Episode obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -104,11 +105,17 @@ namespace Kyoo.Controllers if (obj.ShowID <= 0) throw new InvalidOperationException($"Can't store an episode not related to any show (showID: {obj.ShowID})."); - obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + if (obj.ExternalIDs != null) { - x.ProviderID = await _providers.CreateIfNotExists(x.Provider); - return x; - }))).ToList(); + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + using IServiceScope serviceScope = _serviceProvider.CreateScope(); + IProviderRepository providers = serviceScope.ServiceProvider.GetService(); + + x.ProviderID = await providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } } public async Task Delete(Episode obj) @@ -117,19 +124,19 @@ namespace Kyoo.Controllers await _database.SaveChangesAsync(); } - public async Task> GetEpisodes(long showID, long seasonNumber) + public async Task> GetEpisodes(int showID, int seasonNumber) { return await _database.Episodes.Where(x => x.ShowID == showID && x.SeasonNumber == seasonNumber).ToListAsync(); } - public async Task> GetEpisodes(string showSlug, long seasonNumber) + public async Task> GetEpisodes(string showSlug, int seasonNumber) { return await _database.Episodes.Where(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber).ToListAsync(); } - public async Task> GetEpisodes(long seasonID) + public async Task> GetEpisodes(int seasonID) { return await _database.Episodes.Where(x => x.SeasonID == seasonID).ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/GenreRepository.cs b/Kyoo/Controllers/Repositories/GenreRepository.cs index 1035e54b..a908a339 100644 --- a/Kyoo/Controllers/Repositories/GenreRepository.cs +++ b/Kyoo/Controllers/Repositories/GenreRepository.cs @@ -18,7 +18,7 @@ namespace Kyoo.Controllers _database = database; } - public async Task Get(long id) + public async Task Get(int id) { return await _database.Genres.FirstOrDefaultAsync(x => x.ID == id); } @@ -41,7 +41,7 @@ namespace Kyoo.Controllers return await _database.Genres.ToListAsync(); } - public async Task Create(Genre obj) + public async Task Create(Genre obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -51,7 +51,7 @@ namespace Kyoo.Controllers return obj.ID; } - public async Task CreateIfNotExists(Genre obj) + public async Task CreateIfNotExists(Genre obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs index c73af246..9df08f4b 100644 --- a/Kyoo/Controllers/Repositories/LibraryRepository.cs +++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs @@ -5,29 +5,30 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { public class LibraryRepository : ILibraryRepository { private readonly DatabaseContext _database; - private readonly IProviderRepository _providers; + private readonly IServiceProvider _serviceProvider; - public LibraryRepository(DatabaseContext database, IProviderRepository providers) + public LibraryRepository(DatabaseContext database, IServiceProvider serviceProvider) { _database = database; - _providers = providers; + _serviceProvider = serviceProvider; } - public Task Get(long id) + public Task Get(int id) { return _database.Libraries.FirstOrDefaultAsync(x => x.ID == id); } public Task Get(string slug) { - return _database.Libraries.FirstOrDefaultAsync(x => x.Name == slug); + return _database.Libraries.FirstOrDefaultAsync(x => x.Slug == slug); } public async Task> Search(string query) @@ -43,19 +44,19 @@ namespace Kyoo.Controllers return await _database.Libraries.ToListAsync(); } - public async Task Create(Library obj) + public async Task Create(Library obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); obj.Links = null; await Validate(obj); - await _database.Libraries.AddAsync(obj); + _database.Entry(obj).State = EntityState.Added; await _database.SaveChangesAsync(); return obj.ID; } - public async Task CreateIfNotExists(Library obj) + public async Task CreateIfNotExists(Library obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -87,7 +88,10 @@ namespace Kyoo.Controllers { obj.ProviderLinks = (await Task.WhenAll(obj.ProviderLinks.Select(async x => { - x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + using IServiceScope serviceScope = _serviceProvider.CreateScope(); + IProviderRepository providers = serviceScope.ServiceProvider.GetService(); + + x.ProviderID = await providers.CreateIfNotExists(x.Provider); return x; }))).ToList(); } diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs index 0b702be5..d6fd7e3f 100644 --- a/Kyoo/Controllers/Repositories/PeopleRepository.cs +++ b/Kyoo/Controllers/Repositories/PeopleRepository.cs @@ -19,7 +19,7 @@ namespace Kyoo.Controllers _providers = providers; } - public Task Get(long id) + public Task Get(int id) { return _database.Peoples.FirstOrDefaultAsync(x => x.ID == id); } @@ -42,7 +42,7 @@ namespace Kyoo.Controllers return await _database.Peoples.ToListAsync(); } - public async Task Create(People obj) + public async Task Create(People obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -55,7 +55,7 @@ namespace Kyoo.Controllers return obj.ID; } - public async Task CreateIfNotExists(People obj) + public async Task CreateIfNotExists(People obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); diff --git a/Kyoo/Controllers/Repositories/ProviderRepository.cs b/Kyoo/Controllers/Repositories/ProviderRepository.cs index 4f9b85aa..4b304c45 100644 --- a/Kyoo/Controllers/Repositories/ProviderRepository.cs +++ b/Kyoo/Controllers/Repositories/ProviderRepository.cs @@ -18,7 +18,7 @@ namespace Kyoo.Controllers _database = database; } - public async Task Get(long id) + public async Task Get(int id) { return await _database.Providers.FirstOrDefaultAsync(x => x.ID == id); } @@ -41,17 +41,17 @@ namespace Kyoo.Controllers return await _database.Providers.ToListAsync(); } - public async Task Create(ProviderID obj) + public async Task Create(ProviderID obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); - + await _database.Providers.AddAsync(obj); await _database.SaveChangesAsync(); return obj.ID; } - public async Task CreateIfNotExists(ProviderID obj) + public async Task CreateIfNotExists(ProviderID obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index 686308dc..bf06c538 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -5,22 +5,23 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { public class SeasonRepository : ISeasonRepository { private readonly DatabaseContext _database; - private readonly IProviderRepository _providers; + private readonly IServiceProvider _serviceProvider; - public SeasonRepository(DatabaseContext database, IProviderRepository providers) + public SeasonRepository(DatabaseContext database, IServiceProvider serviceProvider) { _database = database; - _providers = providers; + _serviceProvider = serviceProvider; } - public async Task Get(long id) + public async Task Get(int id) { return await _database.Seasons.FirstOrDefaultAsync(x => x.ID == id); } @@ -31,12 +32,12 @@ namespace Kyoo.Controllers if (index == -1) throw new InvalidOperationException("Invalid season slug. Format: {showSlug}-s{seasonNumber}"); string showSlug = slug.Substring(0, index); - if (!long.TryParse(slug.Substring(index + 2), out long seasonNumber)) + if (!int.TryParse(slug.Substring(index + 2), out int seasonNumber)) throw new InvalidOperationException("Invalid season slug. Format: {showSlug}-s{seasonNumber}"); return Get(showSlug, seasonNumber); } - public async Task Get(string showSlug, long seasonNumber) + public async Task Get(string showSlug, int seasonNumber) { return await _database.Seasons.FirstOrDefaultAsync(x => x.Show.Slug == showSlug && x.SeasonNumber == seasonNumber); @@ -55,7 +56,7 @@ namespace Kyoo.Controllers return await _database.Seasons.ToListAsync(); } - public async Task Create(Season obj) + public async Task Create(Season obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -69,7 +70,7 @@ namespace Kyoo.Controllers return obj.ID; } - public async Task CreateIfNotExists(Season obj) + public async Task CreateIfNotExists(Season obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -102,12 +103,18 @@ namespace Kyoo.Controllers { if (obj.ShowID <= 0) throw new InvalidOperationException($"Can't store a season not related to any show (showID: {obj.ShowID})."); - - obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + + if (obj.ExternalIDs != null) { - x.ProviderID = await _providers.CreateIfNotExists(x.Provider); - return x; - }))).ToList(); + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + using IServiceScope serviceScope = _serviceProvider.CreateScope(); + IProviderRepository providers = serviceScope.ServiceProvider.GetService(); + + x.ProviderID = await providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } } public async Task Delete(Season obj) @@ -116,7 +123,7 @@ namespace Kyoo.Controllers await _database.SaveChangesAsync(); } - public async Task> GetSeasons(long showID) + public async Task> GetSeasons(int showID) { return await _database.Seasons.Where(x => x.ShowID == showID).ToListAsync(); } diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index 21ce741b..b8e2e2d8 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -5,31 +5,26 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { public class ShowRepository : IShowRepository { private readonly DatabaseContext _database; - private readonly IGenreRepository _genres; - private readonly IPeopleRepository _people; - private readonly IStudioRepository _studio; - private readonly IProviderRepository _providers; + private readonly IServiceProvider _serviceProvider; + private readonly IStudioRepository _studios; public ShowRepository(DatabaseContext database, - IGenreRepository genres, - IPeopleRepository people, - IStudioRepository studio, - IProviderRepository providers) + IServiceProvider serviceProvider, + IStudioRepository studios) { _database = database; - _genres = genres; - _people = people; - _studio = studio; - _providers = providers; + _serviceProvider = serviceProvider; + _studios = studios; } - public async Task Get(long id) + public async Task Get(int id) { return await _database.Shows.FirstOrDefaultAsync(x => x.ID == id); } @@ -58,22 +53,18 @@ namespace Kyoo.Controllers return await _database.Shows.ToListAsync(); } - public async Task Create(Show obj) + public async Task Create(Show obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); await Validate(obj); - - obj.Seasons = null; - obj.Episodes = null; - - await _database.Shows.AddAsync(obj); + _database.Entry(obj).State = EntityState.Added; await _database.SaveChangesAsync(); return obj.ID; } - public async Task CreateIfNotExists(Show obj) + public async Task CreateIfNotExists(Show obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -103,22 +94,44 @@ namespace Kyoo.Controllers private async Task Validate(Show obj) { - obj.StudioID = await _studio.CreateIfNotExists(obj.Studio); - obj.GenreLinks = (await Task.WhenAll(obj.GenreLinks.Select(async x => + if (obj.Studio != null) + obj.StudioID = await _studios.CreateIfNotExists(obj.Studio); + + if (obj.GenreLinks != null) { - x.GenreID = await _genres.CreateIfNotExists(x.Genre); - return x; - }))).ToList(); - obj.People = (await Task.WhenAll(obj.People.Select(async x => + obj.GenreLinks = (await Task.WhenAll(obj.GenreLinks.Select(async x => + { + using IServiceScope serviceScope = _serviceProvider.CreateScope(); + IGenreRepository genres = serviceScope.ServiceProvider.GetService(); + + x.GenreID = await genres.CreateIfNotExists(x.Genre); + return x; + }))).ToList(); + } + + if (obj.People != null) { - x.PeopleID = await _people.CreateIfNotExists(x.People); - return x; - }))).ToList(); - obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + obj.People = (await Task.WhenAll(obj.People.Select(async x => + { + using IServiceScope serviceScope = _serviceProvider.CreateScope(); + IPeopleRepository people = serviceScope.ServiceProvider.GetService(); + + x.PeopleID = await people.CreateIfNotExists(x.People); + return x; + }))).ToList(); + } + + if (obj.ExternalIDs != null) { - x.ProviderID = await _providers.CreateIfNotExists(x.Provider); - return x; - }))).ToList(); + obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => + { + using IServiceScope serviceScope = _serviceProvider.CreateScope(); + IProviderRepository providers = serviceScope.ServiceProvider.GetService(); + + x.ProviderID = await providers.CreateIfNotExists(x.Provider); + return x; + }))).ToList(); + } } public async Task Delete(Show show) @@ -127,7 +140,7 @@ namespace Kyoo.Controllers await _database.SaveChangesAsync(); } - public Task AddShowLink(long showID, long? libraryID, long? collectionID) + public async Task AddShowLink(int showID, int? libraryID, int? collectionID) { if (collectionID != null) { @@ -147,7 +160,7 @@ namespace Kyoo.Controllers x => x.LibraryID == libraryID && x.CollectionID == collectionID && x.ShowID == null); } - return Task.CompletedTask; + await _database.SaveChangesAsync(); } } } \ No newline at end of file diff --git a/Kyoo/Controllers/Repositories/StudioRepository.cs b/Kyoo/Controllers/Repositories/StudioRepository.cs index f531d7c1..a51f4ba5 100644 --- a/Kyoo/Controllers/Repositories/StudioRepository.cs +++ b/Kyoo/Controllers/Repositories/StudioRepository.cs @@ -18,7 +18,7 @@ namespace Kyoo.Controllers _database = database; } - public async Task Get(long id) + public async Task Get(int id) { return await _database.Studios.FirstOrDefaultAsync(x => x.ID == id); } @@ -41,7 +41,7 @@ namespace Kyoo.Controllers return await _database.Studios.ToListAsync(); } - public async Task Create(Studio obj) + public async Task Create(Studio obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -51,7 +51,7 @@ namespace Kyoo.Controllers return obj.ID; } - public async Task CreateIfNotExists(Studio obj) + public async Task CreateIfNotExists(Studio obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); diff --git a/Kyoo/Controllers/Repositories/TrackRepository.cs b/Kyoo/Controllers/Repositories/TrackRepository.cs index be67ab2c..6037889c 100644 --- a/Kyoo/Controllers/Repositories/TrackRepository.cs +++ b/Kyoo/Controllers/Repositories/TrackRepository.cs @@ -17,7 +17,7 @@ namespace Kyoo.Controllers _database = database; } - public async Task Get(long id) + public async Task Get(int id) { return await _database.Tracks.FirstOrDefaultAsync(x => x.ID == id); } @@ -27,7 +27,7 @@ namespace Kyoo.Controllers throw new InvalidOperationException("Tracks do not support the get by slug method."); } - public Task Get(long episodeID, string languageTag, bool isForced) + public Task Get(int episodeID, string languageTag, bool isForced) { return _database.Tracks.FirstOrDefaultAsync(x => x.EpisodeID == episodeID && x.Language == languageTag @@ -44,7 +44,7 @@ namespace Kyoo.Controllers return await _database.Tracks.ToListAsync(); } - public async Task Create(Track obj) + public async Task Create(Track obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); @@ -58,7 +58,7 @@ namespace Kyoo.Controllers return obj.ID; } - public Task CreateIfNotExists(Track obj) + public Task CreateIfNotExists(Track obj) { return Create(obj); } diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200526235513_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200607010830_Initial.Designer.cs similarity index 80% rename from Kyoo/Models/DatabaseMigrations/Internal/20200526235513_Initial.Designer.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200607010830_Initial.Designer.cs index 559076f9..1aaddf9b 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200526235513_Initial.Designer.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200607010830_Initial.Designer.cs @@ -10,7 +10,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Kyoo.Models.DatabaseMigrations.Internal { [DbContext(typeof(DatabaseContext))] - [Migration("20200526235513_Initial")] + [Migration("20200607010830_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -23,9 +23,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Collection", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ImgPrimary") @@ -53,16 +53,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.CollectionLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("CollectionID") - .HasColumnType("bigint"); + b.Property("CollectionID") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -75,16 +75,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Episode", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("AbsoluteNumber") - .HasColumnType("bigint"); + b.Property("AbsoluteNumber") + .HasColumnType("integer"); - b.Property("EpisodeNumber") - .HasColumnType("bigint"); + b.Property("EpisodeNumber") + .HasColumnType("integer"); b.Property("ImgPrimary") .HasColumnType("text"); @@ -98,17 +98,17 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("ReleaseDate") .HasColumnType("timestamp without time zone"); - b.Property("Runtime") - .HasColumnType("bigint"); + b.Property("Runtime") + .HasColumnType("integer"); - b.Property("SeasonID") - .HasColumnType("bigint"); + b.Property("SeasonID") + .HasColumnType("integer"); - b.Property("SeasonNumber") - .HasColumnType("bigint"); + b.Property("SeasonNumber") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.Property("Title") .HasColumnType("text"); @@ -124,9 +124,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Genre", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Name") @@ -145,11 +145,11 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.GenreLink", b => { - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); - b.Property("GenreID") - .HasColumnType("bigint"); + b.Property("GenreID") + .HasColumnType("integer"); b.HasKey("ShowID", "GenreID"); @@ -160,9 +160,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Library", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Name") @@ -184,19 +184,19 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.LibraryLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("CollectionID") - .HasColumnType("bigint"); + b.Property("CollectionID") + .HasColumnType("integer"); - b.Property("LibraryID") - .HasColumnType("bigint"); + b.Property("LibraryID") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -211,31 +211,31 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.MetadataID", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("DataID") .HasColumnType("text"); - b.Property("EpisodeID") - .HasColumnType("bigint"); + b.Property("EpisodeID") + .HasColumnType("integer"); b.Property("Link") .HasColumnType("text"); - b.Property("PeopleID") - .HasColumnType("bigint"); + b.Property("PeopleID") + .HasColumnType("integer"); - b.Property("ProviderID") - .HasColumnType("bigint"); + b.Property("ProviderID") + .HasColumnType("integer"); - b.Property("SeasonID") - .HasColumnType("bigint"); + b.Property("SeasonID") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -254,9 +254,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.People", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ImgPrimary") @@ -278,19 +278,19 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.PeopleLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("PeopleID") - .HasColumnType("bigint"); + b.Property("PeopleID") + .HasColumnType("integer"); b.Property("Role") .HasColumnType("text"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.Property("Type") .HasColumnType("text"); @@ -306,9 +306,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.ProviderID", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Logo") @@ -327,16 +327,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.ProviderLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("LibraryID") - .HasColumnType("bigint"); + b.Property("LibraryID") + .HasColumnType("integer"); - b.Property("ProviderID") - .HasColumnType("bigint"); + b.Property("ProviderID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -349,9 +349,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Season", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ImgPrimary") @@ -360,17 +360,17 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Overview") .HasColumnType("text"); - b.Property("SeasonNumber") - .HasColumnType("bigint"); + b.Property("SeasonNumber") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.Property("Title") .HasColumnType("text"); - b.Property("Year") - .HasColumnType("bigint"); + b.Property("Year") + .HasColumnType("integer"); b.HasKey("ID"); @@ -381,9 +381,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Show", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Aliases") @@ -392,8 +392,8 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Backdrop") .HasColumnType("text"); - b.Property("EndYear") - .HasColumnType("bigint"); + b.Property("EndYear") + .HasColumnType("integer"); b.Property("IsMovie") .HasColumnType("boolean"); @@ -413,14 +413,14 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Slug") .HasColumnType("text"); - b.Property("StartYear") - .HasColumnType("bigint"); + b.Property("StartYear") + .HasColumnType("integer"); b.Property("Status") .HasColumnType("integer"); - b.Property("StudioID") - .HasColumnType("bigint"); + b.Property("StudioID") + .HasColumnType("integer"); b.Property("Title") .HasColumnType("text"); @@ -440,9 +440,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Studio", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Name") @@ -461,16 +461,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Track", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Codec") .HasColumnType("text"); - b.Property("EpisodeID") - .HasColumnType("bigint"); + b.Property("EpisodeID") + .HasColumnType("integer"); b.Property("IsDefault") .HasColumnType("boolean"); diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200526235513_Initial.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200607010830_Initial.cs similarity index 88% rename from Kyoo/Models/DatabaseMigrations/Internal/20200526235513_Initial.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200607010830_Initial.cs index d3b90b3a..f83d1361 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200526235513_Initial.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200607010830_Initial.cs @@ -12,7 +12,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Collections", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Slug = table.Column(nullable: true), Name = table.Column(nullable: true), @@ -29,7 +29,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Genres", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Slug = table.Column(nullable: true), Name = table.Column(nullable: true) @@ -43,7 +43,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Libraries", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Slug = table.Column(nullable: true), Name = table.Column(nullable: true), @@ -58,7 +58,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Peoples", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Slug = table.Column(nullable: true), Name = table.Column(nullable: true), @@ -73,7 +73,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Providers", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Name = table.Column(nullable: true), Logo = table.Column(nullable: true) @@ -87,7 +87,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Studios", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Slug = table.Column(nullable: true), Name = table.Column(nullable: true) @@ -101,10 +101,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "ProviderLinks", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ProviderID = table.Column(nullable: false), - LibraryID = table.Column(nullable: true) + ProviderID = table.Column(nullable: false), + LibraryID = table.Column(nullable: true) }, constraints: table => { @@ -127,7 +127,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Shows", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Slug = table.Column(nullable: true), Title = table.Column(nullable: true), @@ -136,13 +136,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal Overview = table.Column(nullable: true), Status = table.Column(nullable: true), TrailerUrl = table.Column(nullable: true), - StartYear = table.Column(nullable: true), - EndYear = table.Column(nullable: true), + StartYear = table.Column(nullable: true), + EndYear = table.Column(nullable: true), Poster = table.Column(nullable: true), Logo = table.Column(nullable: true), Backdrop = table.Column(nullable: true), IsMovie = table.Column(nullable: false), - StudioID = table.Column(nullable: true) + StudioID = table.Column(nullable: true) }, constraints: table => { @@ -159,10 +159,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "CollectionLinks", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - CollectionID = table.Column(nullable: true), - ShowID = table.Column(nullable: false) + CollectionID = table.Column(nullable: true), + ShowID = table.Column(nullable: false) }, constraints: table => { @@ -185,8 +185,8 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "GenreLinks", columns: table => new { - ShowID = table.Column(nullable: false), - GenreID = table.Column(nullable: false) + ShowID = table.Column(nullable: false), + GenreID = table.Column(nullable: false) }, constraints: table => { @@ -209,11 +209,11 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "LibraryLinks", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - LibraryID = table.Column(nullable: false), - ShowID = table.Column(nullable: true), - CollectionID = table.Column(nullable: true) + LibraryID = table.Column(nullable: false), + ShowID = table.Column(nullable: true), + CollectionID = table.Column(nullable: true) }, constraints: table => { @@ -242,10 +242,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "PeopleLinks", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - PeopleID = table.Column(nullable: false), - ShowID = table.Column(nullable: false), + PeopleID = table.Column(nullable: false), + ShowID = table.Column(nullable: false), Role = table.Column(nullable: true), Type = table.Column(nullable: true) }, @@ -270,13 +270,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Seasons", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ShowID = table.Column(nullable: false), - SeasonNumber = table.Column(nullable: false), + ShowID = table.Column(nullable: false), + SeasonNumber = table.Column(nullable: false), Title = table.Column(nullable: true), Overview = table.Column(nullable: true), - Year = table.Column(nullable: true), + Year = table.Column(nullable: true), ImgPrimary = table.Column(nullable: true) }, constraints: table => @@ -294,18 +294,18 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Episodes", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ShowID = table.Column(nullable: false), - SeasonID = table.Column(nullable: true), - SeasonNumber = table.Column(nullable: false), - EpisodeNumber = table.Column(nullable: false), - AbsoluteNumber = table.Column(nullable: false), + ShowID = table.Column(nullable: false), + SeasonID = table.Column(nullable: true), + SeasonNumber = table.Column(nullable: false), + EpisodeNumber = table.Column(nullable: false), + AbsoluteNumber = table.Column(nullable: false), Path = table.Column(nullable: true), Title = table.Column(nullable: true), Overview = table.Column(nullable: true), ReleaseDate = table.Column(nullable: true), - Runtime = table.Column(nullable: false), + Runtime = table.Column(nullable: false), ImgPrimary = table.Column(nullable: true) }, constraints: table => @@ -329,13 +329,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "MetadataIds", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - ProviderID = table.Column(nullable: false), - ShowID = table.Column(nullable: true), - EpisodeID = table.Column(nullable: true), - SeasonID = table.Column(nullable: true), - PeopleID = table.Column(nullable: true), + ProviderID = table.Column(nullable: false), + ShowID = table.Column(nullable: true), + EpisodeID = table.Column(nullable: true), + SeasonID = table.Column(nullable: true), + PeopleID = table.Column(nullable: true), DataID = table.Column(nullable: true), Link = table.Column(nullable: true) }, @@ -378,14 +378,14 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Tracks", columns: table => new { - ID = table.Column(nullable: false) + ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Title = table.Column(nullable: true), Language = table.Column(nullable: true), Codec = table.Column(nullable: true), Path = table.Column(nullable: true), Type = table.Column(nullable: false), - EpisodeID = table.Column(nullable: false), + EpisodeID = table.Column(nullable: false), IsDefault = table.Column(nullable: false), IsForced = table.Column(nullable: false), IsExternal = table.Column(nullable: false) diff --git a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs index be3dd87f..a0e42322 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs @@ -21,9 +21,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Collection", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ImgPrimary") @@ -51,16 +51,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.CollectionLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("CollectionID") - .HasColumnType("bigint"); + b.Property("CollectionID") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -73,16 +73,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Episode", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("AbsoluteNumber") - .HasColumnType("bigint"); + b.Property("AbsoluteNumber") + .HasColumnType("integer"); - b.Property("EpisodeNumber") - .HasColumnType("bigint"); + b.Property("EpisodeNumber") + .HasColumnType("integer"); b.Property("ImgPrimary") .HasColumnType("text"); @@ -96,17 +96,17 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("ReleaseDate") .HasColumnType("timestamp without time zone"); - b.Property("Runtime") - .HasColumnType("bigint"); + b.Property("Runtime") + .HasColumnType("integer"); - b.Property("SeasonID") - .HasColumnType("bigint"); + b.Property("SeasonID") + .HasColumnType("integer"); - b.Property("SeasonNumber") - .HasColumnType("bigint"); + b.Property("SeasonNumber") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.Property("Title") .HasColumnType("text"); @@ -122,9 +122,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Genre", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Name") @@ -143,11 +143,11 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.GenreLink", b => { - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); - b.Property("GenreID") - .HasColumnType("bigint"); + b.Property("GenreID") + .HasColumnType("integer"); b.HasKey("ShowID", "GenreID"); @@ -158,9 +158,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Library", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Name") @@ -182,19 +182,19 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.LibraryLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("CollectionID") - .HasColumnType("bigint"); + b.Property("CollectionID") + .HasColumnType("integer"); - b.Property("LibraryID") - .HasColumnType("bigint"); + b.Property("LibraryID") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -209,31 +209,31 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.MetadataID", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("DataID") .HasColumnType("text"); - b.Property("EpisodeID") - .HasColumnType("bigint"); + b.Property("EpisodeID") + .HasColumnType("integer"); b.Property("Link") .HasColumnType("text"); - b.Property("PeopleID") - .HasColumnType("bigint"); + b.Property("PeopleID") + .HasColumnType("integer"); - b.Property("ProviderID") - .HasColumnType("bigint"); + b.Property("ProviderID") + .HasColumnType("integer"); - b.Property("SeasonID") - .HasColumnType("bigint"); + b.Property("SeasonID") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -252,9 +252,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.People", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ImgPrimary") @@ -276,19 +276,19 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.PeopleLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("PeopleID") - .HasColumnType("bigint"); + b.Property("PeopleID") + .HasColumnType("integer"); b.Property("Role") .HasColumnType("text"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.Property("Type") .HasColumnType("text"); @@ -304,9 +304,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.ProviderID", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Logo") @@ -325,16 +325,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.ProviderLink", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property("LibraryID") - .HasColumnType("bigint"); + b.Property("LibraryID") + .HasColumnType("integer"); - b.Property("ProviderID") - .HasColumnType("bigint"); + b.Property("ProviderID") + .HasColumnType("integer"); b.HasKey("ID"); @@ -347,9 +347,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Season", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ImgPrimary") @@ -358,17 +358,17 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Overview") .HasColumnType("text"); - b.Property("SeasonNumber") - .HasColumnType("bigint"); + b.Property("SeasonNumber") + .HasColumnType("integer"); - b.Property("ShowID") - .HasColumnType("bigint"); + b.Property("ShowID") + .HasColumnType("integer"); b.Property("Title") .HasColumnType("text"); - b.Property("Year") - .HasColumnType("bigint"); + b.Property("Year") + .HasColumnType("integer"); b.HasKey("ID"); @@ -379,9 +379,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Show", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Aliases") @@ -390,8 +390,8 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Backdrop") .HasColumnType("text"); - b.Property("EndYear") - .HasColumnType("bigint"); + b.Property("EndYear") + .HasColumnType("integer"); b.Property("IsMovie") .HasColumnType("boolean"); @@ -411,14 +411,14 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Slug") .HasColumnType("text"); - b.Property("StartYear") - .HasColumnType("bigint"); + b.Property("StartYear") + .HasColumnType("integer"); b.Property("Status") .HasColumnType("integer"); - b.Property("StudioID") - .HasColumnType("bigint"); + b.Property("StudioID") + .HasColumnType("integer"); b.Property("Title") .HasColumnType("text"); @@ -438,9 +438,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Studio", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Name") @@ -459,16 +459,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.Track", b => { - b.Property("ID") + b.Property("ID") .ValueGeneratedOnAdd() - .HasColumnType("bigint") + .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("Codec") .HasColumnType("text"); - b.Property("EpisodeID") - .HasColumnType("bigint"); + b.Property("EpisodeID") + .HasColumnType("integer"); b.Property("IsDefault") .HasColumnType("boolean"); diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index 22baaf05..bd1a5272 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -137,6 +137,18 @@ namespace Kyoo AllowedOrigins = { new Uri(publicUrl).GetLeftPart(UriPartial.Authority) } }); + + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddScoped(); services.AddSingleton(); services.AddSingleton(); diff --git a/Kyoo/Tasks/Crawler.cs b/Kyoo/Tasks/Crawler.cs index 70a88b6c..3a5c8ae9 100644 --- a/Kyoo/Tasks/Crawler.cs +++ b/Kyoo/Tasks/Crawler.cs @@ -134,9 +134,9 @@ namespace Kyoo.Controllers string showPath = Path.GetDirectoryName(path); string collectionName = match.Groups["Collection"]?.Value; string showName = match.Groups["ShowTitle"].Value; - long seasonNumber = long.TryParse(match.Groups["Season"].Value, out long tmp) ? tmp : -1; - long episodeNumber = long.TryParse(match.Groups["Episode"].Value, out tmp) ? tmp : -1; - long absoluteNumber = long.TryParse(match.Groups["Absolute"].Value, out tmp) ? tmp : -1; + int seasonNumber = int.TryParse(match.Groups["Season"].Value, out int tmp) ? tmp : -1; + int episodeNumber = int.TryParse(match.Groups["Episode"].Value, out tmp) ? tmp : -1; + int absoluteNumber = int.TryParse(match.Groups["Absolute"].Value, out tmp) ? tmp : -1; Collection collection = await GetCollection(libraryManager, collectionName, library); bool isMovie = seasonNumber == -1 && episodeNumber == -1 && absoluteNumber == -1; @@ -188,7 +188,7 @@ namespace Kyoo.Controllers private async Task GetSeason(ILibraryManager libraryManager, Show show, - long seasonNumber, + int seasonNumber, Library library) { if (seasonNumber == -1) @@ -207,8 +207,8 @@ namespace Kyoo.Controllers private async Task GetEpisode(ILibraryManager libraryManager, Show show, Season season, - long episodeNumber, - long absoluteNumber, + int episodeNumber, + int absoluteNumber, string episodePath, Library library) { @@ -221,6 +221,7 @@ namespace Kyoo.Controllers season ??= await GetSeason(libraryManager, show, episode.SeasonNumber, library); episode.Season = season; + episode.SeasonID = season?.ID; if (season == null) { await Console.Error.WriteLineAsync("Error: You don't have any provider that support absolute epiode numbering. Install one and try again."); @@ -234,7 +235,13 @@ namespace Kyoo.Controllers private async Task GetMovie(Show show, string episodePath) { - Episode episode = new Episode {Title = show.Title, Path = episodePath, Show = show}; + Episode episode = new Episode + { + Title = show.Title, + Path = episodePath, + Show = show, + ShowID = show.ID + }; episode.Tracks = await GetTracks(episode); return episode; } diff --git a/Kyoo/Views/API/EpisodesAPI.cs b/Kyoo/Views/API/EpisodesAPI.cs index 4e0dbb5b..abf0650d 100644 --- a/Kyoo/Views/API/EpisodesAPI.cs +++ b/Kyoo/Views/API/EpisodesAPI.cs @@ -21,7 +21,7 @@ namespace Kyoo.Api [HttpGet("{showSlug}/season/{seasonNumber}")] [Authorize(Policy="Read")] - public async Task>> GetEpisodesForSeason(string showSlug, long seasonNumber) + public async Task>> GetEpisodesForSeason(string showSlug, int seasonNumber) { IEnumerable episodes = await _libraryManager.GetEpisodes(showSlug, seasonNumber); @@ -34,7 +34,7 @@ namespace Kyoo.Api [HttpGet("{showSlug}/season/{seasonNumber}/episode/{episodeNumber}")] [Authorize(Policy="Read")] [JsonDetailed] - public async Task> GetEpisode(string showSlug, long seasonNumber, long episodeNumber) + public async Task> GetEpisode(string showSlug, int seasonNumber, int episodeNumber) { Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); diff --git a/Kyoo/Views/API/LibrariesAPI.cs b/Kyoo/Views/API/LibrariesAPI.cs index 73a5f907..eeeee468 100644 --- a/Kyoo/Views/API/LibrariesAPI.cs +++ b/Kyoo/Views/API/LibrariesAPI.cs @@ -41,7 +41,7 @@ namespace Kyoo.Api return BadRequest(new {error = "The library's name must be set and not empty"}); if (library.Paths == null || !library.Paths.Any()) return BadRequest(new {error = "The library should have a least one path."}); - if (_libraryManager.GetLibrary(library.Slug) != null) + if (await _libraryManager.GetLibrary(library.Slug) != null) return BadRequest(new {error = "Duplicated library slug"}); await _libraryManager.RegisterLibrary(library); _taskManager.StartTask("scan", library.Slug); diff --git a/Kyoo/Views/API/SubtitleAPI.cs b/Kyoo/Views/API/SubtitleAPI.cs index ea0c73e2..37685101 100644 --- a/Kyoo/Views/API/SubtitleAPI.cs +++ b/Kyoo/Views/API/SubtitleAPI.cs @@ -43,7 +43,7 @@ namespace Kyoo.Api string idString = identifier.IndexOf('-') != -1 ? identifier.Substring(0, identifier.IndexOf('-')) : identifier; - long.TryParse(idString, out long id); + int.TryParse(idString, out int id); subtitle = await _libraryManager.GetTrack(id); } diff --git a/Kyoo/Views/API/ThumbnailAPI.cs b/Kyoo/Views/API/ThumbnailAPI.cs index 12b8035c..455c680d 100644 --- a/Kyoo/Views/API/ThumbnailAPI.cs +++ b/Kyoo/Views/API/ThumbnailAPI.cs @@ -77,7 +77,7 @@ namespace Kyoo.Api [HttpGet("thumb/{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Read")] - public async Task GetEpisodeThumb(string showSlug, long seasonNumber, long episodeNumber) + public async Task GetEpisodeThumb(string showSlug, int seasonNumber, int episodeNumber) { string path = (await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber))?.Path; if (path == null) diff --git a/Kyoo/Views/API/VideoAPI.cs b/Kyoo/Views/API/VideoAPI.cs index c8e6f164..2c12cea7 100644 --- a/Kyoo/Views/API/VideoAPI.cs +++ b/Kyoo/Views/API/VideoAPI.cs @@ -27,7 +27,7 @@ namespace Kyoo.Api [HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Play")] - public async Task Index(string showSlug, long seasonNumber, long episodeNumber) + public async Task Index(string showSlug, int seasonNumber, int episodeNumber) { Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); @@ -38,7 +38,7 @@ namespace Kyoo.Api [HttpGet("transmux/{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Play")] - public async Task Transmux(string showSlug, long seasonNumber, long episodeNumber) + public async Task Transmux(string showSlug, int seasonNumber, int episodeNumber) { Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); @@ -61,7 +61,7 @@ namespace Kyoo.Api [HttpGet("transcode/{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Play")] - public async Task Transcode(string showSlug, long seasonNumber, long episodeNumber) + public async Task Transcode(string showSlug, int seasonNumber, int episodeNumber) { Episode episode = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); diff --git a/Kyoo/Views/API/WatchAPI.cs b/Kyoo/Views/API/WatchAPI.cs index 3ef292f1..07039073 100644 --- a/Kyoo/Views/API/WatchAPI.cs +++ b/Kyoo/Views/API/WatchAPI.cs @@ -19,7 +19,7 @@ namespace Kyoo.Api [HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")] [Authorize(Policy="Read")] - public async Task> Index(string showSlug, long seasonNumber, long episodeNumber) + public async Task> Index(string showSlug, int seasonNumber, int episodeNumber) { Episode item = await _libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber); From e7a3cfc2cc13131cb4c91e65265044b68eb7485c Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 7 Jun 2020 19:31:45 +0200 Subject: [PATCH 17/18] Solving bugs with related entities in repositories --- Kyoo.Common/Kyoo.Common.csproj | 2 +- .../Repositories/EpisodeRepository.cs | 5 ++++- .../Repositories/LibraryRepository.cs | 4 +++- .../Repositories/PeopleRepository.cs | 19 ++++++++++++------- .../Repositories/SeasonRepository.cs | 10 +++++----- Kyoo/Views/API/ShowsAPI.cs | 5 ++++- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Kyoo.Common/Kyoo.Common.csproj b/Kyoo.Common/Kyoo.Common.csproj index 7799859f..bdd20619 100644 --- a/Kyoo.Common/Kyoo.Common.csproj +++ b/Kyoo.Common/Kyoo.Common.csproj @@ -11,7 +11,7 @@ SDG GPL-3.0-or-later true - 1.0.20 + 1.0.21 diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index 157a7a80..231107b6 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -66,7 +66,10 @@ namespace Kyoo.Controllers throw new ArgumentNullException(nameof(obj)); await Validate(obj); - await _database.Episodes.AddAsync(obj); + _database.Entry(obj).State = EntityState.Added; + if (obj.ExternalIDs != null) + foreach (MetadataID entry in obj.ExternalIDs) + _database.Entry(entry).State = EntityState.Added; await _database.SaveChangesAsync(); return obj.ID; } diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs index 9df08f4b..4df5a1d0 100644 --- a/Kyoo/Controllers/Repositories/LibraryRepository.cs +++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs @@ -49,9 +49,11 @@ namespace Kyoo.Controllers if (obj == null) throw new ArgumentNullException(nameof(obj)); - obj.Links = null; await Validate(obj); _database.Entry(obj).State = EntityState.Added; + if (obj.ProviderLinks != null) + foreach (ProviderLink entry in obj.ProviderLinks) + _database.Entry(entry).State = EntityState.Added; await _database.SaveChangesAsync(); return obj.ID; } diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs index d6fd7e3f..26bcc825 100644 --- a/Kyoo/Controllers/Repositories/PeopleRepository.cs +++ b/Kyoo/Controllers/Repositories/PeopleRepository.cs @@ -5,18 +5,19 @@ using System.Threading.Tasks; using Kyoo.Models; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Controllers { public class PeopleRepository : IPeopleRepository { private readonly DatabaseContext _database; - private readonly IProviderRepository _providers; + private readonly IServiceProvider _serviceProvider; - public PeopleRepository(DatabaseContext database, IProviderRepository providers) + public PeopleRepository(DatabaseContext database, IServiceProvider serviceProvider) { _database = database; - _providers = providers; + _serviceProvider = serviceProvider; } public Task Get(int id) @@ -48,9 +49,10 @@ namespace Kyoo.Controllers throw new ArgumentNullException(nameof(obj)); await Validate(obj); - obj.Roles = null; - - await _database.Peoples.AddAsync(obj); + _database.Entry(obj).State = EntityState.Added; + if (obj.ExternalIDs != null) + foreach (MetadataID entry in obj.ExternalIDs) + _database.Entry(entry).State = EntityState.Added; await _database.SaveChangesAsync(); return obj.ID; } @@ -87,7 +89,10 @@ namespace Kyoo.Controllers { obj.ExternalIDs = (await Task.WhenAll(obj.ExternalIDs.Select(async x => { - x.ProviderID = await _providers.CreateIfNotExists(x.Provider); + using IServiceScope serviceScope = _serviceProvider.CreateScope(); + IProviderRepository providers = serviceScope.ServiceProvider.GetService(); + + x.ProviderID = await providers.CreateIfNotExists(x.Provider); return x; }))).ToList(); } diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index bf06c538..6e514871 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -60,12 +60,12 @@ namespace Kyoo.Controllers { if (obj == null) throw new ArgumentNullException(nameof(obj)); - - obj.Show = null; - obj.Episodes = null; - await Validate(obj); - await _database.Seasons.AddAsync(obj); + await Validate(obj); + _database.Entry(obj).State = EntityState.Added; + if (obj.ExternalIDs != null) + foreach (MetadataID entry in obj.ExternalIDs) + _database.Entry(entry).State = EntityState.Added; await _database.SaveChangesAsync(); return obj.ID; } diff --git a/Kyoo/Views/API/ShowsAPI.cs b/Kyoo/Views/API/ShowsAPI.cs index e92c028a..a22a485e 100644 --- a/Kyoo/Views/API/ShowsAPI.cs +++ b/Kyoo/Views/API/ShowsAPI.cs @@ -37,7 +37,10 @@ namespace Kyoo.Api [Authorize(Policy="Read")] public IEnumerable GetShows() { - return _database.LibraryLinks.AsEnumerable().Select(x => x.Show ?? x.Collection.AsShow()); + return _database.LibraryLinks + .Include(x => x.Show) + .Include(x => x.Collection) + .AsEnumerable().Select(x => x.Show ?? x.Collection.AsShow()).ToList(); } [HttpGet("{slug}")] From de503121f2726d33ae9df2db2ef6cd17776ca317 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 7 Jun 2020 20:01:12 +0200 Subject: [PATCH 18/18] Solving bugs with related entities in the show repositories --- Kyoo/Controllers/Repositories/GenreRepository.cs | 2 +- Kyoo/Controllers/Repositories/ShowRepository.cs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Kyoo/Controllers/Repositories/GenreRepository.cs b/Kyoo/Controllers/Repositories/GenreRepository.cs index a908a339..11931c10 100644 --- a/Kyoo/Controllers/Repositories/GenreRepository.cs +++ b/Kyoo/Controllers/Repositories/GenreRepository.cs @@ -58,7 +58,7 @@ namespace Kyoo.Controllers Genre old = await Get(obj.Slug); if (old != null) - return obj.ID; + return old.ID; return await Create(obj); } diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index b8e2e2d8..8d5a6772 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -60,6 +60,15 @@ namespace Kyoo.Controllers await Validate(obj); _database.Entry(obj).State = EntityState.Added; + if (obj.GenreLinks != null) + foreach (GenreLink entry in obj.GenreLinks) + _database.Entry(entry).State = EntityState.Added; + if (obj.People != null) + foreach (PeopleLink entry in obj.People) + _database.Entry(entry).State = EntityState.Added; + if (obj.ExternalIDs != null) + foreach (MetadataID entry in obj.ExternalIDs) + _database.Entry(entry).State = EntityState.Added; await _database.SaveChangesAsync(); return obj.ID; }