From a01888792ab4ae3e68030f4457a3f7aac79c31d7 Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Sun, 14 Mar 2021 17:54:32 +0000 Subject: [PATCH] delet items removed from plex (#77) * delete items removed from plex * fix tests --- .../Fakes/FakeTelevisionRepository.cs | 9 ++++++ .../Repositories/IMovieRepository.cs | 1 + .../Repositories/ITelevisionRepository.cs | 3 ++ ErsatzTV.Core/Plex/PlexMovieLibraryScanner.cs | 4 ++- .../Plex/PlexTelevisionLibraryScanner.cs | 12 ++++---- .../Data/Repositories/MovieRepository.cs | 9 ++++++ .../Data/Repositories/TelevisionRepository.cs | 29 +++++++++++++++++++ 7 files changed, 60 insertions(+), 7 deletions(-) diff --git a/ErsatzTV.Core.Tests/Fakes/FakeTelevisionRepository.cs b/ErsatzTV.Core.Tests/Fakes/FakeTelevisionRepository.cs index 6983d3871..bf3a57155 100644 --- a/ErsatzTV.Core.Tests/Fakes/FakeTelevisionRepository.cs +++ b/ErsatzTV.Core.Tests/Fakes/FakeTelevisionRepository.cs @@ -77,5 +77,14 @@ namespace ErsatzTV.Core.Tests.Fakes throw new NotSupportedException(); public Task AddGenre(ShowMetadata metadata, Genre genre) => throw new NotSupportedException(); + + public Task RemoveMissingPlexShows(PlexLibrary library, List showKeys) => + throw new NotSupportedException(); + + public Task RemoveMissingPlexSeasons(string showKey, List seasonKeys) => + throw new NotSupportedException(); + + public Task RemoveMissingPlexEpisodes(string seasonKey, List episodeKeys) => + throw new NotSupportedException(); } } diff --git a/ErsatzTV.Core/Interfaces/Repositories/IMovieRepository.cs b/ErsatzTV.Core/Interfaces/Repositories/IMovieRepository.cs index 8d2416748..22e6d5f7d 100644 --- a/ErsatzTV.Core/Interfaces/Repositories/IMovieRepository.cs +++ b/ErsatzTV.Core/Interfaces/Repositories/IMovieRepository.cs @@ -17,5 +17,6 @@ namespace ErsatzTV.Core.Interfaces.Repositories Task> FindMoviePaths(LibraryPath libraryPath); Task DeleteByPath(LibraryPath libraryPath, string path); Task AddGenre(MovieMetadata metadata, Genre genre); + Task RemoveMissingPlexMovies(PlexLibrary library, List movieKeys); } } diff --git a/ErsatzTV.Core/Interfaces/Repositories/ITelevisionRepository.cs b/ErsatzTV.Core/Interfaces/Repositories/ITelevisionRepository.cs index a30855055..1816478c3 100644 --- a/ErsatzTV.Core/Interfaces/Repositories/ITelevisionRepository.cs +++ b/ErsatzTV.Core/Interfaces/Repositories/ITelevisionRepository.cs @@ -36,5 +36,8 @@ namespace ErsatzTV.Core.Interfaces.Repositories Task> GetOrAddPlexSeason(PlexLibrary library, PlexSeason item); Task> GetOrAddPlexEpisode(PlexLibrary library, PlexEpisode item); Task AddGenre(ShowMetadata metadata, Genre genre); + Task RemoveMissingPlexShows(PlexLibrary library, List showKeys); + Task RemoveMissingPlexSeasons(string showKey, List seasonKeys); + Task RemoveMissingPlexEpisodes(string seasonKey, List episodeKeys); } } diff --git a/ErsatzTV.Core/Plex/PlexMovieLibraryScanner.cs b/ErsatzTV.Core/Plex/PlexMovieLibraryScanner.cs index ac44f0173..8bc1b6410 100644 --- a/ErsatzTV.Core/Plex/PlexMovieLibraryScanner.cs +++ b/ErsatzTV.Core/Plex/PlexMovieLibraryScanner.cs @@ -45,7 +45,6 @@ namespace ErsatzTV.Core.Plex { foreach (PlexMovie incoming in movieEntries) { - // TODO: optimize dbcontext use here, do we need tracking? can we make partial updates with dapper? // TODO: figure out how to rebuild playlists Either maybeMovie = await _movieRepository .GetOrAdd(plexMediaSourceLibrary, incoming) @@ -59,6 +58,9 @@ namespace ErsatzTV.Core.Plex incoming.Key, error.Value)); } + + var movieKeys = movieEntries.Map(s => s.Key).ToList(); + await _movieRepository.RemoveMissingPlexMovies(plexMediaSourceLibrary, movieKeys); }, error => { diff --git a/ErsatzTV.Core/Plex/PlexTelevisionLibraryScanner.cs b/ErsatzTV.Core/Plex/PlexTelevisionLibraryScanner.cs index dadf7e2af..fa8357462 100644 --- a/ErsatzTV.Core/Plex/PlexTelevisionLibraryScanner.cs +++ b/ErsatzTV.Core/Plex/PlexTelevisionLibraryScanner.cs @@ -45,7 +45,6 @@ namespace ErsatzTV.Core.Plex { foreach (PlexShow incoming in showEntries) { - // TODO: optimize dbcontext use here, do we need tracking? can we make partial updates with dapper? // TODO: figure out how to rebuild playlists Either maybeShow = await _televisionRepository .GetOrAddPlexShow(plexMediaSourceLibrary, incoming) @@ -64,7 +63,8 @@ namespace ErsatzTV.Core.Plex }); } - // TODO: delete removed shows + var showKeys = showEntries.Map(s => s.Key).ToList(); + await _televisionRepository.RemoveMissingPlexShows(plexMediaSourceLibrary, showKeys); return Unit.Default; }, @@ -141,7 +141,6 @@ namespace ErsatzTV.Core.Plex { incoming.ShowId = show.Id; - // TODO: optimize dbcontext use here, do we need tracking? can we make partial updates with dapper? // TODO: figure out how to rebuild playlists Either maybeSeason = await _televisionRepository .GetOrAddPlexSeason(plexMediaSourceLibrary, incoming) @@ -159,7 +158,8 @@ namespace ErsatzTV.Core.Plex }); } - // TODO: delete removed seasons + var seasonKeys = seasonEntries.Map(s => s.Key).ToList(); + await _televisionRepository.RemoveMissingPlexSeasons(show.Key, seasonKeys); return Unit.Default; }, @@ -206,7 +206,6 @@ namespace ErsatzTV.Core.Plex { incoming.SeasonId = season.Id; - // TODO: optimize dbcontext use here, do we need tracking? can we make partial updates with dapper? // TODO: figure out how to rebuild playlists Either maybeEpisode = await _televisionRepository .GetOrAddPlexEpisode(plexMediaSourceLibrary, incoming) @@ -220,7 +219,8 @@ namespace ErsatzTV.Core.Plex error.Value)); } - // TODO: delete removed episodes + var episodeKeys = episodeEntries.Map(s => s.Key).ToList(); + await _televisionRepository.RemoveMissingPlexEpisodes(season.Key, episodeKeys); return Unit.Default; }, diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs index 1386316ab..a795a7eae 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MovieRepository.cs @@ -147,6 +147,15 @@ namespace ErsatzTV.Infrastructure.Data.Repositories "INSERT INTO Genre (Name, MovieMetadataId) VALUES (@Name, @MetadataId)", new { genre.Name, MetadataId = metadata.Id }).ToUnit(); + public Task RemoveMissingPlexMovies(PlexLibrary library, List movieKeys) => + _dbConnection.ExecuteAsync( + @"DELETE FROM MediaItem WHERE Id IN + (SELECT m.Id FROM MediaItem m + INNER JOIN PlexMovie pm ON pm.Id = m.Id + INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId + WHERE lp.LibraryId = @LibraryId AND pm.Key not in @Keys)", + new { LibraryId = library.Id, Keys = movieKeys }).ToUnit(); + private async Task> AddMovie(int libraryPathId, string path) { try diff --git a/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs index bead0b75a..b331a0f79 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs @@ -364,6 +364,35 @@ namespace ErsatzTV.Infrastructure.Data.Repositories "INSERT INTO Genre (Name, SeasonMetadataId) VALUES (@Name, @MetadataId)", new { genre.Name, MetadataId = metadata.Id }).ToUnit(); + public Task RemoveMissingPlexShows(PlexLibrary library, List showKeys) => + _dbConnection.ExecuteAsync( + @"DELETE FROM MediaItem WHERE Id IN + (SELECT m.Id FROM MediaItem m + INNER JOIN PlexShow ps ON ps.Id = m.Id + INNER JOIN LibraryPath lp ON lp.Id = m.LibraryPathId + WHERE lp.LibraryId = @LibraryId AND ps.Key not in @Keys)", + new { LibraryId = library.Id, Keys = showKeys }).ToUnit(); + + public Task RemoveMissingPlexSeasons(string showKey, List seasonKeys) => + _dbConnection.ExecuteAsync( + @"DELETE FROM MediaItem WHERE Id IN + (SELECT m.Id FROM MediaItem m + INNER JOIN Season s ON m.Id = s.Id + INNER JOIN PlexSeason ps ON ps.Id = m.Id + INNER JOIN PlexShow P on P.Id = s.ShowId + WHERE P.Key = @ShowKey AND ps.Key not in @Keys)", + new { ShowKey = showKey, Keys = seasonKeys }).ToUnit(); + + public Task RemoveMissingPlexEpisodes(string seasonKey, List episodeKeys) => + _dbConnection.ExecuteAsync( + @"DELETE FROM MediaItem WHERE Id IN + (SELECT m.Id FROM MediaItem m + INNER JOIN Episode e ON m.Id = e.Id + INNER JOIN PlexEpisode pe ON pe.Id = m.Id + INNER JOIN PlexSeason P on P.Id = e.SeasonId + WHERE P.Key = @SeasonKey AND pe.Key not in @Keys)", + new { SeasonKey = seasonKey, Keys = episodeKeys }).ToUnit(); + public async Task> GetShowItems(int showId) { IEnumerable ids = await _dbConnection.QueryAsync(