public void Setup() { _series = Builder <Series> .CreateNew() .With(s => s.Title = "South Park") .Build(); _namingConfig = NamingConfig.Default; _namingConfig.RenameEpisodes = true; Mocker.GetMock <INamingConfigService>() .Setup(c => c.GetConfig()).Returns(_namingConfig); _episode1 = Builder <Episode> .CreateNew() .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 15) .With(e => e.EpisodeNumber = 6) .With(e => e.AbsoluteEpisodeNumber = 100) .Build(); _episodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "SonarrTest" }; _preferredWords = new PreferredWordMatchResults() { All = new List <string>() { "x265", "extended" }, ByReleaseProfile = new Dictionary <string, List <string> >() { { "CodecProfile", new List <string>() { "x265" } }, { "EditionProfile", new List <string>() { "extended" } } } }; Mocker.GetMock <IQualityDefinitionService>() .Setup(v => v.Get(Moq.It.IsAny <Quality>())) .Returns <Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v)); }
private void AddPreferredWords(Dictionary <string, Func <TokenMatch, string> > tokenHandlers, Series series, EpisodeFile episodeFile, PreferredWordMatchResults preferredWords = null) { if (preferredWords == null) { preferredWords = _preferredWordService.GetMatchingPreferredWords(series, episodeFile.GetSceneOrFileName()); } tokenHandlers["{Preferred Words}"] = m => { var profileName = ""; if (m.CustomFormat != null) { profileName = m.CustomFormat.Trim(); } if (profileName.IsNullOrWhiteSpace()) { return(string.Join(" ", preferredWords.All)); } if (preferredWords.ByReleaseProfile.TryGetValue(profileName, out var profilePreferredWords)) { return(string.Join(" ", profilePreferredWords)); } return(string.Empty); }; }
public string BuildFilePath(List <Episode> episodes, Series series, EpisodeFile episodeFile, string extension, NamingConfig namingConfig = null, PreferredWordMatchResults 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 BuildFileName(List <Episode> episodes, Series series, EpisodeFile episodeFile, string extension = "", NamingConfig namingConfig = null, PreferredWordMatchResults preferredWords = null) { return(BuildFileName(episodes, series, episodeFile, extension, LongPathSupport.MaxFilePathLength, namingConfig, preferredWords)); }
private string BuildFileName(List <Episode> episodes, Series series, EpisodeFile episodeFile, string extension, int maxPath, NamingConfig namingConfig = null, PreferredWordMatchResults 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}", "..."); component = ReplaceReservedDeviceNames(component); components.Add(component); } return(string.Join(Path.DirectorySeparatorChar.ToString(), components) + extension); }
public FileNameSampleService(IBuildFileNames buildFileNames) { _buildFileNames = buildFileNames; _standardSeries = new Series { SeriesType = SeriesTypes.Standard, Title = "The Series Title!", Year = 2010, ImdbId = "tt12345", TvdbId = 12345, TvMazeId = 54321 }; _dailySeries = new Series { SeriesType = SeriesTypes.Daily, Title = "The Series Title!", Year = 2010, ImdbId = "tt12345", TvdbId = 12345, TvMazeId = 54321 }; _animeSeries = new Series { SeriesType = SeriesTypes.Anime, Title = "The Series Title!", Year = 2010, ImdbId = "tt12345", TvdbId = 12345, TvMazeId = 54321 }; _episode1 = new Episode { SeasonNumber = 1, EpisodeNumber = 1, Title = "Episode Title (1)", AirDate = "2013-10-30", AbsoluteEpisodeNumber = 1, }; _episode2 = new Episode { SeasonNumber = 1, EpisodeNumber = 2, Title = "Episode Title (2)", AbsoluteEpisodeNumber = 2 }; _episode3 = new Episode { SeasonNumber = 1, EpisodeNumber = 3, Title = "Episode Title (3)", AbsoluteEpisodeNumber = 3 }; _singleEpisode = new List <Episode> { _episode1 }; _multiEpisodes = new List <Episode> { _episode1, _episode2, _episode3 }; var mediaInfo = new MediaInfoModel() { VideoCodec = "AVC", VideoBitDepth = 10, VideoColourPrimaries = "BT.2020", VideoTransferCharacteristics = "HLG", AudioFormat = "DTS", AudioChannelsContainer = 6, AudioChannelPositions = "3/2/0.1", AudioLanguages = "English", Subtitles = "English/German" }; var mediaInfoAnime = new MediaInfoModel() { VideoCodec = "AVC", VideoBitDepth = 10, VideoColourPrimaries = "BT.2020", VideoTransferCharacteristics = "HLG", AudioFormat = "DTS", AudioChannelsContainer = 6, AudioChannelPositions = "3/2/0.1", AudioLanguages = "Japanese", Subtitles = "Japanese/English" }; _singleEpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p, new Revision(2)), RelativePath = "Series.Title.S01E01.720p.HDTV.x264-EVOLVE.mkv", SceneName = "Series.Title.S01E01.720p.HDTV.x264-EVOLVE", ReleaseGroup = "RlsGrp", MediaInfo = mediaInfo }; _multiEpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p, new Revision(2)), RelativePath = "Series.Title.S01E01-E03.720p.HDTV.x264-EVOLVE.mkv", SceneName = "Series.Title.S01E01-E03.720p.HDTV.x264-EVOLVE", ReleaseGroup = "RlsGrp", MediaInfo = mediaInfo, }; _dailyEpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p, new Revision(2)), RelativePath = "Series.Title.2013.10.30.HDTV.x264-EVOLVE.mkv", SceneName = "Series.Title.2013.10.30.HDTV.x264-EVOLVE", ReleaseGroup = "RlsGrp", MediaInfo = mediaInfo }; _animeEpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p, new Revision(2)), RelativePath = "[RlsGroup] Series Title - 001 [720p].mkv", SceneName = "[RlsGroup] Series Title - 001 [720p]", ReleaseGroup = "RlsGrp", MediaInfo = mediaInfoAnime }; _animeMultiEpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p, new Revision(2)), RelativePath = "[RlsGroup] Series Title - 001 - 103 [720p].mkv", SceneName = "[RlsGroup] Series Title - 001 - 103 [720p]", ReleaseGroup = "RlsGrp", MediaInfo = mediaInfoAnime }; _preferredWords = new PreferredWordMatchResults() { All = new List <string>() { "iNTERNAL" } }; }