Fixed: Not including Original Title/Filename during rename when episode identifiers are missing
Closes #5003
This commit is contained in:
parent
f6664b8b42
commit
9a1a320110
|
@ -79,13 +79,71 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void should_include_current_filename_if_not_including_multiple_naming_tokens()
|
||||
public void should_include_current_filename_if_not_including_season_and_episode_tokens_for_standard_series()
|
||||
{
|
||||
_episodeFile.RelativePath = "My Series - S15E06 - City Sushi";
|
||||
_namingConfig.StandardEpisodeFormat = "{Original Title}";
|
||||
_namingConfig.StandardEpisodeFormat = "{Original Title} {Quality Title}";
|
||||
|
||||
Subject.BuildFileName(new List<Episode> { _episode }, _series, _episodeFile)
|
||||
.Should().Be("My Series - S15E06 - City Sushi");
|
||||
.Should().Be("My Series - S15E06 - City Sushi HDTV-720p");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_include_current_filename_if_not_including_air_date_token_for_daily_series()
|
||||
{
|
||||
_series.SeriesType = SeriesTypes.Daily;
|
||||
_episode.AirDate = "2022-04-28";
|
||||
_episodeFile.RelativePath = "My Series - 2022-04-28 - City Sushi";
|
||||
_namingConfig.DailyEpisodeFormat = "{Original Title} {Quality Title}";
|
||||
|
||||
Subject.BuildFileName(new List<Episode> { _episode }, _series, _episodeFile)
|
||||
.Should().Be("My Series - 2022-04-28 - City Sushi HDTV-720p");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_include_current_filename_if_not_including_absolute_episode_number_token_for_anime_series()
|
||||
{
|
||||
_series.SeriesType = SeriesTypes.Anime;
|
||||
_episode.AbsoluteEpisodeNumber = 123;
|
||||
_episodeFile.RelativePath = "My Series - 123 - City Sushi";
|
||||
_namingConfig.AnimeEpisodeFormat = "{Original Title} {Quality Title}";
|
||||
|
||||
Subject.BuildFileName(new List<Episode> { _episode }, _series, _episodeFile)
|
||||
.Should().Be("My Series - 123 - City Sushi HDTV-720p");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_include_current_filename_if_including_season_and_episode_tokens_for_standard_series()
|
||||
{
|
||||
_episodeFile.RelativePath = "My Series - S15E06 - City Sushi";
|
||||
_namingConfig.StandardEpisodeFormat = "{Series Title} - S{season:00}E{episode:00} {[Original Title]}";
|
||||
|
||||
Subject.BuildFileName(new List<Episode> { _episode }, _series, _episodeFile)
|
||||
.Should().Be("My Series - S15E06");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_include_current_filename_if_including_air_date_token_for_daily_series()
|
||||
{
|
||||
_series.SeriesType = SeriesTypes.Daily;
|
||||
_episode.AirDate = "2022-04-28";
|
||||
_episodeFile.RelativePath = "My Series - 2022-04-28 - City Sushi";
|
||||
_namingConfig.DailyEpisodeFormat = "{Series Title} - {Air-Date} {[Original Title]}";
|
||||
|
||||
Subject.BuildFileName(new List<Episode> { _episode }, _series, _episodeFile)
|
||||
.Should().Be("My Series - 2022-04-28");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_include_current_filename_if_including_absolute_episode_number_token_for_anime_series()
|
||||
{
|
||||
_series.SeriesType = SeriesTypes.Anime;
|
||||
_episode.AbsoluteEpisodeNumber = 123;
|
||||
_episodeFile.RelativePath = "My Series - 123 - City Sushi";
|
||||
_namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:00} {[Original Title]}";
|
||||
|
||||
Subject.BuildFileName(new List<Episode> { _episode }, _series, _episodeFile)
|
||||
.Should().Be("My Series - 123");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace NzbDrone.Core.Organizer
|
|||
private readonly ICached<AbsoluteEpisodeFormat[]> _absoluteEpisodeFormatCache;
|
||||
private readonly ICached<bool> _requiresEpisodeTitleCache;
|
||||
private readonly ICached<bool> _requiresAbsoluteEpisodeNumberCache;
|
||||
private readonly ICached<bool> _patternHasEpisodeIdentifierCache;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private static readonly Regex TitleRegex = new Regex(@"(?<escaped>\{\{|\}\})|\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9+-]+(?<!-)))?(?<suffix>[- ._)\]]*)\}",
|
||||
|
@ -97,6 +98,7 @@ namespace NzbDrone.Core.Organizer
|
|||
_absoluteEpisodeFormatCache = cacheManager.GetCache<AbsoluteEpisodeFormat[]>(GetType(), "absoluteEpisodeFormat");
|
||||
_requiresEpisodeTitleCache = cacheManager.GetCache<bool>(GetType(), "requiresEpisodeTitle");
|
||||
_requiresAbsoluteEpisodeNumberCache = cacheManager.GetCache<bool>(GetType(), "requiresAbsoluteEpisodeNumber");
|
||||
_patternHasEpisodeIdentifierCache = cacheManager.GetCache<bool>(GetType(), "patternHasEpisodeIdentifier");
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -109,7 +111,7 @@ namespace NzbDrone.Core.Organizer
|
|||
|
||||
if (!namingConfig.RenameEpisodes)
|
||||
{
|
||||
return GetOriginalTitle(episodeFile, false) + extension;
|
||||
return GetOriginalTitle(episodeFile, true) + extension;
|
||||
}
|
||||
|
||||
if (namingConfig.StandardEpisodeFormat.IsNullOrWhiteSpace() && series.SeriesType == SeriesTypes.Standard)
|
||||
|
@ -148,7 +150,7 @@ namespace NzbDrone.Core.Organizer
|
|||
{
|
||||
var splitPattern = splitPatterns[i];
|
||||
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
||||
var multipleTokens = TitleRegex.Matches(splitPattern).Count > 1;
|
||||
var patternHasEpisodeIdentifier = GetPatternHasEpisodeIdentifier(splitPattern);
|
||||
|
||||
splitPattern = AddSeasonEpisodeNumberingTokens(splitPattern, tokenHandlers, episodes, namingConfig);
|
||||
splitPattern = AddAbsoluteNumberingTokens(splitPattern, tokenHandlers, series, episodes, namingConfig);
|
||||
|
@ -159,7 +161,7 @@ namespace NzbDrone.Core.Organizer
|
|||
AddIdTokens(tokenHandlers, series);
|
||||
AddEpisodeTokens(tokenHandlers, episodes);
|
||||
AddEpisodeTitlePlaceholderTokens(tokenHandlers);
|
||||
AddEpisodeFileTokens(tokenHandlers, episodeFile, multipleTokens);
|
||||
AddEpisodeFileTokens(tokenHandlers, episodeFile, !patternHasEpisodeIdentifier);
|
||||
AddQualityTokens(tokenHandlers, series, episodeFile);
|
||||
AddMediaInfoTokens(tokenHandlers, episodeFile);
|
||||
AddPreferredWords(tokenHandlers, series, episodeFile, preferredWords);
|
||||
|
@ -585,10 +587,10 @@ namespace NzbDrone.Core.Organizer
|
|||
tokenHandlers["{Episode CleanTitle}"] = m => GetEpisodeTitle(GetEpisodeTitles(episodes).Select(CleanTitle).ToList(), "and", maxLength);
|
||||
}
|
||||
|
||||
private void AddEpisodeFileTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, EpisodeFile episodeFile, bool multipleTokens)
|
||||
private void AddEpisodeFileTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, EpisodeFile episodeFile, bool useCurrentFilenameAsFallback)
|
||||
{
|
||||
tokenHandlers["{Original Title}"] = m => GetOriginalTitle(episodeFile, multipleTokens);
|
||||
tokenHandlers["{Original Filename}"] = m => GetOriginalFileName(episodeFile, multipleTokens);
|
||||
tokenHandlers["{Original Title}"] = m => GetOriginalTitle(episodeFile, useCurrentFilenameAsFallback);
|
||||
tokenHandlers["{Original Filename}"] = m => GetOriginalFileName(episodeFile, useCurrentFilenameAsFallback);
|
||||
tokenHandlers["{Release Group}"] = m => episodeFile.ReleaseGroup ?? m.DefaultValue("Sonarr");
|
||||
}
|
||||
|
||||
|
@ -931,7 +933,7 @@ namespace NzbDrone.Core.Organizer
|
|||
|
||||
private AbsoluteEpisodeFormat[] GetAbsoluteFormat(string pattern)
|
||||
{
|
||||
return _absoluteEpisodeFormatCache.Get(pattern, () => AbsoluteEpisodePatternRegex.Matches(pattern).OfType<Match>()
|
||||
return _absoluteEpisodeFormatCache.Get(pattern, () => AbsoluteEpisodePatternRegex.Matches(pattern).OfType<Match>()
|
||||
.Select(match => new AbsoluteEpisodeFormat
|
||||
{
|
||||
Separator = match.Groups["separator"].Value.IsNotNullOrWhiteSpace() ? match.Groups["separator"].Value : "-",
|
||||
|
@ -939,6 +941,29 @@ namespace NzbDrone.Core.Organizer
|
|||
}).ToArray());
|
||||
}
|
||||
|
||||
private bool GetPatternHasEpisodeIdentifier(string pattern)
|
||||
{
|
||||
return _patternHasEpisodeIdentifierCache.Get(pattern, () =>
|
||||
{
|
||||
if (SeasonEpisodePatternRegex.IsMatch(pattern))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (AbsoluteEpisodePatternRegex.IsMatch(pattern))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (AirDateRegex.IsMatch(pattern))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private List<string> GetEpisodeTitles(List<Episode> episodes)
|
||||
{
|
||||
if (episodes.Count == 1)
|
||||
|
@ -1032,19 +1057,19 @@ namespace NzbDrone.Core.Organizer
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
private string GetOriginalTitle(EpisodeFile episodeFile, bool multipleTokens)
|
||||
private string GetOriginalTitle(EpisodeFile episodeFile, bool useCurrentFilenameAsFallback)
|
||||
{
|
||||
if (episodeFile.SceneName.IsNullOrWhiteSpace())
|
||||
{
|
||||
return GetOriginalFileName(episodeFile, multipleTokens);
|
||||
return GetOriginalFileName(episodeFile, useCurrentFilenameAsFallback);
|
||||
}
|
||||
|
||||
return episodeFile.SceneName;
|
||||
}
|
||||
|
||||
private string GetOriginalFileName(EpisodeFile episodeFile, bool multipleTokens)
|
||||
private string GetOriginalFileName(EpisodeFile episodeFile, bool useCurrentFilenameAsFallback)
|
||||
{
|
||||
if (multipleTokens)
|
||||
if (!useCurrentFilenameAsFallback)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue