Beispiel #1
0
        private async Task HandleSeason(Season season)
        {
            if (season.Series == null ||
                !season.Series.TryGetProviderId(MetadataProvider.Tvdb.ToString(), out var tvdbIdTxt))
            {
                return;
            }

            var tvdbId = Convert.ToInt32(tvdbIdTxt, CultureInfo.InvariantCulture);

            var query = new EpisodeQuery
            {
                AiredSeason = season.IndexNumber
            };
            var allEpisodes = await GetAllEpisodes(tvdbId, season.GetPreferredMetadataLanguage(), query).ConfigureAwait(false);

            var existingEpisodes = season.Children.OfType <Episode>().ToList();

            for (var i = 0; i < allEpisodes.Count; i++)
            {
                var episode = allEpisodes[i];
                if (EpisodeExists(episode, existingEpisodes))
                {
                    continue;
                }

                AddVirtualEpisode(episode, season);
            }
        }
Beispiel #2
0
        private async Task <bool> GetEpisodes()
        {
            try
            {
                var query = new EpisodeQuery
                {
                    UserId   = AuthenticationService.Current.LoggedInUserId,
                    SeasonId = SelectedSeason.Id,
                    SeriesId = SelectedSeason.SeriesId,
                    Fields   = new[]
                    {
                        ItemFields.ParentId,
                        ItemFields.Overview,
                        ItemFields.MediaSources,
                    },
                    IsMissing        = App.SpecificSettings.ShowMissingEpisodes,
                    IsVirtualUnaired = App.SpecificSettings.ShowUnairedEpisodes
                };

                Log.Info("Getting episodes for Season [{0}] ({1}) of TV Show [{2}] ({3})", SelectedSeason.Name, SelectedSeason.Id, SelectedTvSeries.Name, SelectedTvSeries.Id);

                var episodes = await ApiClient.GetEpisodesAsync(query);

                Episodes = episodes.Items.ToList();
                return(true);
            }
            catch (HttpException ex)
            {
                Utils.HandleHttpException("GetEpisodes()", ex, NavigationService, Log);

                App.ShowMessage(AppResources.ErrorEpisodes);
                return(false);
            }
        }
Beispiel #3
0
        // ReSharper disable once InconsistentNaming
        public async void GetEpisodesAsync_With_Query_Makes_The_Right_Request()
        {
            var jsonClient = CreateJsonClient();
            var client     = this.CreateClient(jsonClient);

            const int    Id    = 42;
            const int    Page  = 2;
            const string Route = "/series/42/episodes/query?page=2&airedSeason=1&imdbId=tt0118480";

            var query = new EpisodeQuery
            {
                ImdbId      = "tt0118480",
                AiredSeason = 1
            };

            var expectedData = new TvDbResponse <BasicEpisode[]>();

            jsonClient.GetJsonAsync <TvDbResponse <BasicEpisode[]> >(Route, CancellationToken.None).Returns(expectedData);

            var responseData = await client.GetEpisodesAsync(Id, Page, query, CancellationToken.None);

            await jsonClient.Received().GetJsonAsync <TvDbResponse <BasicEpisode[]> >(Route, CancellationToken.None);

            Assert.Equal(expectedData, responseData);
        }
