Merge pull request #141 from Sonarr/multi-episode-range

Various naming fixes
pull/143/head
Mark McDowall 10 years ago
commit f214e5cb25

@ -82,6 +82,7 @@ namespace NzbDrone.Api.Config
var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec); var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec); var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec); var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
? "Invalid format" ? "Invalid format"
@ -99,6 +100,10 @@ namespace NzbDrone.Api.Config
? "Invalid format" ? "Invalid format"
: animeEpisodeSampleResult.FileName; : animeEpisodeSampleResult.FileName;
sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
? "Invalid format"
: animeMultiEpisodeSampleResult.FileName;
sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace() sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
? "Invalid format" ? "Invalid format"
: _filenameSampleService.GetSeriesFolderSample(nameSpec); : _filenameSampleService.GetSeriesFolderSample(nameSpec);
@ -115,26 +120,22 @@ namespace NzbDrone.Api.Config
var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec); var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec); var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec); var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult); var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult);
var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult); var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult);
var dailyEpisodeValidationResult = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult); var dailyEpisodeValidationResult = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult);
var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult);
var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult);
var validationFailures = new List<ValidationFailure>(); var validationFailures = new List<ValidationFailure>();
if (singleEpisodeValidationResult != null) validationFailures.AddIfNotNull(singleEpisodeValidationResult);
{ validationFailures.AddIfNotNull(multiEpisodeValidationResult);
validationFailures.Add(singleEpisodeValidationResult); validationFailures.AddIfNotNull(dailyEpisodeValidationResult);
} validationFailures.AddIfNotNull(animeEpisodeValidationResult);
validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
if (multiEpisodeValidationResult != null)
{
validationFailures.Add(multiEpisodeValidationResult);
}
if (dailyEpisodeValidationResult != null)
{
validationFailures.Add(dailyEpisodeValidationResult);
}
if (validationFailures.Any()) if (validationFailures.Any())
{ {

@ -6,6 +6,7 @@
public string MultiEpisodeExample { get; set; } public string MultiEpisodeExample { get; set; }
public string DailyEpisodeExample { get; set; } public string DailyEpisodeExample { get; set; }
public string AnimeEpisodeExample { get; set; } public string AnimeEpisodeExample { get; set; }
public string AnimeMultiEpisodeExample { get; set; }
public string SeriesFolderExample { get; set; } public string SeriesFolderExample { get; set; }
public string SeasonFolderExample { get; set; } public string SeasonFolderExample { get; set; }
} }

