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; }
private string BuildTrackSample(Author author, BookFile bookFile, NamingConfig nameSpec) { try { return(_buildFileNames.BuildBookFileName(author, bookFile.Edition.Value, bookFile, nameSpec, _preferredWords)); } catch (NamingFormatException) { return(string.Empty); } }
private string BuildSample(Movie movie, MovieFile movieFile, NamingConfig nameSpec) { try { return(_buildFileNames.BuildFileName(movie, movieFile, nameSpec)); } catch (NamingFormatException) { return(string.Empty); } }
private int GetLengthWithoutEpisodeTitle(string pattern, NamingConfig namingConfig) { var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance); tokenHandlers["{Episode Title}"] = m => string.Empty; tokenHandlers["{Episode CleanTitle}"] = m => string.Empty; var result = ReplaceTokens(pattern, tokenHandlers, namingConfig); return(result.GetByteCount()); }
public SampleResult GetMultiDiscTrackSample(NamingConfig nameSpec) { var result = new SampleResult { FileName = BuildTrackSample(_standardAuthor, _singleTrackFile, nameSpec), Author = _standardAuthor, Book = _standardBook, BookFile = _singleTrackFile }; return(result); }
public SampleResult GetAnimeSample(NamingConfig nameSpec) { var result = new SampleResult { FileName = BuildSample(_singleEpisode, _animeSeries, _animeEpisodeFile, nameSpec), Series = _animeSeries, Episodes = _singleEpisode, EpisodeFile = _animeEpisodeFile }; return(result); }
public SampleResult GetStandardSample(NamingConfig nameSpec) { var result = new SampleResult { Filename = BuildSample(_singleEpisode, _standardSeries, _singleEpisodeFile, nameSpec), Series = _standardSeries, Episodes = _singleEpisode, EpisodeFile = _singleEpisodeFile }; return result; }
public SampleResult GetMultiEpisodeSample(NamingConfig nameSpec) { var result = new SampleResult { FileName = BuildSample(_multiEpisodes, _standardSeries, _multiEpisodeFile, nameSpec), Series = _standardSeries, Episodes = _multiEpisodes, EpisodeFile = _multiEpisodeFile }; return(result); }
public SampleResult GetDailySample(NamingConfig nameSpec) { var result = new SampleResult { Filename = BuildSample(_singleEpisode, _dailySeries, _dailyEpisodeFile, nameSpec), Series = _dailySeries, Episodes = _singleEpisode, EpisodeFile = _dailyEpisodeFile }; return(result); }
public string GetArtistFolder(Artist artist, NamingConfig namingConfig = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance); AddArtistTokens(tokenHandlers, artist); return(CleanFolderName(ReplaceTokens(namingConfig.ArtistFolderFormat, tokenHandlers, namingConfig))); }
public string GetSeriesFolder(Series series, NamingConfig namingConfig = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } var tokenHandlers = new Dictionary <string, Func <TokenMatch, String> >(FileNameBuilderTokenEqualityComparer.Instance); AddSeriesTokens(tokenHandlers, series); return(CleanFolderName(ReplaceTokens(namingConfig.SeriesFolderFormat, tokenHandlers))); }
public string GetMovieFolder(Movie movie, NamingConfig namingConfig = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } var movieFile = movie.MovieFile; var pattern = namingConfig.MovieFolderFormat; var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance); AddMovieTokens(tokenHandlers, movie); AddReleaseDateTokens(tokenHandlers, movie.Year); AddIdTokens(tokenHandlers, movie); if (movie.MovieFile != null) { AddQualityTokens(tokenHandlers, movie, movieFile); AddMediaInfoTokens(tokenHandlers, movieFile); AddMovieFileTokens(tokenHandlers, movieFile); AddTagsTokens(tokenHandlers, movieFile); } else { AddMovieFileTokens(tokenHandlers, new MovieFile { SceneName = $"{movie.Title} {movie.Year}", RelativePath = $"{movie.Title} {movie.Year}" }); } var splitPatterns = pattern.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); var components = new List <string>(); foreach (var s in splitPatterns) { var splitPattern = s; var component = ReplaceTokens(splitPattern, tokenHandlers, namingConfig); component = CleanFolderName(component); component = ReplaceReservedDeviceNames(component); if (component.IsNotNullOrWhiteSpace()) { components.Add(component); } } return(Path.Combine(components.ToArray())); }
public SampleResult GetMultiDiscTrackSample(NamingConfig nameSpec) { _track1.AlbumRelease = _multiRelease; var result = new SampleResult { FileName = BuildTrackSample(_singleTrack, _standardArtist, _standardAlbum, _singleTrackFile, nameSpec), Artist = _standardArtist, Album = _standardAlbum, Tracks = _singleTrack, TrackFile = _singleTrackFile }; return(result); }
public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null, List <CustomFormat> customFormats = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } if (!namingConfig.RenameMovies) { return(GetOriginalTitle(movieFile)); } var pattern = namingConfig.StandardMovieFormat; var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance); UpdateMediaInfoIfNeeded(pattern, movieFile, movie); AddMovieTokens(tokenHandlers, movie); AddReleaseDateTokens(tokenHandlers, movie.Year); AddIdTokens(tokenHandlers, movie); AddQualityTokens(tokenHandlers, movie, movieFile); AddMediaInfoTokens(tokenHandlers, movieFile); AddMovieFileTokens(tokenHandlers, movieFile); AddTagsTokens(tokenHandlers, movieFile); AddCustomFormats(tokenHandlers, movie, movieFile, customFormats); var splitPatterns = pattern.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); var components = new List <string>(); foreach (var s in splitPatterns) { var splitPattern = s; var component = ReplaceTokens(splitPattern, tokenHandlers, namingConfig).Trim(); component = FileNameCleanupRegex.Replace(component, match => match.Captures[0].Value[0].ToString()); component = TrimSeparatorsRegex.Replace(component, string.Empty); component = ReplaceReservedDeviceNames(component); if (component.IsNotNullOrWhiteSpace()) { components.Add(component); } } return(Path.Combine(components.ToArray())); }
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec) { return(new BasicNamingConfig()); //For now let's be lazy var episodeFormat = GetEpisodeFormat(nameSpec.StandardEpisodeFormat).LastOrDefault(); if (episodeFormat == null) { return(new BasicNamingConfig()); } var basicNamingConfig = new BasicNamingConfig { Separator = episodeFormat.Separator, NumberStyle = episodeFormat.SeasonEpisodePattern }; var titleTokens = TitleRegex.Matches(nameSpec.StandardEpisodeFormat); foreach (Match match in titleTokens) { var separator = match.Groups["separator"].Value; var token = match.Groups["token"].Value; if (!separator.Equals(" ")) { basicNamingConfig.ReplaceSpaces = true; } if (token.StartsWith("{Series", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeSeriesTitle = true; } if (token.StartsWith("{Episode", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeEpisodeTitle = true; } if (token.StartsWith("{Quality", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeQuality = true; } } return(basicNamingConfig); }
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec) { var trackFormat = GetTrackFormat(nameSpec.StandardTrackFormat).LastOrDefault(); if (trackFormat == null) { return(new BasicNamingConfig()); } var basicNamingConfig = new BasicNamingConfig { Separator = trackFormat.Separator }; var titleTokens = TitleRegex.Matches(nameSpec.StandardTrackFormat); foreach (Match match in titleTokens) { var separator = match.Groups["separator"].Value; var token = match.Groups["token"].Value; if (!separator.Equals(" ")) { basicNamingConfig.ReplaceSpaces = true; } if (token.StartsWith("{Artist", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeArtistName = true; } if (token.StartsWith("{Album", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeAlbumTitle = true; } if (token.StartsWith("{Quality", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeQuality = true; } } return(basicNamingConfig); }
public string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance); AddSeriesTokens(tokenHandlers, series); AddIdTokens(tokenHandlers, series); AddSeasonTokens(tokenHandlers, seasonNumber); var format = seasonNumber == 0 ? namingConfig.SpecialsFolderFormat : namingConfig.SeasonFolderFormat; var folderName = ReplaceTokens(format, tokenHandlers, namingConfig); return(CleanFolderName(folderName)); }
public string BuildMoviePath(Movie movie, NamingConfig namingConfig = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } var path = movie.Path; var directory = new DirectoryInfo(path).Name; var parentDirectoryPath = new DirectoryInfo(path).Parent.FullName; var movieFile = movie.MovieFile; var pattern = namingConfig.MovieFolderFormat; var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance); AddMovieTokens(tokenHandlers, movie); AddReleaseDateTokens(tokenHandlers, movie.Year); AddImdbIdTokens(tokenHandlers, movie.ImdbId); if (movie.MovieFileId != 0) { movieFile.LazyLoad(); AddQualityTokens(tokenHandlers, movie, movieFile); AddMediaInfoTokens(tokenHandlers, movieFile); AddMovieFileTokens(tokenHandlers, movieFile); AddTagsTokens(tokenHandlers, movieFile); } else { AddMovieFileTokens(tokenHandlers, new MovieFile { SceneName = $"{movie.Title} {movie.Year}", RelativePath = $"{movie.Title} {movie.Year}" }); } var directoryName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim(); directoryName = FileNameCleanupRegex.Replace(directoryName, match => match.Captures[0].Value[0].ToString()); directoryName = TrimSeparatorsRegex.Replace(directoryName, string.Empty); return(Path.Combine(parentDirectoryPath, directoryName)); }
private string ReplaceTokens(string pattern, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, NamingConfig namingConfig) { return TitleRegex.Replace(pattern, match => ReplaceToken(match, tokenHandlers, namingConfig)); }
private string ReplaceToken(Match match, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, NamingConfig namingConfig) { var tokenMatch = new TokenMatch { RegexMatch = match, Prefix = match.Groups["prefix"].Value, Separator = match.Groups["separator"].Value, Suffix = match.Groups["suffix"].Value, Token = match.Groups["token"].Value, CustomFormat = match.Groups["customFormat"].Value }; if (tokenMatch.CustomFormat.IsNullOrWhiteSpace()) { tokenMatch.CustomFormat = null; } var tokenHandler = tokenHandlers.GetValueOrDefault(tokenMatch.Token, m => string.Empty); var replacementText = tokenHandler(tokenMatch).Trim(); if (tokenMatch.Token.All(t => !char.IsLetter(t) || char.IsLower(t))) { replacementText = replacementText.ToLower(); } else if (tokenMatch.Token.All(t => !char.IsLetter(t) || char.IsUpper(t))) { replacementText = replacementText.ToUpper(); } if (!tokenMatch.Separator.IsNullOrWhiteSpace()) { replacementText = replacementText.Replace(" ", tokenMatch.Separator); } replacementText = CleanFileName(replacementText, namingConfig.ReplaceIllegalCharacters); if (!replacementText.IsNullOrWhiteSpace()) { replacementText = tokenMatch.Prefix + replacementText + tokenMatch.Suffix; } return replacementText; }
private string AddSeasonEpisodeNumberingTokens(string pattern, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, List<Episode> episodes, NamingConfig namingConfig) { var episodeFormats = GetEpisodeFormat(pattern).DistinctBy(v => v.SeasonEpisodePattern).ToList(); int index = 1; foreach (var episodeFormat in episodeFormats) { var seasonEpisodePattern = episodeFormat.SeasonEpisodePattern; string formatPattern; switch ((MultiEpisodeStyle)namingConfig.MultiEpisodeStyle) { case MultiEpisodeStyle.Duplicate: formatPattern = episodeFormat.Separator + episodeFormat.SeasonEpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Repeat: formatPattern = episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Scene: formatPattern = "-" + episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Range: formatPattern = "-" + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatRangeNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.PrefixedRange: formatPattern = "-" + episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatRangeNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; //MultiEpisodeStyle.Extend default: formatPattern = "-" + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; } var token = string.Format("{{Season Episode{0}}}", index++); pattern = pattern.Replace(episodeFormat.SeasonEpisodePattern, token); tokenHandlers[token] = m => seasonEpisodePattern; } AddSeasonTokens(tokenHandlers, episodes.First().SeasonNumber); if (episodes.Count > 1) { tokenHandlers["{Episode}"] = m => episodes.First().EpisodeNumber.ToString(m.CustomFormat) + "-" + episodes.Last().EpisodeNumber.ToString(m.CustomFormat); } else { tokenHandlers["{Episode}"] = m => episodes.First().EpisodeNumber.ToString(m.CustomFormat); } return pattern; }
private string AddAbsoluteNumberingTokens(string pattern, Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Series series, List<Episode> episodes, NamingConfig namingConfig) { var absoluteEpisodeFormats = GetAbsoluteFormat(pattern).DistinctBy(v => v.AbsoluteEpisodePattern).ToList(); int index = 1; foreach (var absoluteEpisodeFormat in absoluteEpisodeFormats) { if (series.SeriesType != SeriesTypes.Anime) { pattern = pattern.Replace(absoluteEpisodeFormat.AbsoluteEpisodePattern, ""); continue; } var absoluteEpisodePattern = absoluteEpisodeFormat.AbsoluteEpisodePattern; string formatPattern; switch ((MultiEpisodeStyle) namingConfig.MultiEpisodeStyle) { case MultiEpisodeStyle.Duplicate: formatPattern = absoluteEpisodeFormat.Separator + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Repeat: var repeatSeparator = absoluteEpisodeFormat.Separator.Trim().IsNullOrWhiteSpace() ? " " : absoluteEpisodeFormat.Separator.Trim(); formatPattern = repeatSeparator + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Scene: formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Range: case MultiEpisodeStyle.PrefixedRange: formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; var eps = new List<Episode> {episodes.First()}; if (episodes.Count > 1) eps.Add(episodes.Last()); absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, eps); break; //MultiEpisodeStyle.Extend default: formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; } var token = string.Format("{{Absolute Pattern{0}}}", index++); pattern = pattern.Replace(absoluteEpisodeFormat.AbsoluteEpisodePattern, token); tokenHandlers[token] = m => absoluteEpisodePattern; } return pattern; }
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec) { var episodeFormat = GetEpisodeFormat(nameSpec.StandardEpisodeFormat).LastOrDefault(); if (episodeFormat == null) { return new BasicNamingConfig(); } var basicNamingConfig = new BasicNamingConfig { Separator = episodeFormat.Separator, NumberStyle = episodeFormat.SeasonEpisodePattern }; var titleTokens = TitleRegex.Matches(nameSpec.StandardEpisodeFormat); foreach (Match match in titleTokens) { var separator = match.Groups["separator"].Value; var token = match.Groups["token"].Value; if (!separator.Equals(" ")) { basicNamingConfig.ReplaceSpaces = true; } if (token.StartsWith("{Series", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeSeriesTitle = true; } if (token.StartsWith("{Episode", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeEpisodeTitle = true; } if (token.StartsWith("{Quality", StringComparison.InvariantCultureIgnoreCase)) { basicNamingConfig.IncludeQuality = true; } } return basicNamingConfig; }
public string GetSeasonFolder(Series series, int seasonNumber, NamingConfig namingConfig = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance); AddSeriesTokens(tokenHandlers, series); AddSeasonTokens(tokenHandlers, seasonNumber); return CleanFolderName(ReplaceTokens(namingConfig.SeasonFolderFormat, tokenHandlers, namingConfig)); }
private String AddAbsoluteNumberingTokens(String pattern, Dictionary <String, Func <TokenMatch, String> > tokenHandlers, Series series, List <Episode> episodes, NamingConfig namingConfig) { var absoluteEpisodeFormats = GetAbsoluteFormat(pattern).DistinctBy(v => v.AbsoluteEpisodePattern).ToList(); int index = 1; foreach (var absoluteEpisodeFormat in absoluteEpisodeFormats) { if (series.SeriesType != SeriesTypes.Anime) { pattern = pattern.Replace(absoluteEpisodeFormat.AbsoluteEpisodePattern, ""); continue; } var absoluteEpisodePattern = absoluteEpisodeFormat.AbsoluteEpisodePattern; string formatPattern; switch ((MultiEpisodeStyle)namingConfig.MultiEpisodeStyle) { case MultiEpisodeStyle.Duplicate: formatPattern = absoluteEpisodeFormat.Separator + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Repeat: var repeatSeparator = absoluteEpisodeFormat.Separator.Trim().IsNullOrWhiteSpace() ? " " : absoluteEpisodeFormat.Separator.Trim(); formatPattern = repeatSeparator + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Scene: formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Range: case MultiEpisodeStyle.PrefixedRange: formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; var eps = new List <Episode> { episodes.First() }; if (episodes.Count > 1) { eps.Add(episodes.Last()); } absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, eps); break; //MultiEpisodeStyle.Extend default: formatPattern = "-" + absoluteEpisodeFormat.AbsoluteEpisodePattern; absoluteEpisodePattern = FormatAbsoluteNumberTokens(absoluteEpisodePattern, formatPattern, episodes); break; } var token = String.Format("{{Absolute Pattern{0}}}", index++); pattern = pattern.Replace(absoluteEpisodeFormat.AbsoluteEpisodePattern, token); tokenHandlers[token] = m => absoluteEpisodePattern; } return(pattern); }
public string GetSeasonFolder(string seriesTitle, int seasonNumber, NamingConfig namingConfig) { var tokenValues = new Dictionary<string, string>(FilenameBuilderTokenEqualityComparer.Instance); tokenValues.Add("{Series Title}", seriesTitle); var seasonFolder = ReplaceSeasonTokens(namingConfig.SeasonFolderFormat, seasonNumber); return ReplaceTokens(seasonFolder, tokenValues); }
public string GetSeriesFolder(string seriesTitle, NamingConfig namingConfig) { seriesTitle = CleanFilename(seriesTitle); var tokenValues = new Dictionary<string, string>(FilenameBuilderTokenEqualityComparer.Instance); tokenValues.Add("{Series Title}", seriesTitle); return ReplaceTokens(namingConfig.SeriesFolderFormat, tokenValues); }
public void Save(NamingConfig namingConfig) { _repository.Upsert(namingConfig); }
public string BuildFileName(List <Episode> episodes, Series series, EpisodeFile episodeFile, string extension = "", NamingConfig namingConfig = null, List <string> preferredWords = null) { return(BuildFileName(episodes, series, episodeFile, extension, LongPathSupport.MaxFilePathLength, namingConfig, preferredWords)); }
public NamingConfig Save(NamingConfig namingConfig) { return _repository.Upsert(namingConfig); }
public string BuildFilename(IList<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig namingConfig) { if (!namingConfig.RenameEpisodes) { if (String.IsNullOrWhiteSpace(episodeFile.SceneName)) { return Path.GetFileNameWithoutExtension(episodeFile.Path); } return episodeFile.SceneName; } if (String.IsNullOrWhiteSpace(namingConfig.StandardEpisodeFormat) && series.SeriesType == SeriesTypes.Standard) { throw new NamingFormatException("Standard episode format cannot be null"); } if (String.IsNullOrWhiteSpace(namingConfig.DailyEpisodeFormat) && series.SeriesType == SeriesTypes.Daily) { throw new NamingFormatException("Daily episode format cannot be null"); } var sortedEpisodes = episodes.OrderBy(e => e.EpisodeNumber).ToList(); var pattern = namingConfig.StandardEpisodeFormat; var episodeTitles = new List<string> { sortedEpisodes.First().Title.TrimEnd(EpisodeTitleTrimCharaters) }; var tokenValues = new Dictionary<string, string>(FilenameBuilderTokenEqualityComparer.Instance); tokenValues.Add("{Series Title}", series.Title); tokenValues.Add("{Original Title}", episodeFile.SceneName); tokenValues.Add("{Release Group}", episodeFile.ReleaseGroup); if (series.SeriesType == SeriesTypes.Daily) { pattern = namingConfig.DailyEpisodeFormat; if (!String.IsNullOrWhiteSpace(episodes.First().AirDate)) { tokenValues.Add("{Air Date}", episodes.First().AirDate.Replace('-', ' ')); } else { tokenValues.Add("{Air Date}", "Unknown"); } } var episodeFormat = GetEpisodeFormat(pattern); if (episodeFormat != null) { pattern = pattern.Replace(episodeFormat.SeasonEpisodePattern, "{Season Episode}"); var seasonEpisodePattern = episodeFormat.SeasonEpisodePattern; foreach (var episode in sortedEpisodes.Skip(1)) { switch ((MultiEpisodeStyle)namingConfig.MultiEpisodeStyle) { case MultiEpisodeStyle.Duplicate: seasonEpisodePattern += episodeFormat.Separator + episodeFormat.SeasonEpisodePattern; break; case MultiEpisodeStyle.Repeat: seasonEpisodePattern += episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; break; case MultiEpisodeStyle.Scene: seasonEpisodePattern += "-" + episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; break; //MultiEpisodeStyle.Extend default: seasonEpisodePattern += "-" + episodeFormat.EpisodePattern; break; } episodeTitles.Add(episode.Title.TrimEnd(EpisodeTitleTrimCharaters)); } seasonEpisodePattern = ReplaceNumberTokens(seasonEpisodePattern, sortedEpisodes); tokenValues.Add("{Season Episode}", seasonEpisodePattern); } tokenValues.Add("{Episode Title}", GetEpisodeTitle(episodeTitles)); tokenValues.Add("{Quality Title}", GetQualityTitle(episodeFile.Quality)); var filename = ReplaceTokens(pattern, tokenValues).Trim(); filename = FilenameCleanupRegex.Replace(filename, match => match.Captures[0].Value[0].ToString() ); return CleanFilename(filename); }
private string BuildFileName(List <Episode> episodes, Series series, EpisodeFile episodeFile, string extension, int maxPath, NamingConfig namingConfig = null, List <string> preferredWords = null) { if (namingConfig == null) { namingConfig = _namingConfigService.GetConfig(); } if (!namingConfig.RenameEpisodes) { return(GetOriginalTitle(episodeFile) + extension); } 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; episodes = episodes.OrderBy(e => e.SeasonNumber).ThenBy(e => e.EpisodeNumber).ToList(); if (series.SeriesType == SeriesTypes.Daily && episodes.First().SeasonNumber > 0) { pattern = namingConfig.DailyEpisodeFormat; } if (series.SeriesType == SeriesTypes.Anime && episodes.All(e => e.AbsoluteEpisodeNumber.HasValue)) { pattern = namingConfig.AnimeEpisodeFormat; } var splitPatterns = pattern.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); var components = new List <string>(); for (var i = 0; i < splitPatterns.Length; i++) { var splitPattern = splitPatterns[i]; var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance); splitPattern = AddSeasonEpisodeNumberingTokens(splitPattern, tokenHandlers, episodes, namingConfig); splitPattern = AddAbsoluteNumberingTokens(splitPattern, tokenHandlers, series, episodes, namingConfig); UpdateMediaInfoIfNeeded(splitPattern, episodeFile, series); AddSeriesTokens(tokenHandlers, series); AddIdTokens(tokenHandlers, series); AddEpisodeTokens(tokenHandlers, episodes); AddEpisodeTitlePlaceholderTokens(tokenHandlers); AddEpisodeFileTokens(tokenHandlers, episodeFile); AddQualityTokens(tokenHandlers, series, episodeFile); AddMediaInfoTokens(tokenHandlers, episodeFile); AddPreferredWords(tokenHandlers, series, episodeFile, preferredWords); var component = ReplaceTokens(splitPattern, tokenHandlers, namingConfig, true).Trim(); var maxPathSegmentLength = Math.Min(LongPathSupport.MaxFileNameLength, maxPath); if (i == splitPatterns.Length - 1) { maxPathSegmentLength -= extension.GetByteCount(); } var maxEpisodeTitleLength = maxPathSegmentLength - GetLengthWithoutEpisodeTitle(component, namingConfig); AddEpisodeTitleTokens(tokenHandlers, episodes, maxEpisodeTitleLength); component = ReplaceTokens(component, tokenHandlers, namingConfig).Trim(); component = FileNameCleanupRegex.Replace(component, match => match.Captures[0].Value[0].ToString()); component = TrimSeparatorsRegex.Replace(component, string.Empty); component = component.Replace("{ellipsis}", "..."); components.Add(component); } return(string.Join(Path.DirectorySeparatorChar.ToString(), components) + extension); }
private string ReplaceToken(Match match, Dictionary <string, Func <TokenMatch, string> > tokenHandlers, NamingConfig namingConfig) { var tokenMatch = new TokenMatch { RegexMatch = match, Prefix = match.Groups["prefix"].Value, Separator = match.Groups["separator"].Value, Suffix = match.Groups["suffix"].Value, Token = match.Groups["token"].Value, CustomFormat = match.Groups["customFormat"].Value }; if (tokenMatch.CustomFormat.IsNullOrWhiteSpace()) { tokenMatch.CustomFormat = null; } var tokenHandler = tokenHandlers.GetValueOrDefault(tokenMatch.Token, m => string.Empty); var replacementText = tokenHandler(tokenMatch).Trim(); if (tokenMatch.Token.All(t => !char.IsLetter(t) || char.IsLower(t))) { replacementText = replacementText.ToLower(); } else if (tokenMatch.Token.All(t => !char.IsLetter(t) || char.IsUpper(t))) { replacementText = replacementText.ToUpper(); } if (!tokenMatch.Separator.IsNullOrWhiteSpace()) { replacementText = replacementText.Replace(" ", tokenMatch.Separator); } replacementText = CleanFileName(replacementText, namingConfig.ReplaceIllegalCharacters, namingConfig.ColonReplacementFormat); if (!replacementText.IsNullOrWhiteSpace()) { replacementText = tokenMatch.Prefix + replacementText + tokenMatch.Suffix; } return(replacementText); }
public string BuildFilePath(List <Episode> episodes, Series series, EpisodeFile episodeFile, string extension, NamingConfig namingConfig = null, List <string> preferredWords = null) { Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace(); var seasonPath = BuildSeasonPath(series, episodes.First().SeasonNumber); var remainingPathLength = LongPathSupport.MaxFilePathLength - seasonPath.GetByteCount() - 1; var fileName = BuildFileName(episodes, series, episodeFile, extension, remainingPathLength, namingConfig, preferredWords); return(Path.Combine(seasonPath, fileName)); }
public string GetSeriesFolderSample(NamingConfig nameSpec) { return _buildFileNames.GetSeriesFolder(_standardSeries.Title, nameSpec); }
private string ReplaceToken(Match match, Dictionary <string, Func <TokenMatch, string> > tokenHandlers, NamingConfig namingConfig, bool escape) { if (match.Groups["escaped"].Success) { if (escape) { return(match.Value); } else if (match.Value == "{{") { return("{"); } else if (match.Value == "}}") { return("}"); } } var tokenMatch = new TokenMatch { RegexMatch = match, Prefix = match.Groups["prefix"].Value, Separator = match.Groups["separator"].Value, Suffix = match.Groups["suffix"].Value, Token = match.Groups["token"].Value, CustomFormat = match.Groups["customFormat"].Value }; if (tokenMatch.CustomFormat.IsNullOrWhiteSpace()) { tokenMatch.CustomFormat = null; } var tokenHandler = tokenHandlers.GetValueOrDefault(tokenMatch.Token, m => string.Empty); var replacementText = tokenHandler(tokenMatch); if (replacementText == null) { // Preserve original token if handler returned null return(match.Value); } replacementText = replacementText.Trim(); if (tokenMatch.Token.All(t => !char.IsLetter(t) || char.IsLower(t))) { replacementText = replacementText.ToLower(); } else if (tokenMatch.Token.All(t => !char.IsLetter(t) || char.IsUpper(t))) { replacementText = replacementText.ToUpper(); } if (!tokenMatch.Separator.IsNullOrWhiteSpace()) { replacementText = replacementText.Replace(" ", tokenMatch.Separator); } replacementText = CleanFileName(replacementText, namingConfig.ReplaceIllegalCharacters); if (!replacementText.IsNullOrWhiteSpace()) { replacementText = tokenMatch.Prefix + replacementText + tokenMatch.Suffix; } if (escape) { replacementText = replacementText.Replace("{", "{{").Replace("}", "}}"); } return(replacementText); }
public string BuildFilename(IList<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig nameSpec) { if (!nameSpec.RenameEpisodes) { if (String.IsNullOrWhiteSpace(episodeFile.SceneName)) { return Path.GetFileNameWithoutExtension(episodeFile.Path); } return episodeFile.SceneName; } var sortedEpisodes = episodes.OrderBy(e => e.EpisodeNumber); var numberStyle = GetNumberStyle(nameSpec.NumberStyle); var episodeNames = new List<string> { Parser.Parser.CleanupEpisodeTitle(sortedEpisodes.First().Title) }; var result = String.Empty; if (nameSpec.IncludeSeriesTitle) { result += series.Title + nameSpec.Separator; } if (series.SeriesType == SeriesTypes.Standard) { result += numberStyle.Pattern.Replace("%0e", String.Format("{0:00}", sortedEpisodes.First().EpisodeNumber)); if (episodes.Count > 1) { var multiEpisodeStyle = GetMultiEpisodeStyle(nameSpec.MultiEpisodeStyle); foreach (var episode in sortedEpisodes.Skip(1)) { if (multiEpisodeStyle.Name == "Duplicate") { result += nameSpec.Separator + numberStyle.Pattern; } else { result += multiEpisodeStyle.Pattern; } result = result.Replace("%0e", String.Format("{0:00}", episode.EpisodeNumber)); episodeNames.Add(Parser.Parser.CleanupEpisodeTitle(episode.Title)); } } result = result .Replace("%s", String.Format("{0}", episodes.First().SeasonNumber)) .Replace("%0s", String.Format("{0:00}", episodes.First().SeasonNumber)) .Replace("%x", numberStyle.EpisodeSeparator) .Replace("%p", nameSpec.Separator); } else { if (!String.IsNullOrEmpty(episodes.First().AirDate)) result += episodes.First().AirDate; else result += "Unknown"; } if (nameSpec.IncludeEpisodeTitle) { if (episodeNames.Distinct().Count() == 1) result += nameSpec.Separator + episodeNames.First(); else result += nameSpec.Separator + String.Join(" + ", episodeNames.Distinct()); } if (nameSpec.IncludeQuality) { result += String.Format(" [{0}]", episodeFile.Quality.Quality); if (episodeFile.Quality.Proper) result += " [Proper]"; } if (nameSpec.ReplaceSpaces) result = result.Replace(' ', '.'); _logger.Trace("New File Name is: [{0}]", result.Trim()); return CleanFilename(result.Trim()); }
public BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec) { return(new BasicNamingConfig()); //For now let's be lazy }
public string GetSeriesFolderSample(NamingConfig nameSpec) { return(_buildFileNames.GetSeriesFolder(_standardSeries, nameSpec)); }
private string ReplaceTokens(string pattern, Dictionary <string, Func <TokenMatch, string> > tokenHandlers, NamingConfig namingConfig) { return(TitleRegex.Replace(pattern, match => ReplaceToken(match, tokenHandlers, namingConfig))); }
public string GetSeasonFolderSample(NamingConfig nameSpec) { return(_buildFileNames.GetSeasonFolder(_standardSeries, _episode1.SeasonNumber, nameSpec)); }
public string GetSeasonFolderSample(NamingConfig nameSpec) { return _buildFileNames.GetSeasonFolder(_standardSeries.Title, _episode1.SeasonNumber, nameSpec); }
private string BuildSample(List <Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig nameSpec) { try { return(_buildFileNames.BuildFileName(episodes, series, episodeFile, nameSpec)); } catch (NamingFormatException) { return(String.Empty); } }
private string BuildSample(List<Episode> episodes, Series series, EpisodeFile episodeFile, NamingConfig nameSpec) { try { return _buildFileNames.BuildFilename(episodes, series, episodeFile, nameSpec); } catch (NamingFormatException) { return String.Empty; } }
private String AddSeasonEpisodeNumberingTokens(String pattern, Dictionary <String, Func <TokenMatch, String> > tokenHandlers, List <Episode> episodes, NamingConfig namingConfig) { var episodeFormats = GetEpisodeFormat(pattern).DistinctBy(v => v.SeasonEpisodePattern).ToList(); int index = 1; foreach (var episodeFormat in episodeFormats) { var seasonEpisodePattern = episodeFormat.SeasonEpisodePattern; string formatPattern; switch ((MultiEpisodeStyle)namingConfig.MultiEpisodeStyle) { case MultiEpisodeStyle.Duplicate: formatPattern = episodeFormat.Separator + episodeFormat.SeasonEpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Repeat: formatPattern = episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Scene: formatPattern = "-" + episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.Range: formatPattern = "-" + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatRangeNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; case MultiEpisodeStyle.PrefixedRange: formatPattern = "-" + episodeFormat.EpisodeSeparator + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatRangeNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; //MultiEpisodeStyle.Extend default: formatPattern = "-" + episodeFormat.EpisodePattern; seasonEpisodePattern = FormatNumberTokens(seasonEpisodePattern, formatPattern, episodes); break; } var token = String.Format("{{Season Episode{0}}}", index++); pattern = pattern.Replace(episodeFormat.SeasonEpisodePattern, token); tokenHandlers[token] = m => seasonEpisodePattern; } AddSeasonTokens(tokenHandlers, episodes.First().SeasonNumber); if (episodes.Count > 1) { tokenHandlers["{Episode}"] = m => episodes.First().EpisodeNumber.ToString(m.CustomFormat) + "-" + episodes.Last().EpisodeNumber.ToString(m.CustomFormat); } else { tokenHandlers["{Episode}"] = m => episodes.First().EpisodeNumber.ToString(m.CustomFormat); } return(pattern); }
public SampleResult GetDailySample(NamingConfig nameSpec) { var result = new SampleResult { FileName = BuildSample(_singleEpisode, _dailySeries, _dailyEpisodeFile, nameSpec), Series = _dailySeries, Episodes = _singleEpisode, EpisodeFile = _dailyEpisodeFile }; return result; }
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).Trim(); fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString()); fileName = TrimSeparatorsRegex.Replace(fileName, String.Empty); return(fileName); }
public SampleResult GetAnimeMultiEpisodeSample(NamingConfig nameSpec) { var result = new SampleResult { FileName = BuildSample(_multiEpisodes, _animeSeries, _animeMultiEpisodeFile, nameSpec), Series = _animeSeries, Episodes = _multiEpisodes, EpisodeFile = _animeMultiEpisodeFile }; return result; }