コード例 #1
0
        public async Task <SearchedTvShow> SearchTvShowAsync(TvShowRequest request, int tvDbId)
        {
            try
            {
                var jsonTvShow = await SearchSerieByTvDbIdAsync(tvDbId);

                if (jsonTvShow != null && jsonTvShow.tvdbId == tvDbId)
                {
                    return(new SearchedTvShow
                    {
                        TheTvDbId = jsonTvShow.tvdbId.Value,
                        Title = jsonTvShow.title,
                        FirstAired = jsonTvShow.year > 0 ? jsonTvShow.year.ToString() : string.Empty,
                        Banner = jsonTvShow.remotePoster
                    });
                }

                return(null);
            }
            catch (System.Exception ex)
            {
                _logger.LogError(ex, $"An error occurred while searching for tv show by tvDbId \"{tvDbId}\" from Sonarr: " + ex.Message);
            }

            throw new System.Exception("An error occurred while searching for tv show by tvDbId from Sonarr");
        }
コード例 #2
0
        public async Task Handle_ShouldReturnOnlyShowsWithDrmEnabled(string firstExpectedTitle)
        {
            var handler = new TvShowRequestHandler();
            var request = new TvShowRequest()
            {
                Payload = new List <TvShowRequestDetails>()
                {
                    new TvShowRequestDetails()
                    {
                        Title = "ignored show 1", Drm = false, EpisodeCount = 100
                    },
                    new TvShowRequestDetails()
                    {
                        Title = firstExpectedTitle, Drm = true, EpisodeCount = 100
                    },
                    new TvShowRequestDetails()
                    {
                        Title = "ignored show 2", Drm = false, EpisodeCount = 100
                    },
                    new TvShowRequestDetails()
                    {
                        Title = "ignored show 3", Drm = false, EpisodeCount = 100
                    }
                }
            };

            var result = await handler.Handle(request, CancellationToken.None);

            Assert.NotNull(result?.Response);
            Assert.Single(result.Response);
            Assert.Equal(firstExpectedTitle, result.Response[0].Title);
        }
コード例 #3
0
        public async Task <TvShowRequestResult> RequestTvShowAsync(TvShowRequest request, TvShow tvShow, TvSeason season)
        {
            try
            {
                var requestedSeasons = season is AllTvSeasons
                                        ? new List <TvSeason>(tvShow.Seasons.OfType <NormalTvSeason>())
                                        : season is FutureTvSeasons
                                            ? new List <TvSeason>()
                                            : new List <TvSeason> {
                    season
                };

                if (string.IsNullOrEmpty(tvShow.DownloadClientId))
                {
                    await CreateSonarrTvSeriesAsync(request, tvShow, requestedSeasons);
                }
                else
                {
                    await UpdateSonarrTvSeriesAsync(request, tvShow, requestedSeasons);
                }

                return(new TvShowRequestResult());
            }
            catch (System.Exception ex)
            {
                _logger.LogError(ex, $"An error while requesting tv show \"{tvShow.Title}\" from Sonarr: " + ex.Message);
            }

            throw new System.Exception("An error occurred while requesting a tv show from Sonarr");
        }
コード例 #4
0
        public async Task <IReadOnlyList <SearchedTvShow> > SearchTvShowAsync(TvShowRequest request, string tvShowName)
        {
            try
            {
                var searchTerm = Uri.EscapeDataString(tvShowName.ToLower().Trim().Replace(" ", "+"));
                var response   = await HttpGetAsync($"{BaseURL}/series/lookup?term={searchTerm}");

                await response.ThrowIfNotSuccessfulAsync("SonarrSeriesLookup failed", x => x.message);

                var jsonResponse = await response.Content.ReadAsStringAsync();

                var jsonTvShows = JsonConvert.DeserializeObject <List <JSONTvShow> >(jsonResponse).Where(x => x.tvdbId.HasValue).ToArray();

                return(jsonTvShows.Select(x => new SearchedTvShow
                {
                    TheTvDbId = x.tvdbId.Value,
                    Title = x.title,
                    FirstAired = x.year > 0 ? x.year.ToString() : string.Empty,
                    Banner = x.remotePoster
                }).ToArray());
            }
            catch (System.Exception ex)
            {
                _logger.LogError(ex, $"An error occurred while searching for tv show \"{tvShowName}\" from Sonarr: " + ex.Message);
            }

            throw new System.Exception("An error occurred while searching for tv show from Sonarr");
        }
コード例 #5
0
ファイル: OmbiClient.cs プロジェクト: Qstick/requestrr
        public async Task <IReadOnlyList <SearchedTvShow> > SearchTvShowAsync(TvShowRequest request, string tvShowName)
        {
            var retryCount = 0;

            while (retryCount <= 5)
            {
                try
                {
                    var response = await HttpGetAsync($"{BaseURL}/api/v1/Search/Tv/{tvShowName}");

                    await response.ThrowIfNotSuccessfulAsync("OmbiSearchTvShow failed", x => x.error);

                    var jsonResponse = await response.Content.ReadAsStringAsync();

                    var jsonTvShows = JsonConvert.DeserializeObject <List <JSONTvShow> >(jsonResponse).ToArray();

                    return(jsonTvShows.Select(x => new SearchedTvShow
                    {
                        Title = x.title,
                        Banner = x.banner,
                        TheTvDbId = x.id,
                        FirstAired = x.firstAired,
                    }).ToArray());
                }
                catch (System.Exception ex)
                {
                    _logger.LogError(ex, $"An error occurred while searching for tv show \"{tvShowName}\" from Ombi: " + ex.Message);
                    retryCount++;
                    await Task.Delay(1000);
                }
            }

            throw new System.Exception("An error occurred while searching for tv show from Ombi");
        }
コード例 #6
0
        public void Check_It_Returns_Empty_List_If_Does_Not_Match_Filter_Critea()
        {
            // Setup

            var noDrmRequest = new TvShowRequest
            {
                Drm          = false,
                EpisodeCount = 3
            };

            var zeroEpisodeCountRequest =
                new TvShowRequest
            {
                Drm          = true,
                EpisodeCount = 0
            };

            var tvShowService = new TvShowService();

            // Action
            var tvShowResp = tvShowService.GetFilteredTvShows(new List <TvShowRequest> {
                noDrmRequest, zeroEpisodeCountRequest
            });

            // Assert
            Assert.That(tvShowResp.Count, Is.EqualTo(0));
        }
コード例 #7
0
        public async Task <IActionResult> AddTvShowAsync([FromBody] TvShowRequest tvShow)
        {
            var command = new AddTvShowCommand(_mapper.Map <SonarrTvShowRequest>(tvShow));
            var result  = await _bus.Send(command);

            return(Created("", result));
        }
コード例 #8
0
        public async Task ShowTvShowSelection(TvShowRequest request, IReadOnlyList <SearchedTvShow> searchedTvShows)
        {
            var options = searchedTvShows.Take(15).Select(x => new DiscordSelectComponentOption(GetFormatedTvShowTitle(x), $"{request.CategoryId}/{x.TheTvDbId.ToString()}")).ToList();
            var select  = new DiscordSelectComponent($"TRS/{_interactionContext.User.Id}/{request.CategoryId}", Language.Current.DiscordCommandTvRequestHelpSearchDropdown, options);

            await _interactionContext.EditOriginalResponseAsync(new DiscordWebhookBuilder().AddComponents(select).WithContent(Language.Current.DiscordCommandTvRequestHelpSearch));
        }
コード例 #9
0
ファイル: SonarrClientV2.cs プロジェクト: Qstick/requestrr
        public async Task <TvShow> GetTvShowDetailsAsync(TvShowRequest request, int theTvDbId)
        {
            RefreshSonarrCache();

            try
            {
                int?sonarrSeriesId = null;

                lock (_lock)
                {
                    sonarrSeriesId = _tvDbToSonarrId.ContainsKey(theTvDbId) ? _tvDbToSonarrId[theTvDbId] : (int?)null;
                }

                var jsonTvShow = await FindSeriesInSonarrAsync(theTvDbId, sonarrSeriesId?.ToString());

                var convertedTvShow = Convert(jsonTvShow, jsonTvShow.seasons, jsonTvShow.id.HasValue ? await GetSonarrEpisodesAsync(jsonTvShow.id.Value) : new Dictionary <int, JSONEpisode[]>());
                var searchedTvShow  = (await SearchTvShowAsync(new TvShowRequest(null, int.MinValue), convertedTvShow.Title)).FirstOrDefault(x => x.TheTvDbId == theTvDbId);

                convertedTvShow.Banner = searchedTvShow?.Banner;

                return(convertedTvShow);
            }
            catch (System.Exception ex)
            {
                _logger.LogError(ex, "An error occurred while getting tv show details with Sonarr: " + ex.Message);
            }

            throw new System.Exception("An error occurred while searching for tv show details with Sonarr");
        }
コード例 #10
0
        public async Task Handle_ShouldReturnOnlyShowsWithEpisodes(string firstExpectedTitle, string secondExpectedTitle)
        {
            var handler = new TvShowRequestHandler();
            var request = new TvShowRequest()
            {
                Payload = new List <TvShowRequestDetails>()
                {
                    new TvShowRequestDetails()
                    {
                        Title = "ignored show 1", EpisodeCount = 0, Drm = true
                    },
                    new TvShowRequestDetails()
                    {
                        Title = firstExpectedTitle, EpisodeCount = 100, Drm = true
                    },
                    new TvShowRequestDetails()
                    {
                        Title = secondExpectedTitle, EpisodeCount = 1, Drm = true
                    },
                    new TvShowRequestDetails()
                    {
                        Title = "ignored show 1", EpisodeCount = -1, Drm = true
                    }
                }
            };

            var result = await handler.Handle(request, CancellationToken.None);

            Assert.NotNull(result?.Response);
            Assert.Equal(2, result.Response.Count);
            Assert.Equal(firstExpectedTitle, result.Response[0].Title);
            Assert.Equal(secondExpectedTitle, result.Response[1].Title);
        }
コード例 #11
0
        public async Task Handle_ShouldThrowValidationExceptionForInvalidData()
        {
            var handler = new TvShowRequestHandler();
            var request = new TvShowRequest();

            await Assert.ThrowsAsync <ValidationException>(() => handler.Handle(request, CancellationToken.None));
        }
コード例 #12
0
        private async Task CreateSonarrTvSeriesAsync(TvShowRequest request, TvShow tvShow, IReadOnlyList <TvSeason> seasons)
        {
            SonarrCategory category = null;

            try
            {
                category = SonarrSettings.Categories.Single(x => x.Id == request.CategoryId);
            }
            catch
            {
                _logger.LogError($"An error occurred while requesting a tv show \"{tvShow.Title}\" from Sonarr, could not find category with id {request.CategoryId}");
                throw new System.Exception($"An error occurred while requesting tv show \"{tvShow.Title}\" from Sonarr, could not find category with id {request.CategoryId}");
            }

            var response = await HttpGetAsync($"{BaseURL}/series/lookup?term=tvdb:{tvShow.TheTvDbId}");

            await response.ThrowIfNotSuccessfulAsync("SonarrSeriesLookup failed", x => x.error);

            var jsonResponse = await response.Content.ReadAsStringAsync();

            var jsonTvShow = JsonConvert.DeserializeObject <IEnumerable <JSONTvShow> >(jsonResponse).First();

            int[] tags = category.Tags;

            string seriesType = category.SeriesType;

            if (seriesType == "automatic")
            {
                seriesType = await IsAnimeAsync(tvShow.TheTvDbId) ? "anime" : "standard";
            }

            response = await HttpPostAsync($"{BaseURL}/series", JsonConvert.SerializeObject(new
            {
                title             = jsonTvShow.title,
                qualityProfileId  = category.ProfileId,
                profileId         = category.ProfileId,
                languageProfileId = category.LanguageId,
                titleSlug         = jsonTvShow.titleSlug,
                monitored         = SonarrSettings.MonitorNewRequests,
                images            = new string[0],
                tvdbId            = tvShow.TheTvDbId,
                tags           = JToken.FromObject(tags),
                seriesType     = seriesType,
                year           = jsonTvShow.year,
                seasonFolder   = category.UseSeasonFolders,
                rootFolderPath = category.RootFolder,
                seasons        = jsonTvShow.seasons.Select(s => new
                {
                    seasonNumber = s.seasonNumber,
                    monitored    = seasons.Any(rs => rs.SeasonNumber == s.seasonNumber)
                }),
                addOptions = new
                {
                    searchForMissingEpisodes = SonarrSettings.SearchNewRequests
                }
            }));

            await response.ThrowIfNotSuccessfulAsync("SonarrSeriesCreation failed", x => x.error);
        }
コード例 #13
0
 public TvShow(TvShowRequest r)
 {
     Drm          = r.Drm;
     EpisodeCount = r.EpisodeCount;
     Image        = r.ImageRequest != null ? r.ImageRequest.ShowImage : string.Empty;
     Slug         = r.Slug;
     Title        = r.Title;
 }
コード例 #14
0
        public async Task DisplayMultiSeasonSelectionAsync(TvShowRequest request, TvShow tvShow, TvSeason[] tvSeasons)
        {
            var embed          = GenerateTvShowDetailsAsync(tvShow);
            var options        = tvSeasons.Select(x => new DiscordSelectComponentOption(GetFormattedSeasonName(tvShow, x), $"{request.CategoryId}/{tvShow.TheTvDbId.ToString()}/{x.SeasonNumber.ToString()}")).ToList();
            var seasonSelector = new DiscordSelectComponent($"TSS/{_interactionContext.User.Id}/{request.CategoryId}", Language.Current.DiscordCommandTvRequestHelpSeasonsDropdown, options);

            var builder = (await AddPreviousDropdownsAsync(tvShow, new DiscordWebhookBuilder().AddEmbed(embed))).AddComponents(seasonSelector).WithContent(Language.Current.DiscordCommandTvRequestHelpSeasons);
            await _interactionContext.EditOriginalResponseAsync(builder);
        }
コード例 #15
0
 public async Task HandleSelectionAsync(TvShowRequest request, TvShow tvShow, AllTvSeasons selectedSeason)
 {
     if (tvShow.AllSeasonsFullyRequested())
     {
         await _userInterface.WarnAlreadySeasonAlreadyRequestedAsync(tvShow, new FutureTvSeasons());
     }
     else
     {
         await _userInterface.DisplayTvShowDetailsForSeasonAsync(request, tvShow, selectedSeason);
     }
 }
コード例 #16
0
 public async Task HandleSelectionAsync(TvShowRequest request, TvShow tvShow, NormalTvSeason selectedSeason)
 {
     if (selectedSeason.IsRequested == RequestedState.Full)
     {
         await RequestNotificationsForSeasonAsync(request, tvShow, selectedSeason);
     }
     else
     {
         await _userInterface.DisplayTvShowDetailsForSeasonAsync(request, tvShow, selectedSeason);
     }
 }
コード例 #17
0
 public async Task HandleSelectionAsync(TvShowRequest request, TvShow tvShow, FutureTvSeasons selectedSeason)
 {
     if (tvShow.IsRequested)
     {
         await _tvShowNotificationWorkflow.NotifyForExistingRequestAsync(request.User.UserId, tvShow, selectedSeason);
     }
     else
     {
         await _userInterface.DisplayTvShowDetailsForSeasonAsync(request, tvShow, selectedSeason);
     }
 }
コード例 #18
0
 private async Task RequestNotificationsForSeasonAsync(TvShowRequest request, TvShow tvShow, TvSeason selectedSeason)
 {
     if (selectedSeason.IsAvailable)
     {
         await _userInterface.WarnSeasonAlreadyAvailableAsync(tvShow, selectedSeason);
     }
     else
     {
         await _tvShowNotificationWorkflow.NotifyForExistingRequestAsync(request.User.UserId, tvShow, selectedSeason);
     }
 }
コード例 #19
0
        public async Task DisplayTvShowDetailsForSeasonAsync(TvShowRequest request, TvShow tvShow, TvSeason season)
        {
            var message = season is AllTvSeasons
                ? Language.Current.DiscordCommandTvRequestConfirmAllSeasons
                : season is FutureTvSeasons
                    ? Language.Current.DiscordCommandTvRequestConfirmFutureSeasons
                    : Language.Current.DiscordCommandTvRequestConfirmSeason.ReplaceTokens(LanguageTokens.SeasonNumber, season.SeasonNumber.ToString());

            var requestButton = new DiscordButtonComponent(ButtonStyle.Primary, $"TRC/{_interactionContext.User.Id}/{request.CategoryId}/{tvShow.TheTvDbId}/{season.SeasonNumber}", Language.Current.DiscordCommandRequestButton);

            var embed   = GenerateTvShowDetailsAsync(tvShow);
            var builder = (await AddPreviousDropdownsAsync(tvShow, new DiscordWebhookBuilder().AddEmbed(embed))).AddComponents(requestButton).WithContent(message);
            await _interactionContext.EditOriginalResponseAsync(builder);
        }
コード例 #20
0
        public async Task RequestAsync(TvShowRequest request, TvShow tvShow, NormalTvSeason selectedSeason)
        {
            var result = await _requester.RequestTvShowAsync(request, tvShow, selectedSeason);

            if (result.WasDenied)
            {
                await _userInterface.DisplayRequestDeniedForSeasonAsync(tvShow, selectedSeason);
            }
            else
            {
                await _userInterface.DisplayRequestSuccessForSeasonAsync(tvShow, selectedSeason);

                await _tvShowNotificationWorkflow.NotifyForNewRequestAsync(request.User.UserId, tvShow, selectedSeason);
            }
        }
コード例 #21
0
        public void Check_If_Tv_Request_Has_No_Image_Request_Info_Then_TvShow_Image_Should_Be_An_Empty_String()
        {
            // Setup
            var noImageTvRequest = new TvShowRequest
            {
                ImageRequest = null,
                EpisodeCount = 0
            };

            // Action
            var tvShow = new TvShow(noImageTvRequest);

            // Assert
            Assert.That(tvShow.Image, Is.EqualTo(string.Empty));
        }
コード例 #22
0
        public async Task <IActionResult> Post([FromBody] TvShowRequest request)
        {
            if (request == null)
            {
                return(ParsingError());
            }
            try
            {
                var response = await _mediator.Send(request);

                return(Ok(response));
            }
            catch (ValidationException)
            {
                return(ParsingError());
            }
        }
コード例 #23
0
        public async Task <TvShow> GetTvShowDetailsAsync(TvShowRequest request, int tvDbId)
        {
            try
            {
                var jsonTvShow = await FindSeriesInSonarrAsync(tvDbId);

                var convertedTvShow = Convert(jsonTvShow, jsonTvShow.seasons, jsonTvShow.id.HasValue ? await GetSonarrEpisodesAsync(jsonTvShow.id.Value) : new Dictionary <int, JSONEpisode[]>());

                return(convertedTvShow);
            }
            catch (System.Exception ex)
            {
                _logger.LogError(ex, "An error occurred while getting tv show details with Sonarr: " + ex.Message);
            }

            throw new System.Exception("An error occurred while searching for tv show details with Sonarr");
        }
コード例 #24
0
        public async Task <ActionResult <IEnumerable <TvShow> > > GetAsync(string show, int?pagesize, int?pageNumber, CancellationToken cancellationToken)
        {
            var tvShowRequest = new TvShowRequest
            {
                Name       = show,
                PageSize   = pagesize ?? _applicationSettings.DefaultPageSize,
                PageNumber = pageNumber ?? 0
            };

            var paginatedResult = await _presentationService.GetTvShowsWithActorsSortedDescendingAsync(tvShowRequest, cancellationToken);

            if (paginatedResult?.Items == null)
            {
                return(NotFound());
            }

            return(Ok(paginatedResult.Items));
        }
コード例 #25
0
        public async Task RequestAsync(TvShowRequest request, TvShow tvShow, AllTvSeasons selectedSeason)
        {
            var result = await _requester.RequestTvShowAsync(request, tvShow, selectedSeason);

            if (result.WasDenied)
            {
                await _userInterface.DisplayRequestDeniedForSeasonAsync(tvShow, selectedSeason);
            }
            else
            {
                await _userInterface.DisplayRequestSuccessForSeasonAsync(tvShow, selectedSeason);

                foreach (var season in tvShow.Seasons.OfType <NormalTvSeason>().Where(x => !x.IsAvailable))
                {
                    await _tvShowNotificationWorkflow.NotifyForNewRequestAsync(request.User.UserId, tvShow, season);
                }
            }
        }
コード例 #26
0
ファイル: OmbiClient.cs プロジェクト: Qstick/requestrr
        public async Task <TvShow> GetTvShowDetailsAsync(TvShowRequest request, int TheTvDbId)
        {
            var retryCount = 0;

            while (retryCount <= 5)
            {
                try
                {
                    var jsonTvShow = await FindTvShowByTheTvDbIdAsync(TheTvDbId.ToString());

                    return(Convert(jsonTvShow));
                }
                catch (System.Exception ex)
                {
                    _logger.LogError(ex, "An error occurred while getting details for a tv show from Ombi: " + ex.Message);
                    retryCount++;
                    await Task.Delay(1000);
                }
            }

            throw new System.Exception("An error occurred while getting details for a tv show from Ombi");
        }
コード例 #27
0
ファイル: OmbiClient.cs プロジェクト: Qstick/requestrr
        public async Task <SearchedTvShow> SearchTvShowAsync(TvShowRequest request, int tvDbId)
        {
            var retryCount = 0;

            while (retryCount <= 5)
            {
                try
                {
                    var response = await HttpGetAsync($"{BaseURL}/api/v1/Search/Tv/info/{tvDbId}");

                    await response.ThrowIfNotSuccessfulAsync("OmbiSearchTvShowByTvDbId failed", x => x.error);

                    var jsonResponse = await response.Content.ReadAsStringAsync();

                    var jsonTvShow = JsonConvert.DeserializeObject <JSONTvShow>(jsonResponse);

                    var searchedTvShow = new SearchedTvShow
                    {
                        Title      = jsonTvShow.title,
                        Banner     = jsonTvShow.banner,
                        TheTvDbId  = jsonTvShow.id,
                        FirstAired = jsonTvShow.firstAired,
                    };

                    return(searchedTvShow.TheTvDbId == tvDbId ? searchedTvShow : null);
                }
                catch (System.Exception ex)
                {
                    _logger.LogError(ex, $"An error occurred while searching for tv show by tvDbId \"{tvDbId}\" from Ombi: " + ex.Message);
                    retryCount++;
                    await Task.Delay(1000);
                }
            }

            throw new System.Exception("An error occurred while searching for tv show by tvDbId from Ombi");
        }
コード例 #28
0
 public async Task <PaginatedResult <TvShow> > GetTvShowsWithActorsSortedDescendingAsync(TvShowRequest request, CancellationToken cancellationToken)
 {
     return(await _presentationDal.GetTvShowsWithActorsSortedDescendingAsync(request, cancellationToken));
 }
コード例 #29
0
        public async Task <PaginatedResult <TvShow> > GetTvShowsWithActorsSortedDescendingAsync(TvShowRequest tvShowRequest, CancellationToken cancellationToken)
        {
            var filter = Builders <TvShow> .Filter.Empty;

            if (!string.IsNullOrEmpty(tvShowRequest.Name))
            {
                filter = Builders <TvShow> .Filter.Regex(nameof(tvShowRequest.Name), new BsonRegularExpression(tvShowRequest.Name));
            }

            var sort = Builders <TvShow> .Sort.Ascending(t => t.Id);

            var query = TvShowsCollection.Find(filter);

            var countTask = query.CountAsync(cancellationToken); // using deprecated method since looks like new 'CountDocumentAsync' is buggy

            var results = await query
                          .Sort(sort)
                          .Skip(tvShowRequest.Skip)
                          .Limit(tvShowRequest.Take)
                          .Project(x => new TvShow
            {
                Id   = x.Id,
                Name = x.Name,
                Cast = x.Cast.OrderByDescending(z => z.Birthday).ToArray()
            }).ToListAsync(cancellationToken);

            var count = await countTask;

            return(new PaginatedResult <TvShow>((int)count, results));
        }
コード例 #30
0
        private async Task UpdateSonarrTvSeriesAsync(TvShowRequest request, TvShow tvShow, IReadOnlyList <TvSeason> seasons)
        {
            var response = await HttpGetAsync($"{BaseURL}/series/{tvShow.DownloadClientId}");

            if (!response.IsSuccessStatusCode)
            {
                if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
                {
                    var sonarrTvShow = await FindSeriesInSonarrAsync(tvShow.TheTvDbId);

                    if (sonarrTvShow != null && sonarrTvShow.id.HasValue)
                    {
                        await UpdateSonarrTvSeriesAsync(request, tvShow, seasons);

                        return;
                    }
                    else
                    {
                        await CreateSonarrTvSeriesAsync(request, tvShow, seasons);

                        return;
                    }
                }

                await response.ThrowIfNotSuccessfulAsync("SonarrSerieGet failed", x => x.error);
            }

            var jsonResponse = await response.Content.ReadAsStringAsync();

            dynamic sonarrSeries = JObject.Parse(jsonResponse);

            SonarrCategory category = null;

            try
            {
                category = SonarrSettings.Categories.Single(x => x.Id == request.CategoryId);
            }
            catch
            {
                _logger.LogError($"An error occurred while requesting a tv show \"{tvShow.Title}\" from Sonarr, could not find category with id {request.CategoryId}");
                throw new System.Exception($"An error occurred while requesting tv show \"{tvShow.Title}\" from Sonarr, could not find category with id {request.CategoryId}");
            }

            sonarrSeries.tags              = JToken.FromObject(category.Tags);
            sonarrSeries.qualityProfileId  = category.ProfileId;
            sonarrSeries.languageProfileId = category.LanguageId;
            sonarrSeries.monitored         = SonarrSettings.MonitorNewRequests;
            sonarrSeries.seasonFolder      = category.UseSeasonFolders;

            if (seasons.Any())
            {
                IEnumerable <dynamic> jsonSeasons = sonarrSeries.seasons;

                foreach (var season in jsonSeasons)
                {
                    season.monitored = seasons.Any(s => s.SeasonNumber == (int)season.seasonNumber) ? false : (bool)season.monitored;
                }

                response = await HttpPutAsync($"{BaseURL}/series/{tvShow.DownloadClientId}", JsonConvert.SerializeObject(sonarrSeries));

                await response.ThrowIfNotSuccessfulAsync("SonarrSeriesUpdate failed", x => x.error);

                foreach (var season in jsonSeasons)
                {
                    season.monitored = seasons.Any(s => s.SeasonNumber == (int)season.seasonNumber) ? true : (bool)season.monitored;
                }
            }

            response = await HttpPutAsync($"{BaseURL}/series/{tvShow.DownloadClientId}", JsonConvert.SerializeObject(sonarrSeries));

            await response.ThrowIfNotSuccessfulAsync("SonarrSeriesUpdate failed", x => x.error);

            if (SonarrSettings.SearchNewRequests)
            {
                var episodes = await GetSonarrEpisodesAsync(int.Parse(tvShow.DownloadClientId));

                await Task.WhenAll(seasons.Select(async s =>
                {
                    try
                    {
                        if (episodes[s.SeasonNumber].Any())
                        {
                            var undownloadedEpisodes = episodes[s.SeasonNumber].Where(x => !x.hasFile).Select(x => x.id).ToArray();

                            if (undownloadedEpisodes.Length == episodes[s.SeasonNumber].Count())
                            {
                                response = await HttpPostAsync($"{BaseURL}/command", JsonConvert.SerializeObject(new
                                {
                                    name         = "SeasonSearch",
                                    seasonNumber = s.SeasonNumber,
                                    seriesId     = tvShow.DownloadClientId
                                }));

                                await response.ThrowIfNotSuccessfulAsync("SonarrSeasonSearchCommand failed", x => x.error);
                            }
                            else
                            {
                                await response.ThrowIfNotSuccessfulAsync("SonarrSearchEpisodeCommand failed", x => x.error);
                                response = await HttpPostAsync($"{BaseURL}/command", JsonConvert.SerializeObject(new
                                {
                                    name       = "EpisodeSearch",
                                    episodeIds = undownloadedEpisodes,
                                }));

                                await response.ThrowIfNotSuccessfulAsync("SonarrSearchEpisodeCommand failed", x => x.error);
                            }
                        }
                    }
                    catch (System.Exception ex)
                    {
                        _logger.LogError(ex.Message);
                        throw;
                    }
                }));
            }
        }