diff --git a/frontend/src/App/AppRoutes.js b/frontend/src/App/AppRoutes.js
index 8bf97249c..f7a578da2 100644
--- a/frontend/src/App/AppRoutes.js
+++ b/frontend/src/App/AppRoutes.js
@@ -7,7 +7,7 @@ import HistoryConnector from 'History/HistoryConnector';
import IndexerIndex from 'Indexer/Index/IndexerIndex';
import IndexerStats from 'Indexer/Stats/IndexerStats';
import SearchIndexConnector from 'Search/SearchIndexConnector';
-import ApplicationSettingsConnector from 'Settings/Applications/ApplicationSettingsConnector';
+import ApplicationSettings from 'Settings/Applications/ApplicationSettings';
import DevelopmentSettingsConnector from 'Settings/Development/DevelopmentSettingsConnector';
import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector';
@@ -98,7 +98,7 @@ function AppRoutes(props) {
,
AppSectionDeleteState,
- AppSectionSaveState {}
+ AppSectionSaveState {
+ isTestingAll: boolean;
+}
export interface DownloadClientAppState
extends AppSectionState,
diff --git a/frontend/src/Indexer/Index/IndexerIndex.tsx b/frontend/src/Indexer/Index/IndexerIndex.tsx
index 93bb2cd5e..644c81493 100644
--- a/frontend/src/Indexer/Index/IndexerIndex.tsx
+++ b/frontend/src/Indexer/Index/IndexerIndex.tsx
@@ -45,9 +45,7 @@ import IndexerIndexTable from './Table/IndexerIndexTable';
import IndexerIndexTableOptions from './Table/IndexerIndexTableOptions';
import styles from './IndexerIndex.css';
-function getViewComponent() {
- return IndexerIndexTable;
-}
+const getViewComponent = () => IndexerIndexTable;
interface IndexerIndexProps {
initialScrollTop?: number;
@@ -84,14 +82,6 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
);
const [isSelectMode, setIsSelectMode] = useState(false);
- const onAppIndexerSyncPress = useCallback(() => {
- dispatch(
- executeCommand({
- name: APP_INDEXER_SYNC,
- })
- );
- }, [dispatch]);
-
const onAddIndexerPress = useCallback(() => {
setIsAddIndexerModalOpen(true);
}, [setIsAddIndexerModalOpen]);
@@ -108,6 +98,15 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
setIsEditIndexerModalOpen(false);
}, [setIsEditIndexerModalOpen]);
+ const onAppIndexerSyncPress = useCallback(() => {
+ dispatch(
+ executeCommand({
+ name: APP_INDEXER_SYNC,
+ forceSync: true,
+ })
+ );
+ }, [dispatch]);
+
const onTestAllPress = useCallback(() => {
dispatch(testAllIndexers());
}, [dispatch]);
diff --git a/frontend/src/Settings/Applications/ApplicationSettings.js b/frontend/src/Settings/Applications/ApplicationSettings.js
deleted file mode 100644
index d06b7fb65..000000000
--- a/frontend/src/Settings/Applications/ApplicationSettings.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component, Fragment } from 'react';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
-import { icons } from 'Helpers/Props';
-import AppProfilesConnector from 'Settings/Profiles/App/AppProfilesConnector';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import translate from 'Utilities/String/translate';
-import ApplicationsConnector from './Applications/ApplicationsConnector';
-import ManageApplicationsModal from './Applications/Manage/ManageApplicationsModal';
-
-class ApplicationSettings extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isManageApplicationsOpen: false
- };
- }
-
- //
- // Listeners
-
- onManageApplicationsPress = () => {
- this.setState({ isManageApplicationsOpen: true });
- };
-
- onManageApplicationsModalClose = () => {
- this.setState({ isManageApplicationsOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- isTestingAll,
- isSyncingIndexers,
- onTestAllPress,
- onAppIndexerSyncPress
- } = this.props;
-
- const { isManageApplicationsOpen } = this.state;
-
- return (
-
-
-
-
-
-
-
-
-
-
- }
- />
-
-
-
-
-
-
-
-
- );
- }
-}
-
-ApplicationSettings.propTypes = {
- isTestingAll: PropTypes.bool.isRequired,
- isSyncingIndexers: PropTypes.bool.isRequired,
- onTestAllPress: PropTypes.func.isRequired,
- onAppIndexerSyncPress: PropTypes.func.isRequired
-};
-
-export default ApplicationSettings;
diff --git a/frontend/src/Settings/Applications/ApplicationSettings.tsx b/frontend/src/Settings/Applications/ApplicationSettings.tsx
new file mode 100644
index 000000000..c35d55e2d
--- /dev/null
+++ b/frontend/src/Settings/Applications/ApplicationSettings.tsx
@@ -0,0 +1,102 @@
+import React, { Fragment, useCallback, useState } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import AppState from 'App/State/AppState';
+import { APP_INDEXER_SYNC } from 'Commands/commandNames';
+import PageContent from 'Components/Page/PageContent';
+import PageContentBody from 'Components/Page/PageContentBody';
+import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
+import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
+import { icons } from 'Helpers/Props';
+import AppProfilesConnector from 'Settings/Profiles/App/AppProfilesConnector';
+import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
+import { executeCommand } from 'Store/Actions/commandActions';
+import { testAllApplications } from 'Store/Actions/Settings/applications';
+import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
+import translate from 'Utilities/String/translate';
+import ApplicationsConnector from './Applications/ApplicationsConnector';
+import ManageApplicationsModal from './Applications/Manage/ManageApplicationsModal';
+
+function ApplicationSettings() {
+ const isSyncingIndexers = useSelector(
+ createCommandExecutingSelector(APP_INDEXER_SYNC)
+ );
+ const isTestingAll = useSelector(
+ (state: AppState) => state.settings.applications.isTestingAll
+ );
+ const dispatch = useDispatch();
+
+ const [isManageApplicationsOpen, setIsManageApplicationsOpen] =
+ useState(false);
+
+ const onManageApplicationsPress = useCallback(() => {
+ setIsManageApplicationsOpen(true);
+ }, [setIsManageApplicationsOpen]);
+
+ const onManageApplicationsModalClose = useCallback(() => {
+ setIsManageApplicationsOpen(false);
+ }, [setIsManageApplicationsOpen]);
+
+ const onAppIndexerSyncPress = useCallback(() => {
+ dispatch(
+ executeCommand({
+ name: APP_INDEXER_SYNC,
+ forceSync: true,
+ })
+ );
+ }, [dispatch]);
+
+ const onTestAllPress = useCallback(() => {
+ dispatch(testAllApplications());
+ }, [dispatch]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ }
+ />
+
+
+ {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
+ {/* @ts-ignore */}
+
+ {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */}
+ {/* @ts-ignore */}
+
+
+
+
+
+ );
+}
+
+export default ApplicationSettings;
diff --git a/frontend/src/Settings/Applications/ApplicationSettingsConnector.js b/frontend/src/Settings/Applications/ApplicationSettingsConnector.js
deleted file mode 100644
index aece6e91f..000000000
--- a/frontend/src/Settings/Applications/ApplicationSettingsConnector.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { testAllApplications } from 'Store/Actions/settingsActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import ApplicationSettings from './ApplicationSettings';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.applications.isTestingAll,
- createCommandExecutingSelector(commandNames.APP_INDEXER_SYNC),
- (isTestingAll, isSyncingIndexers) => {
- return {
- isTestingAll,
- isSyncingIndexers
- };
- }
- );
-}
-
-function mapDispatchToProps(dispatch, props) {
- return {
- onTestAllPress() {
- dispatch(testAllApplications());
- },
- onAppIndexerSyncPress() {
- dispatch(executeCommand({
- name: commandNames.APP_INDEXER_SYNC
- }));
- }
- };
-}
-
-export default connect(createMapStateToProps, mapDispatchToProps)(ApplicationSettings);
diff --git a/src/NzbDrone.Core/Applications/ApplicationBase.cs b/src/NzbDrone.Core/Applications/ApplicationBase.cs
index 9cba791e6..e055d37aa 100644
--- a/src/NzbDrone.Core/Applications/ApplicationBase.cs
+++ b/src/NzbDrone.Core/Applications/ApplicationBase.cs
@@ -54,7 +54,7 @@ namespace NzbDrone.Core.Applications
}
public abstract void AddIndexer(IndexerDefinition indexer);
- public abstract void UpdateIndexer(IndexerDefinition indexer);
+ public abstract void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false);
public abstract void RemoveIndexer(int indexerId);
public abstract List GetIndexerMappings();
diff --git a/src/NzbDrone.Core/Applications/ApplicationIndexerSyncCommand.cs b/src/NzbDrone.Core/Applications/ApplicationIndexerSyncCommand.cs
index ad9023993..50318ecbd 100644
--- a/src/NzbDrone.Core/Applications/ApplicationIndexerSyncCommand.cs
+++ b/src/NzbDrone.Core/Applications/ApplicationIndexerSyncCommand.cs
@@ -4,6 +4,13 @@ namespace NzbDrone.Core.Applications
{
public class ApplicationIndexerSyncCommand : Command
{
+ public bool ForceSync { get; set; }
+
+ public ApplicationIndexerSyncCommand()
+ {
+ ForceSync = false;
+ }
+
public override bool SendUpdatesToClient => true;
public override string CompletionMessage => null;
diff --git a/src/NzbDrone.Core/Applications/ApplicationService.cs b/src/NzbDrone.Core/Applications/ApplicationService.cs
index 5d9e868cf..419008f7f 100644
--- a/src/NzbDrone.Core/Applications/ApplicationService.cs
+++ b/src/NzbDrone.Core/Applications/ApplicationService.cs
@@ -104,7 +104,7 @@ namespace NzbDrone.Core.Applications
var indexers = _indexerFactory.AllProviders().Select(i => (IndexerDefinition)i.Definition).ToList();
- SyncIndexers(enabledApps, indexers, true);
+ SyncIndexers(enabledApps, indexers, true, true);
}
public void HandleAsync(ProviderBulkUpdatedEvent message)
@@ -122,10 +122,10 @@ namespace NzbDrone.Core.Applications
var indexers = _indexerFactory.AllProviders().Select(i => (IndexerDefinition)i.Definition).ToList();
- SyncIndexers(enabledApps, indexers, true);
+ SyncIndexers(enabledApps, indexers, true, message.ForceSync);
}
- private void SyncIndexers(List applications, List indexers, bool removeRemote = false)
+ private void SyncIndexers(List applications, List indexers, bool removeRemote = false, bool forceSync = false)
{
foreach (var app in applications)
{
@@ -165,7 +165,7 @@ namespace NzbDrone.Core.Applications
{
if (((ApplicationDefinition)app.Definition).SyncLevel == ApplicationSyncLevel.FullSync && ShouldHandleIndexer(app.Definition, indexer))
{
- ExecuteAction(a => a.UpdateIndexer(definition), app);
+ ExecuteAction(a => a.UpdateIndexer(definition, forceSync), app);
}
}
else
diff --git a/src/NzbDrone.Core/Applications/IApplication.cs b/src/NzbDrone.Core/Applications/IApplication.cs
index 5dd4572f5..599010ee1 100644
--- a/src/NzbDrone.Core/Applications/IApplication.cs
+++ b/src/NzbDrone.Core/Applications/IApplication.cs
@@ -7,7 +7,7 @@ namespace NzbDrone.Core.Applications
public interface IApplication : IProvider
{
void AddIndexer(IndexerDefinition indexer);
- void UpdateIndexer(IndexerDefinition indexer);
+ void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false);
void RemoveIndexer(int indexerId);
List GetIndexerMappings();
}
diff --git a/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs b/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs
index 7ed59061c..47890594e 100644
--- a/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs
+++ b/src/NzbDrone.Core/Applications/LazyLibrarian/LazyLibrarian.cs
@@ -103,7 +103,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
}
}
- public override void UpdateIndexer(IndexerDefinition indexer)
+ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false)
{
_logger.Debug("Updating indexer {0} [{1}]", indexer.Name, indexer.Id);
@@ -118,10 +118,12 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
if (remoteIndexer != null)
{
- _logger.Debug("Remote indexer found, syncing with current settings");
+ _logger.Debug("Remote indexer {0} found", remoteIndexer.Name);
- if (!lazyLibrarianIndexer.Equals(remoteIndexer))
+ if (!lazyLibrarianIndexer.Equals(remoteIndexer) || forceSync)
{
+ _logger.Debug("Syncing remote indexer with current settings");
+
_lazyLibrarianV1Proxy.UpdateIndexer(lazyLibrarianIndexer, Settings);
indexerMapping.RemoteIndexerName = $"{lazyLibrarianIndexer.Type},{lazyLibrarianIndexer.Altername}";
_appIndexerMapService.Update(indexerMapping);
diff --git a/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs b/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs
index 68137dc4d..84e6c4f72 100644
--- a/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs
+++ b/src/NzbDrone.Core/Applications/Lidarr/Lidarr.cs
@@ -96,15 +96,20 @@ namespace NzbDrone.Core.Applications.Lidarr
foreach (var indexer in indexers)
{
- if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value == _configFileProvider.ApiKey)
+ var baseUrl = (string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl")?.Value ?? string.Empty;
+
+ if (!baseUrl.StartsWith(Settings.ProwlarrUrl.TrimEnd('/')) &&
+ (string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value != _configFileProvider.ApiKey)
{
- var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value);
+ continue;
+ }
- 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
- }
+ var match = AppIndexerRegex.Match(baseUrl);
+
+ 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
}
}
@@ -150,7 +155,7 @@ namespace NzbDrone.Core.Applications.Lidarr
}
}
- public override void UpdateIndexer(IndexerDefinition indexer)
+ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false)
{
_logger.Debug("Updating indexer {0} [{1}]", indexer.Name, indexer.Id);
@@ -163,10 +168,12 @@ namespace NzbDrone.Core.Applications.Lidarr
if (remoteIndexer != null)
{
- _logger.Debug("Remote indexer found, syncing with current settings");
+ _logger.Debug("Remote indexer {0} [{1}] found", remoteIndexer.Name, remoteIndexer.Id);
- if (!lidarrIndexer.Equals(remoteIndexer))
+ if (!lidarrIndexer.Equals(remoteIndexer) || forceSync)
{
+ _logger.Debug("Syncing remote indexer with current settings");
+
if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
// Retain user fields not-affiliated with Prowlarr
diff --git a/src/NzbDrone.Core/Applications/Lidarr/LidarrIndexer.cs b/src/NzbDrone.Core/Applications/Lidarr/LidarrIndexer.cs
index 7ac02fd45..45221126e 100644
--- a/src/NzbDrone.Core/Applications/Lidarr/LidarrIndexer.cs
+++ b/src/NzbDrone.Core/Applications/Lidarr/LidarrIndexer.cs
@@ -29,9 +29,12 @@ namespace NzbDrone.Core.Applications.Lidarr
}
var baseUrl = (string)Fields.FirstOrDefault(x => x.Name == "baseUrl").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value;
- var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey").Value;
var cats = JToken.DeepEquals((JArray)Fields.FirstOrDefault(x => x.Name == "categories").Value, (JArray)other.Fields.FirstOrDefault(x => x.Name == "categories").Value);
+ var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var otherApiKey = (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var apiKeyCompare = apiKey == otherApiKey || otherApiKey == "********";
+
var apiPath = Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var otherApiPath = other.Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : other.Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var apiPathCompare = apiPath.Equals(otherApiPath);
@@ -59,7 +62,7 @@ namespace NzbDrone.Core.Applications.Lidarr
other.Implementation == Implementation &&
other.Priority == Priority &&
other.Id == Id &&
- apiKey && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare && discographySeedTimeCompare;
+ apiKeyCompare && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare && discographySeedTimeCompare;
}
}
}
diff --git a/src/NzbDrone.Core/Applications/Mylar/Mylar.cs b/src/NzbDrone.Core/Applications/Mylar/Mylar.cs
index 7d84feae1..45b5667e7 100644
--- a/src/NzbDrone.Core/Applications/Mylar/Mylar.cs
+++ b/src/NzbDrone.Core/Applications/Mylar/Mylar.cs
@@ -103,7 +103,7 @@ namespace NzbDrone.Core.Applications.Mylar
}
}
- public override void UpdateIndexer(IndexerDefinition indexer)
+ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false)
{
_logger.Debug("Updating indexer {0} [{1}]", indexer.Name, indexer.Id);
@@ -118,10 +118,12 @@ namespace NzbDrone.Core.Applications.Mylar
if (remoteIndexer != null)
{
- _logger.Debug("Remote indexer found, syncing with current settings");
+ _logger.Debug("Remote indexer {0} found", remoteIndexer.Name);
- if (!mylarIndexer.Equals(remoteIndexer))
+ if (!mylarIndexer.Equals(remoteIndexer) || forceSync)
{
+ _logger.Debug("Syncing remote indexer with current settings");
+
_mylarV3Proxy.UpdateIndexer(mylarIndexer, Settings);
indexerMapping.RemoteIndexerName = $"{mylarIndexer.Type},{mylarIndexer.Altername}";
_appIndexerMapService.Update(indexerMapping);
diff --git a/src/NzbDrone.Core/Applications/Radarr/Radarr.cs b/src/NzbDrone.Core/Applications/Radarr/Radarr.cs
index a3d63317f..7ab8bf0ab 100644
--- a/src/NzbDrone.Core/Applications/Radarr/Radarr.cs
+++ b/src/NzbDrone.Core/Applications/Radarr/Radarr.cs
@@ -96,15 +96,20 @@ namespace NzbDrone.Core.Applications.Radarr
foreach (var indexer in indexers)
{
- if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value == _configFileProvider.ApiKey)
+ var baseUrl = (string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl")?.Value ?? string.Empty;
+
+ if (!baseUrl.StartsWith(Settings.ProwlarrUrl.TrimEnd('/')) &&
+ (string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value != _configFileProvider.ApiKey)
{
- var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value);
+ continue;
+ }
- 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
- }
+ var match = AppIndexerRegex.Match(baseUrl);
+
+ 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
}
}
@@ -150,7 +155,7 @@ namespace NzbDrone.Core.Applications.Radarr
}
}
- public override void UpdateIndexer(IndexerDefinition indexer)
+ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false)
{
_logger.Debug("Updating indexer {0} [{1}]", indexer.Name, indexer.Id);
@@ -163,9 +168,9 @@ namespace NzbDrone.Core.Applications.Radarr
if (remoteIndexer != null)
{
- _logger.Debug("Remote indexer found, syncing with current settings");
+ _logger.Debug("Remote indexer {0} [{1}] found", remoteIndexer.Name, remoteIndexer.Id);
- if (!radarrIndexer.Equals(remoteIndexer))
+ if (!radarrIndexer.Equals(remoteIndexer) || forceSync)
{
if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
diff --git a/src/NzbDrone.Core/Applications/Radarr/RadarrIndexer.cs b/src/NzbDrone.Core/Applications/Radarr/RadarrIndexer.cs
index 38082724e..d68dda0ad 100644
--- a/src/NzbDrone.Core/Applications/Radarr/RadarrIndexer.cs
+++ b/src/NzbDrone.Core/Applications/Radarr/RadarrIndexer.cs
@@ -29,9 +29,12 @@ namespace NzbDrone.Core.Applications.Radarr
}
var baseUrl = (string)Fields.FirstOrDefault(x => x.Name == "baseUrl").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value;
- var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey").Value;
var cats = JToken.DeepEquals((JArray)Fields.FirstOrDefault(x => x.Name == "categories").Value, (JArray)other.Fields.FirstOrDefault(x => x.Name == "categories").Value);
+ var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var otherApiKey = (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var apiKeyCompare = apiKey == otherApiKey || otherApiKey == "********";
+
var apiPath = Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var otherApiPath = other.Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : other.Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var apiPathCompare = apiPath.Equals(otherApiPath);
@@ -55,7 +58,7 @@ namespace NzbDrone.Core.Applications.Radarr
other.Implementation == Implementation &&
other.Priority == Priority &&
other.Id == Id &&
- apiKey && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare;
+ apiKeyCompare && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare;
}
}
}
diff --git a/src/NzbDrone.Core/Applications/Readarr/Readarr.cs b/src/NzbDrone.Core/Applications/Readarr/Readarr.cs
index 0860c4c6f..a75ccacc3 100644
--- a/src/NzbDrone.Core/Applications/Readarr/Readarr.cs
+++ b/src/NzbDrone.Core/Applications/Readarr/Readarr.cs
@@ -90,21 +90,26 @@ 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 is "Newznab" or "Torznab");
var mappings = new List();
foreach (var indexer in indexers)
{
- if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value == _configFileProvider.ApiKey)
+ var baseUrl = (string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl")?.Value ?? string.Empty;
+
+ if (!baseUrl.StartsWith(Settings.ProwlarrUrl.TrimEnd('/')) &&
+ (string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value != _configFileProvider.ApiKey)
{
- var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value);
+ continue;
+ }
- 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
- }
+ var match = AppIndexerRegex.Match(baseUrl);
+
+ 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
}
}
@@ -150,7 +155,7 @@ namespace NzbDrone.Core.Applications.Readarr
}
}
- public override void UpdateIndexer(IndexerDefinition indexer)
+ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false)
{
_logger.Debug("Updating indexer {0} [{1}]", indexer.Name, indexer.Id);
@@ -163,10 +168,12 @@ namespace NzbDrone.Core.Applications.Readarr
if (remoteIndexer != null)
{
- _logger.Debug("Remote indexer found, syncing with current settings");
+ _logger.Debug("Remote indexer {0} [{1}] found", remoteIndexer.Name, remoteIndexer.Id);
- if (!readarrIndexer.Equals(remoteIndexer))
+ if (!readarrIndexer.Equals(remoteIndexer) || forceSync)
{
+ _logger.Debug("Syncing remote indexer with current settings");
+
if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
// Retain user fields not-affiliated with Prowlarr
diff --git a/src/NzbDrone.Core/Applications/Readarr/ReadarrIndexer.cs b/src/NzbDrone.Core/Applications/Readarr/ReadarrIndexer.cs
index e4683ae01..ca98f5700 100644
--- a/src/NzbDrone.Core/Applications/Readarr/ReadarrIndexer.cs
+++ b/src/NzbDrone.Core/Applications/Readarr/ReadarrIndexer.cs
@@ -28,9 +28,12 @@ namespace NzbDrone.Core.Applications.Readarr
}
var baseUrl = (string)Fields.FirstOrDefault(x => x.Name == "baseUrl").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value;
- var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey").Value;
var cats = JToken.DeepEquals((JArray)Fields.FirstOrDefault(x => x.Name == "categories").Value, (JArray)other.Fields.FirstOrDefault(x => x.Name == "categories").Value);
+ var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var otherApiKey = (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var apiKeyCompare = apiKey == otherApiKey || otherApiKey == "********";
+
var apiPath = Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var otherApiPath = other.Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : other.Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var apiPathCompare = apiPath.Equals(otherApiPath);
@@ -58,7 +61,7 @@ namespace NzbDrone.Core.Applications.Readarr
other.Implementation == Implementation &&
other.Priority == Priority &&
other.Id == Id &&
- apiKey && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare && discographySeedTimeCompare;
+ apiKeyCompare && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare && discographySeedTimeCompare;
}
}
}
diff --git a/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs b/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs
index a894b9d1c..4805cf5bd 100644
--- a/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs
+++ b/src/NzbDrone.Core/Applications/Sonarr/Sonarr.cs
@@ -100,15 +100,20 @@ namespace NzbDrone.Core.Applications.Sonarr
foreach (var indexer in indexers)
{
- if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value == _configFileProvider.ApiKey)
+ var baseUrl = (string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl")?.Value ?? string.Empty;
+
+ if (!baseUrl.StartsWith(Settings.ProwlarrUrl.TrimEnd('/')) &&
+ (string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value != _configFileProvider.ApiKey)
{
- var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value);
+ continue;
+ }
- 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
- }
+ var match = AppIndexerRegex.Match(baseUrl);
+
+ 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
}
}
@@ -155,7 +160,7 @@ namespace NzbDrone.Core.Applications.Sonarr
}
}
- public override void UpdateIndexer(IndexerDefinition indexer)
+ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false)
{
_logger.Debug("Updating indexer {0} [{1}]", indexer.Name, indexer.Id);
@@ -168,10 +173,12 @@ namespace NzbDrone.Core.Applications.Sonarr
if (remoteIndexer != null)
{
- _logger.Debug("Remote indexer found, syncing with current settings");
+ _logger.Debug("Remote indexer {0} [{1}] found", remoteIndexer.Name, remoteIndexer.Id);
- if (!sonarrIndexer.Equals(remoteIndexer))
+ if (!sonarrIndexer.Equals(remoteIndexer) || forceSync)
{
+ _logger.Debug("Syncing remote indexer with current settings");
+
if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexer.Capabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any())
{
// Retain user fields not-affiliated with Prowlarr
diff --git a/src/NzbDrone.Core/Applications/Sonarr/SonarrIndexer.cs b/src/NzbDrone.Core/Applications/Sonarr/SonarrIndexer.cs
index 03c4376c4..8b0b6a561 100644
--- a/src/NzbDrone.Core/Applications/Sonarr/SonarrIndexer.cs
+++ b/src/NzbDrone.Core/Applications/Sonarr/SonarrIndexer.cs
@@ -30,10 +30,13 @@ namespace NzbDrone.Core.Applications.Sonarr
}
var baseUrl = (string)Fields.FirstOrDefault(x => x.Name == "baseUrl").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value;
- var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey").Value;
var cats = JToken.DeepEquals((JArray)Fields.FirstOrDefault(x => x.Name == "categories").Value, (JArray)other.Fields.FirstOrDefault(x => x.Name == "categories").Value);
var animeCats = JToken.DeepEquals((JArray)Fields.FirstOrDefault(x => x.Name == "animeCategories").Value, (JArray)other.Fields.FirstOrDefault(x => x.Name == "animeCategories").Value);
+ var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var otherApiKey = (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var apiKeyCompare = apiKey == otherApiKey || otherApiKey == "********";
+
var apiPath = Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var otherApiPath = other.Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : other.Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var apiPathCompare = apiPath.Equals(otherApiPath);
@@ -65,7 +68,7 @@ namespace NzbDrone.Core.Applications.Sonarr
other.Implementation == Implementation &&
other.Priority == Priority &&
other.Id == Id &&
- apiKey && apiPathCompare && baseUrl && cats && animeCats && animeStandardFormatSearchCompare && minimumSeedersCompare && seedRatioCompare && seedTimeCompare && seasonSeedTimeCompare;
+ apiKeyCompare && apiPathCompare && baseUrl && cats && animeCats && animeStandardFormatSearchCompare && minimumSeedersCompare && seedRatioCompare && seedTimeCompare && seasonSeedTimeCompare;
}
}
}
diff --git a/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs b/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs
index 96076e61f..855692d07 100644
--- a/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs
+++ b/src/NzbDrone.Core/Applications/Whisparr/Whisparr.cs
@@ -90,21 +90,26 @@ 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 is "Newznab" or "Torznab");
var mappings = new List();
foreach (var indexer in indexers)
{
- if ((string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value == _configFileProvider.ApiKey)
+ var baseUrl = (string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl")?.Value ?? string.Empty;
+
+ if (!baseUrl.StartsWith(Settings.ProwlarrUrl.TrimEnd('/')) &&
+ (string)indexer.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value != _configFileProvider.ApiKey)
{
- var match = AppIndexerRegex.Match((string)indexer.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value);
+ continue;
+ }
- 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
- }
+ var match = AppIndexerRegex.Match(baseUrl);
+
+ 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 { IndexerId = indexerId, RemoteIndexerId = indexer.Id });
}
}
@@ -150,7 +155,7 @@ namespace NzbDrone.Core.Applications.Whisparr
}
}
- public override void UpdateIndexer(IndexerDefinition indexer)
+ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = false)
{
_logger.Debug("Updating indexer {0} [{1}]", indexer.Name, indexer.Id);
@@ -163,10 +168,12 @@ namespace NzbDrone.Core.Applications.Whisparr
if (remoteIndexer != null)
{
- _logger.Debug("Remote indexer found, syncing with current settings");
+ _logger.Debug("Remote indexer {0} [{1}] found", remoteIndexer.Name, remoteIndexer.Id);
- if (!whisparrIndexer.Equals(remoteIndexer))
+ if (!whisparrIndexer.Equals(remoteIndexer) || forceSync)
{
+ _logger.Debug("Syncing remote indexer with current settings");
+
if (indexer.Capabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
// Retain user fields not-affiliated with Prowlarr
diff --git a/src/NzbDrone.Core/Applications/Whisparr/WhisparrIndexer.cs b/src/NzbDrone.Core/Applications/Whisparr/WhisparrIndexer.cs
index b1d720360..4cbd2d3ff 100644
--- a/src/NzbDrone.Core/Applications/Whisparr/WhisparrIndexer.cs
+++ b/src/NzbDrone.Core/Applications/Whisparr/WhisparrIndexer.cs
@@ -28,9 +28,12 @@ namespace NzbDrone.Core.Applications.Whisparr
}
var baseUrl = (string)Fields.FirstOrDefault(x => x.Name == "baseUrl").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "baseUrl").Value;
- var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey").Value == (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey").Value;
var cats = JToken.DeepEquals((JArray)Fields.FirstOrDefault(x => x.Name == "categories").Value, (JArray)other.Fields.FirstOrDefault(x => x.Name == "categories").Value);
+ var apiKey = (string)Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var otherApiKey = (string)other.Fields.FirstOrDefault(x => x.Name == "apiKey")?.Value;
+ var apiKeyCompare = apiKey == otherApiKey || otherApiKey == "********";
+
var apiPath = Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var otherApiPath = other.Fields.FirstOrDefault(x => x.Name == "apiPath")?.Value == null ? null : other.Fields.FirstOrDefault(x => x.Name == "apiPath").Value;
var apiPathCompare = apiPath.Equals(otherApiPath);
@@ -54,7 +57,7 @@ namespace NzbDrone.Core.Applications.Whisparr
other.Implementation == Implementation &&
other.Priority == Priority &&
other.Id == Id &&
- apiKey && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare;
+ apiKeyCompare && apiPathCompare && baseUrl && cats && minimumSeedersCompare && seedRatioCompare && seedTimeCompare;
}
}
}
diff --git a/src/Prowlarr.Api.V1/Indexers/IndexerStatusController.cs b/src/Prowlarr.Api.V1/Indexers/IndexerStatusController.cs
index 566be187f..97ebe606d 100644
--- a/src/Prowlarr.Api.V1/Indexers/IndexerStatusController.cs
+++ b/src/Prowlarr.Api.V1/Indexers/IndexerStatusController.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Datastore.Events;
@@ -7,7 +8,6 @@ using NzbDrone.Core.ThingiProvider.Events;
using NzbDrone.SignalR;
using Prowlarr.Http;
using Prowlarr.Http.REST;
-using NotImplementedException = System.NotImplementedException;
namespace Prowlarr.Api.V1.Indexers
{