Merge branch 'rename-existing-folder' into develop

This commit is contained in:
Tim Turner 2017-01-27 19:31:55 -05:00
commit a340bc4da3
12 changed files with 397 additions and 330 deletions

View file

@ -64,6 +64,11 @@ namespace NzbDrone.Common.Extensions
return childPath.Substring(parentPath.Length).Trim(Path.DirectorySeparatorChar); return childPath.Substring(parentPath.Length).Trim(Path.DirectorySeparatorChar);
} }
public static string GetRelativePathWithoutChildCheck(this string parentPath, string childPath)
{
return childPath.Substring(parentPath.Length).Trim(Path.DirectorySeparatorChar);
}
public static string GetParentPath(this string childPath) public static string GetParentPath(this string childPath)
{ {
var parentPath = childPath.TrimEnd('\\', '/'); var parentPath = childPath.TrimEnd('\\', '/');

View file

@ -123,6 +123,17 @@ namespace NzbDrone.Core.Extras
// } // }
//} //}
// TODO
public void Handle(MovieFolderCreatedEvent message)
{
var movie = message.Movie;
foreach(var extraFileManager in _extraFileManagers)
{
//extraFileManager.CreateAfterMovieImport(movie, message.MovieFolder);
}
}
public void Handle(EpisodeFolderCreatedEvent message) public void Handle(EpisodeFolderCreatedEvent message)
{ {
var series = message.Series; var series = message.Series;

View file

@ -116,6 +116,12 @@ namespace NzbDrone.Core.MediaFiles
_diskTransferService.TransferFile(movieFilePath, destinationFilePath, mode); _diskTransferService.TransferFile(movieFilePath, destinationFilePath, mode);
var oldMoviePath = new OsPath(movieFilePath).Directory.FullPath.TrimEnd(Path.DirectorySeparatorChar);
var newMoviePath = new OsPath(destinationFilePath).Directory.FullPath.TrimEnd(Path.DirectorySeparatorChar);
movie.Path = newMoviePath;
movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath); movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath);
_updateMovieFileService.ChangeFileDateForFile(movieFile, movie); _updateMovieFileService.ChangeFileDateForFile(movieFile, movie);
@ -132,6 +138,8 @@ namespace NzbDrone.Core.MediaFiles
_mediaFileAttributeService.SetFilePermissions(destinationFilePath); _mediaFileAttributeService.SetFilePermissions(destinationFilePath);
_diskProvider.DeleteFolder(oldMoviePath, true);
return movieFile; return movieFile;
} }
@ -144,6 +152,7 @@ namespace NzbDrone.Core.MediaFiles
{ {
var movieFolder = Path.GetDirectoryName(filePath); var movieFolder = Path.GetDirectoryName(filePath);
var rootFolder = new OsPath(movieFolder).Directory.FullPath; var rootFolder = new OsPath(movieFolder).Directory.FullPath;
var fileName = Path.GetFileName(filePath);
if (!_diskProvider.FolderExists(rootFolder)) if (!_diskProvider.FolderExists(rootFolder))
{ {
@ -156,7 +165,7 @@ namespace NzbDrone.Core.MediaFiles
if (!_diskProvider.FolderExists(movieFolder)) if (!_diskProvider.FolderExists(movieFolder))
{ {
CreateFolder(movieFolder); CreateFolder(movieFolder);
newEvent.SeriesFolder = movieFolder; newEvent.MovieFolder = movieFolder;
changed = true; changed = true;
} }

View file

@ -71,8 +71,9 @@ namespace NzbDrone.Core.MediaFiles
{ {
MovieId = movie.Id, MovieId = movie.Id,
MovieFileId = file.Id, MovieFileId = file.Id,
ExistingPath = file.RelativePath, ExistingPath = movieFilePath,
NewPath = movie.Path.GetRelativePath(newPath) //NewPath = movie.Path.GetRelativePath(newPath)
NewPath = newPath
}; };
} }
@ -94,6 +95,7 @@ namespace NzbDrone.Core.MediaFiles
_movieFileMover.MoveMovieFile(movieFile, movie); _movieFileMover.MoveMovieFile(movieFile, movie);
_mediaFileService.Update(movieFile); _mediaFileService.Update(movieFile);
_movieService.UpdateMovie(movie);
renamed.Add(movieFile); renamed.Add(movieFile);
_logger.Debug("Renamed movie file: {0}", movieFile); _logger.Debug("Renamed movie file: {0}", movieFile);
@ -122,7 +124,7 @@ namespace NzbDrone.Core.MediaFiles
public void Execute(RenameMovieCommand message) public void Execute(RenameMovieCommand message)
{ {
_logger.Debug("Renaming all files for selected movie"); _logger.Debug("Renaming all files for selected movies");
var moviesToRename = _movieService.GetMovies(message.MovieIds); var moviesToRename = _movieService.GetMovies(message.MovieIds);
foreach(var movie in moviesToRename) foreach(var movie in moviesToRename)

View file

@ -210,7 +210,7 @@ namespace NzbDrone.Core.Notifications
public void Handle(MovieDownloadedEvent message) public void Handle(MovieDownloadedEvent message)
{ {
var downloadMessage = new DownloadMessage(); var downloadMessage = new DownloadMessage();
downloadMessage.Message = GetMessage(message.Movie.Movie, message.Movie.Quality); downloadMessage.Message = GetMessage(message.Movie.Movie, message.Movie.Quality);
downloadMessage.Series = null; downloadMessage.Series = null;
downloadMessage.EpisodeFile = null; downloadMessage.EpisodeFile = null;
downloadMessage.MovieFile = message.MovieFile; downloadMessage.MovieFile = message.MovieFile;

View file

@ -17,7 +17,7 @@ namespace NzbDrone.Core.Notifications.Plex
public interface IPlexServerProxy public interface IPlexServerProxy
{ {
List<PlexSection> GetTvSections(PlexServerSettings settings); List<PlexSection> GetTvSections(PlexServerSettings settings);
List<PlexSection> GetMovieSections(PlexServerSettings settings); List<PlexSection> GetMovieSections(PlexServerSettings settings);
void Update(int sectionId, PlexServerSettings settings); void Update(int sectionId, PlexServerSettings settings);
void UpdateSeries(int metadataId, PlexServerSettings settings); void UpdateSeries(int metadataId, PlexServerSettings settings);
string Version(PlexServerSettings settings); string Version(PlexServerSettings settings);
@ -81,12 +81,12 @@ namespace NzbDrone.Core.Notifications.Plex
return Json.Deserialize<PlexMediaContainerLegacy>(response.Content) return Json.Deserialize<PlexMediaContainerLegacy>(response.Content)
.Sections .Sections
.Where(d => d.Type == "movie") .Where(d => d.Type == "movie")
.Select(s => new PlexSection .Select(s => new PlexSection
{ {
Id = s.Id, Id = s.Id,
Language = s.Language, Language = s.Language,
Locations = s.Locations, Locations = s.Locations,
Type = s.Type Type = s.Type
}) })
.ToList(); .ToList();
} }

View file

@ -86,8 +86,8 @@ namespace NzbDrone.Core.Notifications.Slack
}; };
NotifySlack(payload); NotifySlack(payload);
} }
public override void OnRename(Series series) public override void OnRename(Series series)
{ {
var payload = new SlackPayload var payload = new SlackPayload

View file

@ -1,324 +1,349 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NLog; using NLog;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Qualities; using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Organizer namespace NzbDrone.Core.Organizer
{ {
public interface IBuildFileNames public interface IBuildFileNames
{ {
string BuildFileName(List<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig namingConfig = null); string BuildFileName(List<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig namingConfig = null);
string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null); string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null);
string BuildFilePath(Movie movie, string fileName, string extension); string BuildFilePath(Movie movie, string fileName, string extension);
string BuildFilePath(Series series, int seasonNumber, string fileName, string extension); string BuildFilePath(Series series, int seasonNumber, string fileName, string extension);
string BuildSeasonPath(Series series, int seasonNumber); string BuildSeasonPath(Series series, int seasonNumber);
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, NamingConfig namingConfig = null); string GetMovieFolder(Movie movie, NamingConfig namingConfig = null);
} }
public class FileNameBuilder : IBuildFileNames public class FileNameBuilder : IBuildFileNames
{ {
private readonly INamingConfigService _namingConfigService; private readonly INamingConfigService _namingConfigService;
private readonly IQualityDefinitionService _qualityDefinitionService; private readonly IQualityDefinitionService _qualityDefinitionService;
private readonly ICached<EpisodeFormat[]> _episodeFormatCache; private readonly ICached<EpisodeFormat[]> _episodeFormatCache;
private readonly ICached<AbsoluteEpisodeFormat[]> _absoluteEpisodeFormatCache; private readonly ICached<AbsoluteEpisodeFormat[]> _absoluteEpisodeFormatCache;
private readonly Logger _logger; private readonly Logger _logger;
private static readonly Regex TitleRegex = new Regex(@"\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9]+))?(?<suffix>[- ._)\]]*)\}", private static readonly Regex TitleRegex = new Regex(@"\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9]+))?(?<suffix>[- ._)\]]*)\}",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex EpisodeRegex = new Regex(@"(?<episode>\{episode(?:\:0+)?})", private static readonly Regex EpisodeRegex = new Regex(@"(?<episode>\{episode(?:\:0+)?})",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex TagsRegex = new Regex(@"(?<tags>\{tags(?:\:0+)?})", private static readonly Regex TagsRegex = new Regex(@"(?<tags>\{tags(?:\:0+)?})",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex SeasonRegex = new Regex(@"(?<season>\{season(?:\:0+)?})", private static readonly Regex SeasonRegex = new Regex(@"(?<season>\{season(?:\:0+)?})",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex AbsoluteEpisodeRegex = new Regex(@"(?<absolute>\{absolute(?:\:0+)?})", private static readonly Regex AbsoluteEpisodeRegex = new Regex(@"(?<absolute>\{absolute(?:\:0+)?})",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex SeasonEpisodePatternRegex = new Regex(@"(?<separator>(?<=})[- ._]+?)?(?<seasonEpisode>s?{season(?:\:0+)?}(?<episodeSeparator>[- ._]?[ex])(?<episode>{episode(?:\:0+)?}))(?<separator>[- ._]+?(?={))?", public static readonly Regex SeasonEpisodePatternRegex = new Regex(@"(?<separator>(?<=})[- ._]+?)?(?<seasonEpisode>s?{season(?:\:0+)?}(?<episodeSeparator>[- ._]?[ex])(?<episode>{episode(?:\:0+)?}))(?<separator>[- ._]+?(?={))?",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex AbsoluteEpisodePatternRegex = new Regex(@"(?<separator>(?<=})[- ._]+?)?(?<absolute>{absolute(?:\:0+)?})(?<separator>[- ._]+?(?={))?", public static readonly Regex AbsoluteEpisodePatternRegex = new Regex(@"(?<separator>(?<=})[- ._]+?)?(?<absolute>{absolute(?:\:0+)?})(?<separator>[- ._]+?(?={))?",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex AirDateRegex = new Regex(@"\{Air(\s|\W|_)Date\}", RegexOptions.Compiled | RegexOptions.IgnoreCase); public static readonly Regex AirDateRegex = new Regex(@"\{Air(\s|\W|_)Date\}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex SeriesTitleRegex = new Regex(@"(?<token>\{(?:Series)(?<separator>[- ._])(Clean)?Title\})", public static readonly Regex SeriesTitleRegex = new Regex(@"(?<token>\{(?:Series)(?<separator>[- ._])(Clean)?Title\})",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{((?:(Movie|Original))(?<separator>[- ._])(Clean)?Title(The)?)\})", public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{((?:(Movie|Original))(?<separator>[- ._])(Clean)?Title(The)?)\})",
RegexOptions.Compiled | RegexOptions.IgnoreCase); RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled); private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled);
private static readonly Regex TrimSeparatorsRegex = new Regex(@"[- ._]$", RegexOptions.Compiled); private static readonly Regex TrimSeparatorsRegex = new Regex(@"[- ._]$", RegexOptions.Compiled);
private static readonly Regex ScenifyRemoveChars = new Regex(@"(?<=\s)(,|<|>|\/|\\|;|:|'|""|\||`|~|!|\?|@|$|%|^|\*|-|_|=){1}(?=\s)|('|:|\?|,)(?=(?:(?:s|m)\s)|\s|$)|(\(|\)|\[|\]|\{|\})", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ScenifyRemoveChars = new Regex(@"(?<=\s)(,|<|>|\/|\\|;|:|'|""|\||`|~|!|\?|@|$|%|^|\*|-|_|=){1}(?=\s)|('|:|\?|,)(?=(?:(?:s|m)\s)|\s|$)|(\(|\)|\[|\]|\{|\})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex ScenifyReplaceChars = new Regex(@"[\/]", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ScenifyReplaceChars = new Regex(@"[\/]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
//TODO: Support Written numbers (One, Two, etc) and Roman Numerals (I, II, III etc) //TODO: Support Written numbers (One, Two, etc) and Roman Numerals (I, II, III etc)
private static readonly Regex MultiPartCleanupRegex = new Regex(@"(?:\(\d+\)|(Part|Pt\.?)\s?\d+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex MultiPartCleanupRegex = new Regex(@"(?:\(\d+\)|(Part|Pt\.?)\s?\d+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly char[] EpisodeTitleTrimCharacters = new[] { ' ', '.', '?' }; private static readonly char[] EpisodeTitleTrimCharacters = new[] { ' ', '.', '?' };
public FileNameBuilder(INamingConfigService namingConfigService, public FileNameBuilder(INamingConfigService namingConfigService,
IQualityDefinitionService qualityDefinitionService, IQualityDefinitionService qualityDefinitionService,
ICacheManager cacheManager, ICacheManager cacheManager,
Logger logger) Logger logger)
{
_namingConfigService = namingConfigService;
_qualityDefinitionService = qualityDefinitionService;
//_movieFormatCache = cacheManager.GetCache<MovieFormat>(GetType(), "movieFormat");
_episodeFormatCache = cacheManager.GetCache<EpisodeFormat[]>(GetType(), "episodeFormat");
_absoluteEpisodeFormatCache = cacheManager.GetCache<AbsoluteEpisodeFormat[]>(GetType(), "absoluteEpisodeFormat");
_logger = logger;
}
public string BuildFileName(List<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig namingConfig = null)
{
if (namingConfig == null)
{
namingConfig = _namingConfigService.GetConfig();
}
if (!namingConfig.RenameEpisodes)
{
return GetOriginalTitle(episodeFile);
}
if (namingConfig.StandardEpisodeFormat.IsNullOrWhiteSpace() && series.SeriesType == SeriesTypes.Standard)
{
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);
episodes = episodes.OrderBy(e => e.SeasonNumber).ThenBy(e => e.EpisodeNumber).ToList();
if (series.SeriesType == SeriesTypes.Daily)
{
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();
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
fileName = TrimSeparatorsRegex.Replace(fileName, string.Empty);
return fileName;
}
public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null)
{
if (namingConfig == null)
{
namingConfig = _namingConfigService.GetConfig();
}
if (!namingConfig.RenameEpisodes)
{
return GetOriginalTitle(movieFile);
}
var pattern = namingConfig.StandardMovieFormat;
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year);
AddImdbIdTokens(tokenHandlers, movie.ImdbId);
AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile);
AddTagsTokens(tokenHandlers, movieFile);
var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
fileName = TrimSeparatorsRegex.Replace(fileName, string.Empty);
return fileName;
}
public string BuildFilePath(Series series, int seasonNumber, string fileName, string extension)
{
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
var path = BuildSeasonPath(series, seasonNumber);
return Path.Combine(path, fileName + extension);
}
public string BuildFilePath(Movie movie, string fileName, string extension)
{
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
var path = BuildMoviePath(movie);
return Path.Combine(path, fileName + extension);
}
public string BuildMoviePath(Movie movie)
{ {
_namingConfigService = namingConfigService;
_qualityDefinitionService = qualityDefinitionService;
//_movieFormatCache = cacheManager.GetCache<MovieFormat>(GetType(), "movieFormat");
_episodeFormatCache = cacheManager.GetCache<EpisodeFormat[]>(GetType(), "episodeFormat");
_absoluteEpisodeFormatCache = cacheManager.GetCache<AbsoluteEpisodeFormat[]>(GetType(), "absoluteEpisodeFormat");
_logger = logger;
}
public string BuildFileName(List<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig namingConfig = null)
{
if (namingConfig == null)
{
namingConfig = _namingConfigService.GetConfig();
}
if (!namingConfig.RenameEpisodes)
{
return GetOriginalTitle(episodeFile);
}
if (namingConfig.StandardEpisodeFormat.IsNullOrWhiteSpace() && series.SeriesType == SeriesTypes.Standard)
{
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);
episodes = episodes.OrderBy(e => e.SeasonNumber).ThenBy(e => e.EpisodeNumber).ToList();
if (series.SeriesType == SeriesTypes.Daily)
{
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();
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
fileName = TrimSeparatorsRegex.Replace(fileName, string.Empty);
return fileName;
}
public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null)
{
if (namingConfig == null)
{
namingConfig = _namingConfigService.GetConfig();
}
if (!namingConfig.RenameEpisodes)
{
return GetOriginalTitle(movieFile);
}
//TODO: Update namingConfig for Movies!
var pattern = namingConfig.StandardMovieFormat;
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year); //In case we want to separate the year
AddImdbIdTokens(tokenHandlers, movie.ImdbId);
AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile);
AddTagsTokens(tokenHandlers, movieFile);
var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
fileName = TrimSeparatorsRegex.Replace(fileName, string.Empty);
return fileName;
}
public string BuildFilePath(Series series, int seasonNumber, string fileName, string extension)
{
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
var path = BuildSeasonPath(series, seasonNumber);
return Path.Combine(path, fileName + extension);
}
public string BuildFilePath(Movie movie, string fileName, string extension)
{
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
var path = movie.Path; var path = movie.Path;
var directory = new DirectoryInfo(path).Name;
var parentDirectoryPath = new DirectoryInfo(path).Parent.FullName;
var namingConfig = _namingConfigService.GetConfig();
return Path.Combine(path, fileName + extension); var movieFile = movie.MovieFile;
}
public string BuildSeasonPath(Series series, int seasonNumber) var pattern = namingConfig.MovieFolderFormat;
{ var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
var path = series.Path;
AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year);
AddImdbIdTokens(tokenHandlers, movie.ImdbId);
AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile);
var directoryName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
directoryName = FileNameCleanupRegex.Replace(directoryName, match => match.Captures[0].Value[0].ToString());
directoryName = TrimSeparatorsRegex.Replace(directoryName, string.Empty);
if (series.SeasonFolder) return Path.Combine(parentDirectoryPath, directoryName);
{ }
if (seasonNumber == 0)
{ public string BuildSeasonPath(Series series, int seasonNumber)
path = Path.Combine(path, "Specials"); {
} var path = series.Path;
else
{ if (series.SeasonFolder)
var seasonFolder = GetSeasonFolder(series, seasonNumber); {
if (seasonNumber == 0)
seasonFolder = CleanFileName(seasonFolder); {
path = Path.Combine(path, "Specials");
path = Path.Combine(path, seasonFolder); }
} else
} {
var seasonFolder = GetSeasonFolder(series, seasonNumber);
return path;
} seasonFolder = CleanFileName(seasonFolder);
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec) path = Path.Combine(path, seasonFolder);
{ }
return new BasicNamingConfig(); //For now let's be lazy }
var episodeFormat = GetEpisodeFormat(nameSpec.StandardEpisodeFormat).LastOrDefault(); return path;
}
if (episodeFormat == null)
{ public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec)
return new BasicNamingConfig(); {
} return new BasicNamingConfig(); //For now let's be lazy
var basicNamingConfig = new BasicNamingConfig var episodeFormat = GetEpisodeFormat(nameSpec.StandardEpisodeFormat).LastOrDefault();
{
Separator = episodeFormat.Separator, if (episodeFormat == null)
NumberStyle = episodeFormat.SeasonEpisodePattern {
}; return new BasicNamingConfig();
}
var titleTokens = TitleRegex.Matches(nameSpec.StandardEpisodeFormat);
var basicNamingConfig = new BasicNamingConfig
foreach (Match match in titleTokens) {
{ Separator = episodeFormat.Separator,
var separator = match.Groups["separator"].Value; NumberStyle = episodeFormat.SeasonEpisodePattern
var token = match.Groups["token"].Value; };
if (!separator.Equals(" ")) var titleTokens = TitleRegex.Matches(nameSpec.StandardEpisodeFormat);
{
basicNamingConfig.ReplaceSpaces = true; foreach (Match match in titleTokens)
} {
var separator = match.Groups["separator"].Value;
if (token.StartsWith("{Series", StringComparison.InvariantCultureIgnoreCase)) var token = match.Groups["token"].Value;
{
basicNamingConfig.IncludeSeriesTitle = true; if (!separator.Equals(" "))
} {
basicNamingConfig.ReplaceSpaces = true;
if (token.StartsWith("{Episode", StringComparison.InvariantCultureIgnoreCase)) }
{
basicNamingConfig.IncludeEpisodeTitle = true; if (token.StartsWith("{Series", StringComparison.InvariantCultureIgnoreCase))
} {
basicNamingConfig.IncludeSeriesTitle = true;
if (token.StartsWith("{Quality", StringComparison.InvariantCultureIgnoreCase)) }
{
basicNamingConfig.IncludeQuality = true; if (token.StartsWith("{Episode", StringComparison.InvariantCultureIgnoreCase))
} {
} basicNamingConfig.IncludeEpisodeTitle = true;
}
return basicNamingConfig;
} if (token.StartsWith("{Quality", StringComparison.InvariantCultureIgnoreCase))
{
public string GetSeriesFolder(Series series, NamingConfig namingConfig = null) basicNamingConfig.IncludeQuality = true;
{ }
if (namingConfig == null) }
{
namingConfig = _namingConfigService.GetConfig(); return basicNamingConfig;
} }
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance); public string GetSeriesFolder(Series series, NamingConfig namingConfig = null)
{
AddSeriesTokens(tokenHandlers, series); if (namingConfig == null)
{
return CleanFolderName(ReplaceTokens(namingConfig.SeriesFolderFormat, tokenHandlers, namingConfig)); namingConfig = _namingConfigService.GetConfig();
} }
public string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null) var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
{
if (namingConfig == null) AddSeriesTokens(tokenHandlers, series);
{
namingConfig = _namingConfigService.GetConfig(); return CleanFolderName(ReplaceTokens(namingConfig.SeriesFolderFormat, tokenHandlers, namingConfig));
} }
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance); public string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null)
{
AddSeriesTokens(tokenHandlers, series); if (namingConfig == null)
AddSeasonTokens(tokenHandlers, seasonNumber); {
namingConfig = _namingConfigService.GetConfig();
return CleanFolderName(ReplaceTokens(namingConfig.SeasonFolderFormat, tokenHandlers, namingConfig)); }
}
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
public string GetMovieFolder(Movie movie, NamingConfig namingConfig = null)
{ AddSeriesTokens(tokenHandlers, series);
if(namingConfig == null) AddSeasonTokens(tokenHandlers, seasonNumber);
{
namingConfig = _namingConfigService.GetConfig(); return CleanFolderName(ReplaceTokens(namingConfig.SeasonFolderFormat, tokenHandlers, namingConfig));
} }
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance); public string GetMovieFolder(Movie movie, NamingConfig namingConfig = null)
{
AddMovieTokens(tokenHandlers, movie); if(namingConfig == null)
AddReleaseDateTokens(tokenHandlers, movie.Year); {
AddImdbIdTokens(tokenHandlers, movie.ImdbId); namingConfig = _namingConfigService.GetConfig();
}
return CleanFolderName(ReplaceTokens(namingConfig.MovieFolderFormat, tokenHandlers, namingConfig));
} var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
public static string CleanTitle(string title) AddMovieTokens(tokenHandlers, movie);
{ AddReleaseDateTokens(tokenHandlers, movie.Year);
title = title.Replace("&", "and"); AddImdbIdTokens(tokenHandlers, movie.ImdbId);
title = ScenifyReplaceChars.Replace(title, " ");
title = ScenifyRemoveChars.Replace(title, string.Empty); return CleanFolderName(ReplaceTokens(namingConfig.MovieFolderFormat, tokenHandlers, namingConfig));
}
return title;
} public static string CleanTitle(string title)
{
title = title.Replace("&", "and");
title = ScenifyReplaceChars.Replace(title, " ");
title = ScenifyRemoveChars.Replace(title, string.Empty);
return title;
}
public static string TitleThe(string title) public static string TitleThe(string title)
{ {

View file

@ -74,6 +74,19 @@ module.exports = Marionette.Layout.extend({
var file = movie.model.get("movieFile"); var file = movie.model.get("movieFile");
this.filesCollection.add(file); this.filesCollection.add(file);
//this.listenTo(this.releaseCollection, 'sync', this._showSearchResults); //this.listenTo(this.releaseCollection, 'sync', this._showSearchResults);
this.listenTo(this.model, 'change', function(model, options) {
if (options && options.changeSource === 'signalr') {
this._refresh(movie);
}
});
},
_refresh : function(movie) {
this.filesCollection = new FilesCollection();
var file = movie.model.get("movieFile");
this.filesCollection.add(file);
this.onShow();
}, },
onShow : function() { onShow : function() {

View file

@ -9,6 +9,7 @@ module.exports = Marionette.ItemView.extend({
//var type = this.model.get('seriesType'); //var type = this.model.get('seriesType');
return { return {
rename : this.naming.get('renameEpisodes'), rename : this.naming.get('renameEpisodes'),
folderFormat: this.naming.get('movieFolderFormat'),
format : this.naming.get('standardMovieFormat') format : this.naming.get('standardMovieFormat')
}; };
}, },

View file

@ -1,3 +1,4 @@
{{#if rename}} {{#if rename}}
Folder Naming pattern: {{folderFormat}}<br>
Naming pattern: {{format}} Naming pattern: {{format}}
{{/if}} {{/if}}

View file

@ -9,7 +9,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="alert alert-info"> <div class="alert alert-info">
<div class="path-info x-path-info">All paths are relative to: <strong>{{path}}</strong></div> <div class="path-info x-path-info">Your movie may be moved; see the paths below</div>
<div class="x-format-region"></div> <div class="x-format-region"></div>
</div> </div>