diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index d770a3eea..5ca9e255f 100644
--- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -308,6 +308,7 @@
+
diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/TitleTheFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/TitleTheFixture.cs
new file mode 100644
index 000000000..8145ead25
--- /dev/null
+++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/TitleTheFixture.cs
@@ -0,0 +1,83 @@
+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 TitleTheFixture : CoreTest
+ {
+ private Series _series;
+ private Episode _episode;
+ private EpisodeFile _episodeFile;
+ private NamingConfig _namingConfig;
+
+ [SetUp]
+ public void Setup()
+ {
+ _series = Builder
+ .CreateNew()
+ .With(s => s.Title = "South Park")
+ .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));
+ }
+
+ [TestCase("The Mist", "Mist, The")]
+ [TestCase("A Place to Call Home", "Place to Call Home, A")]
+ [TestCase("An Adventure in Space and Time", "Adventure in Space and Time, An")]
+ [TestCase("The Flash (2010)", "Flash, The (2010)")]
+ [TestCase("A League Of Their Own (AU)", "League Of Their Own, A (AU)")]
+ [TestCase("The Fixer (ZH) (2015)", "Fixer, The (ZH) (2015)")]
+ [TestCase("The Sixth Sense 2 (Thai)", "Sixth Sense 2, The (Thai)")]
+ [TestCase("The Amazing Race (Latin America)", "Amazing Race, The (Latin America)")]
+ [TestCase("The Rat Pack (A&E)", "Rat Pack, The (A&E)")]
+ [TestCase("The Climax: I (Almost) Got Away With It (2016)", "Climax- I (Almost) Got Away With It, The (2016)")]
+ //[TestCase("", "")]
+ public void should_get_expected_title_back(string title, string expected)
+ {
+ _series.Title = title;
+ _namingConfig.StandardEpisodeFormat = "{Series TitleThe}";
+
+ Subject.BuildFileName(new List { _episode }, _series, _episodeFile)
+ .Should().Be(expected);
+ }
+
+ [TestCase("A")]
+ [TestCase("Anne")]
+ [TestCase("Theodore")]
+ [TestCase("3%")]
+ public void should_not_change_title(string title)
+ {
+ _series.Title = title;
+ _namingConfig.StandardEpisodeFormat = "{Series TitleThe}";
+
+ Subject.BuildFileName(new List { _episode }, _series, _episodeFile)
+ .Should().Be(title);
+ }
+ }
+}
diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
index 890c067b1..cd984d7b4 100644
--- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
+++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
@@ -53,7 +53,7 @@ namespace NzbDrone.Core.Organizer
public static readonly Regex AirDateRegex = new Regex(@"\{Air(\s|\W|_)Date\}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
- public static readonly Regex SeriesTitleRegex = new Regex(@"(?\{(?:Series)(?[- ._])(Clean)?Title\})",
+ public static readonly Regex SeriesTitleRegex = new Regex(@"(?\{(?:Series)(?[- ._])(Clean)?Title(The)?\})",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled);
@@ -67,6 +67,8 @@ namespace NzbDrone.Core.Organizer
private static readonly char[] EpisodeTitleTrimCharacters = new[] { ' ', '.', '?' };
+ private static readonly Regex TitlePrefixRegex = new Regex(@"^(The|An|A) (.*?)((?: *\([^)]+\))*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
public FileNameBuilder(INamingConfigService namingConfigService,
IQualityDefinitionService qualityDefinitionService,
ICacheManager cacheManager,
@@ -253,6 +255,11 @@ namespace NzbDrone.Core.Organizer
return title;
}
+ public static string TitleThe(string title)
+ {
+ return TitlePrefixRegex.Replace(title, "$2, $1$3");
+ }
+
public static string CleanFileName(string name, bool replace = true)
{
string result = name;
@@ -277,6 +284,7 @@ namespace NzbDrone.Core.Organizer
{
tokenHandlers["{Series Title}"] = m => series.Title;
tokenHandlers["{Series CleanTitle}"] = m => CleanTitle(series.Title);
+ tokenHandlers["{Series TitleThe}"] = m => TitleThe(series.Title);
}
private string AddSeasonEpisodeNumberingTokens(string pattern, Dictionary> tokenHandlers, List episodes, NamingConfig namingConfig)
diff --git a/src/NzbDrone.Core/Organizer/FileNameSampleService.cs b/src/NzbDrone.Core/Organizer/FileNameSampleService.cs
index 966061fb3..de1046485 100644
--- a/src/NzbDrone.Core/Organizer/FileNameSampleService.cs
+++ b/src/NzbDrone.Core/Organizer/FileNameSampleService.cs
@@ -41,19 +41,19 @@ namespace NzbDrone.Core.Organizer
_standardSeries = new Series
{
SeriesType = SeriesTypes.Standard,
- Title = "Series Title (2010)"
+ Title = "The Series Title (2010)"
};
_dailySeries = new Series
{
SeriesType = SeriesTypes.Daily,
- Title = "Series Title (2010)"
+ Title = "The Series Title (2010)"
};
_animeSeries = new Series
{
SeriesType = SeriesTypes.Anime,
- Title = "Series Title (2010)"
+ Title = "The Series Title (2010)"
};
_episode1 = new Episode
diff --git a/src/UI/Settings/MediaManagement/Naming/Partials/SeriesTitleNamingPartial.hbs b/src/UI/Settings/MediaManagement/Naming/Partials/SeriesTitleNamingPartial.hbs
index cc76c95b5..938055535 100644
--- a/src/UI/Settings/MediaManagement/Naming/Partials/SeriesTitleNamingPartial.hbs
+++ b/src/UI/Settings/MediaManagement/Naming/Partials/SeriesTitleNamingPartial.hbs
@@ -4,6 +4,7 @@
Series Title
Series.Title
Series_Title
+ Series Title, The
Series CleanTitle
Series.CleanTitle
Series_CleanTitle