Exemplo n.º 1
0
        /// <summary>
        /// Set the show
        /// </summary>
        /// <param name="show">Show</param>
        public async Task SetShowAsync(ShowJson show)
        {
            var watch = Stopwatch.StartNew();

            try
            {
                var showToUpdate = User.ShowHistory.FirstOrDefault(a => a.ImdbId == show.ImdbId);
                if (showToUpdate == null)
                {
                    User.ShowHistory.Add(new ShowHistoryJson
                    {
                        ImdbId   = show.ImdbId,
                        Favorite = show.IsFavorite,
                    });
                }
                else
                {
                    showToUpdate.Favorite = show.IsFavorite;
                }

                await UpdateHistoryAsync();
            }
            catch (Exception exception)
            {
                Logger.Error(
                    $"SetShowAsync: {exception.Message}");
            }
            finally
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                Logger.Debug(
                    $"SetShowAsync ({show.ImdbId}) in {elapsedMs} milliseconds.");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get show by its Imdb code
        /// </summary>
        /// <param name="imdbId">Show's Imdb code</param>
        /// <returns>The show</returns>
        public async Task <ShowJson> GetShowAsync(string imdbId, CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Utils.Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Pessimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var restClient = new RestClient(Utils.Constants.PopcornApi);
                    var request = new RestRequest("/{segment}/{show}", Method.GET);
                    request.AddUrlSegment("segment", "shows");
                    request.AddUrlSegment("show", imdbId);
                    var show = new ShowJson();
                    try
                    {
                        var response = await restClient.ExecuteTaskAsync(request, cancellation)
                                       .ConfigureAwait(false);
                        if (response.ErrorException != null)
                        {
                            throw response.ErrorException;
                        }

                        show = JsonSerializer.Deserialize <ShowJson>(response.RawBytes);
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "GetShowAsync cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetShowAsync: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Debug(
                            $"GetShowAsync ({imdbId}) in {elapsedMs} milliseconds.");
                    }

                    return show;
                }, ct).ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="showService">The show service</param>
        /// <param name="subtitlesService">The subtitles service</param>
        /// <param name="showTrailerService">The show trailer service</param>
        /// <param name="cacheService">The cache service</param>
        public ShowDetailsViewModel(IShowService showService, ISubtitlesService subtitlesService, IShowTrailerService showTrailerService, ICacheService cacheService)
        {
            _showTrailerService = showTrailerService;
            _showService        = showService;
            Show = new ShowJson();
            RegisterCommands();
            RegisterMessages();
            CancellationLoadingTrailerToken = new CancellationTokenSource();
            var downloadService = new DownloadShowService <EpisodeShowJson>(cacheService);

            DownloadShow = new DownloadShowViewModel(downloadService, subtitlesService, cacheService);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Load the requested show
        /// </summary>
        /// <param name="show">The show to load</param>
        private async Task LoadShow(ShowJson show)
        {
            var watch = Stopwatch.StartNew();

            Messenger.Default.Send(new LoadShowMessage());
            Show = show;

            watch.Stop();
            var elapsedMs = watch.ElapsedMilliseconds;

            Logger.Debug($"LoadShow ({show.ImdbId}) in {elapsedMs} milliseconds.");
        }
Exemplo n.º 5
0
        /// <summary>
        /// Load movie's trailer asynchronously
        /// </summary>
        /// <param name="show">The show</param>
        /// <param name="ct">Cancellation token</param>
        public async Task LoadTrailerAsync(ShowJson show, CancellationToken ct)
        {
            try
            {
                var trailer = await ShowService.GetShowTrailerAsync(show, ct);

                if (!ct.IsCancellationRequested && string.IsNullOrEmpty(trailer))
                {
                    Logger.Error(
                        $"Failed loading show's trailer: {show.Title}");
                    Messenger.Default.Send(
                        new ManageExceptionMessage(
                            new PopcornException(
                                LocalizationProviderHelper.GetLocalizedValue <string>("TrailerNotAvailable"))));
                    Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                    return;
                }

                if (!ct.IsCancellationRequested)
                {
                    Logger.Debug(
                        $"Show's trailer loaded: {show.Title}");
                    Messenger.Default.Send(new PlayTrailerMessage(trailer, show.Title, () =>
                    {
                        Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                    },
                                                                  () =>
                    {
                        Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                    }, Utils.MediaType.Show));
                }
            }
            catch (Exception exception) when(exception is TaskCanceledException)
            {
                Logger.Debug(
                    "LoadTrailerAsync cancelled.");
                Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
            }
            catch (Exception exception)
            {
                Logger.Error(
                    $"LoadTrailerAsync: {exception.Message}");
                Messenger.Default.Send(
                    new ManageExceptionMessage(
                        new PopcornException(
                            LocalizationProviderHelper.GetLocalizedValue <string>(
                                "TrailerNotAvailable"))));
                Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Get show by its Imdb code
        /// </summary>
        /// <param name="imdbCode">Show's Imdb code</param>
        /// <returns>The show</returns>
        public async Task <ShowJson> GetShowAsync(string imdbCode)
        {
            var watch = Stopwatch.StartNew();

            var restClient = new RestClient(Utils.Constants.PopcornApi);
            var request    = new RestRequest("/{segment}/{show}", Method.GET);

            request.AddUrlSegment("segment", "shows");
            request.AddUrlSegment("show", imdbCode);
            var show = new ShowJson();

            try
            {
                var response = await restClient.ExecuteGetTaskAsync <ShowJson>(request);

                if (response.ErrorException != null)
                {
                    throw response.ErrorException;
                }

                show = response.Data;
            }
            catch (Exception exception) when(exception is TaskCanceledException)
            {
                Logger.Debug(
                    "GetShowAsync cancelled.");
            }
            catch (Exception exception)
            {
                Logger.Error(
                    $"GetShowAsync: {exception.Message}");
                throw;
            }
            finally
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                Logger.Debug(
                    $"GetShowAsync ({imdbCode}) in {elapsedMs} milliseconds.");
            }

            return(show);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Get the link to the youtube trailer of a show
        /// </summary>
        /// <param name="show">The show</param>
        /// <param name="ct">Used to cancel loading trailer</param>
        /// <returns>Video trailer</returns>
        public async Task <string> GetShowTrailerAsync(ShowJson show, CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Utils.Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Pessimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var uri = string.Empty;
                    try
                    {
                        var tmdbVideos = await(await _tmdbService.GetClient).GetTvShowVideosAsync(show.TmdbId);
                        if (tmdbVideos != null && tmdbVideos.Results.Any())
                        {
                            var trailer = tmdbVideos.Results.FirstOrDefault();
                            using (var service = Client.For(YouTube.Default))
                            {
                                var videos = (await service
                                              .GetAllVideosAsync("https://youtube.com/watch?v=" + trailer.Key))
                                             .ToList();
                                if (videos.Any())
                                {
                                    var settings = SimpleIoc.Default.GetInstance <ApplicationSettingsViewModel>();
                                    var maxRes = settings.DefaultHdQuality ? 1080 : 720;
                                    uri =
                                        await videos
                                        .Where(a => !a.Is3D && a.Resolution <= maxRes &&
                                               a.Format == VideoFormat.Mp4 &&
                                               a.AudioBitrate > 0)
                                        .Aggregate((i1, i2) => i1.Resolution > i2.Resolution ? i1 : i2)
                                        .GetUriAsync();
                                }
                            }
                        }
                        else
                        {
                            throw new PopcornException("No trailer found.");
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException ||
                                                     exception is OperationCanceledException)
                    {
                        Logger.Debug(
                            "GetShowTrailerAsync cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetShowTrailerAsync: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Trace(
                            $"GetShowTrailerAsync ({show.ImdbId}) in {elapsedMs} milliseconds.");
                    }

                    return uri;
                }, ct));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Get show by its Imdb code
        /// </summary>
        /// <param name="imdbId">Show's Imdb code</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>The show</returns>
        public async Task <ShowJson> GetShowAsync(string imdbId, CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Optimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var optionsBuilder = new DbContextOptionsBuilder <PopcornContext>();
                    optionsBuilder.UseSqlServer(
                        (ConfigurationManager.GetSection("settings") as NameValueCollection)["SQLConnectionString"],
                        builder =>
                    {
                        builder.CommandTimeout(Convert.ToInt32(TimeSpan.FromSeconds(60).TotalSeconds));
                        builder.EnableRetryOnFailure();
                    });
                    await using var context = new PopcornContext(optionsBuilder.Options);

                    var watch = Stopwatch.StartNew();
                    var showJson = new ShowJson();
                    try
                    {
                        var show = await context.ShowSet.Include(a => a.Rating)
                                   .Include(a => a.Episodes)
                                   .ThenInclude(episode => episode.Torrents)
                                   .ThenInclude(torrent => torrent.Torrent0)
                                   .Include(a => a.Episodes)
                                   .ThenInclude(episode => episode.Torrents)
                                   .ThenInclude(torrent => torrent.Torrent1080p)
                                   .Include(a => a.Episodes)
                                   .ThenInclude(episode => episode.Torrents)
                                   .ThenInclude(torrent => torrent.Torrent480p)
                                   .Include(a => a.Episodes)
                                   .Include(a => a.Episodes)
                                   .ThenInclude(episode => episode.Torrents)
                                   .ThenInclude(torrent => torrent.Torrent720p)
                                   .Include(a => a.Genres)
                                   .Include(a => a.Images)
                                   .Include(a => a.Similars).AsQueryable()
                                   .FirstOrDefaultAsync(a => a.ImdbId == imdbId, cancellation);
                        showJson = ConvertShowToJson(show);
                        var shows = await(await _tmdbService.GetClient).SearchTvShowAsync(show.Title,
                                                                                          cancellationToken: cancellation);
                        if (shows.Results.Any())
                        {
                            foreach (var tvShow in shows.Results)
                            {
                                try
                                {
                                    var result =
                                        await(await _tmdbService.GetClient).GetTvShowExternalIdsAsync(tvShow.Id,
                                                                                                      cancellation);
                                    if (result.ImdbId == show.ImdbId)
                                    {
                                        showJson.TmdbId = result.Id;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.Error(ex);
                                }
                            }
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "GetShowAsync cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetShowAsync: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Trace(
                            $"GetShowAsync ({imdbId}) in {elapsedMs} milliseconds.");
                    }

                    return showJson;
                }, ct));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Get the link to the youtube trailer of a show
        /// </summary>
        /// <param name="show">The show</param>
        /// <param name="ct">Used to cancel loading trailer</param>
        /// <returns>Video trailer</returns>
        public async Task <string> GetShowTrailerAsync(ShowJson show, CancellationToken ct)
        {
            var watch = Stopwatch.StartNew();
            var uri   = string.Empty;

            try
            {
                var shows = await TmdbClient.SearchTvShowAsync(show.Title).ConfigureAwait(false);

                if (shows.Results.Any())
                {
                    Video trailer = null;
                    foreach (var tvShow in shows.Results)
                    {
                        try
                        {
                            var result = await TmdbClient.GetTvShowExternalIdsAsync(tvShow.Id).ConfigureAwait(false);

                            if (result.ImdbId == show.ImdbId)
                            {
                                var videos = await TmdbClient.GetTvShowVideosAsync(result.Id).ConfigureAwait(false);

                                if (videos != null && videos.Results.Any())
                                {
                                    trailer = videos.Results.FirstOrDefault();
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(ex);
                        }
                    }

                    if (trailer != null)
                    {
                        using (var service = Client.For(YouTube.Default))
                        {
                            var videos = (await service.GetAllVideosAsync("https://youtube.com/watch?v=" + trailer.Key)
                                          .ConfigureAwait(false))
                                         .ToList();
                            if (videos.Any())
                            {
                                var settings = SimpleIoc.Default.GetInstance <ApplicationSettingsViewModel>();
                                var maxRes   = settings.DefaultHdQuality ? 1080 : 720;
                                uri =
                                    await videos
                                    .Where(a => !a.Is3D && a.Resolution <= maxRes && a.Format == VideoFormat.Mp4 &&
                                           a.AudioBitrate > 0)
                                    .Aggregate((i1, i2) => i1.Resolution > i2.Resolution ? i1 : i2).GetUriAsync();
                            }
                        }
                    }
                    else
                    {
                        throw new PopcornException("No trailer found.");
                    }
                }
            }
            catch (Exception exception) when(exception is TaskCanceledException ||
                                             exception is OperationCanceledException)
            {
                Logger.Debug(
                    "GetShowTrailerAsync cancelled.");
            }
            catch (Exception exception)
            {
                Logger.Error(
                    $"GetShowTrailerAsync: {exception.Message}");
                throw;
            }
            finally
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                Logger.Debug(
                    $"GetShowTrailerAsync ({show.ImdbId}) in {elapsedMs} milliseconds.");
            }

            return(uri);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Load movie's trailer asynchronously
        /// </summary>
        /// <param name="show">The show</param>
        /// <param name="ct">Cancellation token</param>
        public async Task LoadTrailerAsync(ShowJson show, CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(5, TimeoutStrategy.Pessimistic);

            try
            {
                await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    try
                    {
                        var trailer = await ShowService.GetShowTrailerAsync(show, cancellation);
                        if (!ct.IsCancellationRequested && string.IsNullOrEmpty(trailer))
                        {
                            Logger.Error(
                                $"Failed loading show's trailer: {show.Title}");
                            Messenger.Default.Send(
                                new ManageExceptionMessage(
                                    new TrailerNotAvailableException(
                                        LocalizationProviderHelper.GetLocalizedValue <string>("TrailerNotAvailable"))));
                            Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                            return;
                        }

                        if (!ct.IsCancellationRequested)
                        {
                            Logger.Debug(
                                $"Show's trailer loaded: {show.Title}");
                            Messenger.Default.Send(new PlayTrailerMessage(trailer, show.Title, () =>
                            {
                                Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                            },
                                                                          () =>
                            {
                                Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                            }, Utils.MediaType.Show));
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "LoadTrailerAsync cancelled.");
                        Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"LoadTrailerAsync: {exception.Message}");
                        Messenger.Default.Send(
                            new ManageExceptionMessage(
                                new TrailerNotAvailableException(
                                    LocalizationProviderHelper.GetLocalizedValue <string>(
                                        "TrailerNotAvailable"))));
                        Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                    }
                }, ct).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Load movie's trailer asynchronously
        /// </summary>
        /// <param name="show">The show</param>
        /// <param name="ct">Cancellation token</param>
        public async Task LoadTrailerAsync(ShowJson show, CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Utils.Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Pessimistic);

            try
            {
                await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    try
                    {
                        var trailer = await ShowService.GetShowTrailerAsync(show, cancellation);
                        if (!ct.IsCancellationRequested && string.IsNullOrEmpty(trailer))
                        {
                            Logger.Error(
                                $"Failed loading show's trailer: {show.Title}");
                            Messenger.Default.Send(
                                new ManageExceptionMessage(
                                    new TrailerNotAvailableException(
                                        LocalizationProviderHelper.GetLocalizedValue <string>("TrailerNotAvailable"))));
                            Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                            return;
                        }

                        if (!ct.IsCancellationRequested)
                        {
                            Uri uriResult;
                            bool result = Uri.TryCreate(trailer, UriKind.Absolute, out uriResult) &&
                                          (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
                            if (result)
                            {
                                var client = new HttpClient();
                                try
                                {
                                    using (var response = await client.GetAsync(uriResult, HttpCompletionOption.ResponseHeadersRead, ct))
                                    {
                                        if (response == null || response.StatusCode != HttpStatusCode.OK)
                                        {
                                            Logger.Error(
                                                $"Failed loading show's trailer: {show.Title}");
                                            Messenger.Default.Send(
                                                new ManageExceptionMessage(
                                                    new TrailerNotAvailableException(
                                                        LocalizationProviderHelper.GetLocalizedValue <string>("TrailerNotAvailable"))));
                                            Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                                            return;
                                        }
                                    }
                                }
                                catch (WebException)
                                {
                                    Logger.Error(
                                        $"Failed loading show's trailer: {show.Title}");
                                    Messenger.Default.Send(
                                        new ManageExceptionMessage(
                                            new TrailerNotAvailableException(
                                                LocalizationProviderHelper.GetLocalizedValue <string>("TrailerNotAvailable"))));
                                    Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                                    return;
                                }
                            }
                            else
                            {
                                Logger.Error(
                                    $"Failed loading show's trailer: {show.Title}");
                                Messenger.Default.Send(
                                    new ManageExceptionMessage(
                                        new TrailerNotAvailableException(
                                            LocalizationProviderHelper.GetLocalizedValue <string>("TrailerNotAvailable"))));
                                Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                                return;
                            }

                            Logger.Info(
                                $"Show's trailer loaded: {show.Title}");
                            Messenger.Default.Send(new PlayTrailerMessage(trailer, show.Title, () =>
                            {
                                Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                            },
                                                                          () =>
                            {
                                Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                            }, Utils.MediaType.Show));
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "LoadTrailerAsync cancelled.");
                        Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"LoadTrailerAsync: {exception.Message}");
                        Messenger.Default.Send(
                            new ManageExceptionMessage(
                                new TrailerNotAvailableException(
                                    LocalizationProviderHelper.GetLocalizedValue <string>(
                                        "TrailerNotAvailable"))));
                        Messenger.Default.Send(new StopPlayingTrailerMessage(Utils.MediaType.Show));
                    }
                }, ct);
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Get show by its Imdb code
        /// </summary>
        /// <param name="imdbId">Show's Imdb code</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>The show</returns>
        public async Task <ShowJson> GetShowAsync(string imdbId, CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Optimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var request = new RestRequest("/{segment}/{show}", Method.GET);
                    request.AddUrlSegment("segment", "shows");
                    request.AddUrlSegment("show", imdbId);
                    var show = new ShowJson();
                    try
                    {
                        var response = await _restClient.ExecuteTaskAsync(request, cancellation);
                        if (response.ErrorException != null)
                        {
                            throw response.ErrorException;
                        }

                        show = JsonConvert.DeserializeObject <ShowJson>(response.Content);
                        var shows = await(await _tmdbService.GetClient).SearchTvShowAsync(show.Title, cancellationToken: cancellation);
                        if (shows.Results.Any())
                        {
                            foreach (var tvShow in shows.Results)
                            {
                                try
                                {
                                    var result =
                                        await(await _tmdbService.GetClient).GetTvShowExternalIdsAsync(tvShow.Id, cancellationToken: cancellation);
                                    if (result.ImdbId == show.ImdbId)
                                    {
                                        show.TmdbId = result.Id;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.Error(ex);
                                }
                            }
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "GetShowAsync cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetShowAsync: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Trace(
                            $"GetShowAsync ({imdbId}) in {elapsedMs} milliseconds.");
                    }

                    return show;
                }, ct));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }