added recent grab window to seeker settings

This commit is contained in:
Flaminel committed 2026-10-20 15:55:52 +03:00
1 parent 330130d7bc
commit a3441376f4
7 files changed
+45 -1

No files matched your search

@@ -54,4 +54,5 @@ export const NEW_FEATURES: NewFeature[] = [
{ id: 'theme-follow-system' },
{ id: 'errored-downloads' },
{ id: 'seeker-include-tags' },
{ id: 'seeker-recent-grab-window' },
];
@@ -243,6 +243,7 @@ export class DocumentationService {
'skipTags': 'instance-skip-tags',
'activeDownloadLimit': 'instance-active-download-limit',
'ignoreStruckDownloads': 'instance-ignore-struck-downloads',
'recentGrabWindowHours': 'instance-recent-grab-window',
'minCycleTimeDays': 'instance-min-cycle-time-days',
},
};
@@ -134,6 +134,17 @@
(checkedChange)="patchInstance($index, { ignoreStruckDownloads: $event })"
helpKey="seeker:ignoreStruckDownloads"
featureId="seeker-ignore-struck-downloads" />
<app-number-input
label="Recent Grab Window (Hours)"
placeholder="24"
hint="Skip items the arr grabbed within this many hours, even after the download left the queue (0 = disabled)"
[value]="instance.recentGrabWindowHours"
[min]="0"
[max]="168"
(valueChange)="updateInstanceRecentGrabWindowHours($index, $event)"
helpKey="seeker:recentGrabWindowHours"
featureId="seeker-recent-grab-window"
/>
<app-number-input
label="Min Cycle Time (Days)"
placeholder="7"
@@ -18,6 +18,7 @@ const SONARR: SeekerInstanceConfig = {
arrInstanceEnabled: true,
activeDownloadLimit: 3,
ignoreStruckDownloads: false,
recentGrabWindowHours: 24,
minCycleTimeDays: 7,
monitoredOnly: true,
useCutoff: false,
@@ -35,6 +36,7 @@ const RADARR: SeekerInstanceConfig = {
arrInstanceEnabled: true,
activeDownloadLimit: 5,
ignoreStruckDownloads: true,
recentGrabWindowHours: 48,
minCycleTimeDays: 14,
monitoredOnly: false,
useCutoff: true,
@@ -377,9 +379,11 @@ describe('SeekerComponent', () => {
const { fixture, component } = setup();
setNumberField(fixture, 'Active Download Limit', '9');
setNumberField(fixture, 'Recent Grab Window', '48');
setNumberField(fixture, 'Min Cycle Time', '21');
expect(component.instances()[0].activeDownloadLimit).toBe(9);
expect(component.instances()[0].recentGrabWindowHours).toBe(48);
expect(component.instances()[0].minCycleTimeDays).toBe(21);
});
@@ -387,9 +391,11 @@ describe('SeekerComponent', () => {
const { fixture, component } = setup();
setNumberField(fixture, 'Active Download Limit', '');
setNumberField(fixture, 'Recent Grab Window', '');
setNumberField(fixture, 'Min Cycle Time', '');
expect(component.instances()[0].activeDownloadLimit).toBe(3);
expect(component.instances()[0].recentGrabWindowHours).toBe(24);
expect(component.instances()[0].minCycleTimeDays).toBe(7);
});
@@ -487,7 +493,7 @@ describe('SeekerComponent', () => {
component.seekerForm.searchInterval().value.set(10);
component.seekerForm.selectionStrategy().value.set(SelectionStrategy.NewestFirst);
component.seekerForm.postReleaseGraceHours().value.set(24);
component.patchInstance(0, { skipTags: ['gamma'], includeTags: ['anime'], ignoreStruckDownloads: true });
component.patchInstance(0, { skipTags: ['gamma'], includeTags: ['anime'], ignoreStruckDownloads: true, recentGrabWindowHours: 48 });
fixture.detectChanges();
expect(component.dirty()).toBe(true);
@@ -510,6 +516,7 @@ describe('SeekerComponent', () => {
includeTags: ['anime'],
activeDownloadLimit: 3,
ignoreStruckDownloads: true,
recentGrabWindowHours: 48,
minCycleTimeDays: 7,
monitoredOnly: true,
useCutoff: false,
@@ -522,6 +529,7 @@ describe('SeekerComponent', () => {
includeTags: [],
activeDownloadLimit: 5,
ignoreStruckDownloads: true,
recentGrabWindowHours: 48,
minCycleTimeDays: 14,
monitoredOnly: false,
useCutoff: true,
@@ -75,6 +75,7 @@ interface InstanceState {
arrInstanceEnabled: boolean;
activeDownloadLimit: number;
ignoreStruckDownloads: boolean;
recentGrabWindowHours: number;
minCycleTimeDays: number;
monitoredOnly: boolean;
useCutoff: boolean;
@@ -173,6 +174,7 @@ export class SeekerComponent implements HasPendingChanges {
arrInstanceEnabled: i.arrInstanceEnabled,
activeDownloadLimit: i.activeDownloadLimit,
ignoreStruckDownloads: i.ignoreStruckDownloads,
recentGrabWindowHours: i.recentGrabWindowHours,
minCycleTimeDays: i.minCycleTimeDays,
monitoredOnly: i.monitoredOnly,
useCutoff: i.useCutoff,
@@ -219,6 +221,10 @@ export class SeekerComponent implements HasPendingChanges {
this.patchInstance(index, { minCycleTimeDays: days ?? 7 });
}
updateInstanceRecentGrabWindowHours(index: number, hours: number | null): void {
this.patchInstance(index, { recentGrabWindowHours: hours ?? 24 });
}
getInstanceIcon(instanceType: string): string {
return `icons/ext/${instanceType.toLowerCase()}-light.svg`;
}
@@ -241,6 +247,7 @@ export class SeekerComponent implements HasPendingChanges {
includeTags: i.includeTags,
activeDownloadLimit: i.activeDownloadLimit,
ignoreStruckDownloads: i.ignoreStruckDownloads,
recentGrabWindowHours: i.recentGrabWindowHours,
minCycleTimeDays: i.minCycleTimeDays,
monitoredOnly: i.monitoredOnly,
useCutoff: i.useCutoff,
@@ -21,6 +21,7 @@ export interface SeekerInstanceConfig {
arrInstanceEnabled: boolean;
activeDownloadLimit: number;
ignoreStruckDownloads: boolean;
recentGrabWindowHours: number;
minCycleTimeDays: number;
monitoredOnly: boolean;
useCutoff: boolean;
@@ -44,6 +45,7 @@ export interface UpdateSeekerInstanceConfig {
includeTags: string[];
activeDownloadLimit: number;
ignoreStruckDownloads: boolean;
recentGrabWindowHours: number;
minCycleTimeDays: number;
monitoredOnly: boolean;
useCutoff: boolean;
+14
View File
@@ -249,6 +249,20 @@ Only downloads that have received strikes in the most recent completed `Queue Cl
</ConfigSection>
<ConfigSection
title="Recent Grab Window"
>
Seeker reads the arr's grab history for this many hours and skips every item grabbed in that window, even when the download already left the queue (imported, failed and removed, grabbed by RSS or another tool).
For Sonarr, a grabbed episode skips its whole season for the window.
Set to `0` to turn this off.
Default is `24`, maximum is `168`.
</ConfigSection>
<ConfigSection
title="Min Cycle Time (Days)"
>