Beispiel #4
0
        public async Task GetEpisodeDetails()
        {
            if (NavigationService.IsNetworkAvailable)
            {
                var index = SelectedEpisode.IndexNumber;
                if (SelectedEpisode != null && Episodes.IsNullOrEmpty())
                {
                    SetProgressBar(AppResources.SysTrayGettingEpisodeDetails);

                    try
                    {
                        if (string.IsNullOrEmpty(SelectedEpisode.SeriesId))
                        {
                            var episode = await ApiClient.GetItemAsync(SelectedEpisode.Id, AuthenticationService.Current.LoggedInUserId);

                            if (episode == null)
                            {
                                await _messageBox.ShowAsync(AppResources.ErrorEpisodeDetails);

                                NavigationService.GoBack();
                                return;
                            }

                            SelectedEpisode = episode;
                        }

                        var query = new EpisodeQuery
                        {
                            UserId   = AuthenticationService.Current.LoggedInUserId,
                            SeasonId = SelectedEpisode.SeasonId,
                            SeriesId = SelectedEpisode.SeriesId,
                            Fields   = new[]
                            {
                                ItemFields.ParentId,
                                ItemFields.Overview,
                                ItemFields.MediaSources,
                            }
                        };

                        //Log.Info("Getting episodes for Season [{0}] ({1}) of TV Show [{2}] ({3})", SelectedSeason.Name, SelectedSeason.Id, SelectedTvSeries.Name, SelectedTvSeries.Id);

                        var episodes = await ApiClient.GetEpisodesAsync(query);

                        Episodes = episodes.Items.OrderBy(x => x.IndexNumber).ToList();
                    }
                    catch (HttpException ex)
                    {
                        Utils.HandleHttpException("GetEpisodeDetails()", ex, NavigationService, Log);
                    }

                    SetProgressBar();
                }

                if (SelectedEpisode != null)
                {
                    SelectedEpisode = Episodes.FirstOrDefault(x => x.IndexNumber == index);
                    CanResume       = SelectedEpisode != null && SelectedEpisode.CanResume;
                }
            }
        }
        // TODO use async events
        private void OnLibraryManagerItemRemoved(object sender, ItemChangeEventArgs itemChangeEventArgs)
        {
            // No action needed if the item is virtual
            if (itemChangeEventArgs.Item.IsVirtualItem || !IsEnabledForLibrary(itemChangeEventArgs.Item))
            {
                return;
            }

            // Create a new virtual season if the real one was deleted.
            // Similarly, create a new virtual episode if the real one was deleted.
            if (itemChangeEventArgs.Item is Season season)
            {
                var newSeason = AddVirtualSeason(season.IndexNumber !.Value, season.Series);
                HandleSeason(newSeason).GetAwaiter().GetResult();
            }
            else if (itemChangeEventArgs.Item is Episode episode)
            {
                var tvdbId = Convert.ToInt32(episode.Series?.GetProviderId(MetadataProvider.Tvdb));
                if (tvdbId == 0)
                {
                    return;
                }

                var query = new EpisodeQuery
                {
                    AiredSeason  = episode.ParentIndexNumber,
                    AiredEpisode = episode.IndexNumber
                };
                var episodeRecords = GetAllEpisodes(tvdbId, episode.GetPreferredMetadataLanguage(), query).GetAwaiter().GetResult();

                AddVirtualEpisode(episodeRecords.FirstOrDefault(), episode.Season);
            }
        }
Beispiel #6
0
        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);
                }
            }
        }
Beispiel #7
0
 public Task <TvDbResponse <EpisodeRecord[]> > GetEpisodesPageAsync(
     int tvdbId,
     EpisodeQuery episodeQuery,
     string language,
     CancellationToken cancellationToken)
 {
     return(GetEpisodesPageAsync(tvdbId, 1, episodeQuery, language, cancellationToken));
 }
Beispiel #8
0
        public async Task <string> GetEpisodeTvdbId(int seriesTvdbId, EpisodeQuery episodeQuery,
                                                    string language,
                                                    CancellationToken cancellationToken)
        {
            var episodePage =
                await GetEpisodesPageAsync(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken)
                .ConfigureAwait(false);

            return(episodePage.Data.FirstOrDefault()?.Id.ToString());
        }
        /// <summary>
        /// Gets a page of episodes.
        /// </summary>
        /// <param name="tvdbId">Tvdb series id.</param>
        /// <param name="page">Episode page.</param>
        /// <param name="episodeQuery">Episode query.</param>
        /// <param name="language">Metadata language.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>The page of episodes.</returns>
        public Task <TvDbResponse <EpisodeRecord[]> > GetEpisodesPageAsync(
            int tvdbId,
            int page,
            EpisodeQuery episodeQuery,
            string language,
            CancellationToken cancellationToken)
        {
            var cacheKey = GenerateKey(language, tvdbId, episodeQuery);

            return(TryGetValue(cacheKey, language, tvDbClient => tvDbClient.Series.GetEpisodesAsync(tvdbId, page, episodeQuery, cancellationToken)));
        }
