Skip to content

Commit 4b85191

Browse files
committed
feat(radarr-scanner): remove unmonitored movies from "requests"
1 parent 48ef298 commit 4b85191

File tree

10 files changed

+69
-9
lines changed

10 files changed

+69
-9
lines changed

cypress/config/settings.cypress.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"blacklistedTagsLimit": 50,
2323
"trustProxy": false,
2424
"mediaServerType": 1,
25+
"removeUnmonitoredEnabled": false,
2526
"partialRequestsEnabled": true,
2627
"enableSpecialEpisodes": false,
2728
"locale": "en"

seerr-api.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ components:
239239
partialRequestsEnabled:
240240
type: boolean
241241
example: false
242+
removeUnmonitoredEnabled:
243+
type: boolean
244+
example: false
242245
localLogin:
243246
type: boolean
244247
example: true

server/interfaces/api/settingsInterfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface PublicSettingsResponse {
4141
mediaServerType: number;
4242
partialRequestsEnabled: boolean;
4343
enableSpecialEpisodes: boolean;
44+
removeUnmonitoredEnabled: boolean;
4445
cacheImages: boolean;
4546
vapidPublic: string;
4647
enablePushRegistration: boolean;

server/lib/scanners/baseScanner.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class BaseScanner<T> {
211211

212212
/**
213213
* processShow takes a TMDB ID and an array of ProcessableSeasons, which
214-
* should include the total episodes a sesaon has + the total available
214+
* should include the total episodes a season has + the total available
215215
* episodes that each season currently has. Unlike processMovie, this method
216216
* does not take an `is4k` option. We handle both the 4k _and_ non 4k status
217217
* in one method.
@@ -639,6 +639,21 @@ class BaseScanner<T> {
639639
get protectedBundleSize(): number {
640640
return this.bundleSize;
641641
}
642+
643+
protected async processUnmonitoredMovie(tmdbId: number): Promise<void> {
644+
const mediaRepository = getRepository(Media);
645+
await this.asyncLock.dispatch(tmdbId, async () => {
646+
const existing = await this.getExisting(tmdbId, MediaType.MOVIE);
647+
if (existing && existing.status === MediaStatus.PROCESSING) {
648+
existing.status = MediaStatus.UNKNOWN;
649+
await mediaRepository.save(existing);
650+
this.log(
651+
`Movie TMDB ID ${tmdbId} unmonitored from Radarr. Media status set to UNKNOWN.`,
652+
'info'
653+
);
654+
}
655+
});
656+
}
642657
}
643658

644659
export default BaseScanner;

server/lib/scanners/radarr/index.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,13 @@ class RadarrScanner
7979
}
8080

8181
private async processRadarrMovie(radarrMovie: RadarrMovie): Promise<void> {
82-
if (!radarrMovie.monitored && !radarrMovie.hasFile) {
83-
this.log(
84-
'Title is unmonitored and has not been downloaded. Skipping item.',
85-
'debug',
86-
{
87-
title: radarrMovie.title,
88-
}
89-
);
82+
const settings = getSettings();
83+
if (
84+
settings.main.removeUnmonitoredEnabled &&
85+
!radarrMovie.monitored &&
86+
!radarrMovie.hasFile
87+
) {
88+
this.processUnmonitoredMovie(radarrMovie.tmdbId);
9089
return;
9190
}
9291

server/lib/settings/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export interface MainSettings {
144144
mediaServerType: number;
145145
partialRequestsEnabled: boolean;
146146
enableSpecialEpisodes: boolean;
147+
removeUnmonitoredEnabled: boolean;
147148
locale: string;
148149
youtubeUrl: string;
149150
}
@@ -195,6 +196,7 @@ interface FullPublicSettings extends PublicSettings {
195196
jellyfinServerName?: string;
196197
partialRequestsEnabled: boolean;
197198
enableSpecialEpisodes: boolean;
199+
removeUnmonitoredEnabled: boolean;
198200
cacheImages: boolean;
199201
vapidPublic: string;
200202
enablePushRegistration: boolean;
@@ -401,6 +403,7 @@ class Settings {
401403
mediaServerType: MediaServerType.NOT_CONFIGURED,
402404
partialRequestsEnabled: true,
403405
enableSpecialEpisodes: false,
406+
removeUnmonitoredEnabled: false,
404407
locale: 'en',
405408
youtubeUrl: '',
406409
},
@@ -688,6 +691,7 @@ class Settings {
688691
mediaServerType: this.main.mediaServerType,
689692
partialRequestsEnabled: this.data.main.partialRequestsEnabled,
690693
enableSpecialEpisodes: this.data.main.enableSpecialEpisodes,
694+
removeUnmonitoredEnabled: this.data.main.removeUnmonitoredEnabled,
691695
cacheImages: this.data.main.cacheImages,
692696
vapidPublic: this.vapidPublic,
693697
enablePushRegistration: this.data.notifications.agents.webpush.enabled,

src/components/Settings/SettingsMain/index.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ const messages = defineMessages('components.Settings.SettingsMain', {
6464
validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash',
6565
partialRequestsEnabled: 'Allow Partial Series Requests',
6666
enableSpecialEpisodes: 'Allow Special Episodes Requests',
67+
removeUnmonitoredEnabled: 'Remove Unmonitored Media',
68+
removeUnmonitoredExplanation:
69+
'Remove Movies from Jellyseerr that are not available and have been un-monitored since',
6770
locale: 'Display Language',
6871
youtubeUrl: 'YouTube URL',
6972
youtubeUrlTip:
@@ -175,6 +178,7 @@ const SettingsMain = () => {
175178
enableSpecialEpisodes: data?.enableSpecialEpisodes,
176179
cacheImages: data?.cacheImages,
177180
youtubeUrl: data?.youtubeUrl,
181+
removeUnmonitoredEnabled: data?.removeUnmonitoredEnabled,
178182
}}
179183
enableReinitialize
180184
validationSchema={MainSettingsSchema}
@@ -195,6 +199,7 @@ const SettingsMain = () => {
195199
enableSpecialEpisodes: values.enableSpecialEpisodes,
196200
cacheImages: values.cacheImages,
197201
youtubeUrl: values.youtubeUrl,
202+
removeUnmonitoredEnabled: values.removeUnmonitoredEnabled,
198203
});
199204
mutate('/api/v1/settings/public');
200205
mutate('/api/v1/status');
@@ -535,6 +540,35 @@ const SettingsMain = () => {
535540
/>
536541
</div>
537542
</div>
543+
<div className="form-row">
544+
<label
545+
htmlFor="removeUnmonitoredEnabled"
546+
className="checkbox-label"
547+
>
548+
<span className="mr-2">
549+
{intl.formatMessage(messages.removeUnmonitoredEnabled)}
550+
</span>
551+
<SettingsBadge badgeType="experimental" />
552+
<span className="label-tip">
553+
{intl.formatMessage(
554+
messages.removeUnmonitoredExplanation
555+
)}
556+
</span>
557+
</label>
558+
<div className="form-input-area">
559+
<Field
560+
type="checkbox"
561+
id="removeUnmonitoredEnabled"
562+
name="removeUnmonitoredEnabled"
563+
onChange={() => {
564+
setFieldValue(
565+
'removeUnmonitoredEnabled',
566+
!values.removeUnmonitoredEnabled
567+
);
568+
}}
569+
/>
570+
</div>
571+
</div>
538572
<div className="form-row">
539573
<label htmlFor="youtubeUrl" className="text-label">
540574
{intl.formatMessage(messages.youtubeUrl)}

src/context/SettingsContext.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const defaultSettings = {
2424
mediaServerType: MediaServerType.NOT_CONFIGURED,
2525
partialRequestsEnabled: true,
2626
enableSpecialEpisodes: false,
27+
removeUnmonitoredEnabled: false,
2728
cacheImages: false,
2829
vapidPublic: '',
2930
enablePushRegistration: false,

src/i18n/locale/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@
983983
"components.Settings.SettingsMain.partialRequestsEnabled": "Allow Partial Series Requests",
984984
"components.Settings.SettingsMain.streamingRegion": "Streaming Region",
985985
"components.Settings.SettingsMain.streamingRegionTip": "Show streaming sites by regional availability",
986+
"components.Settings.SettingsMain.removeUnmonitoredFromRequestsEnabled": "Remove Request for Movies that have been un-monitored since",
986987
"components.Settings.SettingsMain.toastApiKeyFailure": "Something went wrong while generating a new API key.",
987988
"components.Settings.SettingsMain.toastApiKeySuccess": "New API key generated successfully!",
988989
"components.Settings.SettingsMain.toastSettingsFailure": "Something went wrong while saving settings.",

src/pages/_app.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ CoreApp.getInitialProps = async (initialProps) => {
242242
mediaServerType: MediaServerType.NOT_CONFIGURED,
243243
partialRequestsEnabled: true,
244244
enableSpecialEpisodes: false,
245+
removeUnmonitoredEnabled: false,
245246
cacheImages: false,
246247
vapidPublic: '',
247248
enablePushRegistration: false,

0 commit comments

Comments
 (0)