From 18941ec259832f291474e5f140fb3f525ed5872c Mon Sep 17 00:00:00 2001 From: Eduard Marbach Date: Fri, 17 Jan 2025 18:38:41 +0100 Subject: [PATCH] feat: add experimental support for cloning quality profiles --- docs/docs/comparison.mdx | 5 +++ docs/docs/configuration/config-file.md | 38 +++++++++++++++++- docs/docs/examples.md | 6 +-- examples/full/config/config.yml | 5 +++ src/config.ts | 53 +++++++++++++++++++++++++- src/types/config.types.ts | 1 + 6 files changed, 101 insertions(+), 7 deletions(-) diff --git a/docs/docs/comparison.mdx b/docs/docs/comparison.mdx index 644fe93..4e3b932 100644 --- a/docs/docs/comparison.mdx +++ b/docs/docs/comparison.mdx @@ -33,6 +33,7 @@ Notes: | Clear all Custom Formats | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Modify Scores | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Profile renaming | :white_check_mark: | | | +| Profile cloning | :white_check_mark: | | | ## Sonarr @@ -51,6 +52,7 @@ Notes: | Clear all Custom Formats | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Modify Scores | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Profile renaming | :white_check_mark: | | | +| Profile cloning | :white_check_mark: | | | ## Whisparr @@ -64,6 +66,7 @@ Notes: | Clear all Custom Formats | :white_check_mark: | | | | Modify Scores | :white_check_mark: | | | | Profile renaming | :white_check_mark: | | | +| Profile cloning | :white_check_mark: | | | ## Readarr @@ -77,6 +80,7 @@ Notes: | Clear all Custom Formats | :white_check_mark: | | | | Modify Scores | :white_check_mark: | | | | Profile renaming | :white_check_mark: | | | +| Profile cloning | :white_check_mark: | | | ## Lidarr @@ -90,3 +94,4 @@ Notes: | Clear all Custom Formats | :white_check_mark: | | | | Modify Scores | :white_check_mark: | | | | Profile renaming | :white_check_mark: | | | +| Profile cloning | :white_check_mark: | | | diff --git a/docs/docs/configuration/config-file.md b/docs/docs/configuration/config-file.md index 3e0c80f..15369c2 100644 --- a/docs/docs/configuration/config-file.md +++ b/docs/docs/configuration/config-file.md @@ -179,6 +179,11 @@ sonarr: # - from: WEB-1080p # to: RenamedProfile + # Ability to clone profiles + # cloneQualityProfiles: + # - from: RenamedExampleProfile + # to: ClonedProfile + # Radarr Configuration radarr: instance1: # Instance name (can be any unique identifier) @@ -361,8 +366,37 @@ Notes: - not supported in templates and will therefore not be merged! - rename order will be displayed in `DEBUG` log like: `DEBUG [16:37:09.377]: Will rename quality profiles in this order: 'ExampleProfile' -> 'RenamedExampleProfile','[German] HD Bluray + WEB' -> 'RenamedProfile'` -- experimental, available since `v1.10.0` -- +- **experimental**, available since `v1.10.0` + +## Quality Profile Cloning {#quality-profile-clone} + +Support has been added to allow cloning quality profiles. +This is useful if you use existing templates for example from TRaSH-Guides but want to duplicate and slightly adjust some Custom Format scores or mappings. + +We achieve the clone by duplicating all quality profiles and duplicating all profile references in the custom formats. + +:::tip +The **ordering** of `rename` and `clone` is important. At the moment we `rename` first and then `clone`! +::: + +```yml +# ... + +sonarr: + instance1: + # ... + + # Ability to clone profiles + cloneQualityProfiles: + - from: ExampleProfile # must be the exact name of the existing profile + to: ClonedProfile1 # will be the new profile +``` + +Notes: + +- not supported in templates and will therefore not be merged! +- clone order will be displayed in `DEBUG` log +- **experimental**, available since `v1.10.0` ## Usage diff --git a/docs/docs/examples.md b/docs/docs/examples.md index d79c1b4..98b684c 100644 --- a/docs/docs/examples.md +++ b/docs/docs/examples.md @@ -297,10 +297,8 @@ sonarr: ### Using templates from TRaSH-Guides/Recyclarr but different names -Some features are available others not yet. - -- renaming quality profiles. How to implement see here: [Renaming Feature](./configuration/config-file.md##quality-profile-rename) -- clone [#115](https://github.com/raydak-labs/configarr/issues/115) +- renaming quality profiles. How to implement see here: [Renaming Feature](./configuration/config-file.md#quality-profile-rename) +- cloning quality profiles. How to implement see here: [Cloning Feature](./configuration/config-file.md#quality-profile-clone) - duplicate templates: You can copy those templates and paste them into a locally mounted folder. Then you can rename them in the templates as required. diff --git a/examples/full/config/config.yml b/examples/full/config/config.yml index 95a09bb..1ff1b3d 100644 --- a/examples/full/config/config.yml +++ b/examples/full/config/config.yml @@ -63,6 +63,11 @@ sonarr: # - from: ExampleProfile # to: RenamedExampleProfile + # Ability to clone profiles + # cloneQualityProfiles: + # - from: RenamedExampleProfile + # to: ClonedProfile + radarr: instance1: # Set the URL/API Key to your actual instance diff --git a/src/config.ts b/src/config.ts index a7e62c2..1841cb6 100644 --- a/src/config.ts +++ b/src/config.ts @@ -29,6 +29,7 @@ import { MergedConfigInstance, } from "./types/config.types"; import { TrashQP } from "./types/trashguide.types"; +import { cloneWithJSON } from "./util"; let config: ConfigSchema; let secrets: any; @@ -397,7 +398,57 @@ export const mergeConfigsAndTemplates = async ( } } - // TODO clone + // Cloning quality profiles + if (instanceConfig.cloneQualityProfiles && instanceConfig.cloneQualityProfiles.length > 0) { + const cloneOrder: string[] = []; + + const newProfiles: ConfigQualityProfile[] = []; + + instanceConfig.cloneQualityProfiles.forEach((e) => { + const cloneSource = e.from; + const cloneTarget = e.to; + + cloneOrder.push(`'${cloneSource}' -> '${cloneTarget}'`); + + let cloneQPReferences = 0; + let cloneCFAssignments = 0; + + mergedTemplates.quality_profiles.forEach((p) => { + if (p.name === cloneSource) { + const clonedQP = cloneWithJSON(p); + clonedQP.name = cloneTarget; + newProfiles.push(clonedQP); + cloneQPReferences++; + } + }); + + mergedTemplates.custom_formats.forEach((p) => { + const cf = p.assign_scores_to?.find((cf) => { + if (cf.name === cloneSource) { + cloneCFAssignments++; + return true; + } + return false; + }); + + if (cf) { + p.assign_scores_to?.push({ name: cloneTarget, score: cf.score }); + } + }); + + if (cloneQPReferences + cloneCFAssignments > 0) { + logger.debug( + `Cloning profile: source '${cloneSource}' - target '${cloneTarget}'. Found QP references ${cloneQPReferences}, CF references ${cloneCFAssignments}`, + ); + } + }); + + mergedTemplates.quality_profiles.push(...newProfiles); + + if (cloneOrder.length > 0) { + logger.debug(`Will clone quality profiles in this order: ${cloneOrder}`); + } + } const recyclarrProfilesMerged = mergedTemplates.quality_profiles.reduce>((p, c) => { const profile = p.get(c.name); diff --git a/src/types/config.types.ts b/src/types/config.types.ts index 3a45f1c..9199429 100644 --- a/src/types/config.types.ts +++ b/src/types/config.types.ts @@ -55,6 +55,7 @@ export type InputConfigArrInstance = { /* @experimental */ media_naming_api?: MediaNamingApiType; renameQualityProfiles?: { from: string; to: string }[]; + cloneQualityProfiles?: { from: string; to: string }[]; // this is recyclarr specific: https://recyclarr.dev/wiki/yaml/config-reference/media-naming/ media_naming?: MediaNamingType;