From ebb48a19cc792c71bfbd57d5f106067190d95339 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 28 Mar 2022 17:34:15 -0700 Subject: [PATCH] Improve usage of Original Title renaming token Fixed: Don't recursively add the current file name to new file name when '{Original Title}' is used in addition to other naming tokens --- .../OriginalTitleFixture.cs | 91 +++++++++++++++++++ .../Organizer/FileNameBuilder.cs | 23 +++-- 2 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/OriginalTitleFixture.cs diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/OriginalTitleFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/OriginalTitleFixture.cs new file mode 100644 index 000000000..ea1ee4dc6 --- /dev/null +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/OriginalTitleFixture.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +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 OriginalTitleFixture : CoreTest + { + private Series _series; + private Episode _episode; + private EpisodeFile _episodeFile; + private NamingConfig _namingConfig; + + [SetUp] + public void Setup() + { + _series = Builder + .CreateNew() + .With(s => s.Title = "My 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 { 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)); + } + + [Test] + public void should_not_recursively_include_current_filename() + { + _episodeFile.RelativePath = "My Series - S15E06 - City Sushi"; + _namingConfig.StandardEpisodeFormat = "{Series Title} - S{season:00}E{episode:00} - {Episode Title} {[Original Title]}"; + + Subject.BuildFileName(new List { _episode }, _series, _episodeFile) + .Should().Be("My Series - S15E06 - City Sushi"); + } + + [Test] + public void should_include_original_title_if_not_current_file_name() + { + _episodeFile.SceneName = "my.series.s15e06"; + _episodeFile.RelativePath = "My Series - S15E06 - City Sushi"; + _namingConfig.StandardEpisodeFormat = "{Series Title} - S{season:00}E{episode:00} - {Episode Title} {[Original Title]}"; + + Subject.BuildFileName(new List { _episode }, _series, _episodeFile) + .Should().Be("My Series - S15E06 - City Sushi [my.series.s15e06]"); + } + + [Test] + public void should_include_current_filename_if_not_renaming_files() + { + _episodeFile.SceneName = "my.series.s15e06"; + _namingConfig.RenameEpisodes = false; + + Subject.BuildFileName(new List { _episode }, _series, _episodeFile) + .Should().Be("my.series.s15e06"); + } + + [Test] + public void should_include_current_filename_if_not_including_multiple_naming_tokens() + { + _episodeFile.RelativePath = "My Series - S15E06 - City Sushi"; + _namingConfig.StandardEpisodeFormat = "{Original Title}"; + + Subject.BuildFileName(new List { _episode }, _series, _episodeFile) + .Should().Be("My Series - S15E06 - City Sushi"); + } + } +} diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index c6f8995b0..1a42bc7cc 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -109,7 +109,7 @@ namespace NzbDrone.Core.Organizer if (!namingConfig.RenameEpisodes) { - return GetOriginalTitle(episodeFile) + extension; + return GetOriginalTitle(episodeFile, false) + extension; } if (namingConfig.StandardEpisodeFormat.IsNullOrWhiteSpace() && series.SeriesType == SeriesTypes.Standard) @@ -148,6 +148,8 @@ namespace NzbDrone.Core.Organizer { var splitPattern = splitPatterns[i]; var tokenHandlers = new Dictionary>(FileNameBuilderTokenEqualityComparer.Instance); + var multipleTokens = TitleRegex.Matches(splitPattern).Count > 1; + splitPattern = AddSeasonEpisodeNumberingTokens(splitPattern, tokenHandlers, episodes, namingConfig); splitPattern = AddAbsoluteNumberingTokens(splitPattern, tokenHandlers, series, episodes, namingConfig); @@ -157,7 +159,7 @@ namespace NzbDrone.Core.Organizer AddIdTokens(tokenHandlers, series); AddEpisodeTokens(tokenHandlers, episodes); AddEpisodeTitlePlaceholderTokens(tokenHandlers); - AddEpisodeFileTokens(tokenHandlers, episodeFile); + AddEpisodeFileTokens(tokenHandlers, episodeFile, multipleTokens); AddQualityTokens(tokenHandlers, series, episodeFile); AddMediaInfoTokens(tokenHandlers, episodeFile); AddPreferredWords(tokenHandlers, series, episodeFile, preferredWords); @@ -583,10 +585,10 @@ namespace NzbDrone.Core.Organizer tokenHandlers["{Episode CleanTitle}"] = m => GetEpisodeTitle(GetEpisodeTitles(episodes).Select(CleanTitle).ToList(), "and", maxLength); } - private void AddEpisodeFileTokens(Dictionary> tokenHandlers, EpisodeFile episodeFile) + private void AddEpisodeFileTokens(Dictionary> tokenHandlers, EpisodeFile episodeFile, bool multipleTokens) { - tokenHandlers["{Original Title}"] = m => GetOriginalTitle(episodeFile); - tokenHandlers["{Original Filename}"] = m => GetOriginalFileName(episodeFile); + tokenHandlers["{Original Title}"] = m => GetOriginalTitle(episodeFile, multipleTokens); + tokenHandlers["{Original Filename}"] = m => GetOriginalFileName(episodeFile, multipleTokens); tokenHandlers["{Release Group}"] = m => episodeFile.ReleaseGroup ?? m.DefaultValue("Sonarr"); } @@ -1030,18 +1032,23 @@ namespace NzbDrone.Core.Organizer return string.Empty; } - private string GetOriginalTitle(EpisodeFile episodeFile) + private string GetOriginalTitle(EpisodeFile episodeFile, bool multipleTokens) { if (episodeFile.SceneName.IsNullOrWhiteSpace()) { - return GetOriginalFileName(episodeFile); + return GetOriginalFileName(episodeFile, multipleTokens); } return episodeFile.SceneName; } - private string GetOriginalFileName(EpisodeFile episodeFile) + private string GetOriginalFileName(EpisodeFile episodeFile, bool multipleTokens) { + if (multipleTokens) + { + return string.Empty; + } + if (episodeFile.RelativePath.IsNullOrWhiteSpace()) { return Path.GetFileNameWithoutExtension(episodeFile.Path);