From 46c4c4e4ff615b45683409b83f0f32e04a11b104 Mon Sep 17 00:00:00 2001 From: Sam Chau Date: Thu, 22 Jan 2026 09:56:15 +1030 Subject: [PATCH] feat: add tag to filter options in upgrades --- src/lib/server/upgrades/normalize.ts | 16 +++++++++++++--- src/lib/server/upgrades/processor.ts | 15 ++++++++++++--- src/lib/server/upgrades/types.ts | 1 + src/lib/shared/filters.ts | 7 +++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/lib/server/upgrades/normalize.ts b/src/lib/server/upgrades/normalize.ts index 8d7dfc9..b74911e 100644 --- a/src/lib/server/upgrades/normalize.ts +++ b/src/lib/server/upgrades/normalize.ts @@ -17,12 +17,14 @@ import type { UpgradeItem } from './types.ts'; * @param movieFile - The movie file (if exists) * @param profile - The quality profile * @param cutoffPercent - The cutoff percentage from filter config (0-100) + * @param tagMap - Map of tag IDs to labels for resolving tag names */ export function normalizeRadarrItem( movie: RadarrMovie, movieFile: RadarrMovieFile | undefined, profile: RadarrQualityProfile | undefined, - cutoffPercent: number + cutoffPercent: number, + tagMap?: Map ): UpgradeItem { // Calculate current score const currentScore = movieFile?.customFormatScore ?? 0; @@ -50,6 +52,12 @@ export function normalizeRadarrItem( const digitalRelease = movie.digitalRelease ?? null; const physicalRelease = movie.physicalRelease ?? null; + // Convert tag IDs to labels + const tags = (movie.tags ?? []) + .map((tagId) => tagMap?.get(tagId) ?? '') + .filter(Boolean) + .join(', '); + return { // Core fields (snake_case for filter matching) id: movie.id, @@ -65,6 +73,7 @@ export function normalizeRadarrItem( genres: movie.genres?.join(', ') ?? '', keywords: movie.keywords?.join(', ') ?? '', release_group: movieFile?.releaseGroup ?? '', + tags, popularity: movie.popularity ?? 0, runtime: movie.runtime ?? 0, size_on_disk: sizeOnDiskGB, @@ -93,11 +102,12 @@ export function normalizeRadarrItems( movies: RadarrMovie[], movieFileMap: Map, profileMap: Map, - cutoffPercent: number + cutoffPercent: number, + tagMap?: Map ): UpgradeItem[] { return movies.map((movie) => { const movieFile = movieFileMap.get(movie.id); const profile = profileMap.get(movie.qualityProfileId); - return normalizeRadarrItem(movie, movieFile, profile, cutoffPercent); + return normalizeRadarrItem(movie, movieFile, profile, cutoffPercent, tagMap); }); } diff --git a/src/lib/server/upgrades/processor.ts b/src/lib/server/upgrades/processor.ts index 0c8279b..1bf359c 100644 --- a/src/lib/server/upgrades/processor.ts +++ b/src/lib/server/upgrades/processor.ts @@ -204,16 +204,25 @@ export async function processUpgradeConfig( const movieFileMap = new Map(movieFiles.map((mf) => [mf.movieId, mf])); const profileMap = new Map(profiles.map((p) => [p.id, p])); + // Fetch tags for normalization and cooldown + const tags = await client.getTags(); + const tagMap = new Map(tags.map((t) => [t.id, t.label])); + // Step 2: Normalize items - const normalizedItems = normalizeRadarrItems(movies, movieFileMap, profileMap, filter.cutoff); + const normalizedItems = normalizeRadarrItems( + movies, + movieFileMap, + profileMap, + filter.cutoff, + tagMap + ); // Step 3: Apply filter rules const matchedItems = normalizedItems.filter((item) => evaluateGroup(item as unknown as Record, filter.group) ); - // Step 4: Filter by cooldown - const tags = await client.getTags(); + // Step 4: Filter by cooldown (tags already fetched above) const afterCooldownItems = filterByCooldown(matchedItems, tags, filter.searchCooldown); const afterCooldownCount = afterCooldownItems.length; diff --git a/src/lib/server/upgrades/types.ts b/src/lib/server/upgrades/types.ts index 868f9a0..a787b53 100644 --- a/src/lib/server/upgrades/types.ts +++ b/src/lib/server/upgrades/types.ts @@ -24,6 +24,7 @@ export interface UpgradeItem { genres: string; keywords: string; release_group: string; + tags: string; popularity: number; runtime: number; size_on_disk: number; diff --git a/src/lib/shared/filters.ts b/src/lib/shared/filters.ts index 54b84b3..155ef72 100644 --- a/src/lib/shared/filters.ts +++ b/src/lib/shared/filters.ts @@ -233,6 +233,13 @@ export const filterFields: FilterField[] = [ operators: textOperators, valueType: 'text' }, + { + id: 'tags', + label: 'Tags', + description: 'Tags applied to the item', + operators: textOperators, + valueType: 'text' + }, // Number fields {