From dbbb6bf0d1231076fdaf8aee529a48f5c310e9b9 Mon Sep 17 00:00:00 2001 From: Robin Dadswell <19610103+RobinDadswell@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:34:27 +0100 Subject: [PATCH] Starts of Jackett Migrations request extension start migration controller/resource removed unneccesary using - probalby more to go still more scaffolding added more framework; contemplating using the importlists from other arrs as a base for this Revert "jackett config" This reverts commit 6523eaf55450ceed84b3667421595a9d9e34dc51. added stuff from nit's radarr pr neated code up a little bit, more to do on this though get config sorted, api logic also added - migration todo and indexer config to do --- .../JackettIndexerConfigDefintion.cs | 26 +++++++ .../Migration/JackettIndexerDefinition.cs | 20 +++++ .../Migration/JackettMigrationService.cs | 77 +++++++++++++++++++ .../Migration/MigrationController.cs | 32 ++++++++ .../Migration/MigrationResource.cs | 4 + .../Extensions/RequestExtensions.cs | 12 +++ 6 files changed, 171 insertions(+) create mode 100644 src/NzbDrone.Core/Migration/JackettIndexerConfigDefintion.cs create mode 100644 src/NzbDrone.Core/Migration/JackettIndexerDefinition.cs create mode 100644 src/NzbDrone.Core/Migration/JackettMigrationService.cs create mode 100644 src/Prowlarr.Api.V1/Migration/MigrationController.cs create mode 100644 src/Prowlarr.Api.V1/Migration/MigrationResource.cs diff --git a/src/NzbDrone.Core/Migration/JackettIndexerConfigDefintion.cs b/src/NzbDrone.Core/Migration/JackettIndexerConfigDefintion.cs new file mode 100644 index 000000000..a3512bf1c --- /dev/null +++ b/src/NzbDrone.Core/Migration/JackettIndexerConfigDefintion.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NzbDrone.Core.Migration +{ + public class JackettIndexerConfigDefintion + { + //TODO: Update to ensure json matches up with Prowlarrs + public string Cookie { get; set; } + public string Username { get; set; } + public string MFA { get; set; } + public string Email { get; set; } + public string Pid { get; set; } + public string Pin { get; set; } + public string Password { get; set; } + public string Passkey { get; set; } + public string ApiKey { get; set; } + public string RssKey { get; set; } + public string CaptchaText { get; set; } + public string CaptchaCookie { get; set; } + public string Filters { get; set; } + } +} diff --git a/src/NzbDrone.Core/Migration/JackettIndexerDefinition.cs b/src/NzbDrone.Core/Migration/JackettIndexerDefinition.cs new file mode 100644 index 000000000..cef035ff6 --- /dev/null +++ b/src/NzbDrone.Core/Migration/JackettIndexerDefinition.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace NzbDrone.Core.Migration +{ + public class JackettIndexerDefinition + { + public string Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public string Type { get; set; } + public string Configured { get; set; } + [JsonProperty("site_link")] + public string SiteLink { get; set; } + public List AlternativeSiteLinks { get; set; } + public string language { get; set; } + + //ignoring last_error, potatoenabled, caps + } +} diff --git a/src/NzbDrone.Core/Migration/JackettMigrationService.cs b/src/NzbDrone.Core/Migration/JackettMigrationService.cs new file mode 100644 index 000000000..00c60bac5 --- /dev/null +++ b/src/NzbDrone.Core/Migration/JackettMigrationService.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net.Http; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NLog; +using NzbDrone.Common.Http; + +namespace NzbDrone.Core.Migration +{ + public interface IJackettMigrationService + { + List GetJackettIndexers(string jackettPath, string jackettApi); + JackettIndexerConfigDefintion GetJackettIndexerConfig(JackettIndexerDefinition jackettIndexerDefinition, string jackettPath, string jackettApi); + void MigrateJackettIndexer(JackettIndexerDefinition jackettIndexer, JackettIndexerConfigDefintion jackettIndexerConfig); + } + + public class JackettMigrationService : IJackettMigrationService + { + private readonly Logger _logger; + public IHttpClient HttpClient { get; set; } + public IHttpRequestBuilderFactory RequestBuilder { get; set; } + public JackettMigrationService(Logger logger) + { + _logger = logger; + } + + public List GetJackettIndexers(string jackettPath, string jackettApi) + { + _logger.Info("Getting all configured Jackett Indexers"); + + var requestBuilder = BuildRequest(jackettPath, jackettApi, true); + + var jsonResponse = JsonConvert.DeserializeObject>(HttpClient.Execute(requestBuilder.Build()).Content); + + return jsonResponse; + } + + public JackettIndexerConfigDefintion GetJackettIndexerConfig(JackettIndexerDefinition jackettIndexerDefinition, string jackettPath, string jackettApi) + { + _logger.Debug($"Getting config from Jackett for {jackettIndexerDefinition.Name}"); + + var requestBuilder = BuildRequest(jackettPath, jackettApi, jackettIndexerDefinition.Id); + + var jsonResponse = JsonConvert.DeserializeObject(HttpClient.Execute(requestBuilder.Build()).Content); + + return jsonResponse; + } + + public void MigrateJackettIndexer(JackettIndexerDefinition jackettIndexer, JackettIndexerConfigDefintion jackettIndexerConfig) + { + _logger.Info($"Creating {jackettIndexer.Name} in Prowlarr"); + + //TODO: Creation Logic of indexers + } + + protected HttpRequestBuilder BuildRequest(string jackettPath, string jackettApi, bool configuredIndexers) + { + var url = jackettPath + "api/v2.0/indexers"; + var requestBuilder = new HttpRequestBuilder(url); + requestBuilder.AddQueryParam("apiKey", jackettApi); + requestBuilder.AddQueryParam("configured", configuredIndexers); + + return requestBuilder; + } + + protected HttpRequestBuilder BuildRequest(string jackettPath, string jackettApi, string indexerId) + { + var url = jackettPath + "api/v2.0/indexers/" + indexerId + "/config"; + var requestBuilder = new HttpRequestBuilder(url); + requestBuilder.AddQueryParam("apiKey", jackettApi); + + return requestBuilder; + } + } +} diff --git a/src/Prowlarr.Api.V1/Migration/MigrationController.cs b/src/Prowlarr.Api.V1/Migration/MigrationController.cs new file mode 100644 index 000000000..11a49aa92 --- /dev/null +++ b/src/Prowlarr.Api.V1/Migration/MigrationController.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using NzbDrone.Core.Migration; +using Prowlarr.Http; + +namespace Prowlarr.Api.V1.Migration +{ + [V1ApiController] + public class MigrationController : Controller + { + private readonly IJackettMigrationService _jackettMigrationService; + + public MigrationController(IJackettMigrationService jackettMigrationService) + { + _jackettMigrationService = jackettMigrationService; + } + + //TODO: Make this work with the frontend (e.g. passing params for jackettPath and jackettApi + [HttpPost("jackettmigration")] + public void JackettMigration() + { + var jackettIndexers = _jackettMigrationService.GetJackettIndexers(jackettPath, jackettApi); + + foreach (var jackettIndexer in jackettIndexers) + { + var indexerconfig = _jackettMigrationService.GetJackettIndexerConfig(jackettIndexer, jackettPath, jackettApi); + _jackettMigrationService.MigrateJackettIndexer(jackettIndexer, indexerconfig); + } + } + } +} diff --git a/src/Prowlarr.Api.V1/Migration/MigrationResource.cs b/src/Prowlarr.Api.V1/Migration/MigrationResource.cs new file mode 100644 index 000000000..10918dd4a --- /dev/null +++ b/src/Prowlarr.Api.V1/Migration/MigrationResource.cs @@ -0,0 +1,4 @@ +namespace Prowlarr.Api.V1.Migration +{ + +} diff --git a/src/Prowlarr.Http/Extensions/RequestExtensions.cs b/src/Prowlarr.Http/Extensions/RequestExtensions.cs index cf65c2480..224cf09ad 100644 --- a/src/Prowlarr.Http/Extensions/RequestExtensions.cs +++ b/src/Prowlarr.Http/Extensions/RequestExtensions.cs @@ -29,6 +29,18 @@ namespace Prowlarr.Http.Extensions return defaultValue; } + public static string GetNullableStringQueryParameter(this HttpRequest request, string parameter, string defaultValue = null) + { + var parameterValue = request.Query[parameter]; + + if (parameterValue.Any()) + { + return parameterValue.ToString(); + } + + return defaultValue; + } + public static PagingResource ReadPagingResourceFromRequest(this HttpRequest request) { if (!int.TryParse(request.Query["PageSize"].ToString(), out var pageSize))