diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.tsx b/frontend/src/Settings/MediaManagement/Naming/NamingModal.tsx index 44debc2a8c..7016ac4fd7 100644 --- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.tsx +++ b/frontend/src/Settings/MediaManagement/Naming/NamingModal.tsx @@ -116,7 +116,12 @@ const movieTokens = [ }, { token: '{Movie CollectionThe}', - example: 'Movie Collection, The', + example: "Movie's Collection, The", + footNotes: '1', + }, + { + token: '{Movie CleanCollectionThe}', + example: 'Movies CleanCollection, The', footNotes: '1', }, { token: '{Movie Certification}', example: 'R' }, diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanCollectionTheFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanCollectionTheFixture.cs new file mode 100644 index 0000000000..1670325fb4 --- /dev/null +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanCollectionTheFixture.cs @@ -0,0 +1,91 @@ +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.Movies; +using NzbDrone.Core.Organizer; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests +{ + [TestFixture] + public class CleanCollectionTheFixture : CoreTest + { + private Movie _movie; + private MovieFile _movieFile; + private NamingConfig _namingConfig; + + [SetUp] + public void Setup() + { + _movie = Builder + .CreateNew() + .With(e => e.Title = "Movie Title") + .Build(); + + _movieFile = new MovieFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "RadarrTest" }; + + _namingConfig = NamingConfig.Default; + _namingConfig.RenameMovies = 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()); + } + + [TestCase("The Badger's Collection", "Badgers Collection, The")] + [TestCase("@ The Movies Collection", "@ The Movies Collection")] // This doesn't seem right; see: FileNameBuilder.ScenifyRemoveChars, looks like it has the "at sign" in the regex + [TestCase("A Stupid/Idiotic Collection", "Stupid Idiotic Collection, A")] + [TestCase("An Astounding & Amazing Collection", "Astounding and Amazing Collection, An")] + [TestCase("The Amazing Animal-Hero's Collection (2001)", "Amazing Animal-Heros Collection, The 2001")] + [TestCase("A Different Movië (AU)", "Different Movie, A AU")] + [TestCase("The Repairër (ZH) (2015)", "Repairer, The ZH 2015")] + [TestCase("The Eighth Sensë 2 (Thai)", "Eighth Sense 2, The Thai")] + [TestCase("The Astonishing Jæg (Latin America)", "Astonishing Jaeg, The Latin America")] + [TestCase("The Hampster Pack (B&F)", "Hampster Pack, The BandF")] + [TestCase("The Gásm: I (Almost) Got Away With It (1900)", "Gasm I Almost Got Away With It, The 1900")] + [TestCase(null, "")] + public void should_get_expected_title_back(string collection, string expected) + { + SetCollectionName(_movie, collection); + _namingConfig.StandardMovieFormat = "{Movie CleanCollectionThe}"; + + Subject.BuildFileName(_movie, _movieFile) + .Should().Be(expected); + } + + [TestCase("A")] + [TestCase("Anne")] + [TestCase("Theodore")] + [TestCase("3%")] + public void should_not_change_title(string collection) + { + SetCollectionName(_movie, collection); + _namingConfig.StandardMovieFormat = "{Movie CleanCollectionThe}"; + + Subject.BuildFileName(_movie, _movieFile) + .Should().Be(collection); + } + + private void SetCollectionName(Movie movie, string collectionName) + { + var metadata = new MovieMetadata() + { + CollectionTitle = collectionName, + }; + movie.MovieMetadata = new Core.Datastore.LazyLoaded(metadata); + movie.MovieMetadata.Value.CollectionTitle = collectionName; + } + } +} diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleTheFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleTheFixture.cs index 9a2a2b7cc0..2ce6ad1d26 100644 --- a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleTheFixture.cs +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleTheFixture.cs @@ -53,6 +53,7 @@ public void Setup() [TestCase("The Amazing Race (Latin America)", "Amazing Race, The Latin America")] [TestCase("The Rat Pack (A&E)", "Rat Pack, The AandE")] [TestCase("The Climax: I (Almost) Got Away With It (2016)", "Climax I Almost Got Away With It, The 2016")] + [TestCase(null, "")] public void should_get_expected_title_back(string title, string expected) { _movie.Title = title; diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index b4fd2476d2..24d69c7cb4 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -223,6 +223,11 @@ public static string TitleThe(string title) public static string CleanTitleThe(string title) { + if (string.IsNullOrWhiteSpace(title)) + { + return string.Empty; + } + if (TitlePrefixRegex.IsMatch(title)) { var splitResult = TitlePrefixRegex.Split(title); @@ -274,6 +279,7 @@ private void AddMovieTokens(Dictionary> tokenHa tokenHandlers["{Movie Certification}"] = m => movie.MovieMetadata.Value.Certification ?? string.Empty; tokenHandlers["{Movie Collection}"] = m => Truncate(movie.MovieMetadata.Value.CollectionTitle, m.CustomFormat) ?? string.Empty; tokenHandlers["{Movie CollectionThe}"] = m => Truncate(TitleThe(movie.MovieMetadata.Value.CollectionTitle), m.CustomFormat) ?? string.Empty; + tokenHandlers["{Movie CleanCollectionThe}"] = m => Truncate(CleanTitleThe(movie.MovieMetadata.Value.CollectionTitle), m.CustomFormat) ?? string.Empty; } private string GetLanguageTitle(Movie movie, string isoCodes)