New: Import from Another Radarr Instance

Co-Authored-By: Leonardo Galli <galli-leo@users.noreply.github.com>
pull/2/head
Qstick 5 years ago
parent 57057911ab
commit 7adfe65f65

@ -51,7 +51,7 @@ namespace NzbDrone.Core.NetImport
public List<INetImport> Discoverable()
{
var enabledImporters = GetAvailableProviders().Where(n => (n.GetType() == typeof(Radarr.RadarrLists) || n.GetType() == typeof(TMDb.Popular.TMDbPopularImport)));
var enabledImporters = GetAvailableProviders().Where(n => (n.GetType() == typeof(RadarrList.RadarrListImport) || n.GetType() == typeof(TMDb.Popular.TMDbPopularImport)));
var indexers = FilterBlockedIndexers(enabledImporters);
return indexers.ToList();
}

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.NetImport.Radarr
{
public class RadarrMovie
{
public string Title { get; set; }
public string SortTitle { get; set; }
public int TmdbId { get; set; }
public string Overview { get; set; }
public List<MediaCover.MediaCover> Images { get; set; }
public bool Monitored { get; set; }
public DateTime InCinemas { get; set; }
public DateTime PhysicalRelease { get; set; }
public int Year { get; set; }
public string TitleSlug { get; set; }
}
}

@ -0,0 +1,39 @@
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.NetImport.Radarr
{
public class RadarrImport : HttpNetImportBase<RadarrSettings>
{
public override string Name => "Radarr";
public override bool Enabled => true;
public override bool EnableAuto => false;
public override NetImportType ListType => NetImportType.Other;
public RadarrImport(IHttpClient httpClient,
IConfigService configService,
IParsingService parsingService,
Logger logger)
: base(httpClient, configService, parsingService, logger)
{
}
public override INetImportRequestGenerator GetRequestGenerator()
{
return new RadarrRequestGenerator()
{
Settings = Settings,
Logger = _logger,
HttpClient = _httpClient
};
}
public override IParseNetImportResponse GetParser()
{
return new RadarrParser(Settings);
}
}
}

@ -1,69 +1,53 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.RadarrAPI;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
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;
private readonly ISearchForNewMovie _skyhookProxy;
private NetImportResponse _importResponse;
public RadarrParser(RadarrSettings settings, ISearchForNewMovie skyhookProxy)
public RadarrParser(RadarrSettings settings)
{
_skyhookProxy = skyhookProxy;
_settings = settings;
}
public IList<Movies.Movie> ParseResponse(NetImportResponse importResponse)
public IList<Movie> ParseResponse(NetImportResponse netMovieImporterResponse)
{
_importResponse = importResponse;
var movies = new List<Movies.Movie>();
if (!PreProcess(_importResponse))
{
return movies;
}
var remoteMovies = Json.Deserialize<List<RadarrMovie>>(netMovieImporterResponse.Content);
var jsonResponse = JsonConvert.DeserializeObject<List<MovieResult>>(_importResponse.Content);
var movies = new List<Movie>();
// no movies were return
if (jsonResponse == null)
foreach (var remoteMovie in remoteMovies)
{
return movies;
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 jsonResponse.SelectList(_skyhookProxy.MapMovie);
return movies;
}
protected virtual bool PreProcess(NetImportResponse netImportResponse)
private static MediaCover.MediaCover MapImage(MediaCover.MediaCover arg, string baseUrl)
{
try
{
var error = JsonConvert.DeserializeObject<RadarrError>(netImportResponse.HttpResponse.Content);
if (error != null && error.Errors != null && error.Errors.Count != 0)
{
throw new RadarrAPIException(error);
}
}
catch (JsonSerializationException)
{
//No error!
}
if (netImportResponse.HttpResponse.StatusCode != System.Net.HttpStatusCode.OK)
var newImage = new MediaCover.MediaCover
{
throw new HttpException(netImportResponse.HttpRequest, netImportResponse.HttpResponse);
}
Url = string.Format("{0}{1}", baseUrl, arg.Url),
CoverType = arg.CoverType
};
return true;
return newImage;
}
}
}

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
namespace NzbDrone.Core.NetImport.Radarr
@ -12,24 +10,24 @@ namespace NzbDrone.Core.NetImport.Radarr
public IHttpClient HttpClient { get; set; }
public Logger Logger { get; set; }
public int MaxPages { get; set; }
public RadarrRequestGenerator()
{
MaxPages = 3;
}
public virtual NetImportPageableRequestChain GetMovies()
{
var pageableRequests = new NetImportPageableRequestChain();
var baseUrl = $"{Settings.APIURL.TrimEnd("/")}";
var baseUrl = Settings.BaseUrl.TrimEnd('/');
var request = new NetImportRequest($"{baseUrl}/api/v3/movie", HttpAccept.Json);
var request = new NetImportRequest($"{baseUrl}{Settings.Path}", HttpAccept.Json);
request.HttpRequest.Headers["X-Api-Key"] = Settings.ApiKey;
request.HttpRequest.SuppressHttpError = true;
pageableRequests.Add(new List<NetImportRequest> { request });
return pageableRequests;
}
}

