From abc7bd4db94320397fdd45fb667801c65c85a346 Mon Sep 17 00:00:00 2001 From: raccommode Date: Mon, 24 Aug 2026 08:21:30 -0400 Subject: [PATCH] feat: Added option to use default Seerr quality profiles --- .../Advanced/RequestModalSettings.cs | 4 +++- .../Configuration/Advanced/SettingsHelper.cs | 3 ++- .../Configuration/config.html | 12 +++++++++++- .../Controllers/SeerrFinController.cs | 6 +++++- .../Inject/seerrfin-modal.js | 19 +++++++++++++++---- .../Inject/seerrfin-tabs.js | 1 + .../Services/JellyseerrRequestService.cs | 15 +++++++++++---- 7 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/RequestModalSettings.cs b/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/RequestModalSettings.cs index 28ba7b7..e67fc0d 100644 --- a/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/RequestModalSettings.cs +++ b/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/RequestModalSettings.cs @@ -2,6 +2,8 @@ namespace Jellyfin.Plugin.SeerrFin.Configuration.Advanced; public class AdvancedRequestModalSettings { + public bool AllowQualityProfileSelection { get; set; } = true; + public bool TvSeasonPickerEnabled { get; set; } = true; public bool IncludeSpecialsSeason { get; set; } @@ -9,4 +11,4 @@ public class AdvancedRequestModalSettings public bool RequireExplicitSeasonSelection { get; set; } public bool ShowRequest4kButton { get; set; } = true; -} \ No newline at end of file +} diff --git a/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/SettingsHelper.cs b/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/SettingsHelper.cs index 1f6a4e7..d289d55 100644 --- a/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/SettingsHelper.cs +++ b/src/Jellyfin.Plugin.SeerrFin/Configuration/Advanced/SettingsHelper.cs @@ -212,6 +212,7 @@ public static object BuildFrontendPayload(PluginConfiguration config) }, requestModal = new { + allowQualityProfileSelection = advanced.RequestModal.AllowQualityProfileSelection, tvSeasonPickerEnabled = advanced.RequestModal.TvSeasonPickerEnabled, includeSpecialsSeason = advanced.RequestModal.IncludeSpecialsSeason, requireExplicitSeasonSelection = advanced.RequestModal.RequireExplicitSeasonSelection, @@ -271,4 +272,4 @@ public static Dictionary GetQualityLabelAliases(PluginConfigur return merged; } -} \ No newline at end of file +} diff --git a/src/Jellyfin.Plugin.SeerrFin/Configuration/config.html b/src/Jellyfin.Plugin.SeerrFin/Configuration/config.html index 8ad1683..8a00c94 100644 --- a/src/Jellyfin.Plugin.SeerrFin/Configuration/config.html +++ b/src/Jellyfin.Plugin.SeerrFin/Configuration/config.html @@ -1403,10 +1403,17 @@
+
+
+ +
When disabled, requests use the default Radarr or Sonarr profile configured in Seerr.
+
+ +
-
Show a season picker before choosing a quality profile for TV.
+
Show a season picker before submitting a TV request.
@@ -2344,6 +2351,7 @@

RefreshOnTabShow: true }, RequestModal: { + AllowQualityProfileSelection: true, TvSeasonPickerEnabled: true, IncludeSpecialsSeason: false, RequireExplicitSeasonSelection: false, @@ -2446,6 +2454,7 @@

document.querySelector('#advSplitPartiallyAvailableFilter').checked = r.SplitPartiallyAvailableFilter === true; const m = advanced.RequestModal; + document.querySelector('#advAllowQualityProfileSelection').checked = m.AllowQualityProfileSelection !== false; document.querySelector('#advTvSeasonPickerEnabled').checked = m.TvSeasonPickerEnabled !== false; document.querySelector('#advIncludeSpecialsSeason').checked = m.IncludeSpecialsSeason === true; document.querySelector('#advRequireExplicitSeasonSelection').checked = m.RequireExplicitSeasonSelection === true; @@ -2518,6 +2527,7 @@

RefreshOnTabShow: document.querySelector('#advRequestsRefreshOnTabShow').checked }, RequestModal: { + AllowQualityProfileSelection: document.querySelector('#advAllowQualityProfileSelection').checked, TvSeasonPickerEnabled: document.querySelector('#advTvSeasonPickerEnabled').checked, IncludeSpecialsSeason: document.querySelector('#advIncludeSpecialsSeason').checked, RequireExplicitSeasonSelection: document.querySelector('#advRequireExplicitSeasonSelection').checked, diff --git a/src/Jellyfin.Plugin.SeerrFin/Controllers/SeerrFinController.cs b/src/Jellyfin.Plugin.SeerrFin/Controllers/SeerrFinController.cs index 1f5515c..5cf50a6 100644 --- a/src/Jellyfin.Plugin.SeerrFin/Controllers/SeerrFinController.cs +++ b/src/Jellyfin.Plugin.SeerrFin/Controllers/SeerrFinController.cs @@ -650,8 +650,12 @@ public async Task MakeDiscoverRequest( return Forbid(); } + bool allowQualityProfileSelection = AdvancedSettingsHelper + .Resolve(SeerrFinPlugin.Instance.Configuration) + .RequestModal + .AllowQualityProfileSelection; (int statusCode, string body, string contentType) = await _requestService - .SubmitRequestAsync(username, payload, cancellationToken) + .SubmitRequestAsync(username, payload, allowQualityProfileSelection, cancellationToken) .ConfigureAwait(false); return new ContentResult diff --git a/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-modal.js b/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-modal.js index f3e18c4..f49e95c 100644 --- a/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-modal.js +++ b/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-modal.js @@ -56,6 +56,7 @@ window.seerrFinLog = window.seerrFinLog || { ? plugin._displaySettings.Advanced.requestModal : null; return { + allowQualityProfileSelection: readAdvancedBool(modal && modal.allowQualityProfileSelection, true), tvSeasonPickerEnabled: readAdvancedBool(modal && modal.tvSeasonPickerEnabled, true), includeSpecialsSeason: readAdvancedBool(modal && modal.includeSpecialsSeason, false), requireExplicitSeasonSelection: readAdvancedBool(modal && modal.requireExplicitSeasonSelection, false), @@ -877,8 +878,9 @@ window.seerrFinLog = window.seerrFinLog || { }); } - function renderQualityModalShell(is4k) { - const title = is4k ? 'Choose 4K quality profile' : 'Choose quality profile'; + function renderQualityModalShell(is4k, useSeerrDefaults) { + const title = useSeerrDefaults ? 'Request' : (is4k ? 'Choose 4K quality profile' : 'Choose quality profile'); + const loadingText = useSeerrDefaults ? 'Submitting request…' : 'Loading profiles…'; return `
@@ -887,7 +889,7 @@ window.seerrFinLog = window.seerrFinLog || {

${title}

-
Loading profiles…
+
${loadingText}
`; } @@ -926,10 +928,11 @@ window.seerrFinLog = window.seerrFinLog || { } is4k = !!is4k; + const useSeerrDefaults = getRequestModalAdvanced().allowQualityProfileSelection === false; // Show shell so the click feels instant (fill profiles when the api returns) closeQualityModal(); - document.body.insertAdjacentHTML('beforeend', renderQualityModalShell(is4k)); + document.body.insertAdjacentHTML('beforeend', renderQualityModalShell(is4k, useSeerrDefaults)); activeQualityRoot = document.body.lastElementChild; const list = activeQualityRoot.querySelector('.bst-quality-list'); @@ -951,6 +954,14 @@ window.seerrFinLog = window.seerrFinLog || { list.innerHTML = `
${escapeHtml(message || 'Request failed')}
`; } + if (useSeerrDefaults) { + submitRequest(mediaId, mediaType, { + is4k: is4k, + seasons: selectedSeasons + }, finishRequest, failRequest).catch(function () {}); + return; + } + ApiClient.ajax({ url: ApiClient.getUrl('SeerrFin/request-options/' + mediaType), type: 'GET', diff --git a/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-tabs.js b/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-tabs.js index 3b2893c..8b282e7 100644 --- a/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-tabs.js +++ b/src/Jellyfin.Plugin.SeerrFin/Inject/seerrfin-tabs.js @@ -1291,6 +1291,7 @@ if (typeof window.seerrFinPlugin === 'undefined') { refreshOnTabShow: self.readAdvancedBool(requests.refreshOnTabShow ?? requests.RefreshOnTabShow, true) }, requestModal: { + allowQualityProfileSelection: self.readAdvancedBool(requestModal.allowQualityProfileSelection ?? requestModal.AllowQualityProfileSelection, true), tvSeasonPickerEnabled: self.readAdvancedBool(requestModal.tvSeasonPickerEnabled ?? requestModal.TvSeasonPickerEnabled, true), includeSpecialsSeason: self.readAdvancedBool(requestModal.includeSpecialsSeason ?? requestModal.IncludeSpecialsSeason, false), requireExplicitSeasonSelection: self.readAdvancedBool(requestModal.requireExplicitSeasonSelection ?? requestModal.RequireExplicitSeasonSelection, false), diff --git a/src/Jellyfin.Plugin.SeerrFin/Services/JellyseerrRequestService.cs b/src/Jellyfin.Plugin.SeerrFin/Services/JellyseerrRequestService.cs index 9f0d206..5c6b0fc 100644 --- a/src/Jellyfin.Plugin.SeerrFin/Services/JellyseerrRequestService.cs +++ b/src/Jellyfin.Plugin.SeerrFin/Services/JellyseerrRequestService.cs @@ -68,7 +68,14 @@ public RequestOptionsResult GetRequestOptionsResult(string username, string medi }; } - public async Task<(int StatusCode, string Body, string ContentType)> SubmitRequestAsync(string username, DiscoverRequestPayload payload, CancellationToken cancellationToken) + public Task<(int StatusCode, string Body, string ContentType)> SubmitRequestAsync(string username, DiscoverRequestPayload payload, CancellationToken cancellationToken) => + SubmitRequestAsync(username, payload, allowQualityProfileSelection: true, cancellationToken: cancellationToken); + + public async Task<(int StatusCode, string Body, string ContentType)> SubmitRequestAsync( + string username, + DiscoverRequestPayload payload, + bool allowQualityProfileSelection, + CancellationToken cancellationToken) { PluginConfiguration config = SeerrFinPlugin.Instance.Configuration; if (string.IsNullOrWhiteSpace(config.JellyseerrUrl) || string.IsNullOrWhiteSpace(config.JellyseerrApiKey)) @@ -104,8 +111,8 @@ public RequestOptionsResult GetRequestOptionsResult(string username, string medi : "all"; } - // Only Advanced Requests can override Seerr defaults - if (HasRequestAdvanced(permissions)) + // Only Advanced Requests can override Seerr defaults, and admins can disable profile selection for the request modal. + if (allowQualityProfileSelection && HasRequestAdvanced(permissions)) { if (payload.ServerId != null) { @@ -314,4 +321,4 @@ public sealed class RequestOptionsResult public bool CanRequestAdvanced { get; init; } public JArray Options { get; init; } = new(); -} \ No newline at end of file +}