New: Update AutoTags on series update

Closes #6783
This commit is contained in:
Mark McDowall 2024-07-09 22:02:23 -07:00 committed by GitHub
parent 293a1bc618
commit 10e9735c1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 103 additions and 26 deletions

View File

@ -5,6 +5,7 @@ using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.AutoTagging;
using NzbDrone.Core.Organizer; using NzbDrone.Core.Organizer;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; 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.Path = @"C:\Test\name".AsOsAgnostic())
.With(s => s.RootFolderPath = "") .With(s => s.RootFolderPath = "")
.Build().ToList(); .Build().ToList();
Mocker.GetMock<IAutoTaggingService>()
.Setup(s => s.GetTagChanges(It.IsAny<Series>()))
.Returns(new AutoTaggingChanges());
} }
[Test] [Test]
@ -79,5 +84,23 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
Subject.UpdateSeries(series, false); Subject.UpdateSeries(series, false);
} }
[Test]
public void should_add_and_remove_tags()
{
_series[0].Tags = new HashSet<int> { 1, 2 };
Mocker.GetMock<IAutoTaggingService>()
.Setup(s => s.GetTagChanges(_series[0]))
.Returns(new AutoTaggingChanges
{
TagsToAdd = new HashSet<int> { 3 },
TagsToRemove = new HashSet<int> { 1 }
});
var result = Subject.UpdateSeries(_series, false);
result[0].Tags.Should().BeEquivalentTo(new[] { 2, 3 });
}
} }
} }

View File

@ -1,8 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.AutoTagging;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
@ -31,6 +33,14 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
new Season { SeasonNumber = 1, Monitored = true }, new Season { SeasonNumber = 1, Monitored = true },
new Season { SeasonNumber = 2, Monitored = true } new Season { SeasonNumber = 2, Monitored = true }
}; };
Mocker.GetMock<IAutoTaggingService>()
.Setup(s => s.GetTagChanges(It.IsAny<Series>()))
.Returns(new AutoTaggingChanges());
Mocker.GetMock<ISeriesRepository>()
.Setup(s => s.Update(It.IsAny<Series>()))
.Returns<Series>(r => r);
} }
private void GivenExistingSeries() private void GivenExistingSeries()
@ -68,5 +78,28 @@ namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
.Verify(v => v.SetEpisodeMonitoredBySeason(_fakeSeries.Id, It.IsAny<int>(), It.IsAny<bool>()), Times.Once()); .Verify(v => v.SetEpisodeMonitoredBySeason(_fakeSeries.Id, It.IsAny<int>(), It.IsAny<bool>()), Times.Once());
} }
[Test]
public void should_add_and_remove_tags()
{
GivenExistingSeries();
var seasonNumber = 1;
var monitored = false;
_fakeSeries.Tags = new HashSet<int> { 1, 2 };
_fakeSeries.Seasons.Single(s => s.SeasonNumber == seasonNumber).Monitored = monitored;
Mocker.GetMock<IAutoTaggingService>()
.Setup(s => s.GetTagChanges(_fakeSeries))
.Returns(new AutoTaggingChanges
{
TagsToAdd = new HashSet<int> { 3 },
TagsToRemove = new HashSet<int> { 1 }
});
var result = Subject.UpdateSeries(_fakeSeries);
result.Tags.Should().BeEquivalentTo(new[] { 2, 3 });
}
} }
} }

View File

@ -198,34 +198,11 @@ namespace NzbDrone.Core.Tv
private void UpdateTags(Series series) private void UpdateTags(Series series)
{ {
_logger.Trace("Updating tags for {0}", series); var tagsUpdated = _seriesService.UpdateTags(series);
var tagsAdded = new HashSet<int>(); if (tagsUpdated)
var tagsRemoved = new HashSet<int>();
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())
{ {
_seriesService.UpdateSeries(series); _seriesService.UpdateSeries(series);
_logger.Debug("Updated tags for '{0}'. Added: {1}, Removed: {2}", series.Title, tagsAdded.Count, tagsRemoved.Count);
} }
} }

View File

@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.AutoTagging;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Tv.Events; using NzbDrone.Core.Tv.Events;
@ -30,6 +31,7 @@ namespace NzbDrone.Core.Tv
List<Series> UpdateSeries(List<Series> series, bool useExistingRelativeFolder); List<Series> UpdateSeries(List<Series> series, bool useExistingRelativeFolder);
bool SeriesPathExists(string folder); bool SeriesPathExists(string folder);
void RemoveAddOptions(Series series); void RemoveAddOptions(Series series);
bool UpdateTags(Series series);
} }
public class SeriesService : ISeriesService public class SeriesService : ISeriesService
@ -38,18 +40,21 @@ namespace NzbDrone.Core.Tv
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IEpisodeService _episodeService; private readonly IEpisodeService _episodeService;
private readonly IBuildSeriesPaths _seriesPathBuilder; private readonly IBuildSeriesPaths _seriesPathBuilder;
private readonly IAutoTaggingService _autoTaggingService;
private readonly Logger _logger; private readonly Logger _logger;
public SeriesService(ISeriesRepository seriesRepository, public SeriesService(ISeriesRepository seriesRepository,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IEpisodeService episodeService, IEpisodeService episodeService,
IBuildSeriesPaths seriesPathBuilder, IBuildSeriesPaths seriesPathBuilder,
IAutoTaggingService autoTaggingService,
Logger logger) Logger logger)
{ {
_seriesRepository = seriesRepository; _seriesRepository = seriesRepository;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_episodeService = episodeService; _episodeService = episodeService;
_seriesPathBuilder = seriesPathBuilder; _seriesPathBuilder = seriesPathBuilder;
_autoTaggingService = autoTaggingService;
_logger = logger; _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. // Never update AddOptions when updating a series, keep it the same as the existing stored series.
series.AddOptions = storedSeries.AddOptions; series.AddOptions = storedSeries.AddOptions;
UpdateTags(series);
var updatedSeries = _seriesRepository.Update(series); var updatedSeries = _seriesRepository.Update(series);
if (publishUpdatedEvent) if (publishUpdatedEvent)
@ -233,6 +239,8 @@ namespace NzbDrone.Core.Tv
{ {
_logger.Trace("Not changing path for: {0}", s.Title); _logger.Trace("Not changing path for: {0}", s.Title);
} }
UpdateTags(s);
} }
_seriesRepository.UpdateMany(series); _seriesRepository.UpdateMany(series);
@ -250,5 +258,41 @@ namespace NzbDrone.Core.Tv
{ {
_seriesRepository.SetFields(series, s => s.AddOptions); _seriesRepository.SetFields(series, s => s.AddOptions);
} }
public bool UpdateTags(Series series)
{
_logger.Trace("Updating tags for {0}", series);
var tagsAdded = new HashSet<int>();
var tagsRemoved = new HashSet<int>();
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;
}
} }
} }