@ -9,7 +9,8 @@ namespace NzbDrone.Core.NetImport.Radarr
{
public RadarrSettingsValidator()
{
RuleFor(c => c.APIURL).ValidRootUrl();
RuleFor(c => c.BaseUrl).ValidRootUrl();
RuleFor(c => c.ApiKey).NotEmpty();
}
}
@ -19,15 +20,15 @@ namespace NzbDrone.Core.NetImport.Radarr
public RadarrSettings()
{
APIURL = "https://api.radarr.video/v2";
Path = "";
BaseUrl = "";
ApiKey = "";
}
[FieldDefinition(0, Label = "Radarr API URL", HelpText = "Link to to Radarr API URL. Use https://staging.api.radarr.video if you are on nightly.")]
public string APIURL { get; set; }
[FieldDefinition(0, Label = "Full URL", HelpText = "URL, including port, of the Radarr V3 instance to import from")]
public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Path to list", HelpText = "Path to the list proxied by the Radarr API. Check the wiki for available lists.")]
public string Path { get; set; }
[FieldDefinition(1, Label = "API Key", HelpText = "Apikey of the Radarr V3 instance to import from")]
public string ApiKey { get; set; }
public NzbDroneValidationResult Validate()
{

@ -6,19 +6,19 @@ using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.NetImport.Radarr
namespace NzbDrone.Core.NetImport.RadarrList
{
public class RadarrLists : HttpNetImportBase<RadarrSettings>
public class RadarrListImport : HttpNetImportBase<RadarrListSettings>
{
private readonly ISearchForNewMovie _skyhookProxy;
public override string Name => "Radarr Lists";
public override NetImportType ListType => NetImportType.Other;
public override bool Enabled => true;
public override bool EnableAuto => false;
private readonly ISearchForNewMovie _skyhookProxy;
public RadarrLists(IHttpClient httpClient,
public RadarrListImport(IHttpClient httpClient,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie skyhookProxy,
@ -44,7 +44,7 @@ namespace NzbDrone.Core.NetImport.Radarr
EnableAuto = true,
ProfileId = 1,
Implementation = GetType().Name,
Settings = new RadarrSettings { Path = "/imdb/top250" },
Settings = new RadarrListSettings { Path = "/imdb/top250" },
};
yield return new NetImportDefinition
{
@ -53,7 +53,7 @@ namespace NzbDrone.Core.NetImport.Radarr
EnableAuto = true,
ProfileId = 1,
Implementation = GetType().Name,
Settings = new RadarrSettings { Path = "/imdb/popular" },
Settings = new RadarrListSettings { Path = "/imdb/popular" },
};
yield return new NetImportDefinition
{
@ -62,14 +62,14 @@ namespace NzbDrone.Core.NetImport.Radarr
EnableAuto = true,
ProfileId = 1,
Implementation = GetType().Name,
Settings = new RadarrSettings { Path = "/imdb/list?listId=LISTID" },
Settings = new RadarrListSettings { Path = "/imdb/list?listId=LISTID" },
};
}
}
public override INetImportRequestGenerator GetRequestGenerator()
{
return new RadarrRequestGenerator()
return new RadarrListRequestGenerator()
{
Settings = Settings,
Logger = _logger,
@ -79,7 +79,7 @@ namespace NzbDrone.Core.NetImport.Radarr
public override IParseNetImportResponse GetParser()
{
return new RadarrParser(Settings, _skyhookProxy);
return new RadarrListParser(_skyhookProxy);
}
}
}

@ -0,0 +1,67 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.RadarrAPI;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
using NzbDrone.Core.Movies;
namespace NzbDrone.Core.NetImport.RadarrList
{
public class RadarrListParser : IParseNetImportResponse
{
private readonly ISearchForNewMovie _skyhookProxy;
public RadarrListParser(ISearchForNewMovie skyhookProxy)
{
_skyhookProxy = skyhookProxy;
}
public IList<Movie> ParseResponse(NetImportResponse netMovieImporterResponse)
{
var importResponse = netMovieImporterResponse;
var movies = new List<Movie>();
if (!PreProcess(importResponse))
{
return movies;
}
var jsonResponse = JsonConvert.DeserializeObject<List<MovieResult>>(importResponse.Content);
// no movies were return
if (jsonResponse == null)
{
return movies;
}
return jsonResponse.SelectList(_skyhookProxy.MapMovie);
}
protected virtual bool PreProcess(NetImportResponse netImportResponse)
{
try
{
var error = JsonConvert.DeserializeObject<RadarrError>(netImportResponse.HttpResponse.Content);
if (error != null && error.Errors != null && error.Errors.Count != 0)
{
throw new RadarrAPIException(error);
}
}
catch (JsonSerializationException)
{
//No error!
}
if (netImportResponse.HttpResponse.StatusCode != System.Net.HttpStatusCode.OK)
{
throw new HttpException(netImportResponse.HttpRequest, netImportResponse.HttpResponse);
}
return true;
}
}
}

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
namespace NzbDrone.Core.NetImport.RadarrList
{
public class RadarrListRequestGenerator : INetImportRequestGenerator
{
public RadarrListSettings Settings { get; set; }
public IHttpClient HttpClient { get; set; }
public Logger Logger { get; set; }
public int MaxPages { get; set; }
public RadarrListRequestGenerator()
{
MaxPages = 3;
}
public virtual NetImportPageableRequestChain GetMovies()
{
var pageableRequests = new NetImportPageableRequestChain();
var baseUrl = $"{Settings.APIURL.TrimEnd("/")}";
var request = new NetImportRequest($"{baseUrl}{Settings.Path}", HttpAccept.Json);
request.HttpRequest.SuppressHttpError = true;
pageableRequests.Add(new List<NetImportRequest> { request });
return pageableRequests;
}
}
}

@ -0,0 +1,37 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.NetImport.RadarrList
{
public class RadarrSettingsValidator : AbstractValidator<RadarrListSettings>
{
public RadarrSettingsValidator()
{
RuleFor(c => c.APIURL).ValidRootUrl();
}
}
public class RadarrListSettings : IProviderConfig
{
private static readonly RadarrSettingsValidator Validator = new RadarrSettingsValidator();
public RadarrListSettings()
{
APIURL = "https://api.radarr.video/v2";
Path = "";
}
[FieldDefinition(0, Label = "Radarr API URL", HelpText = "Link to to Radarr API URL. Use https://staging.api.radarr.video if you are on nightly.")]
public string APIURL { get; set; }
[FieldDefinition(1, Label = "Path to list", HelpText = "Path to the list proxied by the Radarr API. Check the wiki for available lists.")]
public string Path { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}
Loading…
Cancel
Save