@ -20,6 +20,7 @@ namespace NzbDrone.Core.Test.OrganizerTests
private Series _series; private Series _series;
private Episode _episode1; private Episode _episode1;
private Episode _episode2; private Episode _episode2;
private Episode _episode3;
private EpisodeFile _episodeFile; private EpisodeFile _episodeFile;
private NamingConfig _namingConfig; private NamingConfig _namingConfig;
@ -53,6 +54,13 @@ namespace NzbDrone.Core.Test.OrganizerTests
.With(e => e.AbsoluteEpisodeNumber = 101) .With(e => e.AbsoluteEpisodeNumber = 101)
.Build(); .Build();
_episode3 = Builder<Episode>.CreateNew()
.With(e => e.Title = "City Sushi")
.With(e => e.SeasonNumber = 15)
.With(e => e.EpisodeNumber = 8)
.With(e => e.AbsoluteEpisodeNumber = 102)
.Build();
_episodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "DRONE" }; _episodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "DRONE" };
Mocker.GetMock<IQualityDefinitionService>() Mocker.GetMock<IQualityDefinitionService>()
@ -549,8 +557,8 @@ namespace NzbDrone.Core.Test.OrganizerTests
_namingConfig.MultiEpisodeStyle = (int)MultiEpisodeStyle.Duplicate; _namingConfig.MultiEpisodeStyle = (int)MultiEpisodeStyle.Duplicate;
_namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:000} - {Episode Title}"; _namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:000} - {Episode Title}";
Subject.BuildFileName(new List<Episode> { _episode1, _episode2 }, _series, _episodeFile) Subject.BuildFileName(new List<Episode> { _episode1, _episode2, _episode3 }, _series, _episodeFile)
.Should().Be("South Park - 100 - 101 - City Sushi"); .Should().Be("South Park - 100 - 101 - 102 - City Sushi");
} }
[Test] [Test]
@ -682,5 +690,59 @@ namespace NzbDrone.Core.Test.OrganizerTests
Subject.BuildFileName(new List<Episode> { _episode1, _episode2 }, _series, _episodeFile) Subject.BuildFileName(new List<Episode> { _episode1, _episode2 }, _series, _episodeFile)
.Should().Be("South Park - 15x06 - 15x07 - [100-101] - City Sushi - HDTV-720p"); .Should().Be("South Park - 15x06 - 15x07 - [100-101] - City Sushi - HDTV-720p");
} }
[Test]
public void should_format_range_multi_episode_properly()
{
_namingConfig.StandardEpisodeFormat = "{Series Title} - S{season:00}E{episode:00} - {Episode Title}";
_namingConfig.MultiEpisodeStyle = 4;
Subject.BuildFileName(new List<Episode> { _episode1, _episode2, _episode3 }, _series, _episodeFile)
.Should().Be("South Park - S15E06-08 - City Sushi");
}
[Test]
public void should_format_range_multi_episode_anime_properly()
{
_series.SeriesType = SeriesTypes.Anime;
_namingConfig.MultiEpisodeStyle = 4;
_namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:000} - {Episode Title}";
Subject.BuildFileName(new List<Episode> { _episode1, _episode2, _episode3 }, _series, _episodeFile)
.Should().Be("South Park - 100-102 - City Sushi");
}
[Test]
public void should_format_repeat_multi_episode_anime_properly()
{
_series.SeriesType = SeriesTypes.Anime;
_namingConfig.MultiEpisodeStyle = 2;
_namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:000} - {Episode Title}";
Subject.BuildFileName(new List<Episode> { _episode1, _episode2, _episode3 }, _series, _episodeFile)
.Should().Be("South Park - 100-101-102 - City Sushi");
}
[Test]
public void should_format_single_episode_with_range_multi_episode_properly()
{
_namingConfig.StandardEpisodeFormat = "{Series Title} - S{season:00}E{episode:00} - {Episode Title}";
_namingConfig.MultiEpisodeStyle = 4;
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
.Should().Be("South Park - S15E06 - City Sushi");
}
[Test]
public void should_format_single_anime_episode_with_range_multi_episode_properly()
{
_series.SeriesType = SeriesTypes.Anime;
_namingConfig.MultiEpisodeStyle = 4;
_namingConfig.AnimeEpisodeFormat = "{Series Title} - {absolute:000} - {Episode Title}";
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
.Should().Be("South Park - 100 - City Sushi");
}
} }
} }

