diff --git a/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateMultipleSeriesFixture.cs b/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateMultipleSeriesFixture.cs index b48c260fc..b97c3b313 100644 --- a/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateMultipleSeriesFixture.cs +++ b/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateMultipleSeriesFixture.cs @@ -5,6 +5,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.AutoTagging; using NzbDrone.Core.Organizer; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; @@ -28,6 +29,10 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests .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] @@ -79,5 +84,23 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests Subject.UpdateSeries(series, false); } + + [Test] + public void should_add_and_remove_tags() + { + _series[0].Tags = new HashSet { 1, 2 }; + + Mocker.GetMock() + .Setup(s => s.GetTagChanges(_series[0])) + .Returns(new AutoTaggingChanges + { + TagsToAdd = new HashSet { 3 }, + TagsToRemove = new HashSet { 1 } + }); + + var result = Subject.UpdateSeries(_series, false); + + result[0].Tags.Should().BeEquivalentTo(new[] { 2, 3 }); + } } } diff --git a/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateSeriesFixture.cs b/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateSeriesFixture.cs index cc753b716..ba1b4bbf6 100644 --- a/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateSeriesFixture.cs +++ b/src/NzbDrone.Core.Test/TvTests/SeriesServiceTests/UpdateSeriesFixture.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using FizzWare.NBuilder; +using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.AutoTagging; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; @@ -31,6 +33,14 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests new Season { SeasonNumber = 1, Monitored = true }, new Season { SeasonNumber = 2, Monitored = true } }; + + 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() @@ -68,5 +78,28 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests Mocker.GetMock() .Verify(v => v.SetEpisodeMonitoredBySeason(_fakeSeries.Id, It.IsAny(), It.IsAny()), Times.Once()); } + + [Test] + public void should_add_and_remove_tags() + { + GivenExistingSeries(); + var seasonNumber = 1; + var monitored = false; + + _fakeSeries.Tags = new HashSet { 1, 2 }; + _fakeSeries.Seasons.Single(s => s.SeasonNumber == seasonNumber).Monitored = monitored; + + Mocker.GetMock() + .Setup(s => s.GetTagChanges(_fakeSeries)) + .Returns(new AutoTaggingChanges + { + TagsToAdd = new HashSet { 3 }, + TagsToRemove = new HashSet { 1 } + }); + + var result = Subject.UpdateSeries(_fakeSeries); + + result.Tags.Should().BeEquivalentTo(new[] { 2, 3 }); + } } } diff --git a/src/NzbDrone.Core/Tv/RefreshSeriesService.cs b/src/NzbDrone.Core/Tv/RefreshSeriesService.cs index 49aa9ebf6..b9dd08482 100644 --- a/src/NzbDrone.Core/Tv/RefreshSeriesService.cs +++ b/src/NzbDrone.Core/Tv/RefreshSeriesService.cs @@ -198,34 +198,11 @@ namespace NzbDrone.Core.Tv private void UpdateTags(Series series) { - _logger.Trace("Updating tags for {0}", series); + var tagsUpdated = _seriesService.UpdateTags(series); - var tagsAdded = new HashSet(); - var tagsRemoved = new HashSet(); - var changes = _autoTaggingService.GetTagChanges(series); - - foreach (var tag in changes.TagsToRemove) - { - if (series.Tags.Contains(tag)) - { - series.Tags.Remove(tag); - tagsRemoved.Add(tag); - } - } - - foreach (var tag in changes.TagsToAdd) - { - if (!series.Tags.Contains(tag)) - { - series.Tags.Add(tag); - tagsAdded.Add(tag); - } - } - - if (tagsAdded.Any() || tagsRemoved.Any()) + if (tagsUpdated) { _seriesService.UpdateSeries(series); - _logger.Debug("Updated tags for '{0}'. Added: {1}, Removed: {2}", series.Title, tagsAdded.Count, tagsRemoved.Count); } } diff --git a/src/NzbDrone.Core/Tv/SeriesService.cs b/src/NzbDrone.Core/Tv/SeriesService.cs index 6fd4551cf..b582acffa 100644 --- a/src/NzbDrone.Core/Tv/SeriesService.cs +++ b/src/NzbDrone.Core/Tv/SeriesService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NLog; using NzbDrone.Common.Extensions; +using NzbDrone.Core.AutoTagging; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Parser; using NzbDrone.Core.Tv.Events; @@ -30,6 +31,7 @@ namespace NzbDrone.Core.Tv List UpdateSeries(List series, bool useExistingRelativeFolder); bool SeriesPathExists(string folder); void RemoveAddOptions(Series series); + bool UpdateTags(Series series); } public class SeriesService : ISeriesService @@ -38,18 +40,21 @@ namespace NzbDrone.Core.Tv private readonly IEventAggregator _eventAggregator; private readonly IEpisodeService _episodeService; private readonly IBuildSeriesPaths _seriesPathBuilder; + private readonly IAutoTaggingService _autoTaggingService; private readonly Logger _logger; public SeriesService(ISeriesRepository seriesRepository, IEventAggregator eventAggregator, IEpisodeService episodeService, IBuildSeriesPaths seriesPathBuilder, + IAutoTaggingService autoTaggingService, Logger logger) { _seriesRepository = seriesRepository; _eventAggregator = eventAggregator; _episodeService = episodeService; _seriesPathBuilder = seriesPathBuilder; + _autoTaggingService = autoTaggingService; _logger = logger; } @@ -205,6 +210,7 @@ namespace NzbDrone.Core.Tv // Never update AddOptions when updating a series, keep it the same as the existing stored series. series.AddOptions = storedSeries.AddOptions; + UpdateTags(series); var updatedSeries = _seriesRepository.Update(series); if (publishUpdatedEvent) @@ -233,6 +239,8 @@ namespace NzbDrone.Core.Tv { _logger.Trace("Not changing path for: {0}", s.Title); } + + UpdateTags(s); } _seriesRepository.UpdateMany(series); @@ -250,5 +258,41 @@ namespace NzbDrone.Core.Tv { _seriesRepository.SetFields(series, s => s.AddOptions); } + + public bool UpdateTags(Series series) + { + _logger.Trace("Updating tags for {0}", series); + + var tagsAdded = new HashSet(); + var tagsRemoved = new HashSet(); + var changes = _autoTaggingService.GetTagChanges(series); + + foreach (var tag in changes.TagsToRemove) + { + if (series.Tags.Contains(tag)) + { + series.Tags.Remove(tag); + tagsRemoved.Add(tag); + } + } + + foreach (var tag in changes.TagsToAdd) + { + if (!series.Tags.Contains(tag)) + { + series.Tags.Add(tag); + tagsAdded.Add(tag); + } + } + + if (tagsAdded.Any() || tagsRemoved.Any()) + { + _logger.Debug("Updated tags for '{0}'. Added: {1}, Removed: {2}", series.Title, tagsAdded.Count, tagsRemoved.Count); + + return true; + } + + return false; + } } }