From 087f9e12aac522b958fdd3cd7671603ecd8153d1 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 9 Jul 2024 22:02:23 -0700 Subject: [PATCH] New: Update AutoTags on movies update (cherry picked from commit 10e9735c1cb5f3b0d318c195a37df9e3a0407639) Closes #10153 --- .../MovieServiceTests/UpdateMovieFixture.cs | 36 ++++++++++- .../UpdateMultipleMoviesFixture.cs | 23 +++++++ src/NzbDrone.Core/Movies/MovieService.cs | 60 ++++++++++++++++--- .../Movies/RefreshMovieService.cs | 27 +-------- 4 files changed, 112 insertions(+), 34 deletions(-) diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMovieFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMovieFixture.cs index 23b7e0db7..5eab5d137 100644 --- a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMovieFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMovieFixture.cs @@ -1,6 +1,9 @@ +using System.Collections.Generic; using FizzWare.NBuilder; +using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.AutoTagging; using NzbDrone.Core.Movies; using NzbDrone.Core.Test.Framework; @@ -17,9 +20,17 @@ public void Setup() { _fakeMovie = Builder.CreateNew().Build(); _existingMovie = Builder.CreateNew().Build(); + + Mocker.GetMock() + .Setup(s => s.GetTagChanges(It.IsAny())) + .Returns(new AutoTaggingChanges()); + + Mocker.GetMock() + .Setup(s => s.Update(It.IsAny())) + .Returns(r => r); } - private void GivenExistingSeries() + private void GivenExistingMovie() { Mocker.GetMock() .Setup(s => s.GetMovie(It.IsAny())) @@ -29,12 +40,33 @@ private void GivenExistingSeries() [Test] public void should_update_movie_when_it_changes() { - GivenExistingSeries(); + GivenExistingMovie(); Subject.UpdateMovie(_fakeMovie); Mocker.GetMock() .Verify(v => v.Update(_fakeMovie), Times.Once()); } + + [Test] + public void should_add_and_remove_tags() + { + GivenExistingMovie(); + + _fakeMovie.Tags = new HashSet { 1, 2 }; + _fakeMovie.Monitored = false; + + Mocker.GetMock() + .Setup(s => s.GetTagChanges(_fakeMovie)) + .Returns(new AutoTaggingChanges + { + TagsToAdd = new HashSet { 3 }, + TagsToRemove = new HashSet { 1 } + }); + + var result = Subject.UpdateMovie(_fakeMovie); + + result.Tags.Should().BeEquivalentTo(new[] { 2, 3 }); + } } } diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs index 52bd151be..8f035b79c 100644 --- a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/UpdateMultipleMoviesFixture.cs @@ -5,6 +5,7 @@ using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.AutoTagging; using NzbDrone.Core.Movies; using NzbDrone.Core.Organizer; using NzbDrone.Core.Test.Framework; @@ -27,6 +28,10 @@ public void Setup() .With(s => s.Path = @"C:\Test\name".AsOsAgnostic()) .With(s => s.RootFolderPath = "") .Build().ToList(); + + Mocker.GetMock() + .Setup(s => s.GetTagChanges(It.IsAny())) + .Returns(new AutoTaggingChanges()); } [Test] @@ -78,5 +83,23 @@ public void should_be_able_to_update_many_movies() Subject.UpdateMovie(movies, false); } + + [Test] + public void should_add_and_remove_tags() + { + _movies[0].Tags = new HashSet { 1, 2 }; + + Mocker.GetMock() + .Setup(s => s.GetTagChanges(_movies[0])) + .Returns(new AutoTaggingChanges + { + TagsToAdd = new HashSet { 3 }, + TagsToRemove = new HashSet { 1 } + }); + + var result = Subject.UpdateMovie(_movies, false); + + result[0].Tags.Should().BeEquivalentTo(new[] { 2, 3 }); + } } } diff --git a/src/NzbDrone.Core/Movies/MovieService.cs b/src/NzbDrone.Core/Movies/MovieService.cs index 710ddf7fb..f109f2fcb 100644 --- a/src/NzbDrone.Core/Movies/MovieService.cs +++ b/src/NzbDrone.Core/Movies/MovieService.cs @@ -3,6 +3,7 @@ using System.Linq; using NLog; using NzbDrone.Common.Extensions; +using NzbDrone.Core.AutoTagging; using NzbDrone.Core.Configuration; using NzbDrone.Core.Datastore; using NzbDrone.Core.MediaFiles; @@ -40,11 +41,12 @@ public interface IMovieService List GetAllMovies(); Dictionary> AllMovieTags(); Movie UpdateMovie(Movie movie); - List UpdateMovie(List movie, bool useExistingRelativeFolder); + List UpdateMovie(List movies, bool useExistingRelativeFolder); void UpdateLastSearchTime(Movie movie); List GetRecommendedTmdbIds(); bool MoviePathExists(string folder); void RemoveAddOptions(Movie movie); + bool UpdateTags(Movie movie); bool ExistsByMetadataId(int metadataId); HashSet AllMovieWithCollectionsTmdbIds(); } @@ -56,18 +58,21 @@ public class MovieService : IMovieService, IHandle, private readonly IConfigService _configService; private readonly IEventAggregator _eventAggregator; private readonly IBuildMoviePaths _moviePathBuilder; + private readonly IAutoTaggingService _autoTaggingService; private readonly Logger _logger; public MovieService(IMovieRepository movieRepository, IEventAggregator eventAggregator, IConfigService configService, IBuildMoviePaths moviePathBuilder, + IAutoTaggingService autoTaggingService, Logger logger) { _movieRepository = movieRepository; _eventAggregator = eventAggregator; _configService = configService; _moviePathBuilder = moviePathBuilder; + _autoTaggingService = autoTaggingService; _logger = logger; } @@ -242,16 +247,19 @@ public Movie UpdateMovie(Movie movie) { var storedMovie = GetMovie(movie.Id); + UpdateTags(movie); + var updatedMovie = _movieRepository.Update(movie); _eventAggregator.PublishEvent(new MovieEditedEvent(updatedMovie, storedMovie)); return updatedMovie; } - public List UpdateMovie(List movie, bool useExistingRelativeFolder) + public List UpdateMovie(List movies, bool useExistingRelativeFolder) { - _logger.Debug("Updating {0} movie", movie.Count); - foreach (var m in movie) + _logger.Debug("Updating {0} movies", movies.Count); + + foreach (var m in movies) { _logger.Trace("Updating: {0}", m.Title); @@ -265,12 +273,14 @@ public List UpdateMovie(List movie, bool useExistingRelativeFolder { _logger.Trace("Not changing path for: {0}", m.Title); } + + UpdateTags(m); } - _movieRepository.UpdateMany(movie); - _logger.Debug("{0} movie updated", movie.Count); + _movieRepository.UpdateMany(movies); + _logger.Debug("{0} movies updated", movies.Count); - return movie; + return movies; } public void UpdateLastSearchTime(Movie movie) @@ -288,6 +298,42 @@ public void RemoveAddOptions(Movie movie) _movieRepository.SetFields(movie, s => s.AddOptions); } + public bool UpdateTags(Movie movie) + { + _logger.Trace("Updating tags for {0}", movie); + + var tagsAdded = new HashSet(); + var tagsRemoved = new HashSet(); + var changes = _autoTaggingService.GetTagChanges(movie); + + foreach (var tag in changes.TagsToRemove) + { + if (movie.Tags.Contains(tag)) + { + movie.Tags.Remove(tag); + tagsRemoved.Add(tag); + } + } + + foreach (var tag in changes.TagsToAdd) + { + if (!movie.Tags.Contains(tag)) + { + movie.Tags.Add(tag); + tagsAdded.Add(tag); + } + } + + if (tagsAdded.Any() || tagsRemoved.Any()) + { + _logger.Debug("Updated tags for '{0}'. Added: {1}, Removed: {2}", movie.Title, tagsAdded.Count, tagsRemoved.Count); + + return true; + } + + return false; + } + public List GetMoviesByFileId(int fileId) { return _movieRepository.GetMoviesByFileId(fileId); diff --git a/src/NzbDrone.Core/Movies/RefreshMovieService.cs b/src/NzbDrone.Core/Movies/RefreshMovieService.cs index 86c97d678..d919a495e 100644 --- a/src/NzbDrone.Core/Movies/RefreshMovieService.cs +++ b/src/NzbDrone.Core/Movies/RefreshMovieService.cs @@ -210,34 +210,11 @@ private void RescanMovie(Movie movie, bool isNew, CommandTrigger trigger) private void UpdateTags(Movie movie) { - _logger.Trace("Updating tags for {0}", movie); + var tagsUpdated = _movieService.UpdateTags(movie); - var tagsAdded = new HashSet(); - var tagsRemoved = new HashSet(); - var changes = _autoTaggingService.GetTagChanges(movie); - - foreach (var tag in changes.TagsToRemove) - { - if (movie.Tags.Contains(tag)) - { - movie.Tags.Remove(tag); - tagsRemoved.Add(tag); - } - } - - foreach (var tag in changes.TagsToAdd) - { - if (!movie.Tags.Contains(tag)) - { - movie.Tags.Add(tag); - tagsAdded.Add(tag); - } - } - - if (tagsAdded.Any() || tagsRemoved.Any()) + if (tagsUpdated) { _movieService.UpdateMovie(movie); - _logger.Debug("Updated tags for '{0}'. Added: {1}, Removed: {2}", movie.Title, tagsAdded.Count, tagsRemoved.Count); } }