@ -97,6 +97,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("[ANBU-AonE]_Naruto_26-27_[F224EF26].avi", "Naruto", new[] { 26, 27 })] [TestCase("[ANBU-AonE]_Naruto_26-27_[F224EF26].avi", "Naruto", new[] { 26, 27 })]
[TestCase("[Doutei] Recently, My Sister is Unusual - 01-12 [BD][720p-AAC]", "Recently, My Sister is Unusual", new [] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 })] [TestCase("[Doutei] Recently, My Sister is Unusual - 01-12 [BD][720p-AAC]", "Recently, My Sister is Unusual", new [] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 })]
[TestCase("Series Title (2010) - 01-02-03 - Episode Title (1) HDTV-720p", "Series Title (2010)", new [] { 1, 2, 3 })]
public void should_parse_multi_episode_absolute_numbers(string postTitle, string title, int[] absoluteEpisodeNumbers) public void should_parse_multi_episode_absolute_numbers(string postTitle, string title, int[] absoluteEpisodeNumbers)
{ {
var result = Parser.Parser.ParseTitle(postTitle); var result = Parser.Parser.ParseTitle(postTitle);

@ -280,31 +280,40 @@ namespace NzbDrone.Core.Organizer
foreach (var episodeFormat in episodeFormats) foreach (var episodeFormat in episodeFormats)
{ {
var seasonEpisodePattern = episodeFormat.SeasonEpisodePattern; var seasonEpisodePattern = episodeFormat.SeasonEpisodePattern;
string formatPattern;
foreach (var episode in episodes.Skip(1))
{
switch ((MultiEpisodeStyle)namingConfig.MultiEpisodeStyle) switch ((MultiEpisodeStyle)namingConfig.MultiEpisodeStyle)
{ {
case MultiEpisodeStyle.Duplicate: case MultiEpisodeStyle.Duplicate:
seasonEpisodePattern += episodeFormat.Separator + episodeFormat.SeasonEpisodePattern; formatPattern = episodeFormat.Separator + episodeFormat.SeasonEpisodePattern;
seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes);
break; break;
case MultiEpisodeStyle.Repeat: case MultiEpisodeStyle.Repeat:
seasonEpisodePattern += episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; formatPattern = episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern;
seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes);
break; break;
case MultiEpisodeStyle.Scene: case MultiEpisodeStyle.Scene:
seasonEpisodePattern += "-" + episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; formatPattern = "-" + episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern;
seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes);
break;
case MultiEpisodeStyle.Range:
formatPattern = "-" + episodeFormat.EpisodePattern;
var eps = new List<Episode> { episodes.First() };
if (episodes.Count > 1) eps.Add(episodes.Last());
seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, eps);
break; break;
//MultiEpisodeStyle.Extend //MultiEpisodeStyle.Extend
default: default:
seasonEpisodePattern += "-" + episodeFormat.EpisodePattern; formatPattern = "-" + episodeFormat.EpisodePattern;
seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes);
break; break;
} }
}
seasonEpisodePattern = ReplaceNumberTokens(seasonEpisodePattern, episodes);
var token = String.Format("{{Season Episode{0}}}", index++); var token = String.Format("{{Season Episode{0}}}", index++);
pattern = pattern.Replace(episodeFormat.SeasonEpisodePattern, token); pattern = pattern.Replace(episodeFormat.SeasonEpisodePattern, token);
@ -339,33 +348,43 @@ namespace NzbDrone.Core.Organizer
} }
var absoluteEpisodePattern = absoluteEpisodeFormat.AbsoluteEpisodePattern; var absoluteEpisodePattern = absoluteEpisodeFormat.AbsoluteEpisodePattern;
string formatPattern;
foreach (var episode in episodes.Skip(1)) switch ((MultiEpisodeStyle) namingConfig.MultiEpisodeStyle)
{
switch ((MultiEpisodeStyle)namingConfig.MultiEpisodeStyle)
{ {
case MultiEpisodeStyle.Duplicate: case MultiEpisodeStyle.Duplicate:
absoluteEpisodePattern += absoluteEpisodeFormat.Separator + formatPattern = absoluteEpisodeFormat.Separator + absoluteEpisodeFormat.AbsoluteEpisodePattern;
absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes);
break; break;
case MultiEpisodeStyle.Repeat: case MultiEpisodeStyle.Repeat:
absoluteEpisodePattern += absoluteEpisodeFormat.Separator + var repeatSeparator = absoluteEpisodeFormat.Separator.Trim().IsNullOrWhiteSpace() ? " " : absoluteEpisodeFormat.Separator.Trim();
absoluteEpisodeFormat.AbsoluteEpisodePattern;
formatPattern = repeatSeparator + absoluteEpisodeFormat.AbsoluteEpisodePattern;
absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes);
break; break;
case MultiEpisodeStyle.Scene: case MultiEpisodeStyle.Scene:
absoluteEpisodePattern += "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern;
absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes);
break;
case MultiEpisodeStyle.Range:
formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern;
var eps = new List<Episode> {episodes.First()};
if (episodes.Count > 1) eps.Add(episodes.Last());
absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, eps);
break; break;
//MultiEpisodeStyle.Extend //MultiEpisodeStyle.Extend
default: default:
absoluteEpisodePattern += "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern;
absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes);
break; break;
} }
}
absoluteEpisodePattern = ReplaceAbsoluteNumberTokens(absoluteEpisodePattern, episodes);
var token = String.Format("{{Absolute Pattern{0}}}", index++); var token = String.Format("{{Absolute Pattern{0}}}", index++);
pattern = pattern.Replace(absoluteEpisodeFormat.AbsoluteEpisodePattern, token); pattern = pattern.Replace(absoluteEpisodeFormat.AbsoluteEpisodePattern, token);
@ -554,31 +573,30 @@ namespace NzbDrone.Core.Organizer
return replacementText; return replacementText;
} }
private string ReplaceNumberTokens(string pattern, List<Episode> episodes) private string FormatNumberTokens(string basePattern, string formatPattern, List<Episode> episodes)
{ {
var episodeIndex = 0; var pattern = String.Empty;
pattern = EpisodeRegex.Replace(pattern, match =>
for (int i = 0; i < episodes.Count; i++)
{ {
var episode = episodes[episodeIndex]; var patternToReplace = i == 0 ? basePattern : formatPattern;
episodeIndex++;
return ReplaceNumberToken(match.Groups["episode"].Value, episode.EpisodeNumber); pattern += EpisodeRegex.Replace(patternToReplace, match => ReplaceNumberToken(match.Groups["episode"].Value, episodes[i].EpisodeNumber));
}); }
return ReplaceSeasonTokens(pattern, episodes.First().SeasonNumber); return ReplaceSeasonTokens(pattern, episodes.First().SeasonNumber);
} }
private string ReplaceAbsoluteNumberTokens(string pattern, List<Episode> episodes) private string FormatAbsoluteNumberTokens(string basePattern, string formatPattern, List<Episode> episodes)
{ {
var episodeIndex = 0; var pattern = String.Empty;
pattern = AbsoluteEpisodeRegex.Replace(pattern, match =>
for (int i = 0; i < episodes.Count; i++)
{ {
var episode = episodes[episodeIndex]; var patternToReplace = i == 0 ? basePattern : formatPattern;
episodeIndex++;
//TODO: We need to handle this null check somewhere, I think earlier is better... pattern += AbsoluteEpisodeRegex.Replace(patternToReplace, match => ReplaceNumberToken(match.Groups["absolute"].Value, episodes[i].AbsoluteEpisodeNumber.Value));
return ReplaceNumberToken(match.Groups["absolute"].Value, episode.AbsoluteEpisodeNumber.Value); }
});
return ReplaceSeasonTokens(pattern, episodes.First().SeasonNumber); return ReplaceSeasonTokens(pattern, episodes.First().SeasonNumber);
} }
@ -684,6 +702,7 @@ namespace NzbDrone.Core.Organizer
Extend = 0, Extend = 0,
Duplicate = 1, Duplicate = 1,
Repeat = 2, Repeat = 2,
Scene = 3 Scene = 3,
Range = 4
} }
} }