Beispiel #10
0
        public async Task <TvDbResponse <BasicEpisode[]> > GetEpisodesAsync(
            int seriesId,
            int page,
            EpisodeQuery query,
            CancellationToken cancellationToken)
        {
            string url      = $"/series/{seriesId}/episodes/query?page={Math.Max(page, 1)}&{this.UrlHelpers.Querify(query)}";
            var    request  = new ApiRequest("GET", url);
            var    response = await this.ApiClient.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);

            return(this.Parser.Parse <TvDbResponse <BasicEpisode[]> >(response, ErrorMessages.Series.GetAsync));
        }
Beispiel #11
0
        // ReSharper disable once InconsistentNaming
        public Task GetEpisodesAsync_With_Query_Makes_The_Right_Request(int seriesId, int page, int actualPage, int aired, int dvd)
        {
            var query = new EpisodeQuery {
                AiredEpisode = aired, DvdEpisode = dvd
            };

            return(CreateClient()
                   .WithErrorMap(ErrorMessages.Series.GetAsync)
                   .SetResultObject(new TvDbResponse <EpisodeRecord[]>())
                   .WhenCallingAMethod((impl, token) => impl.GetEpisodesAsync(seriesId, page, query, token))
                   .ShouldRequest("GET", $"/series/{seriesId}/episodes/query?page={actualPage}&airedEpisode={aired}&dvdEpisode={dvd}")
                   .RunAsync());
        }
Beispiel #12
0
        // ReSharper disable once InconsistentNaming
        public async void GetEpisodesAsync_With_CancellationToken_With_Query_Throws_With_The_Correct_Message(int statusCode)
        {
            var jsonClient = CreateJsonClient();
            var client     = this.CreateClient(jsonClient);

            var query = new EpisodeQuery
            {
                ImdbId      = "tt0118480",
                AiredSeason = 1
            };

            jsonClient.GetJsonAsync <TvDbResponse <BasicEpisode[]> >(null, CancellationToken.None)
            .ThrowsForAnyArgs(info => new TvDbServerException(null, (HttpStatusCode)statusCode, null));

            var ex = await Assert.ThrowsAsync <TvDbServerException>(async() => await client.GetEpisodesAsync(42, 2, query));

            Assert.Equal(this.ErrorMessages.Series.GetAsync[statusCode], ex.Message);
        }
Beispiel #13
0
        // TODO use async events
        private void OnLibraryManagerItemRemoved(object?sender, ItemChangeEventArgs itemChangeEventArgs)
        {
            // No action needed if the item is virtual
            if (itemChangeEventArgs.Item.IsVirtualItem || !IsEnabledForLibrary(itemChangeEventArgs.Item))
            {
                return;
            }

            // Create a new virtual season if the real one was deleted.
            // Similarly, create a new virtual episode if the real one was deleted.
            if (itemChangeEventArgs.Item is Season season)
            {
                var newSeason = AddVirtualSeason(season.IndexNumber !.Value, season.Series);
                HandleSeason(newSeason).GetAwaiter().GetResult();
            }
            else if (itemChangeEventArgs.Item is Episode episode)
            {
                if (episode.Series == null ||
                    !episode.Series.TryGetProviderId(MetadataProvider.Tvdb.ToString(), out var tvdbIdTxt))
                {
                    return;
                }

                var tvdbId = Convert.ToInt32(tvdbIdTxt, CultureInfo.InvariantCulture);

                var query = new EpisodeQuery
                {
                    AiredSeason  = episode.ParentIndexNumber,
                    AiredEpisode = episode.IndexNumber
                };
                var episodeRecords = GetAllEpisodes(tvdbId, episode.GetPreferredMetadataLanguage(), query).GetAwaiter().GetResult();

                EpisodeRecord?episodeRecord = null;
                if (episodeRecords.Count > 0)
                {
                    episodeRecord = episodeRecords[0];
                }

                AddVirtualEpisode(episodeRecord, episode.Season);
            }
        }
Beispiel #14
0
        public Task <string> GetEpisodeTvdbId(
            EpisodeInfo searchInfo,
            string language,
            CancellationToken cancellationToken)
        {
            searchInfo.SeriesProviderIds.TryGetValue(
                nameof(MetadataProvider.Tvdb),
                out var seriesTvdbId);

            var episodeQuery = new EpisodeQuery();

            // Prefer SxE over premiere date as it is more robust
            if (searchInfo.IndexNumber.HasValue && searchInfo.ParentIndexNumber.HasValue)
            {
                switch (searchInfo.SeriesDisplayOrder)
                {
                case "dvd":
                    episodeQuery.DvdEpisode = searchInfo.IndexNumber.Value;
                    episodeQuery.DvdSeason  = searchInfo.ParentIndexNumber.Value;
                    break;

                case "absolute":
                    episodeQuery.AbsoluteNumber = searchInfo.IndexNumber.Value;
                    break;

                default:
                    // aired order
                    episodeQuery.AiredEpisode = searchInfo.IndexNumber.Value;
                    episodeQuery.AiredSeason  = searchInfo.ParentIndexNumber.Value;
                    break;
                }
            }
            else if (searchInfo.PremiereDate.HasValue)
            {
                // tvdb expects yyyy-mm-dd format
                episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
            }

            return(GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId, CultureInfo.InvariantCulture), episodeQuery, language, cancellationToken));
        }
Beispiel #15
0
        public Task <string> GetEpisodeTvdbId(EpisodeInfo searchInfo, string language,
                                              CancellationToken cancellationToken)
        {
            searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(),
                                                     out var seriesTvdbId);

            var episodeQuery = new EpisodeQuery();

            // Prefer SxE over premiere date as it is more robust
            if (searchInfo.IndexNumber.HasValue && searchInfo.ParentIndexNumber.HasValue)
            {
                episodeQuery.AiredEpisode = searchInfo.IndexNumber.Value;
                episodeQuery.AiredSeason  = searchInfo.ParentIndexNumber.Value;
            }
            else if (searchInfo.PremiereDate.HasValue)
            {
                // tvdb expects yyyy-mm-dd format
                episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd");
            }

            return(GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken));
        }
Beispiel #16
0
        public Task <TvDbResponse <BasicEpisode[]> > GetEpisodesAsync(
            int seriesId,
            int page,
            EpisodeQuery query,
            CancellationToken cancellationToken)
        {
            try
            {
                string requestUri = $"/series/{seriesId}/episodes/query?page={Math.Max(page, 1)}&{this.UrlHelpers.Querify(query)}";

                return(this.GetAsync <BasicEpisode[]>(requestUri, cancellationToken));
            }
            catch (TvDbServerException ex)
            {
                string message = this.GetMessage(ex.StatusCode, this.ErrorMessages.Series.GetAsync);

                if (message == null)
                {
                    throw;
                }

                throw new TvDbServerException(message, ex.StatusCode, ex);
            }
        }
