public void TestGetEpisodeMetadata() { EpisodeInfo episodeInfo = new EpisodeInfo() { Name = "老友记 第一季", ParentIndexNumber = 1, IndexNumber = 1, }; episodeInfo.SeriesProviderIds[FrodoUtils.ProviderId] = "1393859"; var metadataResult = _doubanProvider.GetMetadata(episodeInfo, CancellationToken.None).Result; Assert.True(metadataResult.HasMetadata); EpisodeInfo episodeInfo2 = new EpisodeInfo() { Name = "老友记 第一季", ParentIndexNumber = 1, IndexNumber = 2, }; episodeInfo2.SeriesProviderIds[FrodoUtils.ProviderId] = "1393859"; var metadataResult2 = _doubanProvider.GetMetadata(episodeInfo2, CancellationToken.None).Result; Assert.True(metadataResult2.HasMetadata); }
private void LoadCommentsList() { GUIUtils.SetProperty("#Trakt.Items", string.Empty); GUIBackgroundTask.Instance.ExecuteInBackgroundAndCallback(() => { switch (ShoutType) { case ShoutTypeEnum.movie: if (MovieInfo == null) { return(null); } GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", MovieInfo.Title); return(GetMovieComments()); case ShoutTypeEnum.show: if (ShowInfo == null) { return(null); } GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", ShowInfo.Title); return(GetShowComments()); case ShoutTypeEnum.season: if (SeasonInfo == null) { return(null); } GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", SeasonInfo.Title); return(GetSeasonComments()); case ShoutTypeEnum.episode: if (EpisodeInfo == null) { return(null); } GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", EpisodeInfo.ToString()); return(GetEpisodeComments()); case ShoutTypeEnum.list: if (ListInfo == null) { return(null); } GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", ListInfo.Name); return(GetListComments()); default: return(null); } }, delegate(bool success, object result) { if (success) { SendCommentsToFacade(result as IEnumerable <TraktComment>); } }, Translation.GettingShouts, true); }
public EpisodeInfo GetSeriesFromTags(IDictionary metadata) { EpisodeInfo episodeInfo = new EpisodeInfo(); string tmpString; if (TryGet(metadata, TAG_TITLE, out tmpString)) { episodeInfo.SeriesName.Text = tmpString; } if (TryGet(metadata, TAG_EPISODENAME, out tmpString)) { episodeInfo.EpisodeName.Text = tmpString; } if (TryGet(metadata, TAG_GENRE, out tmpString)) { episodeInfo.Genres = new List <GenreInfo>(tmpString.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Select(s => new GenreInfo { Name = s })); OnlineMatcherService.Instance.AssignMissingSeriesGenreIds(episodeInfo.Genres); } episodeInfo.HasChanged = true; return(episodeInfo); }
public override void Update(MediaItem mediaItem) { base.Update(mediaItem); if (mediaItem == null) { return; } EpisodeInfo episodeInfo = new EpisodeInfo(); if (!episodeInfo.FromMetadata(mediaItem.Aspects)) { return; } Series = episodeInfo.SeriesName.Text; EpisodeName = episodeInfo.EpisodeName.Text; Season = episodeInfo.SeasonNumber.ToString(); EpisodeNumber = string.Join(", ", episodeInfo.EpisodeNumbers.Distinct().OrderBy(e => e)); if (episodeInfo.DvdEpisodeNumbers.Count > 0) { DVDEpisodeNumber = string.Join(", ", episodeInfo.DvdEpisodeNumbers.Distinct().OrderBy(e => e)); } else { DVDEpisodeNumber = EpisodeNumber; } // Use the short string without series name here SimpleTitle = episodeInfo.ToShortString(); StoryPlot = episodeInfo.Summary.Text; FireChange(); }
public EpisodeInfo GetSeriesFromTags(IDictionary metadata) { EpisodeInfo episodeInfo = new EpisodeInfo(); string tmpString; if (TryGet(metadata, TAG_TITLE, out tmpString)) { episodeInfo.SeriesName.Text = tmpString; } if (TryGet(metadata, TAG_EPISODENAME, out tmpString)) { episodeInfo.EpisodeName.Text = tmpString; } if (TryGet(metadata, TAG_GENRE, out tmpString)) { episodeInfo.Genres = new List <GenreInfo>(tmpString.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Select(s => new GenreInfo { Name = s.Trim() })); IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in episodeInfo.Genres) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Series, null, out int genreId)) { genre.Id = genreId; } } } episodeInfo.HasChanged = true; return(episodeInfo); }
private async Task <EpisodeInfo> CreateEpisodeInfo(Episode episode, string episodeId = null) { if (episode == null) { return(null); } if (string.IsNullOrEmpty(episodeId)) { episodeId = episode.IDs.ID.ToString(); } var cacheKey = $"episode:{episodeId}"; EpisodeInfo info = null; if (DataCache.TryGetValue <EpisodeInfo>(cacheKey, out info)) { return(info); } var aniDB = (await ShokoAPI.GetEpisodeAniDb(episodeId)); info = new EpisodeInfo { Id = episodeId, ExtraType = GetExtraType(aniDB), Shoko = (await ShokoAPI.GetEpisode(episodeId)), AniDB = aniDB, TvDB = ((await ShokoAPI.GetEpisodeTvDb(episodeId))?.FirstOrDefault()), }; DataCache.Set <EpisodeInfo>(cacheKey, info, DefaultTimeSpan); return(info); }
public ImageKey[] BuildImageKeysToDown() { List <ImageKey> list = new List <ImageKey>(); int lastEpisodeNo = webtoonInfo.GetLastEpisodeNo(); for (int episodeNo = 1; episodeNo <= lastEpisodeNo; episodeNo++) { if (!webtoonInfo.Episodes.ContainsKey(episodeNo)) { continue; } EpisodeInfo episodeInfo = webtoonInfo.Episodes[episodeNo]; string[] imageUrls = episodeInfo.EpisodeImageUrls; for (int imageIndex = 0; imageIndex < imageUrls.Length; imageIndex++) { ImageKey imageKey = new ImageKey(webtoonInfo.WebtoonTitleId, episodeNo, imageIndex); if (File.Exists(fileNameBuilder.BuildImageFileFullPath(imageKey))) { continue; } list.Add(imageKey); } } return(list.ToArray()); }
public async Task <MetadataResult <Episode> > GetMetadata(EpisodeInfo info, CancellationToken cancellationToken) { _logger.LogInformation($"Douban:GetMetadata for episode {info.Name}"); var result = new MetadataResult <Episode>(); if (info.IsMissingEpisode) { _logger.LogInformation("Do not support MissingEpisode"); return(result); } info.SeriesProviderIds.TryGetValue(ProviderID, out string sid); if (string.IsNullOrEmpty(sid)) { _logger.LogInformation("No douban sid found, just skip"); return(result); } if (!info.IndexNumber.HasValue) { _logger.LogInformation("No episode num found, please check " + "the format of file name"); return(result); } // Start to get information from douban result.Item = new Episode { Name = info.Name, IndexNumber = info.IndexNumber, ParentIndexNumber = info.ParentIndexNumber }; var url = String.Format("https://movie.douban.com/subject/{0}" + "/episode/{1}/", sid, info.IndexNumber); String content = await _doubanAccessor.GetResponseWithDelay(url, cancellationToken); String pattern_name = "data-name=\\\"(.*?)\\\""; Match match = Regex.Match(content, pattern_name); if (match.Success) { var name = match.Groups[1].Value; _logger.LogDebug("The name is {0}", name); result.Item.Name = name; } String pattern_desc = "data-desc=\\\"(.*?)\\\""; match = Regex.Match(content, pattern_desc); if (match.Success) { var desc = match.Groups[1].Value; _logger.LogDebug("The desc is {0}", desc); result.Item.Overview = desc; } result.HasMetadata = true; return(result); }
public Task <MetadataResult <Episode> > GetMetadata(EpisodeInfo info, CancellationToken cancellationToken) { var metadataResult = Try(() => { var result = _mediaItemProcessor.GetResultAsync(info, MediaItemTypes.Episode, GetParentIds(info)); return(result.Map(either => either.Match(r => { _log.Info($"Found data for episode '{info.Name}': '{r.EmbyMetadataResult.Item.Name}'"); info.IndexNumber = null; info.ParentIndexNumber = null; info.Name = ""; info.ProviderIds = new Dictionary <string, string>(); return r.EmbyMetadataResult; }, failure => { _log.Error($"Failed to get data for episode '{info.Name}': {failure.Reason}"); return EmptyMetadataResult; }) )); }) .IfFail(e => { _log.ErrorException($"Failed to get data for episode '{info.Name}'", e); return(EmptyMetadataResult.AsTask()); }); return(metadataResult); }
public IDictionary <Guid, IList <MediaItemAspect> > GetBaseChildAspectsFromExistingAspects(IDictionary <Guid, IList <MediaItemAspect> > existingChildAspects, IDictionary <Guid, IList <MediaItemAspect> > existingParentAspects) { if (existingParentAspects.ContainsKey(SeriesAspect.ASPECT_ID)) { SeriesInfo series = new SeriesInfo(); series.FromMetadata(existingParentAspects); if (existingChildAspects.ContainsKey(SeasonAspect.ASPECT_ID)) { SeasonInfo season = new SeasonInfo(); season.FromMetadata(existingChildAspects); SeasonInfo basicSeason = series.CloneBasicInstance <SeasonInfo>(); basicSeason.SeasonNumber = season.SeasonNumber; IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); basicSeason.SetMetadata(aspects, true); return(aspects); } else if (existingChildAspects.ContainsKey(EpisodeAspect.ASPECT_ID)) { EpisodeInfo episode = new EpisodeInfo(); episode.FromMetadata(existingChildAspects); EpisodeInfo basicEpisode = series.CloneBasicInstance <EpisodeInfo>(); basicEpisode.SeasonNumber = episode.SeasonNumber; basicEpisode.EpisodeNumbers = episode.EpisodeNumbers.ToList(); IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >(); basicEpisode.SetMetadata(aspects, true); return(aspects); } } return(null); }
public void Setup() { _episodeInfo = new EpisodeInfo { Name = "EpisodeName", IndexNumber = 3, ParentIndexNumber = 1, ProviderIds = new Dictionary <string, string> { { "Source", "66" } } }; _mediaItemProcessorResult = Left <ProcessFailedResult, IMetadataFoundResult <Episode> >( new ProcessFailedResult("FailedSource", "MediaItemName", MediaItemTypes.Episode, "Failure reason")); _mediaItemProcessor = Substitute.For <IMediaItemProcessor>(); _mediaItemProcessor.GetResultAsync(_episodeInfo, MediaItemTypes.Episode, Arg.Any <IEnumerable <EmbyItemId> >()) .Returns(x => _mediaItemProcessorResult); _logManager = Substitute.For <ILogManager>(); _logger = Substitute.For <ILogger>(); _logger.WhenForAnyArgs(l => l.Debug(null, null)).Do(c => Console.WriteLine($"Debug: {c.Arg<string>()}")); _logManager.GetLogger("EpisodeProvider").Returns(_logger); _episodeProvider = new EpisodeProvider(_logManager, _mediaItemProcessor); }
/// <summary> /// Gets the new path. /// </summary> /// <param name="sourcePath">The source path.</param> /// <param name="series">The series.</param> /// <param name="seasonNumber">The season number.</param> /// <param name="episodeNumber">The episode number.</param> /// <param name="endingEpisodeNumber">The ending episode number.</param> /// <param name="options">The options.</param> /// <returns>System.String.</returns> private async Task <string> GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int?endingEpisodeNumber, TvFileOrganizationOptions options, CancellationToken cancellationToken) { var episodeInfo = new EpisodeInfo { IndexNumber = episodeNumber, IndexNumberEnd = endingEpisodeNumber, MetadataCountryCode = series.GetPreferredMetadataCountryCode(), MetadataLanguage = series.GetPreferredMetadataLanguage(), ParentIndexNumber = seasonNumber, SeriesProviderIds = series.ProviderIds }; var searchResults = await _providerManager.GetRemoteSearchResults <Episode, EpisodeInfo>(new RemoteSearchQuery <EpisodeInfo> { SearchInfo = episodeInfo }, cancellationToken).ConfigureAwait(false); var episode = searchResults.FirstOrDefault(); if (episode == null) { _logger.Warn("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); return(null); } var newPath = GetSeasonFolderPath(series, seasonNumber, options); var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options); newPath = Path.Combine(newPath, episodeFileName); return(newPath); }
private static void CompareMembers(EpisodeInfo a, EpisodeInfo b) { Assert.AreEqual(a.Name, b.Name); Assert.True(a.Season == b.Season); Assert.True(a.Episode == b.Episode); Assert.True((bool)a == (bool)b); }
protected override async Task <bool> ExtractMetadataAsync(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode) { if (!CanExtract(lfsra, extractedAspectData)) { return(false); } if (extractedAspectData.ContainsKey(EpisodeAspect.ASPECT_ID)) { return(false); } // Handle series information EpisodeInfo episodeInfo = new EpisodeInfo(); using (var rec = new MCRecMetadataEditor(lfsra.LocalFileSystemPath)) { IDictionary tags = rec.GetAttributes(); episodeInfo = GetSeriesFromTags(tags); } if (episodeInfo.IsBaseInfoPresent) { if (!forceQuickMode) { await OnlineMatcherService.Instance.FindAndUpdateEpisodeAsync(episodeInfo).ConfigureAwait(false); } if (episodeInfo.IsBaseInfoPresent) { episodeInfo.SetMetadata(extractedAspectData); } } return(episodeInfo.IsBaseInfoPresent); }
public (int downloadedImageCount, long downloadedImagesSize) GetDownloadedImagesInformation() { WebtoonKey webtoonKey = new WebtoonKey(webtoonInfo.WebtoonTitleId); int count = 0; long size = 0; int lastEpisode = webtoonInfo.GetLastEpisodeNo(); for (int episodeNo = 1; episodeNo <= lastEpisode; episodeNo++) { if (!webtoonInfo.Episodes.ContainsKey(episodeNo)) { continue; } EpisodeInfo episodeInfo = webtoonInfo.Episodes[episodeNo]; string[] imageUrls = episodeInfo.EpisodeImageUrls; for (int imageIndex = 0; imageIndex < imageUrls.Length; imageIndex++) { ImageKey imageKey = new ImageKey(webtoonInfo.WebtoonTitleId, episodeNo, imageIndex); if (File.Exists(fileNameBuilder.BuildImageFileFullPath(imageKey))) { count++; size += new FileInfo(fileNameBuilder.BuildImageFileFullPath(imageKey)).Length; } } } return(count, size); }
public async Task <IEnumerable <EpisodeInfo> > FindMatchingEpisodesAsync(EpisodeInfo episodeInfo, string category) { var tasks = SERIES_MATCHERS.Where(m => category == null || m.Key == category).SelectMany(m => m.Value).Where(m => m.Enabled) .Select(m => m.FindMatchingEpisodesAsync(episodeInfo)).ToList(); //Merge results return(await MergeResults(tasks).ConfigureAwait(false)); }
public Task <IEnumerable <RemoteSearchResult> > GetSearchResults( EpisodeInfo info, CancellationToken cancellationToken) { _logger.LogInformation("Douban:Search for episode {0}", info.Name); // It's needless for season to do search return(Task.FromResult <IEnumerable <RemoteSearchResult> >( new List <RemoteSearchResult>())); }
public async Task <IEnumerable <EpisodeInfo> > FindMatchingEpisodesAsync(EpisodeInfo episodeInfo) { var tasks = SERIES_MATCHERS.Where(m => m.Enabled) .Select(m => m.FindMatchingEpisodesAsync(episodeInfo)).ToList(); //Merge results return(await MergeResults(tasks).ConfigureAwait(false)); }
public override bool UpdateFromOnlineSeriesEpisode(EpisodeInfo episode, string language, bool cacheOnly) { if (episode.SeriesTvdbId > 0) { return(true); } return(false); }
/// <summary> /// Get index number for a movie in a box-set. /// </summary> /// <returns>Absoute index.</returns> public static int GetMovieIndexNumber(GroupInfo group, SeriesInfo series, EpisodeInfo episode) { switch (Plugin.Instance.Configuration.BoxSetGrouping) { default: case GroupType.Default: return(1); case GroupType.ShokoSeries: return(episode.AniDB.EpisodeNumber); case GroupType.ShokoGroup: { int offset = 0; foreach (SeriesInfo s in group.SeriesList) { var sizes = s.Shoko.Sizes.Total; if (s != series) { if (episode.AniDB.Type == EpisodeType.Special) { var index = series.FilteredSpecialEpisodesList.FindIndex(e => string.Equals(e.Id, episode.Id)); if (index == -1) { throw new System.IndexOutOfRangeException("Episode not in filtered list"); } return(offset - (index + 1)); } switch (episode.AniDB.Type) { case EpisodeType.Normal: // offset += 0; // it's not needed, so it's just here as a comment instead. break; case EpisodeType.Parody: offset += sizes?.Episodes ?? 0; goto case EpisodeType.Normal; case EpisodeType.Other: offset += sizes?.Parodies ?? 0; goto case EpisodeType.Parody; } return(offset + episode.AniDB.EpisodeNumber); } else { if (episode.AniDB.Type == EpisodeType.Special) { offset -= series.FilteredSpecialEpisodesList.Count; } offset += (sizes?.Episodes ?? 0) + (sizes?.Parodies ?? 0) + (sizes?.Others ?? 0); } } break; } } return(0); }
protected override bool SetSeriesEpisodeId(EpisodeInfo episode, string id) { if (!string.IsNullOrEmpty(id)) { episode.ImdbId = id; return(true); } return(false); }
/// <inheritdoc /> public async Task <IEnumerable <RemoteImageInfo> > GetImages(BaseItem item, CancellationToken cancellationToken) { var episode = (Episode)item; var series = episode.Series; var imageResult = new List <RemoteImageInfo>(); var language = item.GetPreferredMetadataLanguage(); if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds)) { // Process images try { string?episodeTvdbId = null; if (episode.IndexNumber.HasValue && episode.ParentIndexNumber.HasValue) { var episodeInfo = new EpisodeInfo { IndexNumber = episode.IndexNumber.Value, ParentIndexNumber = episode.ParentIndexNumber.Value, SeriesProviderIds = series.ProviderIds, SeriesDisplayOrder = series.DisplayOrder }; episodeTvdbId = await _tvdbClientManager .GetEpisodeTvdbId(episodeInfo, language, cancellationToken).ConfigureAwait(false); } if (string.IsNullOrEmpty(episodeTvdbId)) { _logger.LogError( "Episode {SeasonNumber}x{EpisodeNumber} not found for series {SeriesTvdbId}", episode.ParentIndexNumber, episode.IndexNumber, series.GetProviderId(TvdbPlugin.ProviderId)); return(imageResult); } var episodeResult = await _tvdbClientManager .GetEpisodesAsync(Convert.ToInt32(episodeTvdbId, CultureInfo.InvariantCulture), language, cancellationToken) .ConfigureAwait(false); var image = GetImageInfo(episodeResult.Data); if (image != null) { imageResult.Add(image); } } catch (TvDbServerException e) { _logger.LogError(e, "Failed to retrieve episode images for series {TvDbId}", series.GetProviderId(TvdbPlugin.ProviderId)); } } return(imageResult); }
protected override bool GetSeriesEpisodeId(EpisodeInfo episode, out string id) { id = null; if (!string.IsNullOrEmpty(episode.ImdbId)) { id = episode.ImdbId; } return(id != null); }
public override bool HasSearchableIds(EpisodeInfo episode) { if (episode.SeriesTvMazeId > 0 || episode.SeriesTvdbId > 0 || !string.IsNullOrWhiteSpace(episode.SeriesImdbId)) { return(true); } return(base.HasSearchableIds(episode)); }
public MovieModel(MovieInfo info, EpisodeInfo lastWatched) { MarkWatchedCommand = new DelegateCommand <EpisodeModel>(OnMarkWatchedCommand); _info = info; FillEpisodesInfo(); SetLastWatched(lastWatched == null ? null : _episodes.FirstOrDefault(e => e.Season == lastWatched.Season && e.Episode == lastWatched.Episode)); }
protected override bool SetSeriesEpisodeId(EpisodeInfo episode, string id) { if (!string.IsNullOrEmpty(id)) { episode.TvMazeId = Convert.ToInt32(id); return(true); } return(false); }
protected override bool GetSeriesEpisodeId(EpisodeInfo episode, out string id) { id = null; if (episode.TvMazeId > 0) { id = episode.TvMazeId.ToString(); } return(id != null); }
public EpisodeInfo GetSeriesFromTags(Argus.Recording recording) { EpisodeInfo episodeInfo = new EpisodeInfo { SeriesName = recording.Title }; if (recording.SeriesNumber.HasValue) { episodeInfo.SeasonNumber = recording.SeriesNumber.Value; } if (recording.EpisodeNumber.HasValue) { episodeInfo.EpisodeNumbers.Add(recording.EpisodeNumber.Value); } if (!episodeInfo.IsBaseInfoPresent) { // 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)) { episodeInfo.SeasonNumber = val; } if (int.TryParse(parts[1], out val)) { episodeInfo.EpisodeNumbers.Add(val); } } } } if (!string.IsNullOrEmpty(recording.Category?.Trim())) { episodeInfo.Genres.Add(new GenreInfo { Name = recording.Category.Trim() }); IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in episodeInfo.Genres) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Series, null, out int genreId)) { genre.Id = genreId; } } } episodeInfo.HasChanged = true; return(episodeInfo); }
public void StandardShownameTestWithX() { var expectedShowDetails = new EpisodeInfo("Arrow", 1, 2); var incorrectShowDetails = new EpisodeInfo("Arrow", 2, 1); var returnedShowDetails = FileCategorizer.GetFileInfo(DefaultShownameWithX); CompareMembers(expectedShowDetails, returnedShowDetails); Assert.AreEqual(expectedShowDetails, returnedShowDetails); Assert.AreNotEqual(incorrectShowDetails, returnedShowDetails); }
public async Task <bool> UpdateEpisodeCharactersAsync(EpisodeInfo episodeInfo) { bool success = false; foreach (ISeriesMatcher matcher in SERIES_MATCHERS.Where(m => m.Enabled)) { success |= await matcher.UpdateEpisodeCharactersAsync(episodeInfo).ConfigureAwait(false); } return(success); }