private void MapSeriesToResult(MetadataResult <Series> result, TvDbSharper.Dto.Series tvdbSeries, string metadataLanguage) { Series series = result.Item; series.SetProviderId(MetadataProviders.Tvdb, tvdbSeries.Id.ToString()); series.Name = tvdbSeries.SeriesName; series.Overview = (tvdbSeries.Overview ?? string.Empty).Trim(); result.ResultLanguage = metadataLanguage; series.AirDays = TVUtils.GetAirDays(tvdbSeries.AirsDayOfWeek); series.AirTime = tvdbSeries.AirsTime; series.CommunityRating = (float?)tvdbSeries.SiteRating; series.SetProviderId(MetadataProviders.Imdb, tvdbSeries.ImdbId); series.SetProviderId(MetadataProviders.Zap2It, tvdbSeries.Zap2itId); if (Enum.TryParse(tvdbSeries.Status, true, out SeriesStatus seriesStatus)) { series.Status = seriesStatus; } if (DateTime.TryParse(tvdbSeries.FirstAired, out var date)) { // dates from tvdb are UTC but without offset or Z series.PremiereDate = date; series.ProductionYear = date.Year; } series.RunTimeTicks = TimeSpan.FromMinutes(Convert.ToDouble(tvdbSeries.Runtime)).Ticks; foreach (var genre in tvdbSeries.Genre) { series.AddGenre(genre); } series.AddStudio(tvdbSeries.Network); if (result.Item.Status.HasValue && result.Item.Status.Value == SeriesStatus.Ended) { try { var episodeSummary = _tvDbClientManager .GetSeriesEpisodeSummaryAsync(tvdbSeries.Id, metadataLanguage, CancellationToken.None).Result.Data; var maxSeasonNumber = episodeSummary.AiredSeasons.Select(s => Convert.ToInt32(s)).Max(); var episodeQuery = new EpisodeQuery { AiredSeason = maxSeasonNumber }; var episodesPage = _tvDbClientManager.GetEpisodesPageAsync(tvdbSeries.Id, episodeQuery, metadataLanguage, CancellationToken.None).Result.Data; result.Item.EndDate = episodesPage.Select(e => { DateTime.TryParse(e.FirstAired, out var firstAired); return(firstAired); }).Max(); } catch (TvDbServerException e) { _logger.LogError(e, "Failed to find series end date for series {TvdbId}", tvdbSeries.Id); } } }
private void FetchDataFromSeriesNode(Series item, XmlReader reader, CancellationToken cancellationToken) { reader.MoveToContent(); // Loop through each element while (reader.Read()) { cancellationToken.ThrowIfCancellationRequested(); if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case "SeriesName": { item.Name = (reader.ReadElementContentAsString() ?? string.Empty).Trim(); break; } case "Overview": { item.Overview = (reader.ReadElementContentAsString() ?? string.Empty).Trim(); break; } case "Airs_DayOfWeek": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.AirDays = TVUtils.GetAirDays(val); } break; } case "Airs_Time": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.AirTime = val; } break; } case "ContentRating": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.OfficialRating = val; } break; } case "Rating": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { // Only fill this if it doesn't already have a value, since we get it from imdb which has better data if (!item.CommunityRating.HasValue || string.IsNullOrWhiteSpace(item.GetProviderId(MetadataProviders.Imdb))) { float rval; // float.TryParse is local aware, so it can be probamatic, force us culture if (float.TryParse(val, NumberStyles.AllowDecimalPoint, _usCulture, out rval)) { item.CommunityRating = rval; } } } break; } case "RatingCount": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { int rval; // int.TryParse is local aware, so it can be probamatic, force us culture if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) { item.VoteCount = rval; } } break; } case "IMDB_ID": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.SetProviderId(MetadataProviders.Imdb, val); } break; } case "zap2it_id": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.SetProviderId(MetadataProviders.Zap2It, val); } break; } case "Status": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { SeriesStatus seriesStatus; if (Enum.TryParse(val, true, out seriesStatus)) { item.Status = seriesStatus; } } break; } case "FirstAired": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { DateTime date; if (DateTime.TryParse(val, out date)) { date = date.ToUniversalTime(); item.PremiereDate = date; item.ProductionYear = date.Year; } } break; } case "Runtime": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { int rval; // int.TryParse is local aware, so it can be probamatic, force us culture if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) { item.RunTimeTicks = TimeSpan.FromMinutes(rval).Ticks; } } break; } case "Genre": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { var vals = val .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) .Select(i => i.Trim()) .Where(i => !string.IsNullOrWhiteSpace(i)) .ToList(); if (vals.Count > 0) { item.Genres.Clear(); foreach (var genre in vals) { item.AddGenre(genre); } } } break; } case "Network": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { var vals = val .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) .Select(i => i.Trim()) .Where(i => !string.IsNullOrWhiteSpace(i)) .ToList(); if (vals.Count > 0) { item.Studios.Clear(); foreach (var genre in vals) { item.AddStudio(genre); } } } break; } default: reader.Skip(); break; } } } }
/// <summary> /// Fetches the data from XML node. /// </summary> /// <param name="reader">The reader.</param> /// <param name="itemResult">The item result.</param> protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult <Series> itemResult) { var item = itemResult.Item; switch (reader.Name) { case "id": { string imdbId = reader.GetAttribute("IMDB"); string tmdbId = reader.GetAttribute("TMDB"); string tvdbId = reader.GetAttribute("TVDB"); if (string.IsNullOrWhiteSpace(tvdbId)) { tvdbId = reader.ReadElementContentAsString(); } if (!string.IsNullOrWhiteSpace(imdbId)) { item.SetProviderId(MetadataProviders.Imdb, imdbId); } if (!string.IsNullOrWhiteSpace(tmdbId)) { item.SetProviderId(MetadataProviders.Tmdb, tmdbId); } if (!string.IsNullOrWhiteSpace(tvdbId)) { item.SetProviderId(MetadataProviders.Tvdb, tvdbId); } break; } case "airs_dayofweek": { item.AirDays = TVUtils.GetAirDays(reader.ReadElementContentAsString()); break; } case "airs_time": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.AirTime = val; } break; } case "status": { var status = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(status)) { if (Enum.TryParse(status, true, out SeriesStatus seriesStatus)) { item.Status = seriesStatus; } else { Logger.LogInformation("Unrecognized series status: " + status); } } break; } default: base.FetchDataFromXmlNode(reader, itemResult); break; } }
/// <summary> /// Fetches the main info. /// </summary> /// <param name="series">The series.</param> /// <param name="doc">The doc.</param> private void FetchMainInfo(Series series, XmlDocument doc) { if (!series.LockedFields.Contains(MetadataFields.Name)) { series.Name = doc.SafeGetString("//SeriesName"); } if (!series.LockedFields.Contains(MetadataFields.Overview)) { series.Overview = doc.SafeGetString("//Overview"); } series.CommunityRating = doc.SafeGetSingle("//Rating", 0, 10); series.AirDays = TVUtils.GetAirDays(doc.SafeGetString("//Airs_DayOfWeek")); series.AirTime = doc.SafeGetString("//Airs_Time"); SeriesStatus seriesStatus; if (Enum.TryParse(doc.SafeGetString("//Status"), true, out seriesStatus)) { series.Status = seriesStatus; } series.PremiereDate = doc.SafeGetDateTime("//FirstAired"); if (series.PremiereDate.HasValue) { series.ProductionYear = series.PremiereDate.Value.Year; } series.RunTimeTicks = TimeSpan.FromMinutes(doc.SafeGetInt32("//Runtime")).Ticks; if (!series.LockedFields.Contains(MetadataFields.Studios)) { string s = doc.SafeGetString("//Network"); if (!string.IsNullOrWhiteSpace(s)) { series.Studios.Clear(); foreach (var studio in s.Trim().Split('|')) { series.AddStudio(studio); } } } series.OfficialRating = doc.SafeGetString("//ContentRating"); if (!series.LockedFields.Contains(MetadataFields.Genres)) { string g = doc.SafeGetString("//Genre"); if (g != null) { string[] genres = g.Trim('|').Split('|'); if (g.Length > 0) { series.Genres.Clear(); foreach (var genre in genres) { series.AddGenre(genre); } } } } if (series.Status == SeriesStatus.Ended) { var document = XDocument.Load(new XmlNodeReader(doc)); var dates = document.Descendants("Episode").Where(x => { var seasonNumber = x.Element("SeasonNumber"); var firstAired = x.Element("FirstAired"); return(firstAired != null && seasonNumber != null && (!string.IsNullOrEmpty(seasonNumber.Value) && seasonNumber.Value != "0") && !string.IsNullOrEmpty(firstAired.Value)); }).Select(x => { DateTime?date = null; DateTime tempDate; var firstAired = x.Element("FirstAired"); if (firstAired != null && DateTime.TryParse(firstAired.Value, out tempDate)) { date = tempDate; } return(date); }).ToList(); if (dates.Any(x => x.HasValue)) { series.EndDate = dates.Where(x => x.HasValue).Max(); } } }
/// <summary> /// Fetches the data from XML node. /// </summary> /// <param name="reader">The reader.</param> /// <param name="result">The result.</param> protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult <Series> result) { var item = result.Item; switch (reader.Name) { case "Series": //MB generated metadata is within a "Series" node using (var subTree = reader.ReadSubtree()) { subTree.MoveToContent(); // Loop through each element while (subTree.Read()) { if (subTree.NodeType == XmlNodeType.Element) { FetchDataFromXmlNode(subTree, result); } } } break; case "id": string id = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(id)) { item.SetProviderId(MetadataProviders.Tvdb, id); } break; case "Airs_DayOfWeek": { item.AirDays = TVUtils.GetAirDays(reader.ReadElementContentAsString()); break; } case "Airs_Time": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.AirTime = val; } break; } case "AnimeSeriesIndex": { var number = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(number)) { int num; if (int.TryParse(number, out num)) { item.AnimeSeriesIndex = num; } } break; } case "Status": { var status = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(status)) { SeriesStatus seriesStatus; if (Enum.TryParse(status, true, out seriesStatus)) { item.Status = seriesStatus; } else { Logger.Info("Unrecognized series status: " + status); } } break; } default: base.FetchDataFromXmlNode(reader, result); break; } }
/// <summary> /// Fetches the data from XML node. /// </summary> /// <param name="reader">The reader.</param> /// <param name="item">The item.</param> protected override void FetchDataFromXmlNode(XmlReader reader, Series item) { switch (reader.Name) { case "id": string id = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(id)) { item.SetProviderId(MetadataProviders.Tvdb, id); } break; case "airs_dayofweek": { item.AirDays = TVUtils.GetAirDays(reader.ReadElementContentAsString()); break; } case "airs_time": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { item.AirTime = val; } break; } case "animeseriesindex": { var number = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(number)) { int num; if (int.TryParse(number, out num)) { item.AnimeSeriesIndex = num; } } break; } case "status": { var status = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(status)) { SeriesStatus seriesStatus; if (Enum.TryParse(status, true, out seriesStatus)) { item.Status = seriesStatus; } else { Logger.Info("Unrecognized series status: " + status); } } break; } default: base.FetchDataFromXmlNode(reader, item); break; } }
/// <summary> /// Fetches the series data. /// </summary> /// <param name="series">The series.</param> /// <param name="seriesId">The series id.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{System.Boolean}.</returns> private async Task <bool> FetchSeriesData(Series series, string seriesId, CancellationToken cancellationToken) { var success = false; var name = series.Name; Logger.Debug("TvDbProvider: Fetching series data: " + name); if (!string.IsNullOrEmpty(seriesId)) { string url = string.Format(seriesGet, TVUtils.TVDBApiKey, seriesId, ConfigurationManager.Configuration.PreferredMetadataLanguage); var doc = new XmlDocument(); try { using (var xml = await HttpClient.Get(url, TvDbResourcePool, cancellationToken).ConfigureAwait(false)) { doc.Load(xml); } } catch (HttpException) { } if (doc.HasChildNodes) { //kick off the actor and image fetch simultaneously var actorTask = FetchActors(series, seriesId, doc, cancellationToken); var imageTask = FetchImages(series, seriesId, cancellationToken); success = true; series.Name = doc.SafeGetString("//SeriesName"); series.Overview = doc.SafeGetString("//Overview"); series.CommunityRating = doc.SafeGetSingle("//Rating", 0, 10); series.AirDays = TVUtils.GetAirDays(doc.SafeGetString("//Airs_DayOfWeek")); series.AirTime = doc.SafeGetString("//Airs_Time"); string n = doc.SafeGetString("//banner"); if (!string.IsNullOrWhiteSpace(n)) { series.SetImage(ImageType.Banner, await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n, "banner" + Path.GetExtension(n), TvDbResourcePool, cancellationToken).ConfigureAwait(false)); } string s = doc.SafeGetString("//Network"); if (!string.IsNullOrWhiteSpace(s)) { series.AddStudios(new List <string>(s.Trim().Split('|'))); } series.OfficialRating = doc.SafeGetString("//ContentRating"); string g = doc.SafeGetString("//Genre"); if (g != null) { string[] genres = g.Trim('|').Split('|'); if (g.Length > 0) { series.AddGenres(genres); } } //wait for other tasks await Task.WhenAll(actorTask, imageTask).ConfigureAwait(false); if (ConfigurationManager.Configuration.SaveLocalMeta) { var ms = new MemoryStream(); doc.Save(ms); await _providerManager.SaveToLibraryFilesystem(series, Path.Combine(series.MetaLocation, LOCAL_META_FILE_NAME), ms, cancellationToken).ConfigureAwait(false); } } } return(success); }