Beispiel #17
0
        private async void GetEpisodes()
        {
            if (TvShows != null)
            {
                //Load Episode Data from TvShows and write back to TvShows;
                var client = new TvDbClient();
                await client.Authentication.AuthenticateAsync(Data.ApiKey, Data.UserName, Data.UserKey);

                client.AcceptedLanguage = Data.prefLang;

                var    tasks    = new List <Task <TvDbResponse <TvDbSharper.Dto.EpisodeRecord[]> > >();
                var    response = new TvDbResponse <EpisodeRecord[]>();
                tvShow show     = TvShows.Find(i => i.tvdbID == actualTvDbID);
                if (show.Count > 1)
                {
                    foreach (showEpisode ep in TvShows.Where(i => i.tvdbID == actualTvDbID))
                    {
                        response = await client.Series.GetEpisodesAsync(ep.tvdbID, 1);

                        for (int i = 2; i <= response.Links.Last; i++)
                        {
                            tasks.Add(client.Series.GetEpisodesAsync(ep.tvdbID, i));
                        }
                    }
                }
                else
                {
                    EpisodeQuery q = new EpisodeQuery();
                    q.AiredSeason  = TvShows[0][0].seasonNr;
                    q.AiredEpisode = TvShows[0][0].episodeNr;
                    response       = await client.Series.GetEpisodesAsync(show.tvdbID, 1, q);
                }

                var results = await Task.WhenAll(tasks);


                //var eps = response.Data.Concat(results.SelectMany(x => x.Data));
                foreach (EpisodeRecord er in response.Data.Concat(results.SelectMany(x => x.Data)))
                {
                    foreach (showEpisode ep in TvShows.Where(i => i.tvdbID == actualTvDbID))
                    {
                        if (er.AiredSeason == ep.seasonNr && er.AiredEpisodeNumber == ep.episodeNr)
                        {
                            //DateTime dt = DateTime.Parse(ep.FirstAired);

                            if (er.EpisodeName == null) //Backup if no German
                            {
                                client.AcceptedLanguage = "en";
                                TvDbResponse <EpisodeRecord> er1 = await client.Episodes.GetAsync(er.Id);

                                ep.episodeName = er1.Data.EpisodeName;
                                ep.description = er1.Data.Overview;
                            }
                            else
                            {
                                ep.episodeName = er.EpisodeName;
                                ep.description = er.Overview;
                            }
                            ep.tvDbEpisodeId = er.Id;
                            if (helper.isDateTime(er.FirstAired))
                            {
                                ep.episodeAirDate = DateTime.Parse(er.FirstAired);
                            }
                            if (ep.episodeName != null && ep.episodeNumbering != null)
                            {
                                ep.newFilename = GetCorrectedFileName(ep.episodeName, ep.episodeNumbering);
                            }
                        }
                    }
                }
                //Episode not found in Episode List
            }
        }
Beispiel #18
0
 public Task <TvDbResponse <BasicEpisode[]> > GetEpisodesAsync(int seriesId, int page, EpisodeQuery query)
 {
     return(this.GetEpisodesAsync(seriesId, page, query, CancellationToken.None));
 }
        private async Task <IReadOnlyList <EpisodeRecord> > GetAllEpisodes(int tvdbId, string acceptedLanguage, EpisodeQuery episodeQuery = null)
        {
            if (string.IsNullOrEmpty(_tvDbClient.Authentication.Token) ||
                DateTime.Now.AddHours(-24) >= _tokenCreatedAt)
            {
                await _tvDbClient.Authentication.AuthenticateAsync(_tvdbApiKey).ConfigureAwait(false);

                _tokenCreatedAt = DateTime.Now;
            }

            _tvDbClient.AcceptedLanguage = acceptedLanguage;

            // Fetch all episodes for the series
            var allEpisodes = new List <EpisodeRecord>();
            var page        = 1;

            while (true)
            {
                episodeQuery ??= new EpisodeQuery();
                var episodes = await _tvDbClient.Series.GetEpisodesAsync(tvdbId, page, episodeQuery).ConfigureAwait(false);

                allEpisodes.AddRange(episodes.Data);
                if (!episodes.Links.Next.HasValue)
                {
                    break;
                }

                page = episodes.Links.Next.Value;
            }

            return(allEpisodes);
        }