From 6660e0c3f37fade91d39141b2830dba4e20a46e2 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Thu, 18 Aug 2022 23:06:49 -0700 Subject: [PATCH] New: Use absolute format if absolute episode number is not required and is missing Closes #5124 --- ...soluteEpisodeNumberSpecificationFixture.cs | 4 +- .../AbsoluteEpisodeFormatFixture.cs | 87 +++++++++++++++++++ .../RequiresAbsoluteEpisodeNumberFixture.cs | 4 +- .../AbsoluteEpisodeNumberSpecification.cs | 2 +- .../Organizer/FileNameBuilder.cs | 13 ++- 5 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/AbsoluteEpisodeFormatFixture.cs diff --git a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecificationFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecificationFixture.cs index 3a64a5127..5562b621a 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecificationFixture.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications }; Mocker.GetMock() - .Setup(s => s.RequiresAbsoluteEpisodeNumber(_series, episodes)) + .Setup(s => s.RequiresAbsoluteEpisodeNumber()) .Returns(true); } @@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications _localEpisode.Episodes.First().AbsoluteEpisodeNumber = null; Mocker.GetMock() - .Setup(s => s.RequiresAbsoluteEpisodeNumber(_series, _localEpisode.Episodes)) + .Setup(s => s.RequiresAbsoluteEpisodeNumber()) .Returns(false); Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue(); diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/AbsoluteEpisodeFormatFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/AbsoluteEpisodeFormatFixture.cs new file mode 100644 index 000000000..e658d0902 --- /dev/null +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/AbsoluteEpisodeFormatFixture.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Organizer; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests +{ + [TestFixture] + public class AbsoluteEpisodeFormatFixture : CoreTest + { + private Series _series; + private Episode _episode; + private EpisodeFile _episodeFile; + private NamingConfig _namingConfig; + + [SetUp] + public void Setup() + { + _series = Builder + .CreateNew() + .With(s => s.SeriesType = SeriesTypes.Anime) + .With(s => s.Title = "Anime Series") + .Build(); + + _episode = Builder.CreateNew() + .With(e => e.Title = "City Sushi") + .With(e => e.SeasonNumber = 15) + .With(e => e.EpisodeNumber = 6) + .With(e => e.AbsoluteEpisodeNumber = 100) + .Build(); + + _episodeFile = new EpisodeFile { Id = 5, Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "SonarrTest" }; + + _namingConfig = NamingConfig.Default; + _namingConfig.RenameEpisodes = true; + + Mocker.GetMock() + .Setup(c => c.GetConfig()).Returns(_namingConfig); + + Mocker.GetMock() + .Setup(v => v.Get(Moq.It.IsAny())) + .Returns(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v)); + + Mocker.GetMock() + .Setup(v => v.All()) + .Returns(new List()); + } + + [Test] + public void should_use_standard_format_if_absolute_format_requires_absolute_episode_number_and_it_is_missing() + { + _episode.AbsoluteEpisodeNumber = null; + _namingConfig.StandardEpisodeFormat = "{Series Title} S{season:00}E{episode:00}"; + _namingConfig.AnimeEpisodeFormat = "{Series Title} {absolute:00} [{ReleaseGroup}]"; + + Subject.BuildFileName(new List { _episode }, _series, _episodeFile) + .Should().Be("Anime Series S15E06"); + } + + [Test] + public void should_use_absolute_format_if_absolute_format_requires_absolute_episode_number_and_it_is_available() + { + _namingConfig.StandardEpisodeFormat = "{Series Title} S{season:00}E{episode:00}"; + _namingConfig.AnimeEpisodeFormat = "{Series Title} {absolute:00} [{ReleaseGroup}]"; + + Subject.BuildFileName(new List { _episode }, _series, _episodeFile) + .Should().Be("Anime Series 100 [SonarrTest]"); + } + + [Test] + public void should_use_absolute_format_if_absolute_format_does_not_require_absolute_episode_number_and_it_is_not_available() + { + _namingConfig.StandardEpisodeFormat = "{Series Title} S{season:00}E{episode:00}"; + _namingConfig.AnimeEpisodeFormat = "{Series Title} S{season:00}E{episode:00} [{ReleaseGroup}]"; + + Subject.BuildFileName(new List { _episode }, _series, _episodeFile) + .Should().Be("Anime Series S15E06 [SonarrTest]"); + } + } +} diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/RequiresAbsoluteEpisodeNumberFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/RequiresAbsoluteEpisodeNumberFixture.cs index 3093e339b..25b5551f1 100644 --- a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/RequiresAbsoluteEpisodeNumberFixture.cs +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/RequiresAbsoluteEpisodeNumberFixture.cs @@ -42,14 +42,14 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests public void should_return_false_when_absolute_episode_number_is_not_part_of_the_pattern() { _namingConfig.AnimeEpisodeFormat = "{Series Title} S{season:00}E{episode:00}"; - Subject.RequiresAbsoluteEpisodeNumber(_series, new List { _episode }).Should().BeFalse(); + Subject.RequiresAbsoluteEpisodeNumber().Should().BeFalse(); } [Test] public void should_return_true_when_absolute_episode_number_is_part_of_the_pattern() { _namingConfig.AnimeEpisodeFormat = "{Series Title} {absolute:00}"; - Subject.RequiresAbsoluteEpisodeNumber(_series, new List { _episode }).Should().BeTrue(); + Subject.RequiresAbsoluteEpisodeNumber().Should().BeTrue(); } } } diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecification.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecification.cs index 1aad4a1e5..9e361ccf9 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/AbsoluteEpisodeNumberSpecification.cs @@ -28,7 +28,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications return Decision.Accept(); } - if (!_buildFileNames.RequiresAbsoluteEpisodeNumber(localEpisode.Series, localEpisode.Episodes)) + if (!_buildFileNames.RequiresAbsoluteEpisodeNumber()) { _logger.Debug("File name format does not require absolute episode number, skipping check"); return Decision.Accept(); diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index f80a7bef3..5360b34f2 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -27,7 +27,7 @@ namespace NzbDrone.Core.Organizer string GetSeriesFolder(Series series, NamingConfig namingConfig = null); string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null); bool RequiresEpisodeTitle(Series series, List episodes); - bool RequiresAbsoluteEpisodeNumber(Series series, List episodes); + bool RequiresAbsoluteEpisodeNumber(); } public class FileNameBuilder : IBuildFileNames @@ -166,7 +166,9 @@ namespace NzbDrone.Core.Organizer pattern = namingConfig.DailyEpisodeFormat; } - if (series.SeriesType == SeriesTypes.Anime && episodes.All(e => e.AbsoluteEpisodeNumber.HasValue)) + if (series.SeriesType == SeriesTypes.Anime && + (episodes.All(e => e.AbsoluteEpisodeNumber.HasValue) || + !RequiresAbsoluteEpisodeNumber())) { pattern = namingConfig.AnimeEpisodeFormat; } @@ -433,13 +435,8 @@ namespace NzbDrone.Core.Organizer }); } - public bool RequiresAbsoluteEpisodeNumber(Series series, List episodes) + public bool RequiresAbsoluteEpisodeNumber() { - if (series.SeriesType != SeriesTypes.Anime) - { - return false; - } - var namingConfig = _namingConfigService.GetConfig(); var pattern = namingConfig.AnimeEpisodeFormat;