@ -13,6 +13,7 @@ namespace NzbDrone.Core.Organizer
SampleResult GetMultiEpisodeSample(NamingConfig nameSpec); SampleResult GetMultiEpisodeSample(NamingConfig nameSpec);
SampleResult GetDailySample(NamingConfig nameSpec); SampleResult GetDailySample(NamingConfig nameSpec);
SampleResult GetAnimeSample(NamingConfig nameSpec); SampleResult GetAnimeSample(NamingConfig nameSpec);
SampleResult GetAnimeMultiEpisodeSample(NamingConfig nameSpec);
String GetSeriesFolderSample(NamingConfig nameSpec); String GetSeriesFolderSample(NamingConfig nameSpec);
String GetSeasonFolderSample(NamingConfig nameSpec); String GetSeasonFolderSample(NamingConfig nameSpec);
} }
@ -25,12 +26,14 @@ namespace NzbDrone.Core.Organizer
private static Series _animeSeries; private static Series _animeSeries;
private static Episode _episode1; private static Episode _episode1;
private static Episode _episode2; private static Episode _episode2;
private static Episode _episode3;
private static List<Episode> _singleEpisode; private static List<Episode> _singleEpisode;
private static List<Episode> _multiEpisodes; private static List<Episode> _multiEpisodes;
private static EpisodeFile _singleEpisodeFile; private static EpisodeFile _singleEpisodeFile;
private static EpisodeFile _multiEpisodeFile; private static EpisodeFile _multiEpisodeFile;
private static EpisodeFile _dailyEpisodeFile; private static EpisodeFile _dailyEpisodeFile;
private static EpisodeFile _animeEpisodeFile; private static EpisodeFile _animeEpisodeFile;
private static EpisodeFile _animeMultiEpisodeFile;
public FileNameSampleService(IBuildFileNames buildFileNames) public FileNameSampleService(IBuildFileNames buildFileNames)
{ {
@ -71,8 +74,16 @@ namespace NzbDrone.Core.Organizer
AbsoluteEpisodeNumber = 2 AbsoluteEpisodeNumber = 2
}; };
_episode3 = new Episode
{
SeasonNumber = 1,
EpisodeNumber = 3,
Title = "Episode Title (3)",
AbsoluteEpisodeNumber = 3
};
_singleEpisode = new List<Episode> { _episode1 }; _singleEpisode = new List<Episode> { _episode1 };
_multiEpisodes = new List<Episode> { _episode1, _episode2 }; _multiEpisodes = new List<Episode> { _episode1, _episode2, _episode3 };
var mediaInfo = new MediaInfoModel() var mediaInfo = new MediaInfoModel()
{ {
@ -102,8 +113,8 @@ namespace NzbDrone.Core.Organizer
_multiEpisodeFile = new EpisodeFile _multiEpisodeFile = new EpisodeFile
{ {
Quality = new QualityModel(Quality.HDTV720p), Quality = new QualityModel(Quality.HDTV720p),
RelativePath = "Series.Title.S01E01-E02.720p.HDTV.x264-EVOLVE.mkv", RelativePath = "Series.Title.S01E01-E03.720p.HDTV.x264-EVOLVE.mkv",
SceneName = "Series.Title.S01E01-E02.720p.HDTV.x264-EVOLVE", SceneName = "Series.Title.S01E01-E03.720p.HDTV.x264-EVOLVE",
ReleaseGroup = "RlsGrp", ReleaseGroup = "RlsGrp",
MediaInfo = mediaInfo, MediaInfo = mediaInfo,
}; };
@ -120,8 +131,17 @@ namespace NzbDrone.Core.Organizer
_animeEpisodeFile = new EpisodeFile _animeEpisodeFile = new EpisodeFile
{ {
Quality = new QualityModel(Quality.HDTV720p), Quality = new QualityModel(Quality.HDTV720p),
RelativePath = "Series.Title.001.HDTV.x264-EVOLVE.mkv", RelativePath = "[RlsGroup] Series Title - 001 [720p].mkv",
SceneName = "Series.Title.001.HDTV.x264-EVOLVE", SceneName = "[RlsGroup] Series Title - 001 [720p]",
ReleaseGroup = "RlsGrp",
MediaInfo = mediaInfoAnime
};
_animeMultiEpisodeFile = new EpisodeFile
{
Quality = new QualityModel(Quality.HDTV720p),
RelativePath = "[RlsGroup] Series Title - 001 - 103 [720p].mkv",
SceneName = "[RlsGroup] Series Title - 001 - 103 [720p]",
ReleaseGroup = "RlsGrp", ReleaseGroup = "RlsGrp",
MediaInfo = mediaInfoAnime MediaInfo = mediaInfoAnime
}; };
@ -179,6 +199,19 @@ namespace NzbDrone.Core.Organizer
return result; return result;
} }
public SampleResult GetAnimeMultiEpisodeSample(NamingConfig nameSpec)
{
var result = new SampleResult
{
FileName = BuildSample(_multiEpisodes, _animeSeries, _animeMultiEpisodeFile, nameSpec),
Series = _animeSeries,
Episodes = _multiEpisodes,
EpisodeFile = _animeMultiEpisodeFile
};
return result;
}
public string GetSeriesFolderSample(NamingConfig nameSpec) public string GetSeriesFolderSample(NamingConfig nameSpec)
{ {
return _buildFileNames.GetSeriesFolder(_standardSeries, nameSpec); return _buildFileNames.GetSeriesFolder(_standardSeries, nameSpec);

@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentValidation.Results; using FluentValidation.Results;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;

@ -87,7 +87,7 @@ namespace NzbDrone.Core.Parser
RegexOptions.IgnoreCase | RegexOptions.Compiled), RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Episodes with airdate //Episodes with airdate
new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})\W+(?<airmonth>[0-1][0-9])\W+(?<airday>[0-3][0-9])", new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})\W+(?<airmonth>[0-1][0-9])\W+(?<airday>[0-3][0-9])(?!\W+[0-3][0-9])",
RegexOptions.IgnoreCase | RegexOptions.Compiled), RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Supports 1103/1113 naming //Supports 1103/1113 naming

