public LocalMovie GetLocalMovie(string filename, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource) { ParsedMovieInfo parsedMovieInfo; if (folderInfo != null) { parsedMovieInfo = folderInfo.JsonClone(); parsedMovieInfo.Quality = QualityParser.ParseQuality(Path.GetFileName(filename)); } else { parsedMovieInfo = Parser.ParseMoviePath(filename, _config.ParsingLeniency > 0); } if (parsedMovieInfo == null) { if (MediaFileExtensions.Extensions.Contains(Path.GetExtension(filename))) { _logger.Warn("Unable to parse movie info from path {0}", filename); } return(null); } return(new LocalMovie { Movie = movie, Quality = parsedMovieInfo.Quality, Path = filename, ParsedMovieInfo = parsedMovieInfo, ExistingFile = movie.Path.IsParentPath(filename) }); }
public void Setup() { _movieFile = Builder <MovieFile> .CreateNew().With(m => m.MovieId = 0).Build(); _oldQuality = new QualityModel(Quality.Bluray720p); _movieFile.Quality = _oldQuality; _newQuality = _oldQuality.JsonClone(); var format = new CustomFormats.CustomFormat("Awesome Format"); format.Id = 1; _newQuality.CustomFormats = new List <CustomFormats.CustomFormat> { format }; _newInfo = new ParsedMovieInfo { Quality = _newQuality }; Mocker.GetMock <IMediaFileService>().Setup(s => s.GetMovies(It.IsAny <IEnumerable <int> >())) .Returns(new List <MovieFile> { _movieFile }); Mocker.GetMock <IHistoryService>().Setup(s => s.FindByMovieId(It.IsAny <int>())) .Returns(new List <History.History>()); }
public ParsedMovieInfo AugmentMovieInfo(ParsedMovieInfo movieInfo, object helper) { if (helper is MovieHistory history && history.EventType == MovieHistoryEventType.Grabbed) { //First we create a release info from history data. var releaseInfo = new ReleaseInfo(); if (int.TryParse(history.Data.GetValueOrDefault("indexerId"), out var indexerId)) { releaseInfo.IndexerId = indexerId; } if (long.TryParse(history.Data.GetValueOrDefault("size"), out var size)) { releaseInfo.Size = size; } if (Enum.TryParse(history.Data.GetValueOrDefault("indexerFlags"), true, out IndexerFlags indexerFlags)) { releaseInfo.IndexerFlags = indexerFlags; } //Now we run the release info augmenters from the history release info. TODO: Add setting to only do that if you trust your indexer! var releaseInfoAugmenters = _augmenters.Where(a => a.Value.HelperType.IsInstanceOfType(releaseInfo)); foreach (var augmenter in releaseInfoAugmenters) { movieInfo = augmenter.Value.AugmentMovieInfo(movieInfo, releaseInfo); } } return(movieInfo); }
public List <CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo) { var matches = MatchFormatTags(movieInfo); var goodMatches = matches.Where(m => m.GoodMatch); return(goodMatches.Select(r => r.CustomFormat).ToList()); }
public List <ImportDecision> GetImportDecisions(List <string> videoFiles, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource, bool filterExistingFiles) { var newFiles = filterExistingFiles ? _mediaFileService.FilterExistingFiles(videoFiles.ToList(), movie) : videoFiles.ToList(); _logger.Debug("Analyzing {0}/{1} files.", newFiles.Count, videoFiles.Count); ParsedMovieInfo downloadClientItemInfo = null; if (downloadClientItem != null) { downloadClientItemInfo = Parser.Parser.ParseMovieTitle(downloadClientItem.Title); downloadClientItemInfo = _parsingService.EnhanceMovieInfo(downloadClientItemInfo); } var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie); var decisions = new List <ImportDecision>(); foreach (var file in newFiles) { var localMovie = new LocalMovie { Movie = movie, DownloadClientMovieInfo = downloadClientItemInfo, FolderMovieInfo = folderInfo, Path = file, SceneSource = sceneSource, ExistingFile = movie.Path.IsParentPath(file) }; decisions.AddIfNotNull(GetDecision(localMovie, downloadClientItem, nonSampleVideoFileCount > 1)); } return(decisions); }
public List <CustomFormat> ParseCustomFormat(MovieHistory history) { var movie = _movieService.GetMovie(history.MovieId); var parsed = _parsingService.ParseMovieInfo(history.SourceTitle, null); Enum.TryParse(history.Data.GetValueOrDefault("indexerFlags"), true, out IndexerFlags flags); long.TryParse(history.Data.GetValueOrDefault("size"), out var size); var info = new ParsedMovieInfo { MovieTitle = movie.Title, SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(), Quality = history.Quality, Languages = history.Languages, ReleaseGroup = parsed?.ReleaseGroup, Edition = parsed?.Edition, Year = movie.Year, ImdbId = movie.ImdbId, ExtraInfo = new Dictionary <string, object> { { "IndexerFlags", flags }, { "Size", size } } }; return(ParseCustomFormat(info)); }
public List <CustomFormat> ParseCustomFormat(Blocklist blocklist) { var movie = _movieService.GetMovie(blocklist.MovieId); var parsed = _parsingService.ParseMovieInfo(blocklist.SourceTitle, null); var info = new ParsedMovieInfo { MovieTitles = new List <string>() { movie.Title }, SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(), Quality = blocklist.Quality, Languages = blocklist.Languages, ReleaseGroup = parsed?.ReleaseGroup, Edition = parsed?.Edition, Year = movie.Year, ImdbId = movie.ImdbId, ExtraInfo = new Dictionary <string, object> { { "IndexerFlags", blocklist.IndexerFlags }, { "Size", blocklist.Size } } }; return(ParseCustomFormat(info)); }
private bool TryGetMovieByImDbId(ParsedMovieInfo parsedMovieInfo, string imdbId, out MappingResult result) { var movie = _movieService.FindByImdbId(imdbId); //Should fix practically all problems, where indexer is s***e at adding correct imdbids to movies. if (movie != null && parsedMovieInfo.Year > 1800 && (parsedMovieInfo.Year != movie.Year && movie.SecondaryYear != parsedMovieInfo.Year)) { result = new MappingResult { Movie = movie, MappingResultType = MappingResultType.WrongYear }; return(false); } if (movie != null) { result = new MappingResult { Movie = movie }; } else { result = new MappingResult { Movie = movie, MappingResultType = MappingResultType.TitleNotFound }; } return(movie != null); }
public ParsedMovieInfo AugmentMovieInfo(ParsedMovieInfo movieInfo, object helper) { if (helper is ParsedMovieInfo otherInfo) { // Create union of all languages if (otherInfo.Languages != null) { movieInfo.Languages = movieInfo.Languages.Union(otherInfo.Languages).Distinct().ToList(); } if ((otherInfo.Edition?.Length ?? 0) > (movieInfo.Edition?.Length ?? 0)) { movieInfo.Edition = otherInfo.Edition; } if (otherInfo.Quality != null) { movieInfo.Quality.CustomFormats = movieInfo.Quality.CustomFormats.Union(otherInfo.Quality.CustomFormats) .Distinct().ToList(); } if (otherInfo.ReleaseGroup.IsNotNullOrWhiteSpace() && movieInfo.ReleaseGroup.IsNullOrWhiteSpace()) { movieInfo.ReleaseGroup = otherInfo.ReleaseGroup; } } return(movieInfo); }
private ParsedMovieInfo EnhanceMinimalInfo(ParsedMovieInfo minimalInfo, List <object> helpers) { minimalInfo.Languages = LanguageParser.ParseLanguages(minimalInfo.SimpleReleaseTitle); _logger.Debug("Language(s) parsed: {0}", string.Join(", ", minimalInfo.Languages.ToExtendedString())); minimalInfo.Quality = QualityParser.ParseQuality(minimalInfo.SimpleReleaseTitle); if (minimalInfo.Edition.IsNullOrWhiteSpace()) { minimalInfo.Edition = Parser.ParseEdition(minimalInfo.SimpleReleaseTitle); } minimalInfo.ReleaseGroup = Parser.ParseReleaseGroup(minimalInfo.SimpleReleaseTitle); minimalInfo.ImdbId = Parser.ParseImdbId(minimalInfo.SimpleReleaseTitle); minimalInfo = AugmentMovieInfo(minimalInfo, helpers); // After the augmenters have done their job on languages we can do our static method as well. minimalInfo.Languages = LanguageParser.EnhanceLanguages(minimalInfo.SimpleReleaseTitle, minimalInfo.Languages); minimalInfo.Quality.Quality = Quality.FindByInfo(minimalInfo.Quality.Source, minimalInfo.Quality.Resolution, minimalInfo.Quality.Modifier); minimalInfo.Quality.CustomFormats = ParseCustomFormat(minimalInfo); _logger.Debug("Quality parsed: {0}", minimalInfo.Quality); return(minimalInfo); }
private MappingResult GetMovie(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchCriteriaBase searchCriteria) { MappingResult result = null; if (!string.IsNullOrWhiteSpace(imdbId) && imdbId != "0") { if (TryGetMovieByImDbId(parsedMovieInfo, imdbId, out result)) { return(result); } } if (searchCriteria != null) { if (TryGetMovieBySearchCriteria(parsedMovieInfo, searchCriteria, out result)) { return(result); } } else { if (TryGetMovieByTitleAndOrYear(parsedMovieInfo, out result)) { return(result); } } // nothing found up to here => logging that and returning null _logger.Debug($"No matching movie {parsedMovieInfo.MovieTitle}"); return(result); }
public List <FormatTagMatchResult> MatchFormatTags(ParsedMovieInfo movieInfo) { var formats = _formatService.All(); if (movieInfo.ExtraInfo.GetValueOrDefault("AdditionalFormats") is List <CustomFormat> additionalFormats) { formats.AddRange(additionalFormats); } var matches = new List <FormatTagMatchResult>(); foreach (var customFormat in formats) { var formatMatches = customFormat.FormatTags.GroupBy(t => t.TagType).Select(g => new FormatTagMatchesGroup(g.Key, g.ToList().ToDictionary(t => t, t => t.DoesItMatch(movieInfo)))); var formatTagMatchesGroups = formatMatches.ToList(); matches.Add(new FormatTagMatchResult { CustomFormat = customFormat, GroupMatches = formatTagMatchesGroups, GoodMatch = formatTagMatchesGroups.All(g => g.DidMatch) }); } return(matches); }
private MappingResult GetMovie(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchCriteriaBase searchCriteria) { // TODO: Answer me this: Wouldn't it be smarter to start out looking for a movie if we have an ImDb Id? MappingResult result = null; if (!String.IsNullOrWhiteSpace(imdbId) && imdbId != "0") { if (TryGetMovieByImDbId(parsedMovieInfo, imdbId, out result)) { return(result); } } if (searchCriteria != null) { if (TryGetMovieBySearchCriteria(parsedMovieInfo, searchCriteria, out result)) { return(result); } } else { TryGetMovieByTitleAndOrYear(parsedMovieInfo, out result); return(result); } // nothing found up to here => logging that and returning null _logger.Debug($"No matching movie {parsedMovieInfo.MovieTitle}"); return(result); }
private CachedSeedConfiguration FetchIndexer(string infoHash) { var historyItem = _downloadHistoryService.GetLatestGrab(infoHash); if (historyItem == null) { _logger.Debug("No download history item for infohash {0}, unable to provide seed configuration", infoHash); return(null); } ParsedMovieInfo parsedMovieInfo = null; if (historyItem.Release != null) { parsedMovieInfo = Parser.Parser.ParseMovieTitle(historyItem.Release.Title); } if (parsedMovieInfo == null) { _logger.Debug("No parsed title in download history item for infohash {0}, unable to provide seed configuration", infoHash); return(null); } return(new CachedSeedConfiguration { IndexerId = historyItem.IndexerId, }); }
private bool ShouldUseFolderName(List <string> videoFiles, Movie movie, ParsedMovieInfo folderInfo) { if (folderInfo == null) { return(false); } //if (folderInfo.FullSeason) //{ // return false; //} return(videoFiles.Count(file => { var size = _diskProvider.GetFileSize(file); var fileQuality = QualityParser.ParseQuality(file); //var sample = null;//_detectSample.IsSample(movie, GetQuality(folderInfo, fileQuality, movie), file, size, folderInfo.IsPossibleSpecialEpisode); //Todo to this return true; //if (sample) { return false; } if (SceneChecker.IsSceneTitle(Path.GetFileName(file))) { return false; } return true; }) == 1); }
public MappingResult Map(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchCriteriaBase searchCriteria = null) { var result = GetMovie(parsedMovieInfo, imdbId, searchCriteria); if (result == null) { result = new MappingResult { MappingResultType = MappingResultType.Unknown }; result.Movie = null; } //Use movie language as fallback if we could't parse a language (more accurate than just using English) if (parsedMovieInfo.Languages.Count <= 1 && parsedMovieInfo.Languages.First() == Language.Unknown && result.Movie != null) { parsedMovieInfo.Languages = new List <Language> { result.Movie.OriginalLanguage }; _logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", result.Movie.OriginalLanguage.Name); } result.RemoteMovie.ParsedMovieInfo = parsedMovieInfo; return(result); }
private bool UseFolderQuality(ParsedMovieInfo folderInfo, QualityModel fileQuality, Movie movie) { if (folderInfo == null) { return(false); } if (folderInfo.Quality.Quality == Quality.Unknown) { return(false); } if (fileQuality.QualitySource == QualitySource.Extension) { return(true); } if (fileQuality.QualitySource == QualitySource.MediaInfo) { return(false); } if (new QualityModelComparer(movie.Profile).Compare(folderInfo.Quality, fileQuality) > 0) { return(true); } return(false); }
//TODO add some good tests for this! public void Execute(UpdateMovieFileQualityCommand command) { var movieFiles = _mediaFileService.GetMovies(command.MovieFileIds); var count = 1; foreach (var movieFile in movieFiles) { _logger.ProgressInfo("Updating quality for {0}/{1} files.", count, movieFiles.Count); var history = _historyService.FindByMovieId(movieFile.MovieId).OrderByDescending(h => h.Date); var latestImported = history.FirstOrDefault(h => h.EventType == HistoryEventType.DownloadFolderImported); var latestImportedName = latestImported?.SourceTitle; var latestGrabbed = history.FirstOrDefault(h => h.EventType == HistoryEventType.Grabbed); var sizeMovie = new LocalMovie(); sizeMovie.Size = movieFile.Size; var helpers = new List <object> { sizeMovie }; if (movieFile.MediaInfo != null) { helpers.Add(movieFile.MediaInfo); } if (latestGrabbed != null) { helpers.Add(latestGrabbed); } ParsedMovieInfo parsedMovieInfo = null; if (latestImportedName?.IsNotNullOrWhiteSpace() == true) { parsedMovieInfo = _parsingService.ParseMovieInfo(latestImportedName, helpers); } if (parsedMovieInfo == null) { _logger.Debug("Could not parse movie info from history source title, using current path instead: {0}.", movieFile.RelativePath); parsedMovieInfo = _parsingService.ParseMovieInfo(movieFile.RelativePath, helpers); } //Only update Custom formats for now. if (parsedMovieInfo != null) { movieFile.Quality.CustomFormats = parsedMovieInfo.Quality.CustomFormats; _mediaFileService.Update(movieFile); _eventAggregator.PublishEvent(new MovieFileUpdatedEvent(movieFile)); } else { _logger.Warn("Could not update custom formats for {0}, since it's title could not be parsed!", movieFile); } count++; } }
private bool TryGetMovieBySearchCriteria(ParsedMovieInfo parsedMovieInfo, SearchCriteriaBase searchCriteria, out MappingResult result) { Movie possibleMovie = null; var possibleTitles = new List <string>(); possibleTitles.Add(searchCriteria.Movie.CleanTitle); possibleTitles.AddRange(searchCriteria.Movie.AlternativeTitles.Select(t => t.CleanTitle)); possibleTitles.AddRange(searchCriteria.Movie.Translations.Select(t => t.CleanTitle)); var cleanTitle = parsedMovieInfo.MovieTitle.CleanMovieTitle(); foreach (var title in possibleTitles) { if (title == cleanTitle) { possibleMovie = searchCriteria.Movie; } foreach (var numeralMapping in _arabicRomanNumeralMappings) { var arabicNumeral = numeralMapping.ArabicNumeralAsString; var romanNumeral = numeralMapping.RomanNumeralLowerCase; //_logger.Debug(cleanTitle); if (title.Replace(arabicNumeral, romanNumeral) == cleanTitle) { possibleMovie = searchCriteria.Movie; } if (title == cleanTitle.Replace(arabicNumeral, romanNumeral)) { possibleMovie = searchCriteria.Movie; } } } if (possibleMovie != null) { if (parsedMovieInfo.Year < 1800 || possibleMovie.Year == parsedMovieInfo.Year || possibleMovie.SecondaryYear == parsedMovieInfo.Year) { result = new MappingResult { Movie = possibleMovie, MappingResultType = MappingResultType.Success }; return(true); } result = new MappingResult { Movie = possibleMovie, MappingResultType = MappingResultType.WrongYear }; return(false); } result = new MappingResult { Movie = searchCriteria.Movie, MappingResultType = MappingResultType.WrongTitle }; return(false); }
public void Setup() { _movie = Builder <Movie> .CreateNew() .With(m => m.Title = "Fack Ju Göthe 2") .With(m => m.CleanTitle = "fackjugoethe2") .With(m => m.Year = 2015) .With(m => m.AlternativeTitles = new LazyList <AlternativeTitle>(new List <AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })) .Build(); _parsedMovieInfo = new ParsedMovieInfo { MovieTitle = _movie.Title, Year = _movie.Year, }; _wrongYearInfo = new ParsedMovieInfo { MovieTitle = _movie.Title, Year = 1900, }; _wrongTitleInfo = new ParsedMovieInfo { MovieTitle = "Other Title", Year = 2015 }; _alternativeTitleInfo = new ParsedMovieInfo { MovieTitle = _movie.AlternativeTitles.First().Title, Year = _movie.Year, }; _romanTitleInfo = new ParsedMovieInfo { MovieTitle = "Fack Ju Göthe II", Year = _movie.Year, }; _umlautInfo = new ParsedMovieInfo { MovieTitle = "Fack Ju Goethe 2", Year = _movie.Year }; _umlautAltInfo = new ParsedMovieInfo { MovieTitle = "Fack Ju Goethe 2: Same same", Year = _movie.Year }; _movieSearchCriteria = new MovieSearchCriteria { Movie = _movie }; }
public ParsedMovieInfo AugmentMovieInfo(ParsedMovieInfo movieInfo, object helper) { if (helper is LocalMovie localMovie && localMovie.Size != 0) { movieInfo.ExtraInfo["Size"] = localMovie.Size; } return(movieInfo); }
public void Setup() { _movie = Builder <Movie> .CreateNew() .Build(); _profile = new Profile { Name = "Test", Cutoff = Quality.HDTV720p.Id, Items = new List <ProfileQualityItem> { new ProfileQualityItem { Allowed = true, Quality = Quality.HDTV720p }, new ProfileQualityItem { Allowed = true, Quality = Quality.WEBDL720p }, new ProfileQualityItem { Allowed = true, Quality = Quality.Bluray720p } }, }; _movie.Profile = _profile; _release = Builder <ReleaseInfo> .CreateNew().Build(); _parsedMovieInfo = Builder <ParsedMovieInfo> .CreateNew().Build(); _parsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p); _remoteMovie = new RemoteMovie(); _remoteMovie.Movie = _movie; _remoteMovie.ParsedMovieInfo = _parsedMovieInfo; _remoteMovie.Release = _release; _temporarilyRejected = new DownloadDecision(_remoteMovie, new Rejection("Temp Rejected", RejectionType.Temporary)); _heldReleases = new List <PendingRelease>(); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.All()) .Returns(_heldReleases); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.AllByMovieId(It.IsAny <int>())) .Returns <int>(i => _heldReleases.Where(v => v.MovieId == i).ToList()); Mocker.GetMock <IMovieService>() .Setup(s => s.GetMovie(It.IsAny <int>())) .Returns(_movie); Mocker.GetMock <IPrioritizeDownloadDecision>() .Setup(s => s.PrioritizeDecisionsForMovies(It.IsAny <List <DownloadDecision> >())) .Returns((List <DownloadDecision> d) => d); }
public void Setup() { _movie = Builder <Movie> .CreateNew() .Build(); _profile = new Profile { Name = "Test", Cutoff = Quality.HDTV720p, Items = new List <ProfileQualityItem> { new ProfileQualityItem { Allowed = true, Quality = Quality.HDTV720p }, new ProfileQualityItem { Allowed = true, Quality = Quality.WEBDL720p }, new ProfileQualityItem { Allowed = true, Quality = Quality.Bluray720p } }, }; _movie.Profile = new LazyLoaded <Profile>(_profile); _release = Builder <ReleaseInfo> .CreateNew().Build(); _parsedMovieInfo = Builder <ParsedMovieInfo> .CreateNew().Build(); _parsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p); _remoteMovie = new RemoteMovie(); //_remoteEpisode.Episodes = new List<Episode>{ _episode }; _remoteMovie.Movie = _movie; _remoteMovie.ParsedMovieInfo = _parsedMovieInfo; _remoteMovie.Release = _release; _temporarilyRejected = new DownloadDecision(_remoteMovie, new Rejection("Temp Rejected", RejectionType.Temporary)); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.All()) .Returns(new List <PendingRelease>()); Mocker.GetMock <IMovieService>() .Setup(s => s.GetMovie(It.IsAny <int>())) .Returns(_movie); Mocker.GetMock <IParsingService>() .Setup(s => s.GetMovie(It.IsAny <string>())) .Returns(_movie); Mocker.GetMock <IPrioritizeDownloadDecision>() .Setup(s => s.PrioritizeDecisions(It.IsAny <List <DownloadDecision> >())) .Returns((List <DownloadDecision> d) => d); }
private QualityModel GetQuality(ParsedMovieInfo folderInfo, QualityModel fileQuality, Movie movie) { if (UseFolderQuality(folderInfo, fileQuality, movie)) { _logger.Debug("Using quality from folder: {0}", folderInfo.Quality); return(folderInfo.Quality); } return(fileQuality); }
public bool DoesItMatch(ParsedMovieInfo movieInfo) { var match = DoesItMatchWithoutMods(movieInfo); if (TagModifier.HasFlag(TagModifier.Not)) { match = !match; } return(match); }
public virtual void Setup() { MovieInfo = new ParsedMovieInfo { MovieTitle = "A Movie", Year = 1998, SimpleReleaseTitle = "A Movie Title 1998 Bluray 1080p", Quality = new QualityModel(Quality.Bluray1080p) }; }
public void should_parse_german_movie(string postTitle, string title, string edition, int year) { ParsedMovieInfo movie = Parser.Parser.ParseMovieTitle(postTitle); using (new AssertionScope()) { movie.PrimaryMovieTitle.Should().Be(title); movie.Edition.Should().Be(edition); movie.Year.Should().Be(year); } }
public bool IsSatisfiedBy(ParsedMovieInfo movieInfo) { var match = IsSatisfiedByWithoutNegate(movieInfo); if (Negate) { match = !match; } return(match); }
public void should_add_edition_if_null() { var folderInfo = new ParsedMovieInfo { Edition = "Directors Cut" }; var result = Subject.AugmentMovieInfo(MovieInfo, folderInfo); result.Edition.Should().Be(folderInfo.Edition); }
private ParsedMovieInfo AugmentMovieInfo(ParsedMovieInfo minimalInfo, List <object> helpers) { var augmenters = _augmenters.Where(a => helpers.Any(t => a.HelperType.IsInstanceOfType(t)) || a.HelperType == null); foreach (var augmenter in augmenters) { minimalInfo = augmenter.AugmentMovieInfo(minimalInfo, helpers.FirstOrDefault(h => augmenter.HelperType.IsInstanceOfType(h))); } return(minimalInfo); }