Trying to fix the edit

This commit is contained in:
Zoe Roux 2020-05-31 05:16:04 +02:00
parent 28d48e9daf
commit 5f030b281f
8 changed files with 128 additions and 47 deletions

View File

@ -44,7 +44,6 @@ namespace Kyoo.Controllers
//Register values //Register values
void Register(object obj); void Register(object obj);
Task Edit(object obj, bool resetOld); Task Edit(object obj, bool resetOld);
void RegisterShowLinks(Library library, Collection collection, Show show);
Task SaveChanges(); Task SaveChanges();
// Validate values // Validate values

View File

@ -7,7 +7,7 @@ namespace Kyoo.Models
{ {
public class Show : IOnMerge public class Show : IOnMerge
{ {
[JsonIgnore] public long ID { get; set; } [NotMergableAttribute] [JsonIgnore] public long ID { get; set; }
public string Slug { get; set; } public string Slug { get; set; }
public string Title { get; set; } public string Title { get; set; }

View File

@ -99,7 +99,10 @@ namespace Kyoo
if (second == null) if (second == null)
return first; return first;
Type type = typeof(T); Type type = first.GetType();
if (second.GetType() != type && second.GetType().IsAssignableFrom(type))
type = second.GetType();
foreach (PropertyInfo property in type.GetProperties().Where(x => x.CanRead && x.CanWrite)) foreach (PropertyInfo property in type.GetProperties().Where(x => x.CanRead && x.CanWrite))
{ {
if (Attribute.GetCustomAttribute(property, typeof(NotMergableAttribute)) != null) if (Attribute.GetCustomAttribute(property, typeof(NotMergableAttribute)) != null)
@ -131,10 +134,10 @@ namespace Kyoo
public static T Nullify<T>(T obj) public static T Nullify<T>(T obj)
{ {
Type type = typeof(T); Type type = obj.GetType();
foreach (PropertyInfo property in type.GetProperties()) foreach (PropertyInfo property in type.GetProperties())
{ {
if (!property.CanWrite) if (!property.CanWrite || Attribute.GetCustomAttribute(property, typeof(NotMergableAttribute)) != null)
continue; continue;
object defaultValue = property.PropertyType.IsValueType object defaultValue = property.PropertyType.IsValueType

View File

@ -191,20 +191,6 @@ namespace Kyoo.Controllers
}); });
} }
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() public Task SaveChanges()
{ {
return SaveChanges(0); return SaveChanges(0);
@ -240,11 +226,12 @@ namespace Kyoo.Controllers
if (resetOld) if (resetOld)
Utility.Nullify(existing); Utility.Nullify(existing);
_database.ChangeTracker.DetectChanges();
Utility.Merge(existing, obj); Utility.Merge(existing, obj);
ValidateRootEntry(_database.Entry(existing), entry => entry.State != EntityState.Added);
_database.ChangeTracker.DetectChanges(); _database.ChangeTracker.DetectChanges();
ValidateRootEntry(_database.Entry(existing), entry => entry.State != EntityState.Unchanged
&& entry.State != EntityState.Deleted);
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
} }
finally finally
@ -277,12 +264,14 @@ namespace Kyoo.Controllers
} }
} }
private void ValidateRootEntry(EntityEntry entry, Func<EntityEntry, bool> shouldRun) private void ValidateRootEntry(EntityEntry entry, Func<EntityEntry, bool> shouldRun, object parentObject = null)
{ {
if (!shouldRun.Invoke(entry)) if (!shouldRun.Invoke(entry))
return; return;
foreach (NavigationEntry navigation in entry.Navigations) foreach (NavigationEntry navigation in entry.Navigations)
{ {
if (!navigation.Metadata.IsCollection() && ReferenceEquals(navigation.CurrentValue, parentObject))
continue;
ValidateNavigation(navigation); ValidateNavigation(navigation);
if (navigation.CurrentValue == null) if (navigation.CurrentValue == null)
continue; continue;
@ -290,10 +279,14 @@ namespace Kyoo.Controllers
{ {
IEnumerable entities = (IEnumerable)navigation.CurrentValue; IEnumerable entities = (IEnumerable)navigation.CurrentValue;
foreach (object childEntry in entities) foreach (object childEntry in entities)
ValidateRootEntry(_database.Entry(childEntry), shouldRun); {
if (ReferenceEquals(childEntry, parentObject))
continue;
ValidateRootEntry(_database.Entry(childEntry), shouldRun, entry.Entity);
}
} }
else else
ValidateRootEntry(_database.Entry(navigation.CurrentValue), shouldRun); ValidateRootEntry(_database.Entry(navigation.CurrentValue), shouldRun, entry.Entity);
} }
} }
@ -335,7 +328,7 @@ namespace Kyoo.Controllers
return list.Select(x => return list.Select(x =>
{ {
T tmp = Validate(x); T tmp = Validate(x);
if (tmp != x) if (!ReferenceEquals(x, tmp))
_database.Entry(x).State = EntityState.Detached; _database.Entry(x).State = EntityState.Detached;
return tmp ?? x; return tmp ?? x;
})/*.GroupBy(GetSlug).Select(x => x.First()).Where(x => x != null)*/.ToList(); })/*.GroupBy(GetSlug).Select(x => x.First()).Where(x => x != null)*/.ToList();
@ -345,13 +338,41 @@ namespace Kyoo.Controllers
{ {
return obj switch return obj switch
{ {
Library library => GetLibrary(library.Slug), Library library => _database.Libraries
Collection collection => GetCollection(collection.Slug), .Include(x => x.Links)
Show show => GetShow(show.Slug), .Include(x => x.Providers)
Season season => GetSeason(season.Show.Slug, season.SeasonNumber), .FirstOrDefault(x => x.Slug == library.Slug),
Episode episode => GetEpisode(episode.Show.Slug, episode.SeasonNumber, episode.EpisodeNumber), Collection collection => _database.Collections
Studio studio => GetStudio(studio.Slug), .Include(x => x.Links)
People people => GetPeople(people.Slug), .FirstOrDefault(x => x.Slug == collection.Slug),
Show show => _database.Shows
.Include(x => x.Seasons)
.Include(x => x.Episodes)
.Include(x => x.People)
.Include(x => x.GenreLinks)
.Include(x => x.Studio)
.Include(x => x.ExternalIDs)
.FirstOrDefault(x => x.Slug == show.Slug),
Season season => _database.Seasons
.Include(x => x.Episodes)
.Include(x => x.ExternalIDs)
.Include(x => x.Show)
.FirstOrDefault(x => x.Show.Slug == season.Show.Slug && x.SeasonNumber == season.SeasonNumber),
Episode episode => _database.Episodes
.Include(x => x.Season)
.Include(x => x.Show)
.Include(x => x.ExternalIDs)
.Include(x => x.Tracks)
.FirstOrDefault(x => x.EpisodeNumber == episode.EpisodeNumber
&& x.SeasonNumber == episode.SeasonNumber
&& x.Show.Slug == episode.Show.Slug),
Studio studio => _database.Studios
.Include(x => x.Shows)
.FirstOrDefault(x => x.Slug == studio.Slug),
People people => _database.Peoples
.Include(x => x.Roles)
.Include(x => x.ExternalIDs)
.FirstOrDefault(x => x.Slug == people.Slug),
Genre genre => GetGenre(genre.Slug), Genre genre => GetGenre(genre.Slug),
ProviderID provider => GetProvider(provider.Name), ProviderID provider => GetProvider(provider.Name),
_ => null _ => null

View File

@ -76,9 +76,12 @@ namespace Kyoo.Controllers
return collection; return collection;
} }
public async Task<Show> CompleteShow(Show show, Library library) public async Task<Show> CompleteShow(Show old, Library library)
{ {
return await GetMetadata(provider => provider.GetShowByID(show), library, $"the show {show.Title}"); Show show = await GetMetadata(provider => provider.GetShowByID(old), library, $"the show {old.Title}");
show.GenreLinks = show.GenreLinks?.GroupBy(x => x.Genre.Slug).Select(x => x.First()).ToList();
show.People = show.People?.GroupBy(x => x.Slug).Select(x => x.First()).ToList();
return show;
} }
public async Task<Show> SearchShow(string showName, bool isMovie, Library library) public async Task<Show> SearchShow(string showName, bool isMovie, Library library)

View File

@ -51,9 +51,9 @@ namespace Kyoo
services.AddDbContext<DatabaseContext>(options => services.AddDbContext<DatabaseContext>(options =>
{ {
options.UseLazyLoadingProxies() options.UseLazyLoadingProxies()
.UseNpgsql(_configuration.GetConnectionString("Database")); .UseNpgsql(_configuration.GetConnectionString("Database"))
// .EnableSensitiveDataLogging() .EnableSensitiveDataLogging();
// .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole())); //.UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
}); });
services.AddDbContext<IdentityDatabase>(options => services.AddDbContext<IdentityDatabase>(options =>

View File

@ -142,8 +142,12 @@ namespace Kyoo.Controllers
long absoluteNumber = long.TryParse(match.Groups["Absolute"].Value, out tmp) ? tmp : -1; long absoluteNumber = long.TryParse(match.Groups["Absolute"].Value, out tmp) ? tmp : -1;
Collection collection = await GetCollection(libraryManager, collectionName, library); Collection collection = await GetCollection(libraryManager, collectionName, library);
if (collection != null)
libraryManager.Register(collection);
bool isMovie = seasonNumber == -1 && episodeNumber == -1 && absoluteNumber == -1; bool isMovie = seasonNumber == -1 && episodeNumber == -1 && absoluteNumber == -1;
Show show = await GetShow(libraryManager, showName, showPath, isMovie, library); Show show = await GetShow(libraryManager, collection, showName, showPath, isMovie, library);
if (isMovie) if (isMovie)
libraryManager.Register(await GetMovie(show, path)); libraryManager.Register(await GetMovie(show, path));
else else
@ -152,9 +156,6 @@ namespace Kyoo.Controllers
Episode episode = await GetEpisode(libraryManager, show, season, episodeNumber, absoluteNumber, path, library); Episode episode = await GetEpisode(libraryManager, show, season, episodeNumber, absoluteNumber, path, library);
libraryManager.Register(episode); libraryManager.Register(episode);
} }
if (collection != null)
libraryManager.Register(collection);
libraryManager.RegisterShowLinks(library, collection, show);
Console.WriteLine($"Registering episode at: {path}"); Console.WriteLine($"Registering episode at: {path}");
await libraryManager.SaveChanges(); await libraryManager.SaveChanges();
} }
@ -162,14 +163,19 @@ namespace Kyoo.Controllers
private async Task<Collection> GetCollection(ILibraryManager libraryManager, string collectionName, Library library) private async Task<Collection> GetCollection(ILibraryManager libraryManager, string collectionName, Library library)
{ {
if (string.IsNullOrEmpty(collectionName)) if (string.IsNullOrEmpty(collectionName))
return await Task.FromResult<Collection>(null); return default;
Collection name = libraryManager.GetCollection(Utility.ToSlug(collectionName)); Collection name = libraryManager.GetCollection(Utility.ToSlug(collectionName));
if (name != null) if (name != null)
return name; return name;
return await _metadataProvider.GetCollectionFromName(collectionName, library); return await _metadataProvider.GetCollectionFromName(collectionName, library);
} }
private async Task<Show> GetShow(ILibraryManager libraryManager, string showTitle, string showPath, bool isMovie, Library library) private async Task<Show> GetShow(ILibraryManager libraryManager,
Collection collection,
string showTitle,
string showPath,
bool isMovie,
Library library)
{ {
Show show = libraryManager.GetShowByPath(showPath); Show show = libraryManager.GetShowByPath(showPath);
if (show != null) if (show != null)
@ -179,6 +185,15 @@ namespace Kyoo.Controllers
show.People = await _metadataProvider.GetPeople(show, library); show.People = await _metadataProvider.GetPeople(show, library);
await _thumbnailsManager.Validate(show.People); await _thumbnailsManager.Validate(show.People);
await _thumbnailsManager.Validate(show); await _thumbnailsManager.Validate(show);
if (collection != null)
{
libraryManager.Register(new LibraryLink {Library = library, Collection = collection});
libraryManager.Register(new CollectionLink { Collection = collection, Show = show});
}
else
libraryManager.Register(new LibraryLink {Library = library, Show = show});
return show; return show;
} }
@ -196,9 +211,20 @@ namespace Kyoo.Controllers
return season; return season;
} }
private async Task<Episode> GetEpisode(ILibraryManager libraryManager, Show show, Season season, long episodeNumber, long absoluteNumber, string episodePath, Library library) private async Task<Episode> 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); Episode episode = await _metadataProvider.GetEpisode(show,
episodePath,
season?.SeasonNumber ?? -1,
episodeNumber,
absoluteNumber,
library);
if (season == null) if (season == null)
season = await GetSeason(libraryManager, show, episode.SeasonNumber, library); season = await GetSeason(libraryManager, show, episode.SeasonNumber, library);
episode.Season = season; episode.Season = season;
@ -223,7 +249,8 @@ namespace Kyoo.Controllers
private async Task<IEnumerable<Track>> GetTracks(Episode episode) private async Task<IEnumerable<Track>> GetTracks(Episode episode)
{ {
IEnumerable<Track> tracks = await _transcoder.GetTrackInfo(episode.Path); IEnumerable<Track> tracks = await _transcoder.GetTrackInfo(episode.Path);
List<Track> epTracks = tracks.Where(x => x.Type != StreamType.Subtitle).Concat(GetExtractedSubtitles(episode)).ToList(); List<Track> epTracks = tracks.Where(x => x.Type != StreamType.Subtitle)
.Concat(GetExtractedSubtitles(episode)).ToList();
if (epTracks.Count(x => !x.IsExternal) < tracks.Count()) if (epTracks.Count(x => !x.IsExternal) < tracks.Count())
epTracks.AddRange(await _transcoder.ExtractSubtitles(episode.Path)); epTracks.AddRange(await _transcoder.ExtractSubtitles(episode.Path));
episode.Tracks = epTracks; episode.Tracks = epTracks;
@ -262,7 +289,33 @@ namespace Kyoo.Controllers
return tracks; return tracks;
} }
private static readonly string[] VideoExtensions = { ".webm", ".mkv", ".flv", ".vob", ".ogg", ".ogv", ".avi", ".mts", ".m2ts", ".ts", ".mov", ".qt", ".asf", ".mp4", ".m4p", ".m4v", ".mpg", ".mp2", ".mpeg", ".mpe", ".mpv", ".m2v", ".3gp", ".3g2" }; private static readonly string[] VideoExtensions =
{
".webm",
".mkv",
".flv",
".vob",
".ogg",
".ogv",
".avi",
".mts",
".m2ts",
".ts",
".mov",
".qt",
".asf",
".mp4",
".m4p",
".m4v",
".mpg",
".mp2",
".mpeg",
".mpe",
".mpv",
".m2v",
".3gp",
".3g2"
};
private static bool IsVideo(string filePath) private static bool IsVideo(string filePath)
{ {

View File

@ -62,6 +62,8 @@ namespace Kyoo.Tasks
edited.ID = old.ID; edited.ID = old.ID;
edited.Slug = old.Slug; edited.Slug = old.Slug;
edited.Path = old.Path; edited.Path = old.Path;
edited.Seasons = old.Seasons;
edited.Episodes = old.Episodes;
await libraryManager.Edit(edited, true); await libraryManager.Edit(edited, true);
await _thumbnailsManager.Validate(edited, true); await _thumbnailsManager.Validate(edited, true);
} }