mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-22 22:43:31 -07:00
1st pass at Movie Naming
Parser is failing on the sample
This commit is contained in:
parent
721767331b
commit
05e4af9ae7
9 changed files with 289 additions and 89 deletions
|
@ -81,39 +81,50 @@ namespace NzbDrone.Api.Config
|
||||||
var nameSpec = config.ToModel();
|
var nameSpec = config.ToModel();
|
||||||
var sampleResource = new NamingSampleResource();
|
var sampleResource = new NamingSampleResource();
|
||||||
|
|
||||||
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 animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
||||||
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
//var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
||||||
|
|
||||||
sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
|
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
|
||||||
? "Invalid format"
|
|
||||||
: singleEpisodeSampleResult.FileName;
|
|
||||||
|
|
||||||
sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
|
|
||||||
? "Invalid format"
|
|
||||||
: multiEpisodeSampleResult.FileName;
|
|
||||||
|
|
||||||
sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
|
//sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: dailyEpisodeSampleResult.FileName;
|
// : singleEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
|
//sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: animeEpisodeSampleResult.FileName;
|
// : multiEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
|
//sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: animeMultiEpisodeSampleResult.FileName;
|
// : dailyEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
|
//sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
|
||||||
? "Invalid format"
|
// ? "Invalid format"
|
||||||
: _filenameSampleService.GetSeriesFolderSample(nameSpec);
|
// : animeEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
|
//sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
|
||||||
|
// ? "Invalid format"
|
||||||
|
// : animeMultiEpisodeSampleResult.FileName;
|
||||||
|
|
||||||
|
sampleResource.MovieExample = _filenameValidationService.ValidateMovieFilename(movieSampleResult) != null
|
||||||
|
? "Invalid Format"
|
||||||
|
: movieSampleResult.FileName;
|
||||||
|
|
||||||
|
//sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
|
||||||
|
// ? "Invalid format"
|
||||||
|
// : _filenameSampleService.GetSeriesFolderSample(nameSpec);
|
||||||
|
|
||||||
|
//sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
|
||||||
|
// ? "Invalid format"
|
||||||
|
// : _filenameSampleService.GetSeasonFolderSample(nameSpec);
|
||||||
|
|
||||||
|
sampleResource.MovieFolderExample = nameSpec.MovieFolderFormat.IsNullOrWhiteSpace()
|
||||||
? "Invalid format"
|
? "Invalid format"
|
||||||
: _filenameSampleService.GetSeasonFolderSample(nameSpec);
|
: _filenameSampleService.GetMovieFolderSample(nameSpec);
|
||||||
|
|
||||||
return sampleResource.AsResponse();
|
return sampleResource.AsResponse();
|
||||||
}
|
}
|
||||||
|
@ -126,7 +137,7 @@ namespace NzbDrone.Api.Config
|
||||||
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
||||||
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
||||||
|
|
||||||
//var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
|
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
|
||||||
|
|
||||||
var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult);
|
var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult);
|
||||||
var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult);
|
var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult);
|
||||||
|
@ -134,7 +145,7 @@ namespace NzbDrone.Api.Config
|
||||||
var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult);
|
var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult);
|
||||||
var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult);
|
var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult);
|
||||||
|
|
||||||
//var standardMovieValidationResult = _filenameValidationService.ValidateStandardMovieFilename(movieSampleResult);
|
var standardMovieValidationResult = _filenameValidationService.ValidateMovieFilename(movieSampleResult);
|
||||||
|
|
||||||
var validationFailures = new List<ValidationFailure>();
|
var validationFailures = new List<ValidationFailure>();
|
||||||
|
|
||||||
|
@ -144,7 +155,7 @@ namespace NzbDrone.Api.Config
|
||||||
validationFailures.AddIfNotNull(animeEpisodeValidationResult);
|
validationFailures.AddIfNotNull(animeEpisodeValidationResult);
|
||||||
validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
|
validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
|
||||||
|
|
||||||
//validationFailures.AddIfNotNull(standardMovieValidationResult);
|
validationFailures.AddIfNotNull(standardMovieValidationResult);
|
||||||
|
|
||||||
if (validationFailures.Any())
|
if (validationFailures.Any())
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,12 +68,12 @@ namespace NzbDrone.Api.Config
|
||||||
|
|
||||||
RenameEpisodes = resource.RenameEpisodes,
|
RenameEpisodes = resource.RenameEpisodes,
|
||||||
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
||||||
MultiEpisodeStyle = resource.MultiEpisodeStyle,
|
//MultiEpisodeStyle = resource.MultiEpisodeStyle,
|
||||||
StandardEpisodeFormat = resource.StandardEpisodeFormat,
|
//StandardEpisodeFormat = resource.StandardEpisodeFormat,
|
||||||
DailyEpisodeFormat = resource.DailyEpisodeFormat,
|
//DailyEpisodeFormat = resource.DailyEpisodeFormat,
|
||||||
AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
|
//AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
|
||||||
SeriesFolderFormat = resource.SeriesFolderFormat,
|
//SeriesFolderFormat = resource.SeriesFolderFormat,
|
||||||
SeasonFolderFormat = resource.SeasonFolderFormat,
|
//SeasonFolderFormat = resource.SeasonFolderFormat,
|
||||||
StandardMovieFormat = resource.StandardMovieFormat,
|
StandardMovieFormat = resource.StandardMovieFormat,
|
||||||
MovieFolderFormat = resource.MovieFolderFormat
|
MovieFolderFormat = resource.MovieFolderFormat
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
|
||||||
// Output Settings
|
// Output Settings
|
||||||
var movieTitlePattern = "";
|
var movieTitlePattern = "";
|
||||||
var movieYearPattern = "({Release Year})";
|
//var movieYearPattern = "({Release Year})";
|
||||||
var qualityFormat = " [{Quality Title}]";
|
var qualityFormat = " [{Quality Title}]";
|
||||||
|
|
||||||
if (replaceSpaces)
|
if (replaceSpaces)
|
||||||
|
@ -55,11 +55,10 @@ namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
|
||||||
movieTitlePattern += separator;
|
movieTitlePattern += separator;
|
||||||
|
|
||||||
var standardMovieFormat = string.Format("{0}{1}{2}", movieTitlePattern,
|
var standardMovieFormat = string.Format("{0}{1}", movieTitlePattern,
|
||||||
movieYearPattern,
|
|
||||||
qualityFormat);
|
qualityFormat);
|
||||||
|
|
||||||
var movieFolderFormat = string.Format("{0}{1}", movieTitlePattern, movieYearPattern);
|
var movieFolderFormat = string.Format("{0}", movieTitlePattern);
|
||||||
|
|
||||||
if (includeQuality)
|
if (includeQuality)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
||||||
string GetSeriesFolder(Series series, NamingConfig namingConfig = null);
|
string GetSeriesFolder(Series series, NamingConfig namingConfig = null);
|
||||||
string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null);
|
string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null);
|
||||||
string GetMovieFolder(Movie movie);
|
string GetMovieFolder(Movie movie, NamingConfig namingConfig = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileNameBuilder : IBuildFileNames
|
public class FileNameBuilder : IBuildFileNames
|
||||||
|
@ -79,6 +79,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
{
|
{
|
||||||
_namingConfigService = namingConfigService;
|
_namingConfigService = namingConfigService;
|
||||||
_qualityDefinitionService = qualityDefinitionService;
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
|
//_movieFormatCache = cacheManager.GetCache<MovieFormat>(GetType(), "movieFormat");
|
||||||
_episodeFormatCache = cacheManager.GetCache<EpisodeFormat[]>(GetType(), "episodeFormat");
|
_episodeFormatCache = cacheManager.GetCache<EpisodeFormat[]>(GetType(), "episodeFormat");
|
||||||
_absoluteEpisodeFormatCache = cacheManager.GetCache<AbsoluteEpisodeFormat[]>(GetType(), "absoluteEpisodeFormat");
|
_absoluteEpisodeFormatCache = cacheManager.GetCache<AbsoluteEpisodeFormat[]>(GetType(), "absoluteEpisodeFormat");
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -154,52 +155,20 @@ namespace NzbDrone.Core.Organizer
|
||||||
return GetOriginalTitle(movieFile);
|
return GetOriginalTitle(movieFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (namingConfig.StandardEpisodeFormat.IsNullOrWhiteSpace() && series.SeriesType == SeriesTypes.Standard)
|
//TODO: Update namingConfig for Movies!
|
||||||
{
|
var pattern = namingConfig.StandardMovieFormat;
|
||||||
throw new NamingFormatException("Standard episode format cannot be empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namingConfig.DailyEpisodeFormat.IsNullOrWhiteSpace() && series.SeriesType == SeriesTypes.Daily)
|
|
||||||
{
|
|
||||||
throw new NamingFormatException("Daily episode format cannot be empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namingConfig.AnimeEpisodeFormat.IsNullOrWhiteSpace() && series.SeriesType == SeriesTypes.Anime)
|
|
||||||
{
|
|
||||||
throw new NamingFormatException("Anime episode format cannot be empty");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*var pattern = namingConfig.StandardEpisodeFormat;
|
|
||||||
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
||||||
|
|
||||||
episodes = episodes.OrderBy(e => e.SeasonNumber).ThenBy(e => e.EpisodeNumber).ToList();
|
AddMovieTokens(tokenHandlers, movie);
|
||||||
|
//AddReleaseDateTokens(tokenHandlers, movie.Year); //In case we want to separate the year
|
||||||
if (series.SeriesType == SeriesTypes.Daily)
|
AddQualityTokens(tokenHandlers, movie, movieFile);
|
||||||
{
|
AddMediaInfoTokens(tokenHandlers, movieFile);
|
||||||
pattern = namingConfig.DailyEpisodeFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (series.SeriesType == SeriesTypes.Anime && episodes.All(e => e.AbsoluteEpisodeNumber.HasValue))
|
|
||||||
{
|
|
||||||
pattern = namingConfig.AnimeEpisodeFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern = AddSeasonEpisodeNumberingTokens(pattern, tokenHandlers, episodes, namingConfig);
|
|
||||||
pattern = AddAbsoluteNumberingTokens(pattern, tokenHandlers, series, episodes, namingConfig);
|
|
||||||
|
|
||||||
AddSeriesTokens(tokenHandlers, series);
|
|
||||||
AddEpisodeTokens(tokenHandlers, episodes);
|
|
||||||
AddEpisodeFileTokens(tokenHandlers, episodeFile);
|
|
||||||
AddQualityTokens(tokenHandlers, series, episodeFile);
|
|
||||||
AddMediaInfoTokens(tokenHandlers, episodeFile);
|
|
||||||
|
|
||||||
var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
|
var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
|
||||||
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
|
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
|
||||||
fileName = TrimSeparatorsRegex.Replace(fileName, string.Empty);*/
|
fileName = TrimSeparatorsRegex.Replace(fileName, string.Empty);
|
||||||
|
|
||||||
//TODO: Update namingConfig for Movies!
|
return fileName;
|
||||||
|
|
||||||
return GetOriginalTitle(movieFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BuildFilePath(Series series, int seasonNumber, string fileName, string extension)
|
public string BuildFilePath(Series series, int seasonNumber, string fileName, string extension)
|
||||||
|
@ -318,9 +287,18 @@ namespace NzbDrone.Core.Organizer
|
||||||
return CleanFolderName(ReplaceTokens(namingConfig.SeasonFolderFormat, tokenHandlers, namingConfig));
|
return CleanFolderName(ReplaceTokens(namingConfig.SeasonFolderFormat, tokenHandlers, namingConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetMovieFolder(Movie movie)
|
public string GetMovieFolder(Movie movie, NamingConfig namingConfig = null)
|
||||||
{
|
{
|
||||||
return CleanFolderName(movie.Title);
|
if(namingConfig == null)
|
||||||
|
{
|
||||||
|
namingConfig = _namingConfigService.GetConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
|
||||||
|
|
||||||
|
AddMovieTokens(tokenHandlers, movie);
|
||||||
|
|
||||||
|
return CleanFolderName(ReplaceTokens(namingConfig.MovieFolderFormat, tokenHandlers, namingConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string CleanTitle(string title)
|
public static string CleanTitle(string title)
|
||||||
|
@ -484,6 +462,17 @@ namespace NzbDrone.Core.Organizer
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddMovieTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Movie movie)
|
||||||
|
{
|
||||||
|
tokenHandlers["{Movie Title}"] = m => movie.Title;
|
||||||
|
tokenHandlers["{Movie CleanTitle}"] = m => CleanTitle(movie.Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddReleaseDateTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, int releaseYear)
|
||||||
|
{
|
||||||
|
tokenHandlers["{Release Year}"] = m => string.Format("({0})", releaseYear.ToString()); //Do I need m.CustomFormat?
|
||||||
|
}
|
||||||
|
|
||||||
private void AddSeasonTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, int seasonNumber)
|
private void AddSeasonTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, int seasonNumber)
|
||||||
{
|
{
|
||||||
tokenHandlers["{Season}"] = m => seasonNumber.ToString(m.CustomFormat);
|
tokenHandlers["{Season}"] = m => seasonNumber.ToString(m.CustomFormat);
|
||||||
|
@ -523,6 +512,18 @@ namespace NzbDrone.Core.Organizer
|
||||||
tokenHandlers["{Quality Real}"] = m => qualityReal;
|
tokenHandlers["{Quality Real}"] = m => qualityReal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddQualityTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Movie movie, MovieFile movieFile)
|
||||||
|
{
|
||||||
|
var qualityTitle = _qualityDefinitionService.Get(movieFile.Quality.Quality).Title;
|
||||||
|
var qualityProper = GetQualityProper(movie, movieFile.Quality);
|
||||||
|
var qualityReal = GetQualityReal(movie, movieFile.Quality);
|
||||||
|
|
||||||
|
tokenHandlers["{Quality Full}"] = m => String.Format("{0} {1} {2}", qualityTitle, qualityProper, qualityReal);
|
||||||
|
tokenHandlers["{Quality Title}"] = m => qualityTitle;
|
||||||
|
tokenHandlers["{Quality Proper}"] = m => qualityProper;
|
||||||
|
tokenHandlers["{Quality Real}"] = m => qualityReal;
|
||||||
|
}
|
||||||
|
|
||||||
private void AddMediaInfoTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, EpisodeFile episodeFile)
|
private void AddMediaInfoTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, EpisodeFile episodeFile)
|
||||||
{
|
{
|
||||||
if (episodeFile.MediaInfo == null) return;
|
if (episodeFile.MediaInfo == null) return;
|
||||||
|
@ -627,6 +628,110 @@ namespace NzbDrone.Core.Organizer
|
||||||
tokenHandlers["{MediaInfo Full}"] = m => string.Format("{0} {1}{2} {3}", videoCodec, audioCodec, mediaInfoAudioLanguages, mediaInfoSubtitleLanguages);
|
tokenHandlers["{MediaInfo Full}"] = m => string.Format("{0} {1}{2} {3}", videoCodec, audioCodec, mediaInfoAudioLanguages, mediaInfoSubtitleLanguages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddMediaInfoTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, MovieFile movieFile)
|
||||||
|
{
|
||||||
|
if (movieFile.MediaInfo == null) return;
|
||||||
|
|
||||||
|
string videoCodec;
|
||||||
|
switch (movieFile.MediaInfo.VideoCodec)
|
||||||
|
{
|
||||||
|
case "AVC":
|
||||||
|
if (movieFile.SceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(movieFile.SceneName).Contains("h264"))
|
||||||
|
{
|
||||||
|
videoCodec = "h264";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
videoCodec = "x264";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "V_MPEGH/ISO/HEVC":
|
||||||
|
if (movieFile.SceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(movieFile.SceneName).Contains("h265"))
|
||||||
|
{
|
||||||
|
videoCodec = "h265";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
videoCodec = "x265";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "MPEG-2 Video":
|
||||||
|
videoCodec = "MPEG2";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
videoCodec = movieFile.MediaInfo.VideoCodec;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
string audioCodec;
|
||||||
|
switch (movieFile.MediaInfo.AudioFormat)
|
||||||
|
{
|
||||||
|
case "AC-3":
|
||||||
|
audioCodec = "AC3";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "E-AC-3":
|
||||||
|
audioCodec = "EAC3";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "MPEG Audio":
|
||||||
|
if (movieFile.MediaInfo.AudioProfile == "Layer 3")
|
||||||
|
{
|
||||||
|
audioCodec = "MP3";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioCodec = movieFile.MediaInfo.AudioFormat;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "DTS":
|
||||||
|
audioCodec = movieFile.MediaInfo.AudioFormat;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
audioCodec = movieFile.MediaInfo.AudioFormat;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaInfoAudioLanguages = GetLanguagesToken(movieFile.MediaInfo.AudioLanguages);
|
||||||
|
if (!mediaInfoAudioLanguages.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
mediaInfoAudioLanguages = string.Format("[{0}]", mediaInfoAudioLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mediaInfoAudioLanguages == "[EN]")
|
||||||
|
{
|
||||||
|
mediaInfoAudioLanguages = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaInfoSubtitleLanguages = GetLanguagesToken(movieFile.MediaInfo.Subtitles);
|
||||||
|
if (!mediaInfoSubtitleLanguages.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
mediaInfoSubtitleLanguages = string.Format("[{0}]", mediaInfoSubtitleLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoBitDepth = movieFile.MediaInfo.VideoBitDepth > 0 ? movieFile.MediaInfo.VideoBitDepth.ToString() : string.Empty;
|
||||||
|
var audioChannels = movieFile.MediaInfo.FormattedAudioChannels > 0 ?
|
||||||
|
movieFile.MediaInfo.FormattedAudioChannels.ToString("F1", CultureInfo.InvariantCulture) :
|
||||||
|
string.Empty;
|
||||||
|
|
||||||
|
tokenHandlers["{MediaInfo Video}"] = m => videoCodec;
|
||||||
|
tokenHandlers["{MediaInfo VideoCodec}"] = m => videoCodec;
|
||||||
|
tokenHandlers["{MediaInfo VideoBitDepth}"] = m => videoBitDepth;
|
||||||
|
|
||||||
|
tokenHandlers["{MediaInfo Audio}"] = m => audioCodec;
|
||||||
|
tokenHandlers["{MediaInfo AudioCodec}"] = m => audioCodec;
|
||||||
|
tokenHandlers["{MediaInfo AudioChannels}"] = m => audioChannels;
|
||||||
|
|
||||||
|
tokenHandlers["{MediaInfo Simple}"] = m => string.Format("{0} {1}", videoCodec, audioCodec);
|
||||||
|
|
||||||
|
tokenHandlers["{MediaInfo Full}"] = m => string.Format("{0} {1}{2} {3}", videoCodec, audioCodec, mediaInfoAudioLanguages, mediaInfoSubtitleLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
private string GetLanguagesToken(string mediaInfoLanguages)
|
private string GetLanguagesToken(string mediaInfoLanguages)
|
||||||
{
|
{
|
||||||
List<string> tokens = new List<string>();
|
List<string> tokens = new List<string>();
|
||||||
|
@ -806,6 +911,16 @@ namespace NzbDrone.Core.Organizer
|
||||||
return MultiPartCleanupRegex.Replace(title, string.Empty).Trim();
|
return MultiPartCleanupRegex.Replace(title, string.Empty).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetQualityProper(Movie movie, QualityModel quality)
|
||||||
|
{
|
||||||
|
if (quality.Revision.Version > 1)
|
||||||
|
{
|
||||||
|
return "Proper";
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private string GetQualityProper(Series series, QualityModel quality)
|
private string GetQualityProper(Series series, QualityModel quality)
|
||||||
{
|
{
|
||||||
if (quality.Revision.Version > 1)
|
if (quality.Revision.Version > 1)
|
||||||
|
@ -831,6 +946,16 @@ namespace NzbDrone.Core.Organizer
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetQualityReal(Movie movie, QualityModel quality)
|
||||||
|
{
|
||||||
|
if (quality.Revision.Real > 0)
|
||||||
|
{
|
||||||
|
return "REAL";
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private string GetOriginalTitle(EpisodeFile episodeFile)
|
private string GetOriginalTitle(EpisodeFile episodeFile)
|
||||||
{
|
{
|
||||||
if (episodeFile.SceneName.IsNullOrWhiteSpace())
|
if (episodeFile.SceneName.IsNullOrWhiteSpace())
|
||||||
|
|
|
@ -3,6 +3,7 @@ using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Organizer
|
namespace NzbDrone.Core.Organizer
|
||||||
{
|
{
|
||||||
|
@ -13,8 +14,10 @@ namespace NzbDrone.Core.Organizer
|
||||||
SampleResult GetDailySample(NamingConfig nameSpec);
|
SampleResult GetDailySample(NamingConfig nameSpec);
|
||||||
SampleResult GetAnimeSample(NamingConfig nameSpec);
|
SampleResult GetAnimeSample(NamingConfig nameSpec);
|
||||||
SampleResult GetAnimeMultiEpisodeSample(NamingConfig nameSpec);
|
SampleResult GetAnimeMultiEpisodeSample(NamingConfig nameSpec);
|
||||||
|
SampleResult GetMovieSample(NamingConfig nameSpec);
|
||||||
string GetSeriesFolderSample(NamingConfig nameSpec);
|
string GetSeriesFolderSample(NamingConfig nameSpec);
|
||||||
string GetSeasonFolderSample(NamingConfig nameSpec);
|
string GetSeasonFolderSample(NamingConfig nameSpec);
|
||||||
|
string GetMovieFolderSample(NamingConfig nameSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileNameSampleService : IFilenameSampleService
|
public class FileNameSampleService : IFilenameSampleService
|
||||||
|
@ -34,10 +37,18 @@ namespace NzbDrone.Core.Organizer
|
||||||
private static EpisodeFile _animeEpisodeFile;
|
private static EpisodeFile _animeEpisodeFile;
|
||||||
private static EpisodeFile _animeMultiEpisodeFile;
|
private static EpisodeFile _animeMultiEpisodeFile;
|
||||||
|
|
||||||
|
private static MovieFile _movieFile;
|
||||||
|
private static Movie _movie;
|
||||||
|
|
||||||
public FileNameSampleService(IBuildFileNames buildFileNames)
|
public FileNameSampleService(IBuildFileNames buildFileNames)
|
||||||
{
|
{
|
||||||
_buildFileNames = buildFileNames;
|
_buildFileNames = buildFileNames;
|
||||||
|
|
||||||
|
_movie = new Movie
|
||||||
|
{
|
||||||
|
Title = "Movie Title (2010)"
|
||||||
|
};
|
||||||
|
|
||||||
_standardSeries = new Series
|
_standardSeries = new Series
|
||||||
{
|
{
|
||||||
SeriesType = SeriesTypes.Standard,
|
SeriesType = SeriesTypes.Standard,
|
||||||
|
@ -106,6 +117,15 @@ namespace NzbDrone.Core.Organizer
|
||||||
Subtitles = "Japanese/English"
|
Subtitles = "Japanese/English"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_movieFile = new MovieFile
|
||||||
|
{
|
||||||
|
Quality = new QualityModel(Quality.Bluray1080p, new Revision(2)),
|
||||||
|
RelativePath = "Movie.Title.2010.1080p.BluRay.DTS.x264-EVOLVE.mkv",
|
||||||
|
SceneName = "Movie.Title.2010.1080p.BluRay.DTS.x264-EVOLVE",
|
||||||
|
ReleaseGroup = "RlsGrp",
|
||||||
|
MediaInfo = mediaInfo
|
||||||
|
};
|
||||||
|
|
||||||
_singleEpisodeFile = new EpisodeFile
|
_singleEpisodeFile = new EpisodeFile
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.HDTV720p, new Revision(2)),
|
Quality = new QualityModel(Quality.HDTV720p, new Revision(2)),
|
||||||
|
@ -217,6 +237,16 @@ namespace NzbDrone.Core.Organizer
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SampleResult GetMovieSample(NamingConfig nameSpec)
|
||||||
|
{
|
||||||
|
var result = new SampleResult
|
||||||
|
{
|
||||||
|
FileName = BuildSample(_movie, _movieFile, nameSpec),
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public string GetSeriesFolderSample(NamingConfig nameSpec)
|
public string GetSeriesFolderSample(NamingConfig nameSpec)
|
||||||
{
|
{
|
||||||
return _buildFileNames.GetSeriesFolder(_standardSeries, nameSpec);
|
return _buildFileNames.GetSeriesFolder(_standardSeries, nameSpec);
|
||||||
|
@ -227,6 +257,11 @@ namespace NzbDrone.Core.Organizer
|
||||||
return _buildFileNames.GetSeasonFolder(_standardSeries, _episode1.SeasonNumber, nameSpec);
|
return _buildFileNames.GetSeasonFolder(_standardSeries, _episode1.SeasonNumber, nameSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetMovieFolderSample(NamingConfig nameSpec)
|
||||||
|
{
|
||||||
|
return _buildFileNames.GetMovieFolder(_movie, nameSpec);
|
||||||
|
}
|
||||||
|
|
||||||
private string BuildSample(List<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig nameSpec)
|
private string BuildSample(List<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig nameSpec)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -238,5 +273,17 @@ namespace NzbDrone.Core.Organizer
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string BuildSample(Movie movie, MovieFile movieFile, NamingConfig nameSpec)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _buildFileNames.BuildFileName(movie, movieFile, nameSpec);
|
||||||
|
}
|
||||||
|
catch (NamingFormatException)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,26 @@ namespace NzbDrone.Core.Organizer
|
||||||
ValidationFailure ValidateStandardFilename(SampleResult sampleResult);
|
ValidationFailure ValidateStandardFilename(SampleResult sampleResult);
|
||||||
ValidationFailure ValidateDailyFilename(SampleResult sampleResult);
|
ValidationFailure ValidateDailyFilename(SampleResult sampleResult);
|
||||||
ValidationFailure ValidateAnimeFilename(SampleResult sampleResult);
|
ValidationFailure ValidateAnimeFilename(SampleResult sampleResult);
|
||||||
|
ValidationFailure ValidateMovieFilename(SampleResult sampleResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileNameValidationService : IFilenameValidationService
|
public class FileNameValidationService : IFilenameValidationService
|
||||||
{
|
{
|
||||||
private const string ERROR_MESSAGE = "Produces invalid file names";
|
private const string ERROR_MESSAGE = "Produces invalid file names";
|
||||||
|
|
||||||
|
public ValidationFailure ValidateMovieFilename(SampleResult sampleResult)
|
||||||
|
{
|
||||||
|
var validationFailure = new ValidationFailure("MovieFormat", ERROR_MESSAGE);
|
||||||
|
var parsedMovieInfo = Parser.Parser.ParseMovieTitle(sampleResult.FileName);
|
||||||
|
|
||||||
|
if(parsedMovieInfo == null)
|
||||||
|
{
|
||||||
|
return validationFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public ValidationFailure ValidateStandardFilename(SampleResult sampleResult)
|
public ValidationFailure ValidateStandardFilename(SampleResult sampleResult)
|
||||||
{
|
{
|
||||||
var validationFailure = new ValidationFailure("StandardEpisodeFormat", ERROR_MESSAGE);
|
var validationFailure = new ValidationFailure("StandardEpisodeFormat", ERROR_MESSAGE);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<legend>File Management</legend>
|
<legend>File Management</legend>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">Ignore Deleted Episodes</label>
|
<label class="col-sm-3 control-label">Ignore Deleted Movies</label>
|
||||||
|
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<span class="help-inline-checkbox">
|
<span class="help-inline-checkbox">
|
||||||
<i class="icon-sonarr-form-info" title="Episodes deleted from disk are automatically unmonitored in Radarr"/>
|
<i class="icon-sonarr-form-info" title="Movies deleted from disk are automatically unmonitored in Radarr"/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -19,7 +19,9 @@ module.exports = (function() {
|
||||||
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',
|
||||||
seasonFolderExample : '.x-season-folder-example'
|
seasonFolderExample : '.x-season-folder-example',
|
||||||
|
movieExample : '.x-movie-example',
|
||||||
|
movieFolderExample : '.x-movie-folder-example'
|
||||||
},
|
},
|
||||||
events : {
|
events : {
|
||||||
"change .x-rename-episodes" : '_setFailedDownloadOptionsVisibility',
|
"change .x-rename-episodes" : '_setFailedDownloadOptionsVisibility',
|
||||||
|
@ -58,6 +60,8 @@ module.exports = (function() {
|
||||||
this.ui.animeMultiEpisodeExample.html(this.namingSampleModel.get('animeMultiEpisodeExample'));
|
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'));
|
||||||
|
this.ui.movieExample.html(this.namingSampleModel.get('movieExample'));
|
||||||
|
this.ui.movieFolderExample.html(this.namingSampleModel.get('movieFolderExample'));
|
||||||
},
|
},
|
||||||
_addToken : function(e) {
|
_addToken : function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
{{> MovieTitleNamingPartial}}
|
{{> MovieTitleNamingPartial}}
|
||||||
{{> ReleaseYearNamingPartial}}
|
{{!--{{> ReleaseYearNamingPartial}}--}}
|
||||||
{{> QualityNamingPartial}}
|
{{> QualityNamingPartial}}
|
||||||
{{> MediaInfoNamingPartial}}
|
{{> MediaInfoNamingPartial}}
|
||||||
{{> ReleaseGroupNamingPartial}}
|
{{> ReleaseGroupNamingPartial}}
|
||||||
|
@ -160,7 +160,7 @@
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
{{> MovieTitleNamingPartial}}
|
{{> MovieTitleNamingPartial}}
|
||||||
{{> ReleaseYearNamingPartial}}
|
{{!--{{> ReleaseYearNamingPartial}}--}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -208,7 +208,7 @@
|
||||||
<label class="col-sm-3 control-label">Movie Example</label>
|
<label class="col-sm-3 control-label">Movie Example</label>
|
||||||
|
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<p class="form-control-static x-single-episode-example naming-example"></p>
|
<p class="form-control-static x-movie-example naming-example"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@
|
||||||
<label class="col-sm-3 control-label">Movie Folder Example</label>
|
<label class="col-sm-3 control-label">Movie Folder Example</label>
|
||||||
|
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<p class="form-control-static x-series-folder-example naming-example"></p>
|
<p class="form-control-static x-movie-folder-example naming-example"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue