From 7bbebe53a36ff7ea8e7bd6192630bf84a4a46a62 Mon Sep 17 00:00:00 2001 From: Leonardo Galli Date: Tue, 6 Jun 2017 19:50:53 +0200 Subject: [PATCH] Added: Custom Class for Radarr API requests. Also implements new error handling present on staging server. --- .../RadarrAPI/RadarrAPIClient.cs | 98 +++++++++++++++++++ .../RadarrAPI/RadarrResources.cs | 47 +++++++++ .../MetadataSource/SkyHook/SkyHookProxy.cs | 73 ++++++-------- src/NzbDrone.Core/NzbDrone.Core.csproj | 3 + 4 files changed, 176 insertions(+), 45 deletions(-) create mode 100644 src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrAPIClient.cs create mode 100644 src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrResources.cs diff --git a/src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrAPIClient.cs b/src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrAPIClient.cs new file mode 100644 index 000000000..49bdce34b --- /dev/null +++ b/src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrAPIClient.cs @@ -0,0 +1,98 @@ +using NzbDrone.Common.Http; +using NzbDrone.Core.Configuration; +using System; +using Newtonsoft.Json; +using System.Collections.Generic; +using NzbDrone.Core.MetadataSource.SkyHook.Resource; + +namespace NzbDrone.Core.MetadataSource.RadarrAPI +{ + public interface IRadarrAPIClient + { + IHttpRequestBuilderFactory RadarrAPI { get; } + List DiscoverMovies(string action, Func enhanceRequest); + } + + public class RadarrAPIClient : IRadarrAPIClient + { + private readonly IHttpClient _httpClient; + + public RadarrAPIClient(IConfigFileProvider configFile, IHttpClient httpClient) + { + _httpClient = httpClient; + + if (configFile.Branch == "nightly") + { + RadarrAPI = new HttpRequestBuilder("https://staging.api.radarr.video/{route}/{action}") + .CreateFactory(); + } + else + { + RadarrAPI = new HttpRequestBuilder("https://api.radarr.video/v2/{route}/{action}") + .CreateFactory(); + } + + } + + private HttpResponse Execute(HttpRequest request) + { + if (request.Method == HttpMethod.GET) + { + return _httpClient.Get(request); + } + else if (request.Method == HttpMethod.POST) + { + return _httpClient.Post(request); + } + else + { + throw new NotImplementedException($"Method {request.Method} not implemented"); + } + } + + private T Execute(HttpRequest request) + { + request.AllowAutoRedirect = true; + request.Headers.Accept = HttpAccept.Json.Value; + request.SuppressHttpError = true; + + var response = Execute(request); + + try + { + var error = JsonConvert.DeserializeObject(response.Content); + + if (error != null && error.Errors.Count != 0) + { + throw new RadarrAPIException(error); + } + } + catch (JsonSerializationException) + { + //No error! + } + + + if (response.StatusCode != System.Net.HttpStatusCode.OK) + { + throw new HttpException(request, response); + } + + return JsonConvert.DeserializeObject(response.Content); + } + + public List DiscoverMovies(string action, Func enhanceRequest = null ) + { + var request = RadarrAPI.Create().SetSegment("route", "discovery").SetSegment("action", action).Build(); + + if (enhanceRequest != null) + { + request = enhanceRequest(request); + } + + return Execute>(request); + } + + public IHttpRequestBuilderFactory RadarrAPI { get; private set; } + } +} diff --git a/src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrResources.cs b/src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrResources.cs new file mode 100644 index 000000000..88c068cb6 --- /dev/null +++ b/src/NzbDrone.Core/MetadataSource/RadarrAPI/RadarrResources.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +namespace NzbDrone.Core.MetadataSource.RadarrAPI +{ + public class Error + { + [JsonProperty("id")] + public string RayId { get; set; } + + [JsonProperty("status")] + public int Status { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("detail")] + public string Detail { get; set; } + } + + public class RadarrError + { + [JsonProperty("errors")] + public IList Errors { get; set; } + } + + public class RadarrAPIException : Exception + { + RadarrError APIErrors; + + public RadarrAPIException(RadarrError apiError) : base(HumanReadable(apiError)) + { + + } + + private static string HumanReadable(RadarrError APIErrors) + { + var firstError = APIErrors.Errors.First(); + var details = string.Join("\n", APIErrors.Errors.Select(error => + { + return $"{error.Title} ({error.Status}, RayId: {error.RayId}), Details: {error.Detail}"; + })); + return $"Error while calling api: {firstError.Title}\nFull error(s): {details}"; + } + } +} diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs index 824285ed1..4defaa6a1 100644 --- a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs +++ b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs @@ -17,6 +17,8 @@ using NzbDrone.Core.Parser; using NzbDrone.Core.Profiles; using NzbDrone.Common.Serializer; using NzbDrone.Core.NetImport.ImportExclusions; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.MetadataSource.RadarrAPI; namespace NzbDrone.Core.MetadataSource.SkyHook { @@ -31,9 +33,12 @@ namespace NzbDrone.Core.MetadataSource.SkyHook private readonly IMovieService _movieService; private readonly IPreDBService _predbService; private readonly IImportExclusionsService _exclusionService; + private readonly IRadarrAPIClient _radarrAPI; + + private readonly IHttpRequestBuilderFactory _apiBuilder; public SkyHookProxy(IHttpClient httpClient, ISonarrCloudRequestBuilder requestBuilder, ITmdbConfigService configService, IMovieService movieService, - IPreDBService predbService, IImportExclusionsService exclusionService, Logger logger) + IPreDBService predbService, IImportExclusionsService exclusionService, IRadarrAPIClient radarrAPI, Logger logger) { _httpClient = httpClient; _requestBuilder = requestBuilder.SkyHookTvdb; @@ -42,6 +47,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook _movieService = movieService; _predbService = predbService; _exclusionService = exclusionService; + _radarrAPI = radarrAPI; + _logger = logger; } @@ -362,55 +369,31 @@ namespace NzbDrone.Core.MetadataSource.SkyHook string allIds = string.Join(",", allMovies.Select(m => m.TmdbId)); string ignoredIds = string.Join(",", allExclusions.Select(ex => ex.TmdbId)); - HttpRequest request; - List results; + List results = new List(); - /*if (action == "upcoming") + try { - var lastWeek = DateTime.Now.AddDays(-7); - var threeWeeks = DateTime.Now.AddDays(7 * 3); - - request = _movieBuilder.Create().SetSegment("route", "discover") - .SetSegment("id", "movie") - .SetSegment("secondaryRoute", "") - .AddQueryParam("region", "us") - .AddQueryParam("with_release_type", "5|4|6") - .AddQueryParam("release_date.gte", lastWeek.ToString("yyyy-MM-dd")) - .AddQueryParam("sort_by", "popularity.desc") - .AddQueryParam("release_date.lte", threeWeeks.ToString("yyyy-MM-dd")).Build(); - - - var response = _httpClient.Get(request); - - if (response.StatusCode != HttpStatusCode.OK) + results = _radarrAPI.DiscoverMovies(action, (request) => { - throw new HttpException(request, response); - } + request.AllowAutoRedirect = true; + request.Method = HttpMethod.POST; + request.Headers.ContentType = "application/x-www-form-urlencoded"; + request.SetContent($"tmdbIds={allIds}&ignoredIds={ignoredIds}"); + return request; + }); - results = response.Resource.results.ToList(); + results = results.Where(m => allMovies.None(mo => mo.TmdbId == m.id) && allExclusions.None(ex => ex.TmdbId == m.id)).ToList(); + } + catch (RadarrAPIException exception) + { + _logger.Error(exception, "Failed to discover movies for action {0}!", action); + } + catch (Exception exception) + { + _logger.Error(exception, "Failed to discover movies for action {0}!", action); } - else - {*/ - request = new HttpRequestBuilder("https://api.radarr.video/{action}/").SetSegment("action", action).Build(); - - request.AllowAutoRedirect = true; - request.Method = HttpMethod.POST; - request.Headers.ContentType = "application/x-www-form-urlencoded"; - request.SetContent($"tmdbids={allIds}&ignoredIds={ignoredIds}"); - - var response = _httpClient.Post>(request); - - if (response.StatusCode != HttpStatusCode.OK) - { - throw new HttpException(request, response); - } - - results = response.Resource; - //} - - results = results.Where(m => allMovies.None(mo => mo.TmdbId == m.id) && allExclusions.None(ex => ex.TmdbId == m.id)).ToList(); - return results.SelectList(MapMovie); + return results.SelectList(MapMovie); } private string StripTrailingTheFromTitle(string title) @@ -499,7 +482,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook _logger.Warn("Cleaned response: " + responseCleaned); - ImdbResource json = JsonConvert.DeserializeObject(responseCleaned); + ImdbResource json =Json Convert.DeserializeObject(responseCleaned); _logger.Warn("Json object: " + json); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 6218e92f2..28a7fad20 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -1285,6 +1285,8 @@ + + @@ -1356,6 +1358,7 @@ +