private async Task HandleSeries(Series series)
        {
            var tvdbId = Convert.ToInt32(series.GetProviderId(MetadataProvider.Tvdb));

            if (tvdbId == 0)
            {
                return;
            }

            var children         = series.GetRecursiveChildren();
            var existingSeasons  = new List <Season>();
            var existingEpisodes = new Dictionary <int, List <Episode> >();

            for (var i = 0; i < children.Count; i++)
            {
                switch (children[i])
                {
                case Season season:
                    if (season.IndexNumber.HasValue)
                    {
                        existingSeasons.Add(season);
                    }

                    break;

                case Episode episode:
                    var seasonNumber = episode.ParentIndexNumber ?? 1;
                    if (!existingEpisodes.ContainsKey(seasonNumber))
                    {
                        existingEpisodes[seasonNumber] = new List <Episode>();
                    }

                    existingEpisodes[seasonNumber].Add(episode);
                    break;
                }
            }

            var allEpisodes = await GetAllEpisodes(tvdbId, series.GetPreferredMetadataLanguage()).ConfigureAwait(false);

            var allSeasons = allEpisodes
                             .Where(ep => ep.AiredSeason.HasValue)
                             .Select(ep => ep.AiredSeason.Value)
                             .Distinct()
                             .ToList();

            // Add missing seasons
            var newSeasons = AddMissingSeasons(series, existingSeasons, allSeasons);

            AddMissingEpisodes(existingEpisodes, allEpisodes, existingSeasons.Concat(newSeasons).ToList());
        }
        private RemoteImageInfo GetImageFromSeriesData(Series series, string personName, CancellationToken cancellationToken)
        {
            var tvdbPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, series.GetProviderId(MetadataProviders.Tvdb));

            var actorXmlPath = Path.Combine(tvdbPath, "actors.xml");

            try
            {
                return GetImageInfo(actorXmlPath, personName, cancellationToken);
            }
            catch (FileNotFoundException)
            {
                return null;
            }
        }
        /// <summary>
        /// Downloads the image from series.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="series">The series.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        private async Task DownloadImageFromSeries(BaseItem item, Series series, CancellationToken cancellationToken)
        {
            var tvdbPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, series.GetProviderId(MetadataProviders.Tvdb));

            var actorXmlPath = Path.Combine(tvdbPath, "actors.xml");

            var xmlDoc = new XmlDocument();

            xmlDoc.Load(actorXmlPath);

            var actorNodes = xmlDoc.SelectNodes("//Actor");

            if (actorNodes == null)
            {
                return;
            }

            foreach (var actorNode in actorNodes.OfType<XmlNode>())
            {
                var name = actorNode.SafeGetString("Name");

                if (string.Equals(item.Name, name, StringComparison.OrdinalIgnoreCase))
                {
                    var image = actorNode.SafeGetString("Image");

                    if (!string.IsNullOrEmpty(image))
                    {
                        var url = TVUtils.BannerUrl + image;

                        await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool,
                                                       ImageType.Primary, null, cancellationToken).ConfigureAwait(false);
                    }

                    break;
                }
            }
        }
        /// <summary>
        /// Add or remove a Show(Series) to/from the users trakt.tv library
        /// </summary>
        /// <param name="show">The show to remove</param>
        /// <param name="traktUser">The user who's library is being updated</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="eventType"></param>
        /// <returns>Task{TraktResponseDataContract}.</returns>
        public async Task<TraktSyncResponse> SendLibraryUpdateAsync(Series show, TraktUser traktUser, CancellationToken cancellationToken, EventType eventType)
        {
            if (show == null)
                throw new ArgumentNullException("show");
            if (traktUser == null)
                throw new ArgumentNullException("traktUser");

            if (eventType == EventType.Update) return null;

            var showPayload = new List<TraktShowCollected>
            {
                new TraktShowCollected
                {
                    Title = show.Name,
                    Year = show.ProductionYear,
                    Ids = new TraktShowId
                    {
                        Tvdb = show.GetProviderId(MetadataProviders.Tvdb).ConvertToInt(),
                        Imdb = show.GetProviderId(MetadataProviders.Imdb),
                        TvRage = show.GetProviderId(MetadataProviders.TvRage).ConvertToInt()
                    },
                }
            };

            var data = new TraktSyncCollected
            {
                Shows = showPayload.ToList()
            };

            var url = eventType == EventType.Add ? TraktUris.SyncCollectionAdd : TraktUris.SyncCollectionRemove;
            var response = await PostToTrakt(url, data, cancellationToken, traktUser);
            return _jsonSerializer.DeserializeFromStream<TraktSyncResponse>(response);
        }
        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":
                            {
                                if (!item.LockedFields.Contains(MetadataFields.Name))
                                {
                                    item.Name = (reader.ReadElementContentAsString() ?? string.Empty).Trim();
                                }
                                break;
                            }

                        case "Overview":
                            {
                                if (!item.LockedFields.Contains(MetadataFields.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))
                                {
                                    if (!item.LockedFields.Contains(MetadataFields.OfficialRating))
                                    {
                                        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) && !item.LockedFields.Contains(MetadataFields.Runtime))
                                {
                                    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))
                                {
                                    // Only fill this in if there's no existing genres, because Imdb data from Omdb is preferred
                                    if (!item.LockedFields.Contains(MetadataFields.Genres) && (item.Genres.Count == 0 || !string.Equals(item.GetPreferredMetadataLanguage(), "en", StringComparison.OrdinalIgnoreCase)))
                                    {
                                        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))
                                {
                                    if (!item.LockedFields.Contains(MetadataFields.Studios))
                                    {
                                        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;
                    }
                }
            }
        }
Beispiel #6
0
        private void AttachSoundtrackIds(BaseItemDto dto, Series item, User user)
        {
            var tvdb = item.GetProviderId(MetadataProviders.Tvdb);

            if (string.IsNullOrEmpty(tvdb))
            {
                return;
            }

            var recursiveChildren = user == null
                                        ? _libraryManager.RootFolder.RecursiveChildren
                                        : user.RootFolder.GetRecursiveChildren(user);

            dto.SoundtrackIds = recursiveChildren
                .Where(i =>
                {
                    if (!string.IsNullOrEmpty(tvdb) &&
                        string.Equals(tvdb, i.GetProviderId(MetadataProviders.Tvdb), StringComparison.OrdinalIgnoreCase) &&
                        i is MusicAlbum)
                    {
                        return true;
                    }
                    return false;
                })
                .Select(GetClientItemId)
                .ToArray();
        }
        public static bool IsMatch(Series item, TraktShow show)
        {
                var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
                if (!string.IsNullOrWhiteSpace(tvdb) &&
                    string.Equals(tvdb, show.Ids.Tvdb.ToString(), StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }

                var imdb = item.GetProviderId(MetadataProviders.Imdb);
                if (!string.IsNullOrWhiteSpace(imdb) &&
                    string.Equals(imdb, show.Ids.Imdb, StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }

                return false;
        }
        public async Task Run(Series series, CancellationToken cancellationToken)
        {
            var tvdbId = series.GetProviderId(MetadataProviders.Tvdb);

            // Can't proceed without a tvdb id
            if (string.IsNullOrEmpty(tvdbId))
            {
                return;
            }

            var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, tvdbId);

            var episodeFiles = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly)
                .Select(Path.GetFileNameWithoutExtension)
                .Where(i => i.StartsWith("episode-", StringComparison.OrdinalIgnoreCase))
                .ToList();

            var episodeLookup = episodeFiles
                .Select(i =>
                {
                    var parts = i.Split('-');

                    if (parts.Length == 3)
                    {
                        int seasonNumber;

                        if (int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out seasonNumber))
                        {
                            int episodeNumber;

                            if (int.TryParse(parts[2], NumberStyles.Integer, UsCulture, out episodeNumber))
                            {
                                return new Tuple<int, int>(seasonNumber, episodeNumber);
                            }
                        }
                    }

                    return new Tuple<int, int>(-1, -1);
                })
                .Where(i => i.Item1 != -1 && i.Item2 != -1)
                .ToList();

            var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(series, episodeLookup, cancellationToken)
                .ConfigureAwait(false);

            var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(series, episodeLookup, cancellationToken)
                .ConfigureAwait(false);

            var hasNewEpisodes = false;
            var hasNewSeasons = false;

            if (series.ContainsEpisodesWithoutSeasonFolders)
            {
                hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
            }

            if (_config.Configuration.EnableInternetProviders)
            {
                hasNewEpisodes = await AddMissingEpisodes(series, seriesDataPath, episodeLookup, cancellationToken)
                    .ConfigureAwait(false);
            }

            if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
            {
                await series.RefreshMetadata(cancellationToken, true)
                    .ConfigureAwait(false);

                await series.ValidateChildren(new Progress<double>(), cancellationToken, true)
                    .ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Downloads the image from series.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="series">The series.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        private async Task DownloadImageFromSeries(BaseItem item, Series series, CancellationToken cancellationToken)
        {
            var tvdbPath = RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, series.GetProviderId(MetadataProviders.Tvdb));

            var actorXmlPath = Path.Combine(tvdbPath, "actors.xml");

            var url = FetchImageUrl(item, actorXmlPath, cancellationToken);

            if (!string.IsNullOrEmpty(url))
            {
                url = TVUtils.BannerUrl + url;

                await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool,
                                               ImageType.Primary, null, cancellationToken).ConfigureAwait(false);
            }
        }
