diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js b/frontend/src/Settings/MediaManagement/Naming/NamingModal.js index c24006b16..85d9493cf 100644 --- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js +++ b/frontend/src/Settings/MediaManagement/Naming/NamingModal.js @@ -59,15 +59,29 @@ const authorTokens = [ ]; const bookTokens = [ - { token: '{Book Title}', example: 'Book Title' }, + { token: '{Book Title}', example: 'Book Title!: Subtitle!' }, - { token: '{Book TitleThe}', example: 'Book Title, The' }, + { token: '{Book TitleThe}', example: 'Book Title!, The: Subtitle!' }, - { token: '{Book CleanTitle}', example: 'Book Title' }, + { token: '{Book CleanTitle}', example: 'Book Title: Subtitle' }, - { token: '{Book Type}', example: 'Book Type' }, + { token: '{Book TitleNoSub}', example: 'Book Title!' }, - { token: '{Book Disambiguation}', example: 'Disambiguation' } + { token: '{Book TitleTheNoSub}', example: 'Book Title!, The' }, + + { token: '{Book CleanTitleNoSub}', example: 'Book Title' }, + + { token: '{Book Subtitle}', example: 'Subtitle!' }, + + { token: '{Book SubtitleThe}', example: 'Subtitle!, The' }, + + { token: '{Book CleanSubtitle}', example: 'Subtitle' }, + + { token: '{Book Disambiguation}', example: 'Disambiguation' }, + + { token: '{PartNumber}', example: '2' }, + + { token: '{PartCount}', example: '10' } ]; const releaseDateTokens = [ diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleFixture.cs index b6b58a970..7508b63ef 100644 --- a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleFixture.cs +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/CleanTitleFixture.cs @@ -31,6 +31,7 @@ public void Setup() _book = Builder .CreateNew() .With(s => s.Title = "Hail to the King") + .With(s => s.AuthorMetadata = _author.Metadata.Value) .Build(); _edition = Builder diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs index d1085ce1f..6a8da1822 100644 --- a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs @@ -38,6 +38,7 @@ public void Setup() _book = Builder .CreateNew() .With(s => s.Title = "Hybrid Theory") + .With(s => s.AuthorMetadata = _author.Metadata.Value) .Build(); _edition = Builder @@ -433,7 +434,7 @@ public void should_replace_double_period_with_single_period() { _namingConfig.StandardBookFormat = "{Author.Name}.{Book.Title}"; - Subject.BuildBookFileName(new Author { Name = "In The Woods." }, new Edition { Title = "30 Rock", Book = new Book() }, _trackFile) + Subject.BuildBookFileName(new Author { Name = "In The Woods." }, new Edition { Title = "30 Rock", Book = new Book { AuthorMetadata = new AuthorMetadata { Name = "Author" } } }, _trackFile) .Should().Be("In.The.Woods.30.Rock"); } @@ -442,7 +443,7 @@ public void should_replace_triple_period_with_single_period() { _namingConfig.StandardBookFormat = "{Author.Name}.{Book.Title}"; - Subject.BuildBookFileName(new Author { Name = "In The Woods..." }, new Edition { Title = "30 Rock", Book = new Book() }, _trackFile) + Subject.BuildBookFileName(new Author { Name = "In The Woods..." }, new Edition { Title = "30 Rock", Book = new Book { AuthorMetadata = new AuthorMetadata { Name = "Author" } } }, _trackFile) .Should().Be("In.The.Woods.30.Rock"); } diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/TitleTheFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/TitleTheFixture.cs index 53b911867..9e01cfbc4 100644 --- a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/TitleTheFixture.cs +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/TitleTheFixture.cs @@ -31,6 +31,7 @@ public void Setup() _book = Builder .CreateNew() .With(s => s.Title = "Anthology") + .With(s => s.AuthorMetadata = _author.Metadata.Value) .Build(); _edition = Builder diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index d108be7ae..cc8e44a4d 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -10,6 +10,7 @@ using NzbDrone.Common.Extensions; using NzbDrone.Core.Books; using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Parser; using NzbDrone.Core.Profiles.Releases; using NzbDrone.Core.Qualities; @@ -44,7 +45,7 @@ public class FileNameBuilder : IBuildFileNames public static readonly Regex AuthorNameRegex = new Regex(@"(?\{(?:Author)(?[- ._])(Clean)?Name(The)?\})", RegexOptions.Compiled | RegexOptions.IgnoreCase); - public static readonly Regex BookTitleRegex = new Regex(@"(?\{(?:Book)(?[- ._])(Clean)?Title(The)?\})", + public static readonly Regex BookTitleRegex = new Regex(@"(?\{(?:Book)(?[- ._])(Clean)?Title(The)?(NoSub)?\})", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled); @@ -234,6 +235,16 @@ private void AddBookTokens(Dictionary> tokenHan tokenHandlers["{Book CleanTitle}"] = m => CleanTitle(edition.Title); tokenHandlers["{Book TitleThe}"] = m => TitleThe(edition.Title); + var (titleNoSub, subtitle) = edition.Title.SplitBookTitle(edition.Book.Value.AuthorMetadata.Value.Name); + + tokenHandlers["{Book TitleNoSub}"] = m => titleNoSub; + tokenHandlers["{Book CleanTitleNoSub}"] = m => CleanTitle(titleNoSub); + tokenHandlers["{Book TitleTheNoSub}"] = m => TitleThe(titleNoSub); + + tokenHandlers["{Book Subtitle}"] = m => subtitle; + tokenHandlers["{Book CleanSubtitle}"] = m => CleanTitle(subtitle); + tokenHandlers["{Book SubtitleThe}"] = m => TitleThe(subtitle); + if (edition.Disambiguation != null) { tokenHandlers["{Book Disambiguation}"] = m => edition.Disambiguation;