static SeriesInfo ParseSeries(Match ma) { SeriesInfo info = new SeriesInfo(); Group group = ma.Groups[GROUP_SERIES]; if (group.Length > 0) info.Series = SeriesInfo.CleanupWhiteSpaces(group.Value); group = ma.Groups[GROUP_EPISODE]; if (group.Length > 0) info.Episode = SeriesInfo.CleanupWhiteSpaces(group.Value); group = ma.Groups[GROUP_SEASONNUM]; int tmpInt; if (group.Length > 0 && int.TryParse(group.Value, out tmpInt)) info.SeasonNumber = tmpInt; // There can be multipe episode numbers in one file group = ma.Groups[GROUP_EPISODENUM]; if (group.Length > 0) { foreach (Capture capture in group.Captures) { int episodeNum; if (int.TryParse(capture.Value, out episodeNum)) info.EpisodeNumbers.Add(episodeNum); } } return info; }
/// <summary> /// Tries to match series by checking the <paramref name="folderOrFileName"/> for known patterns. The match is only successful, /// if the <see cref="SeriesInfo.IsCompleteMatch"/> is <c>true</c>. /// </summary> /// <param name="folderOrFileName">Full path to file</param> /// <param name="seriesInfo">Returns the parsed SeriesInfo</param> /// <returns><c>true</c> if successful.</returns> public bool MatchSeries(string folderOrFileName, out SeriesInfo seriesInfo) { foreach (Regex matcher in _matchers) { Match ma = matcher.Match(folderOrFileName); seriesInfo = ParseSeries(ma); if (seriesInfo.IsCompleteMatch) return true; } seriesInfo = null; return false; }
/// <summary> /// Tries to match series by checking the <paramref name="folderOrFileName"/> for known patterns. The match is only successful, /// if the <see cref="SeriesInfo.IsCompleteMatch"/> is <c>true</c>. /// </summary> /// <param name="folderOrFileName">Full path to file</param> /// <param name="seriesInfo">Returns the parsed SeriesInfo</param> /// <returns><c>true</c> if successful.</returns> public bool MatchSeries(string folderOrFileName, out SeriesInfo seriesInfo) { foreach (Regex matcher in _matchers) { // Calling EnsureLocalFileSystemAccess not necessary; only string operation Match ma = matcher.Match(folderOrFileName); seriesInfo = ParseSeries(ma); if (seriesInfo.IsCompleteMatch) return true; } seriesInfo = null; return false; }
/// <summary> /// Tries to match series by reading matroska tags from <paramref name="folderOrFileLfsra"/>. /// </summary> /// <param name="folderOrFileLfsra"><see cref="ILocalFsResourceAccessor"/> to file or folder</param> /// <param name="seriesInfo">Returns the parsed SeriesInfo</param> /// <param name="extractedAspectData">Dictionary containing a mapping of media item aspect ids to /// already present media item aspects, this metadata extractor should edit. If a media item aspect is not present /// in this dictionary but found by this metadata extractor, it will add it to the dictionary.</param> /// <returns><c>true</c> if successful.</returns> public bool MatchSeries(ILocalFsResourceAccessor folderOrFileLfsra, out SeriesInfo seriesInfo, ref IDictionary<Guid, MediaItemAspect> extractedAspectData) { // Calling EnsureLocalFileSystemAccess not necessary; only string operation string extensionLower = StringUtils.TrimToEmpty(Path.GetExtension(folderOrFileLfsra.LocalFileSystemPath)).ToLower(); if (!MatroskaConsts.MATROSKA_VIDEO_EXTENSIONS.Contains(extensionLower)) { seriesInfo = null; return false; } MatroskaInfoReader mkvReader = new MatroskaInfoReader(folderOrFileLfsra); // 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); return true; }
public SeriesItem(MediaItem mediaItem) : base(mediaItem) { SeriesInfo seriesInfo = new SeriesInfo(); MediaItemAspect seriesAspect; if (!mediaItem.Aspects.TryGetValue(SeriesAspect.ASPECT_ID, out seriesAspect)) return; Series = seriesInfo.Series = (string) seriesAspect[SeriesAspect.ATTR_SERIESNAME] ?? string.Empty; EpisodeName = seriesInfo.Episode = (string) seriesAspect[SeriesAspect.ATTR_EPISODENAME] ?? string.Empty; seriesInfo.SeasonNumber = (int) (seriesAspect[SeriesAspect.ATTR_SEASON] ?? 0); Season = seriesInfo.SeasonNumber.ToString(); IList<int> episodes = seriesAspect[SeriesAspect.ATTR_EPISODE] as IList<int>; if (episodes != null) { foreach (int episode in episodes) seriesInfo.EpisodeNumbers.Add(episode); EpisodeNumber = seriesInfo.FormatString(string.Format("{{{0}}}", SeriesInfo.EPISODENUM_INDEX)); } // Use the short string without series name here SimpleTitle = seriesInfo.ToShortString(); }
/// <summary> /// Tries to match series by checking the <paramref name="folderOrFileName"/> for known patterns. The match is only successful, /// if the <see cref="SeriesInfo.IsCompleteMatch"/> is <c>true</c>. /// </summary> /// <param name="folderOrFileName">Full path to file</param> /// <param name="seriesInfo">Returns the parsed SeriesInfo</param> /// <returns><c>true</c> if successful.</returns> public bool MatchSeries(string folderOrFileName, out SeriesInfo seriesInfo) { var settings = ServiceRegistration.Get<ISettingsManager>().Load<SeriesMetadataExtractorSettings>(); // First do replacements before match foreach (var replacement in settings.Replacements.Where(r => r.BeforeMatch)) { replacement.Replace(ref folderOrFileName); } foreach (var pattern in settings.Patterns) { // Calling EnsureLocalFileSystemAccess not necessary; only string operation Regex matcher; if (pattern.GetRegex(out matcher)) { Match ma = matcher.Match(folderOrFileName); seriesInfo = ParseSeries(ma); if (seriesInfo.IsCompleteMatch) { // Do replacements after successful match foreach (var replacement in settings.Replacements.Where(r => !r.BeforeMatch)) { string tmp = seriesInfo.Series; replacement.Replace(ref tmp); seriesInfo.Series = tmp; tmp = seriesInfo.Episode; replacement.Replace(ref tmp); seriesInfo.Episode = tmp; } return true; } } } seriesInfo = null; return false; }
protected SeriesInfo GetSeriesFromTags(IDictionary<string, IList<string>> extractedTags) { SeriesInfo seriesInfo = new SeriesInfo(); if (extractedTags[MatroskaConsts.TAG_EPISODE_TITLE] != null) seriesInfo.Episode = extractedTags[MatroskaConsts.TAG_EPISODE_TITLE].FirstOrDefault(); if (extractedTags[MatroskaConsts.TAG_SERIES_TITLE] != null) seriesInfo.Series = extractedTags[MatroskaConsts.TAG_SERIES_TITLE].FirstOrDefault(); if (extractedTags[MatroskaConsts.TAG_SEASON_NUMBER] != null) int.TryParse(extractedTags[MatroskaConsts.TAG_SEASON_NUMBER].FirstOrDefault(), out seriesInfo.SeasonNumber); if (extractedTags[MatroskaConsts.TAG_EPISODE_NUMBER] != null) { int episodeNum; if (int.TryParse(extractedTags[MatroskaConsts.TAG_EPISODE_NUMBER].FirstOrDefault(), out episodeNum)) seriesInfo.EpisodeNumbers.Add(episodeNum); } return seriesInfo; }
/// <summary> /// Tries to match series by checking the <paramref name="folderOrFileLfsra"/> for known patterns. The match is only successful, /// if the <see cref="SeriesInfo.IsCompleteMatch"/> is <c>true</c>. /// </summary> /// <param name="folderOrFileLfsra"><see cref="ILocalFsResourceAccessor"/> to file</param> /// <param name="seriesInfo">Returns the parsed SeriesInfo</param> /// <returns><c>true</c> if successful.</returns> public bool MatchSeries(ILocalFsResourceAccessor folderOrFileLfsra, out SeriesInfo seriesInfo) { return MatchSeries(folderOrFileLfsra.LocalFileSystemPath, out seriesInfo); }
public SeriesInfo GetSeriesFromTags(Tags extractedTags) { SeriesInfo seriesInfo = new SeriesInfo(); string tmpString; if (TryGet(extractedTags, TAG_TITLE, out tmpString)) seriesInfo.Series = tmpString; if (TryGet(extractedTags, TAG_EPISODENAME, out tmpString)) seriesInfo.Episode = tmpString; if (TryGet(extractedTags, TAG_SERIESNUM, out tmpString)) int.TryParse(tmpString, out seriesInfo.SeasonNumber); if (TryGet(extractedTags, TAG_EPISODENUM, out tmpString)) { int episodeNum; if (int.TryParse(tmpString, out episodeNum)) seriesInfo.EpisodeNumbers.Add(episodeNum); } return seriesInfo; }
protected SeriesInfo GetSeriesFromTags(IDictionary<string, IList<string>> extractedTags) { SeriesInfo seriesInfo = new SeriesInfo(); if (extractedTags[MatroskaConsts.TAG_EPISODE_TITLE] != null) seriesInfo.Episode = extractedTags[MatroskaConsts.TAG_EPISODE_TITLE].FirstOrDefault(); if (extractedTags[MatroskaConsts.TAG_SERIES_TITLE] != null) seriesInfo.Series = extractedTags[MatroskaConsts.TAG_SERIES_TITLE].FirstOrDefault(); if (extractedTags[MatroskaConsts.TAG_SERIES_IMDB_ID] != null) { string imdbId; foreach (string candidate in extractedTags[MatroskaConsts.TAG_SERIES_IMDB_ID]) if (ImdbIdMatcher.TryMatchImdbId(candidate, out imdbId)) { seriesInfo.ImdbId = imdbId; break; } } // On Series, the counting tag is "TVDB" if (extractedTags[MatroskaConsts.TAG_SERIES_TVDB_ID] != null) { int tmp; foreach (string candidate in extractedTags[MatroskaConsts.TAG_SERIES_TVDB_ID]) if(int.TryParse(candidate, out tmp) == true) { seriesInfo.TvdbId = tmp; break; } } int tmpInt; if (extractedTags[MatroskaConsts.TAG_SEASON_NUMBER] != null && int.TryParse(extractedTags[MatroskaConsts.TAG_SEASON_NUMBER].FirstOrDefault(), out tmpInt)) seriesInfo.SeasonNumber = tmpInt; if (extractedTags[MatroskaConsts.TAG_EPISODE_NUMBER] != null) { int episodeNum; foreach (string s in extractedTags[MatroskaConsts.TAG_EPISODE_NUMBER]) if (int.TryParse(s, out episodeNum)) if (!seriesInfo.EpisodeNumbers.Contains(episodeNum)) seriesInfo.EpisodeNumbers.Add(episodeNum); } return seriesInfo; }
public SeriesInfo GetSeriesFromTags(Argus.Recording recording) { SeriesInfo seriesInfo = new SeriesInfo { Series = recording.Title }; if (recording.SeriesNumber.HasValue) seriesInfo.SeasonNumber = recording.SeriesNumber.Value; if (recording.EpisodeNumber.HasValue) seriesInfo.EpisodeNumbers.Add(recording.EpisodeNumber.Value); if (!seriesInfo.IsCompleteMatch) { // Check for formatted display value, i.e.: // <EpisodeNumberDisplay>1.4</EpisodeNumberDisplay> if (!string.IsNullOrWhiteSpace(recording.EpisodeNumberDisplay)) { var parts = recording.EpisodeNumberDisplay.Split('.'); if (parts.Length == 2) { int val; if (int.TryParse(parts[0], out val)) seriesInfo.SeasonNumber = val; if (int.TryParse(parts[1], out val)) seriesInfo.EpisodeNumbers.Add(val); } } } return seriesInfo; }
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); }