From 15eed2510774dadc19d482d0d05f53d37972523f Mon Sep 17 00:00:00 2001 From: nitrobass24 Date: Mon, 6 Apr 2026 21:08:05 -0500 Subject: [PATCH] Fix null safety, equality contract, and silent HTTP errors in Qui application - Prevent NullReferenceException in UpdateIndexer when indexerMapping is null - Normalize Categories comparison in QuiIndexer.Equals for null/empty symmetry and add GetHashCode override to maintain equality/hash contract - Check response status in RemoveIndexer so failed DELETEs raise HttpException Co-Authored-By: Claude Opus 4.6 (1M context) --- src/NzbDrone.Core/Applications/Qui/Qui.cs | 2 +- src/NzbDrone.Core/Applications/Qui/QuiIndexer.cs | 11 ++++++++++- src/NzbDrone.Core/Applications/Qui/QuiProxy.cs | 7 ++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/NzbDrone.Core/Applications/Qui/Qui.cs b/src/NzbDrone.Core/Applications/Qui/Qui.cs index fbfc6cead..752171ece 100644 --- a/src/NzbDrone.Core/Applications/Qui/Qui.cs +++ b/src/NzbDrone.Core/Applications/Qui/Qui.cs @@ -145,7 +145,7 @@ public override void UpdateIndexer(IndexerDefinition indexer, bool forceSync = f var quiIndexer = BuildQuiIndexer(indexer, indexerCapabilities, indexerMapping?.RemoteIndexerId ?? 0); - var remoteIndexer = _quiProxy.GetIndexer(indexerMapping.RemoteIndexerId, Settings); + var remoteIndexer = _quiProxy.GetIndexer(indexerMapping?.RemoteIndexerId ?? 0, Settings); if (remoteIndexer != null) { diff --git a/src/NzbDrone.Core/Applications/Qui/QuiIndexer.cs b/src/NzbDrone.Core/Applications/Qui/QuiIndexer.cs index 82bb3ecf5..ae34e48fa 100644 --- a/src/NzbDrone.Core/Applications/Qui/QuiIndexer.cs +++ b/src/NzbDrone.Core/Applications/Qui/QuiIndexer.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; @@ -58,13 +59,21 @@ public bool Equals(QuiIndexer other) return false; } + var thisCategories = (Categories ?? Enumerable.Empty()).OrderBy(c => c); + var otherCategories = (other.Categories ?? Enumerable.Empty()).OrderBy(c => c); + return other.BaseUrl == BaseUrl && other.ApiKey == ApiKey && other.Name == Name && other.Enabled == Enabled && other.Priority == Priority && other.IndexerId == IndexerId && - other.Categories?.OrderBy(c => c).SequenceEqual(Categories?.OrderBy(c => c) ?? Enumerable.Empty()) == true; + otherCategories.SequenceEqual(thisCategories); + } + + public override int GetHashCode() + { + return HashCode.Combine(BaseUrl, ApiKey, Name, Enabled, Priority, IndexerId); } } } diff --git a/src/NzbDrone.Core/Applications/Qui/QuiProxy.cs b/src/NzbDrone.Core/Applications/Qui/QuiProxy.cs index c1ad12754..be0f9bc69 100644 --- a/src/NzbDrone.Core/Applications/Qui/QuiProxy.cs +++ b/src/NzbDrone.Core/Applications/Qui/QuiProxy.cs @@ -82,7 +82,12 @@ public QuiIndexer UpdateIndexer(QuiIndexer indexer, QuiSettings settings) public void RemoveIndexer(int indexerId, QuiSettings settings) { var request = BuildRequest(settings, $"{AppIndexerApiRoute}/{indexerId}", HttpMethod.Delete); - _httpClient.Execute(request); + var response = _httpClient.Execute(request); + + if ((int)response.StatusCode >= 300) + { + throw new HttpException(response); + } } public ValidationFailure TestConnection(QuiSettings settings)