diff --git a/src/NzbDrone.Core/Applications/ApplicationBase.cs b/src/NzbDrone.Core/Applications/ApplicationBase.cs index cb31fc7d8..82fb56d86 100644 --- a/src/NzbDrone.Core/Applications/ApplicationBase.cs +++ b/src/NzbDrone.Core/Applications/ApplicationBase.cs @@ -14,8 +14,7 @@ namespace NzbDrone.Core.Applications protected readonly IAppIndexerMapService _appIndexerMapService; protected readonly Logger _logger; - protected static readonly Regex AppIndexerRegex = new Regex(@"\/(?\d{1,3})(?:\/(?:api)?\/?)?$", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + protected static readonly Regex AppIndexerRegex = new (@"\/(?\d{1,3})(?:\/(?:api)?\/?)?$", RegexOptions.IgnoreCase | RegexOptions.Compiled); public abstract string Name { get; } diff --git a/src/NzbDrone.Core/Applications/ApplicationService.cs b/src/NzbDrone.Core/Applications/ApplicationService.cs index a6a20f5dc..c26ea4672 100644 --- a/src/NzbDrone.Core/Applications/ApplicationService.cs +++ b/src/NzbDrone.Core/Applications/ApplicationService.cs @@ -90,8 +90,8 @@ namespace NzbDrone.Core.Applications public void HandleAsync(ProviderUpdatedEvent message) { var enabledApps = _applicationsFactory.SyncEnabled() - .Where(n => ((ApplicationDefinition)n.Definition).SyncLevel == ApplicationSyncLevel.FullSync) - .ToList(); + .Where(n => ((ApplicationDefinition)n.Definition).SyncLevel == ApplicationSyncLevel.FullSync) + .ToList(); SyncIndexers(enabledApps, new List { (IndexerDefinition)message.Definition }); } @@ -181,7 +181,7 @@ namespace NzbDrone.Core.Applications foreach (var mapping in indexerMappings) { - if (!allIndexers.Any(x => x.Id == mapping.IndexerId)) + if (allIndexers.All(x => x.Id != mapping.IndexerId)) { _logger.Info("Indexer with the ID {0} was found within {1} but is no longer defined within Prowlarr, this is being removed.", mapping.IndexerId, app.Name); ExecuteAction(a => a.RemoveIndexer(mapping.IndexerId), app); @@ -195,17 +195,19 @@ namespace NzbDrone.Core.Applications { if (app.Tags.Empty()) { - _logger.Debug("No tags set for this application."); + _logger.Debug("No tags set to application {0}.", app.Name); return true; } - if (app.Tags.Intersect(indexer.Tags).Any()) + var intersectingTags = app.Tags.Intersect(indexer.Tags).ToArray(); + + if (intersectingTags.Any()) { - _logger.Debug("Application and indexer have one or more intersecting tags."); + _logger.Debug("Application {0} and indexer {1} [{2}] have {3} intersecting tags.", app.Name, indexer.Name, indexer.Id, intersectingTags.Length); return true; } - _logger.Debug("{0} does not have any intersecting tags with {1}. Indexer will not be synced", app.Name, indexer.Name); + _logger.Debug("Application {0} does not have any intersecting tags with {1} [{2}]. Indexer will not be synced.", app.Name, indexer.Name, indexer.Id); return false; } @@ -240,14 +242,8 @@ namespace NzbDrone.Core.Applications } catch (TooManyRequestsException ex) { - if (ex.RetryAfter != TimeSpan.Zero) - { - _applicationStatusService.RecordFailure(application.Definition.Id, ex.RetryAfter); - } - else - { - _applicationStatusService.RecordFailure(application.Definition.Id, TimeSpan.FromHours(1)); - } + var minimumBackOff = ex.RetryAfter != TimeSpan.Zero ? ex.RetryAfter : TimeSpan.FromHours(1); + _applicationStatusService.RecordFailure(application.Definition.Id, minimumBackOff); _logger.Warn("API Request Limit reached for {0}", this); } @@ -265,11 +261,9 @@ namespace NzbDrone.Core.Applications private TResult ExecuteAction(Func applicationAction, IApplication application) { - TResult result; - try { - result = applicationAction(application); + var result = applicationAction(application); _applicationStatusService.RecordSuccess(application.Definition.Id); return result; } @@ -297,14 +291,8 @@ namespace NzbDrone.Core.Applications } catch (TooManyRequestsException ex) { - if (ex.RetryAfter != TimeSpan.Zero) - { - _applicationStatusService.RecordFailure(application.Definition.Id, ex.RetryAfter); - } - else - { - _applicationStatusService.RecordFailure(application.Definition.Id, TimeSpan.FromHours(1)); - } + var minimumBackOff = ex.RetryAfter != TimeSpan.Zero ? ex.RetryAfter : TimeSpan.FromHours(1); + _applicationStatusService.RecordFailure(application.Definition.Id, minimumBackOff); _logger.Warn("API Request Limit reached for {0}", this); } diff --git a/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs b/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs index da68d6d0c..e965d12b4 100644 --- a/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs +++ b/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Net; using FluentValidation.Results; using NLog; -using NzbDrone.Common.Cache; using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; using NzbDrone.Core.Indexers; @@ -56,8 +55,8 @@ namespace NzbDrone.Core.Applications.LazyLibrarian 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(new AppIndexerMap { RemoteIndexerName = $"{indexer.Type},{indexer.Name}", IndexerId = indexerId }); + // Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(new AppIndexerMap { IndexerId = indexerId, RemoteIndexerName = $"{indexer.Type},{indexer.Name}" }); } } } @@ -67,15 +66,19 @@ namespace NzbDrone.Core.Applications.LazyLibrarian public override void AddIndexer(IndexerDefinition indexer) { - if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) + if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty()) { - var lazyLibrarianIndexer = BuildLazyLibrarianIndexer(indexer, indexer.Protocol); + _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); - var remoteIndexer = _lazyLibrarianV1Proxy.AddIndexer(lazyLibrarianIndexer, Settings); - _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerName = $"{remoteIndexer.Type},{remoteIndexer.Name}" }); + return; } - _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); + _logger.Trace("Adding indexer {0} [{1}]", indexer.Name, indexer.Id); + + var lazyLibrarianIndexer = BuildLazyLibrarianIndexer(indexer, indexer.Protocol); + + var remoteIndexer = _lazyLibrarianV1Proxy.AddIndexer(lazyLibrarianIndexer, Settings); + _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerName = $"{remoteIndexer.Type},{remoteIndexer.Name}" }); } public override void RemoveIndexer(int indexerId) @@ -123,13 +126,13 @@ namespace NzbDrone.Core.Applications.LazyLibrarian if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - _logger.Debug("Remote indexer not found, re-adding {0} to LazyLibrarian", indexer.Name); + _logger.Debug("Remote indexer not found, re-adding {0} [{1}] to LazyLibrarian", indexer.Name, indexer.Id); var newRemoteIndexer = _lazyLibrarianV1Proxy.AddIndexer(lazyLibrarianIndexer, Settings); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerName = $"{newRemoteIndexer.Type},{newRemoteIndexer.Name}" }); } else { - _logger.Debug("Remote indexer not found for {0}, skipping re-add to LazyLibrarian due to indexer capabilities", indexer.Name); + _logger.Debug("Remote indexer not found for {0} [{1}], skipping re-add to LazyLibrarian due to indexer capabilities", indexer.Name, indexer.Id); } } } diff --git a/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs b/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs index 503f3f097..30965e6ca 100644 --- a/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs +++ b/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Applications.Lidarr public override List GetIndexerMappings() { var indexers = _lidarrV1Proxy.GetIndexers(Settings) - .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); + .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); var mappings = new List(); @@ -73,8 +73,8 @@ namespace NzbDrone.Core.Applications.Lidarr 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(new AppIndexerMap { RemoteIndexerId = indexer.Id, IndexerId = indexerId }); + // Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(new AppIndexerMap { IndexerId = indexerId, RemoteIndexerId = indexer.Id }); } } } @@ -84,15 +84,19 @@ namespace NzbDrone.Core.Applications.Lidarr public override void AddIndexer(IndexerDefinition indexer) { - if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) + if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty()) { - var lidarrIndexer = BuildLidarrIndexer(indexer, indexer.Protocol); + _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); - var remoteIndexer = _lidarrV1Proxy.AddIndexer(lidarrIndexer, Settings); - _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); + return; } - _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); + _logger.Trace("Adding indexer {0} [{1}]", indexer.Name, indexer.Id); + + var lidarrIndexer = BuildLidarrIndexer(indexer, indexer.Protocol); + + var remoteIndexer = _lidarrV1Proxy.AddIndexer(lidarrIndexer, Settings); + _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); } public override void RemoveIndexer(int indexerId) @@ -129,7 +133,10 @@ namespace NzbDrone.Core.Applications.Lidarr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { // Retain user fields not-affiliated with Prowlarr - lidarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => !lidarrIndexer.Fields.Any(s => s.Name == f.Name))); + lidarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => lidarrIndexer.Fields.All(s => s.Name != f.Name))); + + // Retain user tags not-affiliated with Prowlarr + lidarrIndexer.Tags.UnionWith(remoteIndexer.Tags); // Retain user settings not-affiliated with Prowlarr lidarrIndexer.DownloadClientId = remoteIndexer.DownloadClientId; @@ -151,14 +158,14 @@ namespace NzbDrone.Core.Applications.Lidarr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - _logger.Debug("Remote indexer not found, re-adding {0} to Lidarr", indexer.Name); + _logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Lidarr", indexer.Name, indexer.Id); lidarrIndexer.Id = 0; var newRemoteIndexer = _lidarrV1Proxy.AddIndexer(lidarrIndexer, Settings); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = newRemoteIndexer.Id }); } else { - _logger.Debug("Remote indexer not found for {0}, skipping re-add to Lidarr due to indexer capabilities", indexer.Name); + _logger.Debug("Remote indexer not found for {0} [{1}], skipping re-add to Lidarr due to indexer capabilities", indexer.Name, indexer.Id); } } } @@ -167,10 +174,10 @@ namespace NzbDrone.Core.Applications.Lidarr { var cacheKey = $"{Settings.BaseUrl}"; var schemas = _schemaCache.Get(cacheKey, () => _lidarrV1Proxy.GetIndexerSchema(Settings), TimeSpan.FromDays(7)); - var syncFields = new string[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime", "seedCriteria.discographySeedTime" }; + var syncFields = new[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime", "seedCriteria.discographySeedTime" }; - var newznab = schemas.Where(i => i.Implementation == "Newznab").First(); - var torznab = schemas.Where(i => i.Implementation == "Torznab").First(); + var newznab = schemas.First(i => i.Implementation == "Newznab"); + var torznab = schemas.First(i => i.Implementation == "Torznab"); var schema = protocol == DownloadProtocol.Usenet ? newznab : torznab; @@ -184,7 +191,8 @@ namespace NzbDrone.Core.Applications.Lidarr Priority = indexer.Priority, Implementation = indexer.Protocol == DownloadProtocol.Usenet ? "Newznab" : "Torznab", ConfigContract = schema.ConfigContract, - Fields = new List() + Fields = new List(), + Tags = new HashSet() }; lidarrIndexer.Fields.AddRange(schema.Fields.Where(x => syncFields.Contains(x.Name))); diff --git a/src/NzbDrone.Core/Applications/Mylar/Mylar.cs b/src/NzbDrone.Core/Applications/Mylar/Mylar.cs index 69c92b949..052a96ff1 100644 --- a/src/NzbDrone.Core/Applications/Mylar/Mylar.cs +++ b/src/NzbDrone.Core/Applications/Mylar/Mylar.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; using FluentValidation.Results; -using Newtonsoft.Json.Linq; using NLog; -using NzbDrone.Common.Cache; using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; using NzbDrone.Core.Indexers; @@ -57,8 +55,8 @@ namespace NzbDrone.Core.Applications.Mylar 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(new AppIndexerMap { RemoteIndexerName = $"{indexer.Type},{indexer.Name}", IndexerId = indexerId }); + // Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(new AppIndexerMap { IndexerId = indexerId, RemoteIndexerName = $"{indexer.Type},{indexer.Name}" }); } } } @@ -68,15 +66,19 @@ namespace NzbDrone.Core.Applications.Mylar public override void AddIndexer(IndexerDefinition indexer) { - if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) + if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty()) { - var mylarIndexer = BuildMylarIndexer(indexer, indexer.Protocol); + _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); - var remoteIndexer = _mylarV3Proxy.AddIndexer(mylarIndexer, Settings); - _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerName = $"{remoteIndexer.Type},{remoteIndexer.Name}" }); + return; } - _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); + _logger.Trace("Adding indexer {0} [{1}]", indexer.Name, indexer.Id); + + var mylarIndexer = BuildMylarIndexer(indexer, indexer.Protocol); + + var remoteIndexer = _mylarV3Proxy.AddIndexer(mylarIndexer, Settings); + _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerName = $"{remoteIndexer.Type},{remoteIndexer.Name}" }); } public override void RemoveIndexer(int indexerId) @@ -124,13 +126,13 @@ namespace NzbDrone.Core.Applications.Mylar if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - _logger.Debug("Remote indexer not found, re-adding {0} to Mylar", indexer.Name); + _logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Mylar", indexer.Name, indexer.Id); var newRemoteIndexer = _mylarV3Proxy.AddIndexer(mylarIndexer, Settings); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerName = $"{newRemoteIndexer.Type},{newRemoteIndexer.Name}" }); } else { - _logger.Debug("Remote indexer not found for {0}, skipping re-add to Mylar due to indexer capabilities", indexer.Name); + _logger.Debug("Remote indexer not found for {0} [{1}], skipping re-add to Mylar due to indexer capabilities", indexer.Name, indexer.Id); } } } diff --git a/src/NzbDrone.Core/Applications/Radarr/Radarr.cs b/src/NzbDrone.Core/Applications/Radarr/Radarr.cs index 298b93041..41e0799ee 100644 --- a/src/NzbDrone.Core/Applications/Radarr/Radarr.cs +++ b/src/NzbDrone.Core/Applications/Radarr/Radarr.cs @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Applications.Radarr public override List GetIndexerMappings() { var indexers = _radarrV3Proxy.GetIndexers(Settings) - .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); + .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); var mappings = new List(); @@ -73,8 +73,8 @@ namespace NzbDrone.Core.Applications.Radarr 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(new AppIndexerMap { RemoteIndexerId = indexer.Id, IndexerId = indexerId }); + // Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(new AppIndexerMap { IndexerId = indexerId, RemoteIndexerId = indexer.Id }); } } } @@ -84,15 +84,19 @@ namespace NzbDrone.Core.Applications.Radarr public override void AddIndexer(IndexerDefinition indexer) { - if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) + if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty()) { - var radarrIndexer = BuildRadarrIndexer(indexer, indexer.Protocol); + _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); - var remoteIndexer = _radarrV3Proxy.AddIndexer(radarrIndexer, Settings); - _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); + return; } - _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); + _logger.Trace("Adding indexer {0} [{1}]", indexer.Name, indexer.Id); + + var radarrIndexer = BuildRadarrIndexer(indexer, indexer.Protocol); + + var remoteIndexer = _radarrV3Proxy.AddIndexer(radarrIndexer, Settings); + _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); } public override void RemoveIndexer(int indexerId) @@ -129,7 +133,10 @@ namespace NzbDrone.Core.Applications.Radarr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { // Retain user fields not-affiliated with Prowlarr - radarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => !radarrIndexer.Fields.Any(s => s.Name == f.Name))); + radarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => radarrIndexer.Fields.All(s => s.Name != f.Name))); + + // Retain user tags not-affiliated with Prowlarr + radarrIndexer.Tags.UnionWith(remoteIndexer.Tags); // Retain user settings not-affiliated with Prowlarr radarrIndexer.DownloadClientId = remoteIndexer.DownloadClientId; @@ -151,14 +158,14 @@ namespace NzbDrone.Core.Applications.Radarr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - _logger.Debug("Remote indexer not found, re-adding {0} to Radarr", indexer.Name); + _logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Radarr", indexer.Name, indexer.Id); radarrIndexer.Id = 0; var newRemoteIndexer = _radarrV3Proxy.AddIndexer(radarrIndexer, Settings); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = newRemoteIndexer.Id }); } else { - _logger.Debug("Remote indexer not found for {0}, skipping re-add to Radarr due to indexer capabilities", indexer.Name); + _logger.Debug("Remote indexer not found for {0} [{1}], skipping re-add to Radarr due to indexer capabilities", indexer.Name, indexer.Id); } } } @@ -167,10 +174,10 @@ namespace NzbDrone.Core.Applications.Radarr { var cacheKey = $"{Settings.BaseUrl}"; var schemas = _schemaCache.Get(cacheKey, () => _radarrV3Proxy.GetIndexerSchema(Settings), TimeSpan.FromDays(7)); - var syncFields = new string[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime" }; + var syncFields = new[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime" }; - var newznab = schemas.Where(i => i.Implementation == "Newznab").First(); - var torznab = schemas.Where(i => i.Implementation == "Torznab").First(); + var newznab = schemas.First(i => i.Implementation == "Newznab"); + var torznab = schemas.First(i => i.Implementation == "Torznab"); var schema = protocol == DownloadProtocol.Usenet ? newznab : torznab; @@ -184,7 +191,8 @@ namespace NzbDrone.Core.Applications.Radarr Priority = indexer.Priority, Implementation = indexer.Protocol == DownloadProtocol.Usenet ? "Newznab" : "Torznab", ConfigContract = schema.ConfigContract, - Fields = new List() + Fields = new List(), + Tags = new HashSet() }; radarrIndexer.Fields.AddRange(schema.Fields.Where(x => syncFields.Contains(x.Name))); diff --git a/src/NzbDrone.Core/Applications/Readarr/Readarr.cs b/src/NzbDrone.Core/Applications/Readarr/Readarr.cs index f0c45a38d..5349324f8 100644 --- a/src/NzbDrone.Core/Applications/Readarr/Readarr.cs +++ b/src/NzbDrone.Core/Applications/Readarr/Readarr.cs @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Applications.Readarr public override List GetIndexerMappings() { var indexers = _readarrV1Proxy.GetIndexers(Settings) - .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); + .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); var mappings = new List(); @@ -73,8 +73,8 @@ namespace NzbDrone.Core.Applications.Readarr 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(new AppIndexerMap { RemoteIndexerId = indexer.Id, IndexerId = indexerId }); + // Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(new AppIndexerMap { IndexerId = indexerId, RemoteIndexerId = indexer.Id }); } } } @@ -84,15 +84,19 @@ namespace NzbDrone.Core.Applications.Readarr public override void AddIndexer(IndexerDefinition indexer) { - if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) + if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty()) { - var readarrIndexer = BuildReadarrIndexer(indexer, indexer.Protocol); + _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); - var remoteIndexer = _readarrV1Proxy.AddIndexer(readarrIndexer, Settings); - _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); + return; } - _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); + _logger.Trace("Adding indexer {0} [{1}]", indexer.Name, indexer.Id); + + var readarrIndexer = BuildReadarrIndexer(indexer, indexer.Protocol); + + var remoteIndexer = _readarrV1Proxy.AddIndexer(readarrIndexer, Settings); + _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); } public override void RemoveIndexer(int indexerId) @@ -128,7 +132,11 @@ namespace NzbDrone.Core.Applications.Readarr { if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - readarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => !readarrIndexer.Fields.Any(s => s.Name == f.Name))); + // Retain user fields not-affiliated with Prowlarr + readarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => readarrIndexer.Fields.All(s => s.Name != f.Name))); + + // Retain user tags not-affiliated with Prowlarr + readarrIndexer.Tags.UnionWith(remoteIndexer.Tags); // Update the indexer if it still has categories that match _readarrV1Proxy.UpdateIndexer(readarrIndexer, Settings); @@ -147,14 +155,14 @@ namespace NzbDrone.Core.Applications.Readarr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - _logger.Debug("Remote indexer not found, re-adding {0} to Readarr", indexer.Name); + _logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Readarr", indexer.Name, indexer.Id); readarrIndexer.Id = 0; var newRemoteIndexer = _readarrV1Proxy.AddIndexer(readarrIndexer, Settings); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = newRemoteIndexer.Id }); } else { - _logger.Debug("Remote indexer not found for {0}, skipping re-add to Readarr due to indexer capabilities", indexer.Name); + _logger.Debug("Remote indexer not found for {0} [{1}], skipping re-add to Readarr due to indexer capabilities", indexer.Name, indexer.Id); } } } @@ -163,10 +171,10 @@ namespace NzbDrone.Core.Applications.Readarr { var cacheKey = $"{Settings.BaseUrl}"; var schemas = _schemaCache.Get(cacheKey, () => _readarrV1Proxy.GetIndexerSchema(Settings), TimeSpan.FromDays(7)); - var syncFields = new string[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime", "seedCriteria.discographySeedTime" }; + var syncFields = new[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime", "seedCriteria.discographySeedTime" }; - var newznab = schemas.Where(i => i.Implementation == "Newznab").First(); - var torznab = schemas.Where(i => i.Implementation == "Torznab").First(); + var newznab = schemas.First(i => i.Implementation == "Newznab"); + var torznab = schemas.First(i => i.Implementation == "Torznab"); var schema = protocol == DownloadProtocol.Usenet ? newznab : torznab; @@ -180,7 +188,8 @@ namespace NzbDrone.Core.Applications.Readarr Priority = indexer.Priority, Implementation = indexer.Protocol == DownloadProtocol.Usenet ? "Newznab" : "Torznab", ConfigContract = schema.ConfigContract, - Fields = new List() + Fields = new List(), + Tags = new HashSet() }; readarrIndexer.Fields.AddRange(schema.Fields.Where(x => syncFields.Contains(x.Name))); diff --git a/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs b/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs index 7149cc663..d079bf0c5 100644 --- a/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs +++ b/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Applications.Sonarr public override List GetIndexerMappings() { var indexers = _sonarrV3Proxy.GetIndexers(Settings) - .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); + .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); var mappings = new List(); @@ -73,8 +73,8 @@ namespace NzbDrone.Core.Applications.Sonarr 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(new AppIndexerMap { RemoteIndexerId = indexer.Id, IndexerId = indexerId }); + // Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(new AppIndexerMap { IndexerId = indexerId, RemoteIndexerId = indexer.Id }); } } } @@ -84,15 +84,20 @@ namespace NzbDrone.Core.Applications.Sonarr public override void AddIndexer(IndexerDefinition indexer) { - if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexer.Capabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any()) + if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty() && + indexer.Capabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Empty()) { - var sonarrIndexer = BuildSonarrIndexer(indexer, indexer.Protocol); + _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); - var remoteIndexer = _sonarrV3Proxy.AddIndexer(sonarrIndexer, Settings); - _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); + return; } - _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); + _logger.Trace("Adding indexer {0} [{1}]", indexer.Name, indexer.Id); + + var sonarrIndexer = BuildSonarrIndexer(indexer, indexer.Protocol); + + var remoteIndexer = _sonarrV3Proxy.AddIndexer(sonarrIndexer, Settings); + _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); } public override void RemoveIndexer(int indexerId) @@ -129,7 +134,10 @@ namespace NzbDrone.Core.Applications.Sonarr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexer.Capabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any()) { // Retain user fields not-affiliated with Prowlarr - sonarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => !sonarrIndexer.Fields.Any(s => s.Name == f.Name))); + sonarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => sonarrIndexer.Fields.All(s => s.Name != f.Name))); + + // Retain user tags not-affiliated with Prowlarr + sonarrIndexer.Tags.UnionWith(remoteIndexer.Tags); // Retain user settings not-affiliated with Prowlarr sonarrIndexer.DownloadClientId = remoteIndexer.DownloadClientId; @@ -152,14 +160,14 @@ namespace NzbDrone.Core.Applications.Sonarr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexer.Capabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any()) { - _logger.Debug("Remote indexer not found, re-adding {0} to Sonarr", indexer.Name); + _logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Sonarr", indexer.Name, indexer.Id); sonarrIndexer.Id = 0; var newRemoteIndexer = _sonarrV3Proxy.AddIndexer(sonarrIndexer, Settings); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = newRemoteIndexer.Id }); } else { - _logger.Debug("Remote indexer not found for {0}, skipping re-add to Sonarr due to indexer capabilities", indexer.Name); + _logger.Debug("Remote indexer not found for {0} [{1}], skipping re-add to Sonarr due to indexer capabilities", indexer.Name, indexer.Id); } } } @@ -168,10 +176,10 @@ namespace NzbDrone.Core.Applications.Sonarr { var cacheKey = $"{Settings.BaseUrl}"; var schemas = _schemaCache.Get(cacheKey, () => _sonarrV3Proxy.GetIndexerSchema(Settings), TimeSpan.FromDays(7)); - var syncFields = new string[] { "baseUrl", "apiPath", "apiKey", "categories", "animeCategories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime", "seedCriteria.seasonPackSeedTime" }; + var syncFields = new[] { "baseUrl", "apiPath", "apiKey", "categories", "animeCategories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime", "seedCriteria.seasonPackSeedTime" }; - var newznab = schemas.Where(i => i.Implementation == "Newznab").First(); - var torznab = schemas.Where(i => i.Implementation == "Torznab").First(); + var newznab = schemas.First(i => i.Implementation == "Newznab"); + var torznab = schemas.First(i => i.Implementation == "Torznab"); var schema = protocol == DownloadProtocol.Usenet ? newznab : torznab; @@ -185,7 +193,8 @@ namespace NzbDrone.Core.Applications.Sonarr Priority = indexer.Priority, Implementation = indexer.Protocol == DownloadProtocol.Usenet ? "Newznab" : "Torznab", ConfigContract = schema.ConfigContract, - Fields = new List() + Fields = new List(), + Tags = new HashSet() }; sonarrIndexer.Fields.AddRange(schema.Fields.Where(x => syncFields.Contains(x.Name))); diff --git a/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs b/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs index b1a58cfb9..6d16318ed 100644 --- a/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs +++ b/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Applications.Whisparr public override List GetIndexerMappings() { var indexers = _whisparrV3Proxy.GetIndexers(Settings) - .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); + .Where(i => i.Implementation == "Newznab" || i.Implementation == "Torznab"); var mappings = new List(); @@ -73,8 +73,8 @@ namespace NzbDrone.Core.Applications.Whisparr 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(new AppIndexerMap { RemoteIndexerId = indexer.Id, IndexerId = indexerId }); + // Add parsed mapping if it's mapped to a Indexer in this Prowlarr instance + mappings.Add(new AppIndexerMap { IndexerId = indexerId, RemoteIndexerId = indexer.Id }); } } } @@ -84,15 +84,19 @@ namespace NzbDrone.Core.Applications.Whisparr public override void AddIndexer(IndexerDefinition indexer) { - if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) + if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty()) { - var radarrIndexer = BuildWhisparrIndexer(indexer, indexer.Protocol); + _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); - var remoteIndexer = _whisparrV3Proxy.AddIndexer(radarrIndexer, Settings); - _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); + return; } - _logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id); + _logger.Trace("Adding indexer {0} [{1}]", indexer.Name, indexer.Id); + + var whisparrIndexer = BuildWhisparrIndexer(indexer, indexer.Protocol); + + var remoteIndexer = _whisparrV3Proxy.AddIndexer(whisparrIndexer, Settings); + _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = remoteIndexer.Id }); } public override void RemoveIndexer(int indexerId) @@ -128,7 +132,11 @@ namespace NzbDrone.Core.Applications.Whisparr { if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - whisparrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => !whisparrIndexer.Fields.Any(s => s.Name == f.Name))); + // Retain user fields not-affiliated with Prowlarr + whisparrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => whisparrIndexer.Fields.All(s => s.Name != f.Name))); + + // Retain user tags not-affiliated with Prowlarr + whisparrIndexer.Tags.UnionWith(remoteIndexer.Tags); // Update the indexer if it still has categories that match _whisparrV3Proxy.UpdateIndexer(whisparrIndexer, Settings); @@ -147,14 +155,14 @@ namespace NzbDrone.Core.Applications.Whisparr if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any()) { - _logger.Debug("Remote indexer not found, re-adding {0} to Whisparr", indexer.Name); + _logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Whisparr", indexer.Name, indexer.Id); whisparrIndexer.Id = 0; var newRemoteIndexer = _whisparrV3Proxy.AddIndexer(whisparrIndexer, Settings); _appIndexerMapService.Insert(new AppIndexerMap { AppId = Definition.Id, IndexerId = indexer.Id, RemoteIndexerId = newRemoteIndexer.Id }); } else { - _logger.Debug("Remote indexer not found for {0}, skipping re-add to Radarr due to indexer capabilities", indexer.Name); + _logger.Debug("Remote indexer not found for {0} [{1}], skipping re-add to Whisparr due to indexer capabilities", indexer.Name, indexer.Id); } } } @@ -163,10 +171,10 @@ namespace NzbDrone.Core.Applications.Whisparr { var cacheKey = $"{Settings.BaseUrl}"; var schemas = _schemaCache.Get(cacheKey, () => _whisparrV3Proxy.GetIndexerSchema(Settings), TimeSpan.FromDays(7)); - var syncFields = new string[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime" }; + var syncFields = new[] { "baseUrl", "apiPath", "apiKey", "categories", "minimumSeeders", "seedCriteria.seedRatio", "seedCriteria.seedTime" }; - var newznab = schemas.Where(i => i.Implementation == "Newznab").First(); - var torznab = schemas.Where(i => i.Implementation == "Torznab").First(); + var newznab = schemas.First(i => i.Implementation == "Newznab"); + var torznab = schemas.First(i => i.Implementation == "Torznab"); var schema = protocol == DownloadProtocol.Usenet ? newznab : torznab; @@ -180,7 +188,8 @@ namespace NzbDrone.Core.Applications.Whisparr Priority = indexer.Priority, Implementation = indexer.Protocol == DownloadProtocol.Usenet ? "Newznab" : "Torznab", ConfigContract = schema.ConfigContract, - Fields = new List() + Fields = new List(), + Tags = new HashSet() }; whisparrIndexer.Fields.AddRange(schema.Fields.Where(x => syncFields.Contains(x.Name)));