protected bool ExtractSeriesData(string localFsResourcePath, IDictionary <Guid, MediaItemAspect> extractedAspectData) { // VideoAspect must be present to be sure it is actually a video resource. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { return(false); } SeriesInfo seriesInfo; // Try to get extended information out of matroska files) MatroskaMatcher matroskaMatcher = new MatroskaMatcher(); matroskaMatcher.MatchSeries(localFsResourcePath, out seriesInfo, ref extractedAspectData); // If no information from mkv were found, try name matching if (seriesInfo == null || !seriesInfo.IsCompleteMatch) { // Try to match series from folder and file namings SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(localFsResourcePath, out seriesInfo); } // Lookup online information (incl. fanart) if (seriesInfo != null && seriesInfo.IsCompleteMatch) { SeriesTvDbMatcher.Instance.FindAndUpdateSeries(seriesInfo); seriesInfo.SetMetadata(extractedAspectData); } return(seriesInfo != null && seriesInfo.IsCompleteMatch); }
protected bool ExtractSeriesData(ILocalFsResourceAccessor lfsra, IDictionary <Guid, MediaItemAspect> extractedAspectData) { // VideoAspect must be present to be sure it is actually a video resource. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { return(false); } SeriesInfo seriesInfo; // Try to get extended information out of matroska files) MatroskaMatcher matroskaMatcher = new MatroskaMatcher(); if (matroskaMatcher.MatchSeries(lfsra, out seriesInfo, ref extractedAspectData)) { ServiceRegistration.Get <ILogger>().Debug("ExtractSeriesData: Found SeriesInformation by MatroskaMatcher for {0}, IMDB {1}, TVDB {2}, IsCompleteMatch {3}", seriesInfo.Series, seriesInfo.ImdbId, seriesInfo.TvdbId, seriesInfo.IsCompleteMatch); } // If no information from mkv were found, try name matching if (seriesInfo == null || !seriesInfo.IsCompleteMatch) { // Try to match series from folder and file namings SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(lfsra, out seriesInfo); } // Lookup online information (incl. fanart) if (seriesInfo != null && seriesInfo.IsCompleteMatch) { SeriesTvDbMatcher.Instance.FindAndUpdateSeries(seriesInfo); seriesInfo.SetMetadata(extractedAspectData); } return(seriesInfo != null && seriesInfo.IsCompleteMatch); }
protected bool ExtractSeriesData(ILocalFsResourceAccessor lfsra, IDictionary <Guid, MediaItemAspect> extractedAspectData) { // VideoAspect must be present to be sure it is actually a video resource. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { return(false); } SeriesInfo seriesInfo = null; // First check if we already have a complete match from a previous MDE string title; int tvDbId; int seasonNumber; IEnumerable <int> episodeNumbers; if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) && MediaItemAspect.TryGetAttribute(extractedAspectData, SeriesAspect.ATTR_TVDB_ID, out tvDbId) && MediaItemAspect.TryGetAttribute(extractedAspectData, SeriesAspect.ATTR_SEASON, out seasonNumber) && (episodeNumbers = extractedAspectData[SeriesAspect.ASPECT_ID].GetCollectionAttribute <int>(SeriesAspect.ATTR_EPISODE)) != null) { seriesInfo = new SeriesInfo { Series = title, TvdbId = tvDbId, SeasonNumber = seasonNumber, }; episodeNumbers.ToList().ForEach(n => seriesInfo.EpisodeNumbers.Add(n)); } // If there was no complete match, yet, try to get extended information out of matroska files) if (seriesInfo == null || !seriesInfo.IsCompleteMatch) { MatroskaMatcher matroskaMatcher = new MatroskaMatcher(); if (matroskaMatcher.MatchSeries(lfsra, out seriesInfo, ref extractedAspectData)) { ServiceRegistration.Get <ILogger>().Debug("ExtractSeriesData: Found SeriesInformation by MatroskaMatcher for {0}, IMDB {1}, TVDB {2}, IsCompleteMatch {3}", seriesInfo.Series, seriesInfo.ImdbId, seriesInfo.TvdbId, seriesInfo.IsCompleteMatch); } } // If no information was found before, try name matching if (seriesInfo == null || !seriesInfo.IsCompleteMatch) { // Try to match series from folder and file namings SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(lfsra, out seriesInfo); } // Lookup online information (incl. fanart) if (seriesInfo != null && seriesInfo.IsCompleteMatch) { SeriesTvDbMatcher.Instance.FindAndUpdateSeries(seriesInfo); if (!_onlyFanArt) { seriesInfo.SetMetadata(extractedAspectData); } } return(seriesInfo != null && seriesInfo.IsCompleteMatch && !_onlyFanArt); }
public void SeriesMatchesAreCorrect() { Init(); List <string> shouldMatchPaths = new List <string> { @"\\SAGESERVER\TV Series\Almost Human\Almost.Human.S01E01.720p.HDTV.X264-DIMENSION.mkv", @"F:\TVSeries\The Bill Engvall Show\Season 1\The Bill Engvall Show - 101 - Good People.avi", @"G:\Serien\The Big Bang Theory\Staffel 1 [DEU-ENG][720p]\S01E01 Penny und die Physiker.mkv", @"G:\Serien\The Big Bang Theory\Staffel 1 [DEU-ENG][720p]\1x01 Penny und die Physiker.mkv", @"D:\Capture\EUReKA - Die geheime Stadt\EUReKA - Die geheime Stadt - (Lyncht Fargo) S4 E3 - 2011-05-02 - 21_15.ts", @"M:\Serien\Stargate Universe Season 1\Stargate Universe S01.E01_02 - Die Destiny.avi", @"M:\Serien\Caprica\Caprica 1x01 - Pilot (1).mkv", @"M:\\Serien\\Fringe Season 3\\Fringe S03E04 - Träumen Gestaltwandler von elektrischen Schafen.avi", @"\The.Vampire.Diaries.S03-E13.720p.WEB-DL.mkv", @"\Nikita.S02_E02.720p.WEB-DL.mkv", @"\Switched.at.Birth.S01E10.The Homecoming.720p.WEB-DL.DD5.1.H.264-NT.mkv", @"\The.Lying.Game.111.WEB.DL.mkv", @"\Unforgettable.S01E02.720p.WEB-DL.mkv", @"\Grimm.S01E06.720p.HDTV.X264-DIMENSION.mkv", @"\The.Secret.Circle.S01E01.720p.WEB-DL.mkv", @"\Lost.Girl.S02E06.720p.WEB-DL.mkv", @"\Fringe.S04E08.720p.WEB-DL.mkv", @"\the_fades.1x01.720p_hdtv_x264-fov.mkv", @"\Once.Upon.A.Time.S01E13.720p.WEB-DL.mkv", @"\The.Lying.Game.114.WEB.DL.mkv", @"X:\USB_Backup\Filme\CodecTest\Dr. House - S01E01 Irgendwas.mkv", @"Z:\Serien\Hawaii Five-O\Staffel 02\11 - In Der Falle.mkv", @"Z:\Serien\Hawaii Five-O\Season 02\11 - In Der Falle.mkv", @"Z:\Serien\Hawaii Five-O\02. Staffel\12 - In Der Falle.mkv", @"Z:\Serien\Hawaii Five-O\Temporada 02\11 - In Der Falle.mkv", @"Z:\Serien\Hawaii Five-O\02\11 - In Der Falle.mkv", //@"Z:\Serien\Hawaii Five-O\2\11 In Der Falle.mkv", @"Z:\Serien\The Mentalist\4\11 - Die Geister, Die Wir Riefen.mkv", //@"Z:\Serien\The Mentalist\4\11 Die Geister, Die Wir Riefen.mkv", @"\\BNAS\TV\All\Comedy\Farther Ted\Series 1\01 - Good Luke Father Ted.mkv", @"\\BNAS\TV\All\Comedy\Black Adder\Black Adder 1\01 - The Foretelling.avi", }; SeriesMatcher matcher = new SeriesMatcher(); foreach (string folderOrFileName in shouldMatchPaths) { SeriesInfo seriesInfo; bool match = matcher.MatchSeries(folderOrFileName, out seriesInfo); Assert.IsTrue(match, string.Format("Failed to match path '{0}'", folderOrFileName)); } }
public void SeriesFalseMatches() { List <string> shouldNotMatchPaths = new List <string> { @"\\Fool's Gold (2008).mkv", @"Into the Blue (2005)", @"\\Iron Man 2 Disc 1.mkv", @"\\Salt - Blu-ray™.mkv", @"\\Transformers Revenge of the Fallen Disc 1.mkv", // FIXME: this one is currently wrongly matched // @"Polizeiruf 110\Polizeiruf 110 - SE - Liebeswahn (Das Erste HD - 2014-01-12 20_15).ts", }; SeriesMatcher matcher = new SeriesMatcher(); foreach (string folderOrFileName in shouldNotMatchPaths) { SeriesInfo seriesInfo; bool match = matcher.MatchSeries(folderOrFileName, out seriesInfo); Assert.IsFalse(match, string.Format("Wrong match for '{0}' should not be matched!", folderOrFileName)); } }
protected bool ExtractSeriesData(string localFsResourcePath, IDictionary <Guid, MediaItemAspect> extractedAspectData) { SeriesInfo seriesInfo = null; string extensionUpper = StringUtils.TrimToEmpty(Path.GetExtension(localFsResourcePath)).ToUpper(); // Try to get extended information out of matroska files) if (extensionUpper == ".MKV" || extensionUpper == ".MK3D") { MatroskaInfoReader mkvReader = new MatroskaInfoReader(localFsResourcePath); // Add keys to be extracted to tags dictionary, matching results will returned as value Dictionary <string, IList <string> > tagsToExtract = MatroskaConsts.DefaultTags; mkvReader.ReadTags(tagsToExtract); string title = string.Empty; IList <string> tags = tagsToExtract[MatroskaConsts.TAG_SIMPLE_TITLE]; if (tags != null) { title = tags.FirstOrDefault(); } if (!string.IsNullOrEmpty(title)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, title); } string yearCandidate = null; tags = tagsToExtract[MatroskaConsts.TAG_EPISODE_YEAR] ?? tagsToExtract[MatroskaConsts.TAG_SEASON_YEAR]; if (tags != null) { yearCandidate = (tags.FirstOrDefault() ?? string.Empty).Substring(0, 4); } int year; if (int.TryParse(yearCandidate, out year)) { MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, new DateTime(year, 1, 1)); } tags = tagsToExtract[MatroskaConsts.TAG_EPISODE_SUMMARY]; string plot = tags != null?tags.FirstOrDefault() : string.Empty; if (!string.IsNullOrEmpty(plot)) { MediaItemAspect.SetAttribute(extractedAspectData, VideoAspect.ATTR_STORYPLOT, plot); } // Series and episode handling. Prefer information from tags. seriesInfo = GetSeriesFromTags(tagsToExtract); } // If now information from mkv were found, try name matching if (seriesInfo == null || !seriesInfo.IsCompleteMatch) { // Try to match series from folder and file namings SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(localFsResourcePath, out seriesInfo); } // Lookup online information (incl. fanart) if (seriesInfo != null && seriesInfo.IsCompleteMatch) { SeriesTvDbMatcher.Instance.FindAndUpdateSeries(seriesInfo); seriesInfo.SetMetadata(extractedAspectData); } return(seriesInfo != null && seriesInfo.IsCompleteMatch); }
public async Task <IList <MediaItemSearchResult> > SearchForMatchesAsync(IDictionary <Guid, IList <MediaItemAspect> > searchAspectData, ICollection <string> searchCategories) { try { if (!(searchCategories?.Contains(MEDIA_CATEGORY_NAME_SERIES) ?? true)) { return(null); } string searchData = null; var reimportAspect = MediaItemAspect.GetAspect(searchAspectData, ReimportAspect.Metadata); if (reimportAspect != null) { searchData = reimportAspect.GetAttributeValue <string>(ReimportAspect.ATTR_SEARCH); } ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Search aspects to use: '{0}'", string.Join(",", searchAspectData.Keys)); //Prepare search info EpisodeInfo episodeSearchinfo = null; SeriesInfo seriesSearchinfo = null; List <MediaItemSearchResult> searchResults = new List <MediaItemSearchResult>(); if (!string.IsNullOrEmpty(searchData)) { if (searchAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { EpisodeInfo episode = new EpisodeInfo(); episode.FromMetadata(searchAspectData); episodeSearchinfo = new EpisodeInfo(); episodeSearchinfo.SeasonNumber = episode.SeasonNumber; episodeSearchinfo.EpisodeNumbers = episode.EpisodeNumbers.ToList(); if (searchData.StartsWith("tt", StringComparison.InvariantCultureIgnoreCase) && !searchData.Contains(" ") && int.TryParse(searchData.Substring(2), out int id)) { episodeSearchinfo.SeriesImdbId = searchData; } else if (!searchData.Contains(" ") && int.TryParse(searchData, out int tvDbSeriesId)) { episodeSearchinfo.SeriesTvdbId = tvDbSeriesId; } else //Fallabck to name search { searchData = searchData.Trim(); SeriesMatcher seriesMatcher = new SeriesMatcher(); //Add extension to simulate a file name which the matcher expects EpisodeInfo tempEpisodeInfo = new EpisodeInfo(); tempEpisodeInfo.SeasonNumber = episode.SeasonNumber; if (seriesMatcher.MatchSeries(searchData + ".ext", tempEpisodeInfo)) { episodeSearchinfo.SeriesName = tempEpisodeInfo.SeriesName; episodeSearchinfo.SeasonNumber = tempEpisodeInfo.SeasonNumber; episodeSearchinfo.EpisodeNumbers = tempEpisodeInfo.EpisodeNumbers.ToList(); } } ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Searching for episode matches on search: '{0}'", searchData); } else if (searchAspectData.ContainsKey(SeriesAspect.ASPECT_ID)) { seriesSearchinfo = new SeriesInfo(); if (searchData.StartsWith("tt", StringComparison.InvariantCultureIgnoreCase) && !searchData.Contains(" ") && int.TryParse(searchData.Substring(2), out int id)) { seriesSearchinfo.ImdbId = searchData; } else if (!searchData.Contains(" ") && int.TryParse(searchData, out int tvDbSeriesId)) { seriesSearchinfo.TvdbId = tvDbSeriesId; } else //Fallabck to name search { searchData = searchData.Trim(); EpisodeInfo tempEpisodeInfo = new EpisodeInfo(); tempEpisodeInfo.SeasonNumber = 1; SeriesMatcher seriesMatcher = new SeriesMatcher(); //Add extension to simulate a file name which the matcher expects seriesMatcher.MatchSeries(searchData + " S01E01.ext", tempEpisodeInfo); if (tempEpisodeInfo.SeriesFirstAired.HasValue) { seriesSearchinfo.SeriesName = tempEpisodeInfo.SeriesName; seriesSearchinfo.FirstAired = tempEpisodeInfo.SeriesFirstAired; } else { seriesSearchinfo.SeriesName = searchData; } ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Searching for series matches on search: '{0}'", searchData); } } } else { if (searchAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { episodeSearchinfo = new EpisodeInfo(); episodeSearchinfo.FromMetadata(searchAspectData); ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Searching for episode matches on aspects"); } else if (searchAspectData.ContainsKey(SeriesAspect.ASPECT_ID)) { seriesSearchinfo = new SeriesInfo(); seriesSearchinfo.FromMetadata(searchAspectData); ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Searching for series matches on aspects"); } } //Perform online search if (episodeSearchinfo != null) { List <int> epNos = new List <int>(episodeSearchinfo.EpisodeNumbers.OrderBy(e => e)); var matches = await OnlineMatcherService.Instance.FindMatchingEpisodesAsync(episodeSearchinfo).ConfigureAwait(false); ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Episode search returned {0} matches", matches.Count()); if (epNos.Count > 1) { //Check if double episode is in the search results if (!matches.Any(e => e.EpisodeNumbers.SequenceEqual(epNos))) { //Add a double episode if it's not var potentialEpisodes = new Dictionary <int, List <EpisodeInfo> >(); foreach (var episodeNo in epNos) { potentialEpisodes[episodeNo] = matches.Where(e => e.FirstEpisodeNumber == episodeNo && e.EpisodeNumbers.Count == 1).ToList(); } //Merge fitting episodes var mergedEpisodes = new List <EpisodeInfo>(); foreach (var episodeNo in epNos) { if (episodeNo == episodeSearchinfo.FirstEpisodeNumber) { foreach (var episode in potentialEpisodes[episodeNo]) { mergedEpisodes.Add(episode.Clone()); } } else { foreach (var mergedEpisode in mergedEpisodes) { var nextEpisode = potentialEpisodes[episodeNo].FirstOrDefault(e => e.SeriesTvdbId > 0 && e.SeriesTvdbId == mergedEpisode.SeriesTvdbId && e.SeasonNumber == mergedEpisode.SeasonNumber); if (nextEpisode == null) { nextEpisode = potentialEpisodes[episodeNo].FirstOrDefault(e => !string.IsNullOrEmpty(e.SeriesImdbId) && e.SeriesImdbId.Equals(mergedEpisode.SeriesImdbId, StringComparison.InvariantCultureIgnoreCase) && e.SeasonNumber == mergedEpisode.SeasonNumber); } if (nextEpisode == null) { nextEpisode = potentialEpisodes[episodeNo].FirstOrDefault(e => e.SeriesMovieDbId > 0 && e.SeriesMovieDbId == mergedEpisode.SeriesMovieDbId && e.SeasonNumber == mergedEpisode.SeasonNumber); } if (nextEpisode != null) { MergeEpisodeDetails(mergedEpisode, nextEpisode); } } } } //Add valid merged episodes to search result var list = matches.ToList(); var validMergedEpisodes = mergedEpisodes.Where(e => e.EpisodeNumbers.SequenceEqual(epNos)); list.AddRange(validMergedEpisodes); matches = list.AsEnumerable(); if (validMergedEpisodes.Count() > 0) { ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Added {0} multi-episodes to matches", validMergedEpisodes.Count()); } } } foreach (var match in matches) { var result = new MediaItemSearchResult { Name = $"{match.SeriesName}{(match.SeriesFirstAired == null || match.SeriesName.Text.EndsWith($"({match.SeriesFirstAired.Value.Year})") ? "" : $" ({match.SeriesFirstAired.Value.Year})")}" + $" S{(match.SeasonNumber.HasValue ? match.SeasonNumber.Value.ToString("00") : "??")}{(match.EpisodeNumbers.Count > 0 ? string.Join("", match.EpisodeNumbers.Select(e => "E" + e.ToString("00"))) : "E??")}" + $"{(match.EpisodeName.IsEmpty ? "" : $": {match.EpisodeName.Text}")}", Description = match.Summary.IsEmpty ? "" : match.Summary.Text, }; //Add external Ids if (match.TvdbId > 0) { result.ExternalIds.Add("thetvdb.com", match.TvdbId.ToString()); } if (!string.IsNullOrEmpty(match.ImdbId)) { result.ExternalIds.Add("imdb.com", match.ImdbId); } if (match.MovieDbId > 0) { result.ExternalIds.Add("themoviedb.org", match.MovieDbId.ToString()); } //Assign aspects and remove unwanted aspects match.SetMetadata(result.AspectData, true); CleanReimportAspects(result.AspectData); searchResults.Add(result); } return(searchResults); } else if (seriesSearchinfo != null) { var matches = await OnlineMatcherService.Instance.FindMatchingSeriesAsync(seriesSearchinfo).ConfigureAwait(false); ServiceRegistration.Get <ILogger>().Debug("SeriesMetadataExtractor: Series search returned {0} matches", matches.Count()); foreach (var match in matches) { var result = new MediaItemSearchResult { Name = $"{match.SeriesName}{(match.FirstAired == null || match.SeriesName.Text.EndsWith($"({match.FirstAired.Value.Year})") ? "" : $" ({match.FirstAired.Value.Year})")}", Description = match.Description.IsEmpty ? "" : match.Description.Text, }; //Add external Ids if (match.TvdbId > 0) { result.ExternalIds.Add("thetvdb.com", match.TvdbId.ToString()); } if (!string.IsNullOrEmpty(match.ImdbId)) { result.ExternalIds.Add("imdb.com", match.ImdbId); } if (match.MovieDbId > 0) { result.ExternalIds.Add("themoviedb.org", match.MovieDbId.ToString()); } //Assign aspects and remove unwanted aspects match.SetMetadata(result.AspectData, true); CleanReimportAspects(result.AspectData); searchResults.Add(result); } return(searchResults); }
protected async Task <bool> ExtractSeriesDataAsync(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData) { // VideoAspect must be present to be sure it is actually a video resource. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID) && !extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID)) { return(false); } bool isReimport = extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID); EpisodeInfo episodeInfo = new EpisodeInfo(); episodeInfo.FromMetadata(extractedAspectData); if (!isReimport) //Ignore file based information for reimports because they might be the cause of the wrong match { // If there was no complete match, yet, try to get extended information out of matroska files) if (!episodeInfo.IsBaseInfoPresent || !episodeInfo.HasExternalId) { try { MatroskaMatcher matroskaMatcher = new MatroskaMatcher(); if (await matroskaMatcher.MatchSeriesAsync(lfsra, episodeInfo).ConfigureAwait(false)) { ServiceRegistration.Get <ILogger>().Debug("ExtractSeriesData: Found EpisodeInfo by MatroskaMatcher for {0}, IMDB {1}, TVDB {2}, TMDB {3}, AreReqiredFieldsFilled {4}", episodeInfo.SeriesName, episodeInfo.SeriesImdbId, episodeInfo.SeriesTvdbId, episodeInfo.SeriesMovieDbId, episodeInfo.IsBaseInfoPresent); } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("ExtractSeriesData: Exception reading matroska tags for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } // If no information was found before, try name matching if (!episodeInfo.IsBaseInfoPresent) { // Try to match series from folder and file naming SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(lfsra, episodeInfo); } //Prepare online search improvements if (episodeInfo.SeriesFirstAired == null) { EpisodeInfo tempEpisodeInfo = new EpisodeInfo(); SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(lfsra, tempEpisodeInfo); if (tempEpisodeInfo.SeriesFirstAired.HasValue) { episodeInfo.SeriesFirstAired = tempEpisodeInfo.SeriesFirstAired; } } if (string.IsNullOrEmpty(episodeInfo.SeriesAlternateName)) { var mediaItemPath = lfsra.CanonicalLocalResourcePath; var seriesMediaItemDirectoryPath = ResourcePathHelper.Combine(mediaItemPath, "../../"); episodeInfo.SeriesAlternateName = seriesMediaItemDirectoryPath.FileName; } } if (episodeInfo.Languages.Count == 0) { IList <MultipleMediaItemAspect> audioAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, VideoAudioStreamAspect.Metadata, out audioAspects)) { foreach (MultipleMediaItemAspect aspect in audioAspects) { string language = (string)aspect.GetAttributeValue(VideoAudioStreamAspect.ATTR_AUDIOLANGUAGE); if (!string.IsNullOrEmpty(language) && !episodeInfo.Languages.Contains(language)) { episodeInfo.Languages.Add(language); } } } } if (SkipOnlineSearches && !SkipFanArtDownload) { EpisodeInfo tempInfo = episodeInfo.Clone(); await OnlineMatcherService.Instance.FindAndUpdateEpisodeAsync(tempInfo).ConfigureAwait(false); episodeInfo.CopyIdsFrom(tempInfo); episodeInfo.HasChanged = tempInfo.HasChanged; } else if (!SkipOnlineSearches) { await OnlineMatcherService.Instance.FindAndUpdateEpisodeAsync(episodeInfo).ConfigureAwait(false); } if (episodeInfo.EpisodeName.IsEmpty) { if (episodeInfo.EpisodeNumbers.Any()) { episodeInfo.EpisodeName = $"E{episodeInfo.EpisodeNumbers.First().ToString("000")}"; } } //Send it to the videos section if (!SkipOnlineSearches && !episodeInfo.HasExternalId) { return(false); } if (episodeInfo.EpisodeNameSort.IsEmpty) { if (!episodeInfo.SeriesName.IsEmpty && episodeInfo.SeasonNumber.HasValue && episodeInfo.DvdEpisodeNumbers.Any()) { episodeInfo.EpisodeNameSort = $"{episodeInfo.SeriesName.Text} S{episodeInfo.SeasonNumber.Value.ToString("00")}E{episodeInfo.DvdEpisodeNumbers.First().ToString("000.000")}"; } if (!episodeInfo.SeriesName.IsEmpty && episodeInfo.SeasonNumber.HasValue && episodeInfo.EpisodeNumbers.Any()) { episodeInfo.EpisodeNameSort = $"{episodeInfo.SeriesName.Text} S{episodeInfo.SeasonNumber.Value.ToString("00")}E{episodeInfo.EpisodeNumbers.First().ToString("000")}"; } else if (!episodeInfo.EpisodeName.IsEmpty) { episodeInfo.EpisodeNameSort = BaseInfo.GetSortTitle(episodeInfo.EpisodeName.Text); } } episodeInfo.SetMetadata(extractedAspectData); return(episodeInfo.IsBaseInfoPresent); }
protected bool ExtractSeriesData(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly) { // VideoAspect must be present to be sure it is actually a video resource. if (!extractedAspectData.ContainsKey(VideoStreamAspect.ASPECT_ID) && !extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID)) { return(false); } if (extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID) && !importOnly) { return(false); //Subtitles can only be imported not refreshed } bool refresh = false; if (extractedAspectData.ContainsKey(EpisodeAspect.ASPECT_ID)) { refresh = true; } EpisodeInfo episodeInfo = new EpisodeInfo(); if (refresh) { episodeInfo.FromMetadata(extractedAspectData); } ISeriesRelationshipExtractor.UpdateEpisodeSeries(extractedAspectData, episodeInfo); if (!episodeInfo.IsBaseInfoPresent) { string title = null; int seasonNumber; SingleMediaItemAspect episodeAspect; MediaItemAspect.TryGetAspect(extractedAspectData, EpisodeAspect.Metadata, out episodeAspect); IEnumerable <int> episodeNumbers; if (MediaItemAspect.TryGetAttribute(extractedAspectData, EpisodeAspect.ATTR_SERIES_NAME, out title) && MediaItemAspect.TryGetAttribute(extractedAspectData, EpisodeAspect.ATTR_SEASON, out seasonNumber) && (episodeNumbers = episodeAspect.GetCollectionAttribute <int>(EpisodeAspect.ATTR_EPISODE)) != null) { episodeInfo.SeriesName = title; episodeInfo.SeasonNumber = seasonNumber; episodeInfo.EpisodeNumbers.Clear(); episodeNumbers.ToList().ForEach(n => episodeInfo.EpisodeNumbers.Add(n)); } } // If there was no complete match, yet, try to get extended information out of matroska files) if (!episodeInfo.IsBaseInfoPresent || !episodeInfo.HasExternalId) { try { MatroskaMatcher matroskaMatcher = new MatroskaMatcher(); if (matroskaMatcher.MatchSeries(lfsra, episodeInfo)) { ServiceRegistration.Get <ILogger>().Debug("ExtractSeriesData: Found EpisodeInfo by MatroskaMatcher for {0}, IMDB {1}, TVDB {2}, TMDB {3}, AreReqiredFieldsFilled {4}", episodeInfo.SeriesName, episodeInfo.SeriesImdbId, episodeInfo.SeriesTvdbId, episodeInfo.SeriesMovieDbId, episodeInfo.IsBaseInfoPresent); } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("ExtractSeriesData: Exception reading matroska tags for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } // If no information was found before, try name matching if (!episodeInfo.IsBaseInfoPresent) { // Try to match series from folder and file naming SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(lfsra, episodeInfo); } //Prepare online search improvements if (episodeInfo.SeriesFirstAired == null) { EpisodeInfo tempEpisodeInfo = new EpisodeInfo(); SeriesMatcher seriesMatcher = new SeriesMatcher(); seriesMatcher.MatchSeries(lfsra, tempEpisodeInfo); if (tempEpisodeInfo.SeriesFirstAired.HasValue) { episodeInfo.SeriesFirstAired = tempEpisodeInfo.SeriesFirstAired; } } if (string.IsNullOrEmpty(episodeInfo.SeriesAlternateName)) { var mediaItemPath = lfsra.CanonicalLocalResourcePath; var seriesMediaItemDirectoryPath = ResourcePathHelper.Combine(mediaItemPath, "../../"); episodeInfo.SeriesAlternateName = seriesMediaItemDirectoryPath.FileName; } if (episodeInfo.Languages.Count == 0) { IList <MultipleMediaItemAspect> audioAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, VideoAudioStreamAspect.Metadata, out audioAspects)) { foreach (MultipleMediaItemAspect aspect in audioAspects) { string language = (string)aspect.GetAttributeValue(VideoAudioStreamAspect.ATTR_AUDIOLANGUAGE); if (!string.IsNullOrEmpty(language) && !episodeInfo.Languages.Contains(language)) { episodeInfo.Languages.Add(language); } } } } episodeInfo.AssignNameId(); if (SkipOnlineSearches && !SkipFanArtDownload) { EpisodeInfo tempInfo = episodeInfo.Clone(); OnlineMatcherService.Instance.FindAndUpdateEpisode(tempInfo, importOnly); episodeInfo.CopyIdsFrom(tempInfo); episodeInfo.HasChanged = tempInfo.HasChanged; } else if (!SkipOnlineSearches) { OnlineMatcherService.Instance.FindAndUpdateEpisode(episodeInfo, importOnly); } //Send it to the videos section if (!SkipOnlineSearches && !episodeInfo.HasExternalId) { return(false); } if (refresh) { if ((IncludeActorDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_ACTOR) && episodeInfo.Actors.Count > 0) || (IncludeCharacterDetails && !BaseInfo.HasRelationship(extractedAspectData, CharacterAspect.ROLE_CHARACTER) && episodeInfo.Characters.Count > 0) || (IncludeDirectorDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_DIRECTOR) && episodeInfo.Directors.Count > 0) || (IncludeWriterDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_WRITER) && episodeInfo.Writers.Count > 0) || (!BaseInfo.HasRelationship(extractedAspectData, SeriesAspect.ROLE_SERIES) && !episodeInfo.SeriesName.IsEmpty) || (!BaseInfo.HasRelationship(extractedAspectData, SeasonAspect.ROLE_SEASON) && episodeInfo.SeasonNumber.HasValue)) { episodeInfo.HasChanged = true; } } if (!episodeInfo.HasChanged && !importOnly) { return(false); } episodeInfo.SetMetadata(extractedAspectData); return(episodeInfo.IsBaseInfoPresent); }