New: Allow Filter by Profile from Radarr Instance List

This commit is contained in:
Qstick 2020-04-10 23:48:23 -04:00
parent 6739bf72c4
commit 55134d76c1
6 changed files with 188 additions and 101 deletions

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace NzbDrone.Core.NetImport.Radarr namespace NzbDrone.Core.NetImport.Radarr
@ -15,5 +15,12 @@ namespace NzbDrone.Core.NetImport.Radarr
public DateTime PhysicalRelease { get; set; } public DateTime PhysicalRelease { get; set; }
public int Year { get; set; } public int Year { get; set; }
public string TitleSlug { get; set; } public string TitleSlug { get; set; }
public int QualityProfileId { get; set; }
}
public class RadarrProfile
{
public string Name { get; set; }
public int Id { get; set; }
} }
} }

View File

@ -1,39 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentValidation.Results;
using NLog; using NLog;
using NzbDrone.Common.Http; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.NetImport.Radarr namespace NzbDrone.Core.NetImport.Radarr
{ {
public class RadarrImport : HttpNetImportBase<RadarrSettings> public class RadarrImport : NetImportBase<RadarrSettings>
{ {
private readonly IRadarrV3Proxy _radarrV3Proxy;
public override string Name => "Radarr"; public override string Name => "Radarr";
public override bool Enabled => true; public override bool Enabled => true;
public override bool EnableAuto => false; public override bool EnableAuto => false;
public override NetImportType ListType => NetImportType.Program; public override NetImportType ListType => NetImportType.Program;
public RadarrImport(IHttpClient httpClient, public RadarrImport(IRadarrV3Proxy radarrV3Proxy,
IConfigService configService, IConfigService configService,
IParsingService parsingService, IParsingService parsingService,
Logger logger) Logger logger)
: base(httpClient, configService, parsingService, logger) : base(configService, parsingService, logger)
{ {
_radarrV3Proxy = radarrV3Proxy;
} }
public override INetImportRequestGenerator GetRequestGenerator() public override NetImportFetchResult Fetch()
{ {
return new RadarrRequestGenerator() var movies = new List<Movie>();
var anyFailure = false;
try
{ {
Settings = Settings, var remoteMovies = _radarrV3Proxy.GetMovies(Settings);
Logger = _logger,
HttpClient = _httpClient foreach (var remoteMovie in remoteMovies)
{
if (!Settings.ProfileIds.Any() || Settings.ProfileIds.Contains(remoteMovie.QualityProfileId))
{
movies.Add(new Movie
{
TmdbId = remoteMovie.TmdbId,
Title = remoteMovie.Title,
SortTitle = remoteMovie.SortTitle,
TitleSlug = remoteMovie.TitleSlug,
Overview = remoteMovie.Overview,
Images = remoteMovie.Images.Select(x => MapImage(x, Settings.BaseUrl)).ToList(),
Monitored = remoteMovie.Monitored,
PhysicalRelease = remoteMovie.PhysicalRelease,
InCinemas = remoteMovie.InCinemas,
Year = remoteMovie.Year
});
}
}
}
catch
{
anyFailure = true;
}
return new NetImportFetchResult { Movies = movies, AnyFailure = anyFailure };
}
public override object RequestAction(string action, IDictionary<string, string> query)
{
if (action == "getDevices")
{
// Return early if there is not an API key
if (Settings.ApiKey.IsNullOrWhiteSpace())
{
return new
{
devices = new List<object>()
}; };
} }
public override IParseNetImportResponse GetParser() Settings.Validate().Filter("ApiKey").ThrowOnError();
var devices = _radarrV3Proxy.GetProfiles(Settings);
return new
{ {
return new RadarrParser(Settings); options = devices.OrderBy(d => d.Name, StringComparer.InvariantCultureIgnoreCase)
.Select(d => new
{
id = d.Id,
name = d.Name
})
};
}
return new { };
}
protected override void Test(List<ValidationFailure> failures)
{
failures.AddIfNotNull(_radarrV3Proxy.Test(Settings));
}
private static MediaCover.MediaCover MapImage(MediaCover.MediaCover arg, string baseUrl)
{
var newImage = new MediaCover.MediaCover
{
Url = string.Format("{0}{1}", baseUrl, arg.Url),
CoverType = arg.CoverType
};
return newImage;
} }
} }
} }

View File

@ -1,53 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Movies;
namespace NzbDrone.Core.NetImport.Radarr
{
public class RadarrParser : IParseNetImportResponse
{
private readonly RadarrSettings _settings;
public RadarrParser(RadarrSettings settings)
{
_settings = settings;
}
public IList<Movie> ParseResponse(NetImportResponse netMovieImporterResponse)
{
var remoteMovies = Json.Deserialize<List<RadarrMovie>>(netMovieImporterResponse.Content);
var movies = new List<Movie>();
foreach (var remoteMovie in remoteMovies)
{
movies.Add(new Movie
{
TmdbId = remoteMovie.TmdbId,
Title = remoteMovie.Title,
SortTitle = remoteMovie.SortTitle,
TitleSlug = remoteMovie.TitleSlug,
Overview = remoteMovie.Overview,
Images = remoteMovie.Images.Select(x => MapImage(x, _settings.BaseUrl)).ToList(),
Monitored = remoteMovie.Monitored,
PhysicalRelease = remoteMovie.PhysicalRelease,
InCinemas = remoteMovie.InCinemas,
Year = remoteMovie.Year
});
}
return movies;
}
private static MediaCover.MediaCover MapImage(MediaCover.MediaCover arg, string baseUrl)
{
var newImage = new MediaCover.MediaCover
{
Url = string.Format("{0}{1}", baseUrl, arg.Url),
CoverType = arg.CoverType
};
return newImage;
}
}
}

View File

@ -1,34 +0,0 @@
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Http;
namespace NzbDrone.Core.NetImport.Radarr
{
public class RadarrRequestGenerator : INetImportRequestGenerator
{
public RadarrSettings Settings { get; set; }
public IHttpClient HttpClient { get; set; }
public Logger Logger { get; set; }
public RadarrRequestGenerator()
{
}
public virtual NetImportPageableRequestChain GetMovies()
{
var pageableRequests = new NetImportPageableRequestChain();
var baseUrl = Settings.BaseUrl.TrimEnd('/');
var request = new NetImportRequest($"{baseUrl}/api/v3/movie", HttpAccept.Json);
request.HttpRequest.Headers["X-Api-Key"] = Settings.ApiKey;
request.HttpRequest.SuppressHttpError = true;
pageableRequests.Add(new List<NetImportRequest> { request });
return pageableRequests;
}
}
}

View File

@ -1,4 +1,5 @@
using FluentValidation; using System.Collections.Generic;
using FluentValidation;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
@ -22,6 +23,7 @@ namespace NzbDrone.Core.NetImport.Radarr
{ {
BaseUrl = ""; BaseUrl = "";
ApiKey = ""; ApiKey = "";
ProfileIds = new int[] { };
} }
[FieldDefinition(0, Label = "Full URL", HelpText = "URL, including port, of the Radarr V3 instance to import from")] [FieldDefinition(0, Label = "Full URL", HelpText = "URL, including port, of the Radarr V3 instance to import from")]
@ -30,6 +32,9 @@ namespace NzbDrone.Core.NetImport.Radarr
[FieldDefinition(1, Label = "API Key", HelpText = "Apikey of the Radarr V3 instance to import from")] [FieldDefinition(1, Label = "API Key", HelpText = "Apikey of the Radarr V3 instance to import from")]
public string ApiKey { get; set; } public string ApiKey { get; set; }
[FieldDefinition(2, Type = FieldType.Device, Label = "Profiles", HelpText = "Profiles from the source instance to import from")]
public IEnumerable<int> ProfileIds { get; set; }
public NzbDroneValidationResult Validate() public NzbDroneValidationResult Validate()
{ {
return new NzbDroneValidationResult(Validator.Validate(this)); return new NzbDroneValidationResult(Validator.Validate(this));

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Net;
using FluentValidation.Results;
using Newtonsoft.Json;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
namespace NzbDrone.Core.NetImport.Radarr
{
public interface IRadarrV3Proxy
{
List<RadarrMovie> GetMovies(RadarrSettings settings);
List<RadarrProfile> GetProfiles(RadarrSettings settings);
ValidationFailure Test(RadarrSettings settings);
}
public class RadarrV3Proxy : IRadarrV3Proxy
{
private readonly IHttpClient _httpClient;
private readonly Logger _logger;
public RadarrV3Proxy(IHttpClient httpClient, Logger logger)
{
_httpClient = httpClient;
_logger = logger;
}
public List<RadarrMovie> GetMovies(RadarrSettings settings)
{
return Execute<RadarrMovie>("/api/v3/movie", settings);
}
public List<RadarrProfile> GetProfiles(RadarrSettings settings)
{
return Execute<RadarrProfile>("/api/v3/qualityprofile", settings);
}
public ValidationFailure Test(RadarrSettings settings)
{
try
{
GetMovies(settings);
}
catch (HttpException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
{
_logger.Error(ex, "API Key is invalid");
return new ValidationFailure("ApiKey", "API Key is invalid");
}
_logger.Error(ex, "Unable to send test message");
return new ValidationFailure("ApiKey", "Unable to send test message");
}
catch (Exception ex)
{
_logger.Error(ex, "Unable to send test message");
return new ValidationFailure("", "Unable to send test message");
}
return null;
}
private List<TResource> Execute<TResource>(string resource, RadarrSettings settings)
{
if (settings.BaseUrl.IsNullOrWhiteSpace() || settings.ApiKey.IsNullOrWhiteSpace())
{
return new List<TResource>();
}
var baseUrl = settings.BaseUrl.TrimEnd('/');
var request = new HttpRequestBuilder(baseUrl).Resource(resource).Accept(HttpAccept.Json)
.SetHeader("X-Api-Key", settings.ApiKey).Build();
var response = _httpClient.Get(request);
var results = JsonConvert.DeserializeObject<List<TResource>>(response.Content);
return results;
}
}
}