diff --git a/src/NzbDrone.Core/Applications/ApplicationBase.cs b/src/NzbDrone.Core/Applications/ApplicationBase.cs index 9707ffb5d..9772ce1f0 100644 --- a/src/NzbDrone.Core/Applications/ApplicationBase.cs +++ b/src/NzbDrone.Core/Applications/ApplicationBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.RegularExpressions; using FluentValidation.Results; using NLog; using NzbDrone.Core.Indexers; @@ -13,6 +14,9 @@ namespace NzbDrone.Core.Applications protected readonly IAppIndexerMapService _appIndexerMapService; protected readonly Logger _logger; + protected static readonly Regex AppIndexerRegex = new Regex(@"api\/v\d*\/indexer\/(?\d*)", + RegexOptions.IgnoreCase | RegexOptions.Compiled); + public abstract string Name { get; } public Type ConfigContract => typeof(TSettings); @@ -54,6 +58,7 @@ namespace NzbDrone.Core.Applications public abstract void AddIndexer(IndexerDefinition indexer); public abstract void UpdateIndexer(IndexerDefinition indexer); public abstract void RemoveIndexer(int indexerId); + public abstract Dictionary GetIndexerMappings(); public virtual object RequestAction(string action, IDictionary query) { diff --git a/src/NzbDrone.Core/Applications/ApplicationService.cs b/src/NzbDrone.Core/Applications/ApplicationService.cs index 7926a6bf2..63665dfd7 100644 --- a/src/NzbDrone.Core/Applications/ApplicationService.cs +++ b/src/NzbDrone.Core/Applications/ApplicationService.cs @@ -111,6 +111,23 @@ namespace NzbDrone.Core.Applications { var indexerMappings = _appIndexerMapService.GetMappingsForApp(app.Definition.Id); + //Remote-Local mappings currently stored by Prowlarr + var prowlarrMappings = indexerMappings.ToDictionary(i => i.RemoteIndexerId, i => i.IndexerId); + + //Get Dictionary of Remote Indexers point to Prowlarr and what they are mapped to + var remoteMappings = app.GetIndexerMappings(); + + //Add mappings if not already in db, these were setup manually in the app or orphaned by a table wipe + foreach (var mapping in remoteMappings) + { + if (!prowlarrMappings.ContainsKey(mapping.Key)) + { + var addMapping = new AppIndexerMap { AppId = app.Definition.Id, RemoteIndexerId = mapping.Key, IndexerId = mapping.Value }; + _appIndexerMapService.Insert(addMapping); + indexerMappings.Add(addMapping); + } + } + foreach (var indexer in indexers) { var definition = indexer; diff --git a/src/NzbDrone.Core/Applications/IApplication.cs b/src/NzbDrone.Core/Applications/IApplication.cs index 27ed112ba..f947b59d8 100644 --- a/src/NzbDrone.Core/Applications/IApplication.cs +++ b/src/NzbDrone.Core/Applications/IApplication.cs @@ -9,5 +9,6 @@ namespace NzbDrone.Core.Applications void AddIndexer(IndexerDefinition indexer); void UpdateIndexer(IndexerDefinition indexer); void RemoveIndexer(int indexerId); + Dictionary GetIndexerMappings(); } } diff --git a/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs b/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs index bcbfa14f7..1bc9aad61 100644 --- a/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs +++ b/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs @@ -37,6 +37,28 @@ namespace NzbDrone.Core.Applications.Lidarr return new ValidationResult(failures); } + public override Dictionary GetIndexerMappings() + { + var indexers = _lidarrV1Proxy.GetIndexers(Settings); + var mappings = new Dictionary(); + + foreach (var indexer in indexers) + { + if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value == _configFileProvider.ApiKey) + { + var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value); + + if (match.Groups["indexer"].Success && int.TryParse(match.Groups["indexer"].Value, out var indexerId)) + { + //Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(indexer.Id, indexerId); + } + } + } + + return mappings; + } + public override void AddIndexer(IndexerDefinition indexer) { if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) @@ -69,7 +91,7 @@ namespace NzbDrone.Core.Applications.Lidarr var appMappings = _appIndexerMapService.GetMappingsForApp(Definition.Id); var indexerMapping = appMappings.FirstOrDefault(m => m.IndexerId == indexer.Id); - var readarrIndexer = BuildLidarrIndexer(indexer, indexer.Protocol, indexerMapping?.RemoteIndexerId ?? 0); + var lidarrIndexer = BuildLidarrIndexer(indexer, indexer.Protocol, indexerMapping?.RemoteIndexerId ?? 0); var remoteIndexer = _lidarrV1Proxy.GetIndexer(indexerMapping.RemoteIndexerId, Settings); @@ -77,17 +99,17 @@ namespace NzbDrone.Core.Applications.Lidarr { _logger.Debug("Remote indexer found, syncing with current settings"); - if (!readarrIndexer.Equals(remoteIndexer)) + if (!lidarrIndexer.Equals(remoteIndexer)) { - _lidarrV1Proxy.UpdateIndexer(readarrIndexer, Settings); + _lidarrV1Proxy.UpdateIndexer(lidarrIndexer, Settings); } } else { _logger.Debug("Remote indexer not found, re-adding indexer to Lidarr"); - readarrIndexer.Id = 0; + lidarrIndexer.Id = 0; - var newRemoteIndexer = _lidarrV1Proxy.AddIndexer(readarrIndexer, Settings); + var newRemoteIndexer = _lidarrV1Proxy.AddIndexer(lidarrIndexer, Settings); _appIndexerMapService.Delete(indexerMapping.Id); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = newRemoteIndexer.Id }); } diff --git a/src/NzbDrone.Core/Applications/Lidarr/LidarrV1Proxy.cs b/src/NzbDrone.Core/Applications/Lidarr/LidarrV1Proxy.cs index a0cacc605..1fbd17872 100644 --- a/src/NzbDrone.Core/Applications/Lidarr/LidarrV1Proxy.cs +++ b/src/NzbDrone.Core/Applications/Lidarr/LidarrV1Proxy.cs @@ -64,7 +64,7 @@ namespace NzbDrone.Core.Applications.Lidarr public void RemoveIndexer(int indexerId, LidarrSettings settings) { var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.DELETE); - var response = _httpClient.Execute(request); + _httpClient.Execute(request); } public List GetIndexerSchema(LidarrSettings settings) diff --git a/src/NzbDrone.Core/Applications/Radarr/Radarr.cs b/src/NzbDrone.Core/Applications/Radarr/Radarr.cs index 9f0c509c9..38d4856d7 100644 --- a/src/NzbDrone.Core/Applications/Radarr/Radarr.cs +++ b/src/NzbDrone.Core/Applications/Radarr/Radarr.cs @@ -37,6 +37,28 @@ namespace NzbDrone.Core.Applications.Radarr return new ValidationResult(failures); } + public override Dictionary GetIndexerMappings() + { + var indexers = _radarrV3Proxy.GetIndexers(Settings); + var mappings = new Dictionary(); + + foreach (var indexer in indexers) + { + if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value == _configFileProvider.ApiKey) + { + var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value); + + if (match.Groups["indexer"].Success && int.TryParse(match.Groups["indexer"].Value, out var indexerId)) + { + //Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(indexer.Id, indexerId); + } + } + } + + return mappings; + } + public override void AddIndexer(IndexerDefinition indexer) { if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) diff --git a/src/NzbDrone.Core/Applications/Radarr/RadarrV3Proxy.cs b/src/NzbDrone.Core/Applications/Radarr/RadarrV3Proxy.cs index a2f7087e5..5d53fa1ae 100644 --- a/src/NzbDrone.Core/Applications/Radarr/RadarrV3Proxy.cs +++ b/src/NzbDrone.Core/Applications/Radarr/RadarrV3Proxy.cs @@ -64,7 +64,7 @@ namespace NzbDrone.Core.Applications.Radarr public void RemoveIndexer(int indexerId, RadarrSettings settings) { var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.DELETE); - var response = _httpClient.Execute(request); + _httpClient.Execute(request); } public List GetIndexerSchema(RadarrSettings settings) diff --git a/src/NzbDrone.Core/Applications/Readarr/Readarr.cs b/src/NzbDrone.Core/Applications/Readarr/Readarr.cs index c91be7b8f..36b57c564 100644 --- a/src/NzbDrone.Core/Applications/Readarr/Readarr.cs +++ b/src/NzbDrone.Core/Applications/Readarr/Readarr.cs @@ -37,6 +37,28 @@ namespace NzbDrone.Core.Applications.Readarr return new ValidationResult(failures); } + public override Dictionary GetIndexerMappings() + { + var indexers = _readarrV1Proxy.GetIndexers(Settings); + var mappings = new Dictionary(); + + foreach (var indexer in indexers) + { + if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value == _configFileProvider.ApiKey) + { + var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value); + + if (match.Groups["indexer"].Success && int.TryParse(match.Groups["indexer"].Value, out var indexerId)) + { + //Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(indexer.Id, indexerId); + } + } + } + + return mappings; + } + public override void AddIndexer(IndexerDefinition indexer) { if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) diff --git a/src/NzbDrone.Core/Applications/Readarr/ReadarrV1Proxy.cs b/src/NzbDrone.Core/Applications/Readarr/ReadarrV1Proxy.cs index eaffae394..f4e63aee5 100644 --- a/src/NzbDrone.Core/Applications/Readarr/ReadarrV1Proxy.cs +++ b/src/NzbDrone.Core/Applications/Readarr/ReadarrV1Proxy.cs @@ -64,7 +64,7 @@ namespace NzbDrone.Core.Applications.Readarr public void RemoveIndexer(int indexerId, ReadarrSettings settings) { var request = BuildRequest(settings, $"/api/v1/indexer/{indexerId}", HttpMethod.DELETE); - var response = _httpClient.Execute(request); + _httpClient.Execute(request); } public List GetIndexerSchema(ReadarrSettings settings) diff --git a/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs b/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs index 0920aa02b..51a140da3 100644 --- a/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs +++ b/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs @@ -37,6 +37,28 @@ namespace NzbDrone.Core.Applications.Sonarr return new ValidationResult(failures); } + public override Dictionary GetIndexerMappings() + { + var indexers = _sonarrV3Proxy.GetIndexers(Settings); + var mappings = new Dictionary(); + + foreach (var indexer in indexers) + { + if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey").Value == _configFileProvider.ApiKey) + { + var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value); + + if (match.Groups["indexer"].Success && int.TryParse(match.Groups["indexer"].Value, out var indexerId)) + { + //Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(indexer.Id, indexerId); + } + } + } + + return mappings; + } + public override void AddIndexer(IndexerDefinition indexer) { if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) diff --git a/src/NzbDrone.Core/Applications/Sonarr/SonarrV3Proxy.cs b/src/NzbDrone.Core/Applications/Sonarr/SonarrV3Proxy.cs index 2d8779db1..67f612bc2 100644 --- a/src/NzbDrone.Core/Applications/Sonarr/SonarrV3Proxy.cs +++ b/src/NzbDrone.Core/Applications/Sonarr/SonarrV3Proxy.cs @@ -64,7 +64,7 @@ namespace NzbDrone.Core.Applications.Sonarr public void RemoveIndexer(int indexerId, SonarrSettings settings) { var request = BuildRequest(settings, $"/api/v3/indexer/{indexerId}", HttpMethod.DELETE); - var response = _httpClient.Execute(request); + _httpClient.Execute(request); } public List GetIndexerSchema(SonarrSettings settings)