Beispiel #10
0
        private async Task<TraktResponseDataContract> SendEpisodePlaystateUpdatesInternalAsync(List<object> episodesPayload, Series series, TraktUser traktUser, bool seen, CancellationToken cancellationToken)
        {
            var data = new
            {
                username = traktUser.UserName,
                password = traktUser.PasswordHash,
                imdb_id = series.GetProviderId(MetadataProviders.Imdb),
                tvdb_id = series.GetProviderId(MetadataProviders.Tvdb),
                title = series.Name,
                year = (series.ProductionYear ?? 0).ToString(CultureInfo.InvariantCulture),
                episodes = episodesPayload
            };

            var options = new HttpRequestOptions
            {
                RequestContent = _jsonSerializer.SerializeToString(data),
                ResourcePool = Plugin.Instance.TraktResourcePool,
                CancellationToken = cancellationToken,
                Url = seen ? TraktUris.ShowEpisodeSeen : TraktUris.ShowEpisodeUnSeen
            };

            var response = await _httpClient.Post(options).ConfigureAwait(false);

            return _jsonSerializer.DeserializeFromStream<TraktResponseDataContract>(response.Content);
        }
Beispiel #11
0
        /// <summary>
        /// Add or remove a Show(Series) to/from the users trakt.tv library
        /// </summary>
        /// <param name="show">The show to remove</param>
        /// <param name="traktUser">The user who's library is being updated</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="eventType"></param>
        /// <returns>Task{TraktResponseDataContract}.</returns>
        public async Task<TraktResponseDataContract> SendLibraryUpdateAsync(Series show, TraktUser traktUser, CancellationToken cancellationToken, EventType eventType)
        {
            if (show == null)
                throw new ArgumentNullException("show");
            if (traktUser == null)
                throw new ArgumentNullException("traktUser");

            if (eventType == EventType.Update) return null;

            var data = new
            {
                username = traktUser.UserName,
                password = traktUser.PasswordHash,
                tvdb_id = show.GetProviderId(MetadataProviders.Tvdb),
                title = show.Name,
                year = show.ProductionYear
            };

            var options = new HttpRequestOptions
                                                {
                                                    RequestContent = _jsonSerializer.SerializeToString(data),
                                                    ResourcePool = Plugin.Instance.TraktResourcePool,
                                                    CancellationToken = cancellationToken
                                                };

            switch (eventType)
            {
                case EventType.Add:
                    
                    break;
                case EventType.Remove:
                    options.Url = TraktUris.ShowUnLibrary;
                    break;
            }

            var response = await _httpClient.Post(options).ConfigureAwait(false);

            return _jsonSerializer.DeserializeFromStream<TraktResponseDataContract>(response.Content);
        }