From 6d662e49c5a18fdf9c4d83f7894eb936f603b4a5 Mon Sep 17 00:00:00 2001 From: bonswouar Date: Sat, 14 Dec 2024 23:41:50 +0100 Subject: [PATCH] feat(radarr-scanner): remove unmonitored movies from "requests" --- cypress/config/settings.cypress.json | 1 + overseerr-api.yml | 3 ++ server/interfaces/api/settingsInterfaces.ts | 1 + server/lib/scanners/baseScanner.ts | 17 +++++++++- server/lib/scanners/radarr/index.ts | 15 ++++---- server/lib/settings/index.ts | 4 +++ .../Settings/SettingsMain/index.tsx | 34 +++++++++++++++++++ src/context/SettingsContext.tsx | 1 + src/i18n/locale/en.json | 1 + src/pages/_app.tsx | 1 + 10 files changed, 69 insertions(+), 9 deletions(-) diff --git a/cypress/config/settings.cypress.json b/cypress/config/settings.cypress.json index e3d31cc11..59af947fd 100644 --- a/cypress/config/settings.cypress.json +++ b/cypress/config/settings.cypress.json @@ -23,6 +23,7 @@ "mediaServerType": 1, "partialRequestsEnabled": true, "enableSpecialEpisodes": false, + "removeUnmonitoredEnabled": false, "locale": "en" }, "plex": { diff --git a/overseerr-api.yml b/overseerr-api.yml index 06a7523d0..3b149e6c6 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -176,6 +176,9 @@ components: partialRequestsEnabled: type: boolean example: false + removeUnmonitoredEnabled: + type: boolean + example: false localLogin: type: boolean example: true diff --git a/server/interfaces/api/settingsInterfaces.ts b/server/interfaces/api/settingsInterfaces.ts index 017eef856..03f65843c 100644 --- a/server/interfaces/api/settingsInterfaces.ts +++ b/server/interfaces/api/settingsInterfaces.ts @@ -38,6 +38,7 @@ export interface PublicSettingsResponse { mediaServerType: number; partialRequestsEnabled: boolean; enableSpecialEpisodes: boolean; + removeUnmonitoredEnabled: boolean; cacheImages: boolean; vapidPublic: string; enablePushRegistration: boolean; diff --git a/server/lib/scanners/baseScanner.ts b/server/lib/scanners/baseScanner.ts index f0f3db7e6..03f426c5b 100644 --- a/server/lib/scanners/baseScanner.ts +++ b/server/lib/scanners/baseScanner.ts @@ -211,7 +211,7 @@ class BaseScanner { /** * processShow takes a TMDB ID and an array of ProcessableSeasons, which - * should include the total episodes a sesaon has + the total available + * should include the total episodes a season has + the total available * episodes that each season currently has. Unlike processMovie, this method * does not take an `is4k` option. We handle both the 4k _and_ non 4k status * in one method. @@ -618,6 +618,21 @@ class BaseScanner { get protectedBundleSize(): number { return this.bundleSize; } + + protected async processUnmonitoredMovie(tmdbId: number): Promise { + const mediaRepository = getRepository(Media); + await this.asyncLock.dispatch(tmdbId, async () => { + const existing = await this.getExisting(tmdbId, MediaType.MOVIE); + if (existing && existing.status === MediaStatus.PROCESSING) { + existing.status = MediaStatus.UNKNOWN; + await mediaRepository.save(existing); + this.log( + `Movie TMDB ID ${tmdbId} unmonitored from Radarr. Media status set to UNKNOWN.`, + 'info' + ); + } + }); + } } export default BaseScanner; diff --git a/server/lib/scanners/radarr/index.ts b/server/lib/scanners/radarr/index.ts index bc299d7b1..465204590 100644 --- a/server/lib/scanners/radarr/index.ts +++ b/server/lib/scanners/radarr/index.ts @@ -79,14 +79,13 @@ class RadarrScanner } private async processRadarrMovie(radarrMovie: RadarrMovie): Promise { - if (!radarrMovie.monitored && !radarrMovie.hasFile) { - this.log( - 'Title is unmonitored and has not been downloaded. Skipping item.', - 'debug', - { - title: radarrMovie.title, - } - ); + const settings = getSettings(); + if ( + settings.main.removeUnmonitoredEnabled && + !radarrMovie.monitored && + !radarrMovie.hasFile + ) { + this.processUnmonitoredMovie(radarrMovie.tmdbId); return; } diff --git a/server/lib/settings/index.ts b/server/lib/settings/index.ts index cd8ebb974..b28599319 100644 --- a/server/lib/settings/index.ts +++ b/server/lib/settings/index.ts @@ -132,6 +132,7 @@ export interface MainSettings { mediaServerType: number; partialRequestsEnabled: boolean; enableSpecialEpisodes: boolean; + removeUnmonitoredEnabled: boolean; locale: string; proxy: ProxySettings; } @@ -156,6 +157,7 @@ interface FullPublicSettings extends PublicSettings { jellyfinServerName?: string; partialRequestsEnabled: boolean; enableSpecialEpisodes: boolean; + removeUnmonitoredEnabled: boolean; cacheImages: boolean; vapidPublic: string; enablePushRegistration: boolean; @@ -346,6 +348,7 @@ class Settings { mediaServerType: MediaServerType.NOT_CONFIGURED, partialRequestsEnabled: true, enableSpecialEpisodes: false, + removeUnmonitoredEnabled: false, locale: 'en', proxy: { enabled: false, @@ -591,6 +594,7 @@ class Settings { mediaServerType: this.main.mediaServerType, partialRequestsEnabled: this.data.main.partialRequestsEnabled, enableSpecialEpisodes: this.data.main.enableSpecialEpisodes, + removeUnmonitoredEnabled: this.data.main.removeUnmonitoredEnabled, cacheImages: this.data.main.cacheImages, vapidPublic: this.vapidPublic, enablePushRegistration: this.data.notifications.agents.webpush.enabled, diff --git a/src/components/Settings/SettingsMain/index.tsx b/src/components/Settings/SettingsMain/index.tsx index 199b220a3..b79c03ba8 100644 --- a/src/components/Settings/SettingsMain/index.tsx +++ b/src/components/Settings/SettingsMain/index.tsx @@ -57,6 +57,9 @@ const messages = defineMessages('components.Settings.SettingsMain', { validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash', partialRequestsEnabled: 'Allow Partial Series Requests', enableSpecialEpisodes: 'Allow Special Episodes Requests', + removeUnmonitoredEnabled: 'Remove Unmonitored Media', + removeUnmonitoredExplanation: + 'Remove Movies/Seasons from Jellyseerr that are not available and have been un-monitored since', locale: 'Display Language', proxyEnabled: 'HTTP(S) Proxy', proxyHostname: 'Proxy Hostname', @@ -160,6 +163,7 @@ const SettingsMain = () => { streamingRegion: data?.streamingRegion || 'US', partialRequestsEnabled: data?.partialRequestsEnabled, enableSpecialEpisodes: data?.enableSpecialEpisodes, + removeUnmonitoredEnabled: data?.removeUnmonitoredEnabled, trustProxy: data?.trustProxy, cacheImages: data?.cacheImages, proxyEnabled: data?.proxy?.enabled, @@ -191,6 +195,7 @@ const SettingsMain = () => { originalLanguage: values.originalLanguage, partialRequestsEnabled: values.partialRequestsEnabled, enableSpecialEpisodes: values.enableSpecialEpisodes, + removeUnmonitoredEnabled: values.removeUnmonitoredEnabled, trustProxy: values.trustProxy, cacheImages: values.cacheImages, proxy: { @@ -524,6 +529,35 @@ const SettingsMain = () => { /> +
+ +
+ { + setFieldValue( + 'removeUnmonitoredEnabled', + !values.removeUnmonitoredEnabled + ); + }} + /> +
+