@ -14,11 +14,12 @@ define(
ui: { ui: {
namingOptions : '.x-naming-options', namingOptions : '.x-naming-options',
renameEpisodesCheckbox: '.x-rename-episodes', renameEpisodesCheckbox : '.x-rename-episodes',
singleEpisodeExample : '.x-single-episode-example', singleEpisodeExample : '.x-single-episode-example',
multiEpisodeExample : '.x-multi-episode-example', multiEpisodeExample : '.x-multi-episode-example',
dailyEpisodeExample : '.x-daily-episode-example', dailyEpisodeExample : '.x-daily-episode-example',
animeEpisodeExample : '.x-anime-episode-example', animeEpisodeExample : '.x-anime-episode-example',
animeMultiEpisodeExample : '.x-anime-multi-episode-example',
namingTokenHelper : '.x-naming-token-helper', namingTokenHelper : '.x-naming-token-helper',
multiEpisodeStyle : '.x-multi-episode-style', multiEpisodeStyle : '.x-multi-episode-style',
seriesFolderExample : '.x-series-folder-example', seriesFolderExample : '.x-series-folder-example',
@ -70,6 +71,7 @@ define(
this.ui.multiEpisodeExample.html(this.namingSampleModel.get('multiEpisodeExample')); this.ui.multiEpisodeExample.html(this.namingSampleModel.get('multiEpisodeExample'));
this.ui.dailyEpisodeExample.html(this.namingSampleModel.get('dailyEpisodeExample')); this.ui.dailyEpisodeExample.html(this.namingSampleModel.get('dailyEpisodeExample'));
this.ui.animeEpisodeExample.html(this.namingSampleModel.get('animeEpisodeExample')); this.ui.animeEpisodeExample.html(this.namingSampleModel.get('animeEpisodeExample'));
this.ui.animeMultiEpisodeExample.html(this.namingSampleModel.get('animeMultiEpisodeExample'));
this.ui.seriesFolderExample.html(this.namingSampleModel.get('seriesFolderExample')); this.ui.seriesFolderExample.html(this.namingSampleModel.get('seriesFolderExample'));
this.ui.seasonFolderExample.html(this.namingSampleModel.get('seasonFolderExample')); this.ui.seasonFolderExample.html(this.namingSampleModel.get('seasonFolderExample'));
}, },

@ -175,6 +175,7 @@
<option value="1">Duplicate</option> <option value="1">Duplicate</option>
<option value="2">Repeat</option> <option value="2">Repeat</option>
<option value="3">Scene</option> <option value="3">Scene</option>
<option value="4">Range</option>
</select> </select>
</div> </div>
</div> </div>
@ -212,6 +213,14 @@
</div> </div>
</div> </div>
<div class="form-group">
<label class="col-sm-3 control-label">Anime Multi-Episode Example</label>
<div class="col-sm-8">
<p class="form-control-static x-anime-multi-episode-example naming-example"></p>
</div>
</div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label">Series Folder Example</label> <label class="col-sm-3 control-label">Series Folder Example</label>

Loading…
Cancel
Save