feat: Deprecate `names` list for custom formats in config YAML

gui
Robert Dailey 2 years ago
parent 008ca5dd10
commit 154ec7cf7e

@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- JSON Schema added to the config template YAML file. - JSON Schema added to the config template YAML file.
- `names` list under `custom_formats` in config YAML is now deprecated. Use `trash_ids` to list your
custom formats instead.
## [2.2.1] - 2022-06-18 ## [2.2.1] - 2022-06-18

@ -127,7 +127,7 @@
"items": { "items": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"description": "A list of one or more sets of custom formats (by name and/or trash_id), each with an optional set of quality profiles names that identify which quality profiles to assign the scores for those custom formats to.", "description": "A list of one or more sets of custom formats each with an optional set of quality profiles names that identify which quality profiles to assign the scores for those custom formats to.",
"anyOf": [ "anyOf": [
{"required": ["trash_ids"]}, {"required": ["trash_ids"]},
{"required": ["names"]} {"required": ["names"]}

@ -11,7 +11,7 @@
# Configuration specific to Sonarr # Configuration specific to Sonarr
sonarr: sonarr:
# Set the URL/API Key to your actual instance # Set the URL/API Key to your actual instance
- base_url: http://localhost:8989 - base_url: http://localhost:8989
api_key: f7e74ba6c80046e39e076a27af5a8444 api_key: f7e74ba6c80046e39e076a27af5a8444
@ -46,19 +46,17 @@ radarr:
delete_old_custom_formats: false delete_old_custom_formats: false
custom_formats: custom_formats:
# A list of custom formats to sync to Radarr. Must match the "name" in the importable JSON. # A list of custom formats to sync to Radarr. Must match the "trash_id" in the guide JSON.
# Do NOT use the heading names here, those do not work! These are case-insensitive. - trash_ids:
- names: - ed38b889b31be83fda192888e2286d83 # BR-DISK
- BR-DISK - 90cedc1fea7ea5d11298bebd3d1d3223 # EVO (no WEBDL)
- EVO (no WEBDL) - 90a6f9a284dff5103f6346090e6280c8 # LQ
- LQ - dc98083864ea246d05a42df0d05f81cc # x265 (720/1080p)
- x265 (720/1080p) - b8cd450cbfa689c0259a01d9e29ba3d6 # 3D
- 3D
# Uncomment the below properties to specify one or more quality profiles that should be # Uncomment the below properties to specify one or more quality profiles that should be
# updated with scores from the guide for each custom format. Without this, custom formats # updated with scores from the guide for each custom format. Without this, custom formats
# are synced to Radarr but no scores are set in any quality profiles. # are synced to Radarr but no scores are set in any quality profiles.
# quality_profiles: # quality_profiles:
# - name: Quality Profile 1 # - name: Quality Profile 1
# - name: Quality Profile 2 # - name: Quality Profile 2

@ -4,6 +4,7 @@ using FluentAssertions;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Serilog;
using TestLibrary.FluentAssertions; using TestLibrary.FluentAssertions;
using TrashLib.Radarr.Config; using TrashLib.Radarr.Config;
using TrashLib.Radarr.CustomFormat.Guide; using TrashLib.Radarr.CustomFormat.Guide;
@ -21,7 +22,7 @@ public class GuideProcessorTest
private class TestGuideProcessorSteps : IGuideProcessorSteps private class TestGuideProcessorSteps : IGuideProcessorSteps
{ {
public ICustomFormatStep CustomFormat { get; } = new CustomFormatStep(); public ICustomFormatStep CustomFormat { get; } = new CustomFormatStep();
public IConfigStep Config { get; } = new ConfigStep(); public IConfigStep Config { get; } = new ConfigStep(Substitute.For<ILogger>());
public IQualityProfileStep QualityProfile { get; } = new QualityProfileStep(); public IQualityProfileStep QualityProfile { get; } = new QualityProfileStep();
} }

@ -1,6 +1,7 @@
using FluentAssertions; using FluentAssertions;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NUnit.Framework; using NUnit.Framework;
using TestLibrary.AutoFixture;
using TrashLib.Radarr.Config; using TrashLib.Radarr.Config;
using TrashLib.Radarr.CustomFormat.Models; using TrashLib.Radarr.CustomFormat.Models;
using TrashLib.Radarr.CustomFormat.Models.Cache; using TrashLib.Radarr.CustomFormat.Models.Cache;
@ -13,8 +14,8 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.GuideSteps;
[Parallelizable(ParallelScope.All)] [Parallelizable(ParallelScope.All)]
public class ConfigStepTest public class ConfigStepTest
{ {
[Test] [Test, AutoMockData]
public void Cache_names_are_used_instead_of_name_in_json_data() public void Cache_names_are_used_instead_of_name_in_json_data(ConfigStep processor)
{ {
var testProcessedCfs = new List<ProcessedCustomFormatData> var testProcessedCfs = new List<ProcessedCustomFormatData>
{ {
@ -30,7 +31,6 @@ public class ConfigStepTest
} }
}; };
var processor = new ConfigStep();
processor.Process(testProcessedCfs, testConfig); processor.Process(testProcessedCfs, testConfig);
processor.CustomFormatsNotInGuide.Should().BeEmpty(); processor.CustomFormatsNotInGuide.Should().BeEmpty();
@ -46,8 +46,8 @@ public class ConfigStepTest
.WhenTypeIs<JToken>()); .WhenTypeIs<JToken>());
} }
[Test] [Test, AutoMockData]
public void Custom_formats_missing_from_config_are_skipped() public void Custom_formats_missing_from_config_are_skipped(ConfigStep processor)
{ {
var testProcessedCfs = new List<ProcessedCustomFormatData> var testProcessedCfs = new List<ProcessedCustomFormatData>
{ {
@ -63,7 +63,6 @@ public class ConfigStepTest
} }
}; };
var processor = new ConfigStep();
processor.Process(testProcessedCfs, testConfig); processor.Process(testProcessedCfs, testConfig);
processor.CustomFormatsNotInGuide.Should().BeEmpty(); processor.CustomFormatsNotInGuide.Should().BeEmpty();
@ -81,8 +80,8 @@ public class ConfigStepTest
.WhenTypeIs<JToken>()); .WhenTypeIs<JToken>());
} }
[Test] [Test, AutoMockData]
public void Custom_formats_missing_from_guide_are_added_to_not_in_guide_list() public void Custom_formats_missing_from_guide_are_added_to_not_in_guide_list(ConfigStep processor)
{ {
var testProcessedCfs = new List<ProcessedCustomFormatData> var testProcessedCfs = new List<ProcessedCustomFormatData>
{ {
@ -98,7 +97,6 @@ public class ConfigStepTest
} }
}; };
var processor = new ConfigStep();
processor.Process(testProcessedCfs, testConfig); processor.Process(testProcessedCfs, testConfig);
processor.CustomFormatsNotInGuide.Should().BeEquivalentTo(new List<string> {"name3"}, op => op processor.CustomFormatsNotInGuide.Should().BeEquivalentTo(new List<string> {"name3"}, op => op
@ -118,8 +116,8 @@ public class ConfigStepTest
.WhenTypeIs<JToken>()); .WhenTypeIs<JToken>());
} }
[Test] [Test, AutoMockData]
public void Duplicate_config_name_and_id_are_ignored() public void Duplicate_config_name_and_id_are_ignored(ConfigStep processor)
{ {
var testProcessedCfs = new List<ProcessedCustomFormatData> var testProcessedCfs = new List<ProcessedCustomFormatData>
{ {
@ -135,7 +133,6 @@ public class ConfigStepTest
} }
}; };
var processor = new ConfigStep();
processor.Process(testProcessedCfs, testConfig); processor.Process(testProcessedCfs, testConfig);
processor.CustomFormatsNotInGuide.Should().BeEmpty(); processor.CustomFormatsNotInGuide.Should().BeEmpty();
@ -148,8 +145,8 @@ public class ConfigStepTest
}); });
} }
[Test] [Test, AutoMockData]
public void Duplicate_config_names_are_ignored() public void Duplicate_config_names_are_ignored(ConfigStep processor)
{ {
var testProcessedCfs = new List<ProcessedCustomFormatData> var testProcessedCfs = new List<ProcessedCustomFormatData>
{ {
@ -161,7 +158,6 @@ public class ConfigStepTest
new() {Names = new List<string> {"name1", "name1"}} new() {Names = new List<string> {"name1", "name1"}}
}; };
var processor = new ConfigStep();
processor.Process(testProcessedCfs, testConfig); processor.Process(testProcessedCfs, testConfig);
processor.CustomFormatsNotInGuide.Should().BeEmpty(); processor.CustomFormatsNotInGuide.Should().BeEmpty();
@ -174,8 +170,8 @@ public class ConfigStepTest
}); });
} }
[Test] [Test, AutoMockData]
public void Find_custom_formats_by_name_and_trash_id() public void Find_custom_formats_by_name_and_trash_id(ConfigStep processor)
{ {
var testProcessedCfs = new List<ProcessedCustomFormatData> var testProcessedCfs = new List<ProcessedCustomFormatData>
{ {
@ -197,7 +193,6 @@ public class ConfigStepTest
} }
}; };
var processor = new ConfigStep();
processor.Process(testProcessedCfs, testConfig); processor.Process(testProcessedCfs, testConfig);
processor.CustomFormatsNotInGuide.Should().BeEmpty(); processor.CustomFormatsNotInGuide.Should().BeEmpty();

@ -2,6 +2,7 @@ using System.Collections.ObjectModel;
using FluentAssertions; using FluentAssertions;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NUnit.Framework; using NUnit.Framework;
using TestLibrary.AutoFixture;
using TestLibrary.FluentAssertions; using TestLibrary.FluentAssertions;
using TrashLib.Radarr.Config; using TrashLib.Radarr.Config;
using TrashLib.Radarr.CustomFormat.Models; using TrashLib.Radarr.CustomFormat.Models;
@ -61,8 +62,8 @@ public class CustomFormatStepTest
}); });
} }
[Test] [Test, AutoMockData]
public void Cache_entry_is_not_set_when_id_is_different() public void Cache_entry_is_not_set_when_id_is_different(CustomFormatStep processor)
{ {
var guideData = new List<CustomFormatData> var guideData = new List<CustomFormatData>
{ {
@ -82,7 +83,6 @@ public class CustomFormatStepTest
} }
}; };
var processor = new CustomFormatStep();
processor.Process(guideData, testConfig, testCache); processor.Process(guideData, testConfig, testCache);
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -95,8 +95,8 @@ public class CustomFormatStepTest
}); });
} }
[Test] [Test, AutoMockData]
public void Cfs_not_in_config_are_skipped() public void Cfs_not_in_config_are_skipped(CustomFormatStep processor)
{ {
var ctx = new Context(); var ctx = new Context();
var testConfig = new List<CustomFormatConfig> var testConfig = new List<CustomFormatConfig>
@ -104,7 +104,6 @@ public class CustomFormatStepTest
new() {Names = new List<string> {"name1", "name3"}} new() {Names = new List<string> {"name1", "name3"}}
}; };
var processor = new CustomFormatStep();
processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache());
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -118,8 +117,8 @@ public class CustomFormatStepTest
}); });
} }
[Test] [Test, AutoMockData]
public void Config_cfs_in_different_sections_are_processed() public void Config_cfs_in_different_sections_are_processed(CustomFormatStep processor)
{ {
var ctx = new Context(); var ctx = new Context();
var testConfig = new List<CustomFormatConfig> var testConfig = new List<CustomFormatConfig>
@ -128,7 +127,6 @@ public class CustomFormatStepTest
new() {Names = new List<string> {"name2"}} new() {Names = new List<string> {"name2"}}
}; };
var processor = new CustomFormatStep();
processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache());
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -143,8 +141,8 @@ public class CustomFormatStepTest
op => op.Using(new JsonEquivalencyStep())); op => op.Using(new JsonEquivalencyStep()));
} }
[Test] [Test, AutoMockData]
public void Custom_format_is_deleted_if_in_config_and_cache_but_not_in_guide() public void Custom_format_is_deleted_if_in_config_and_cache_but_not_in_guide(CustomFormatStep processor)
{ {
var guideData = new List<CustomFormatData> var guideData = new List<CustomFormatData>
{ {
@ -161,7 +159,6 @@ public class CustomFormatStepTest
TrashIdMappings = new Collection<TrashIdMapping> {new("id1000", "name1")} TrashIdMappings = new Collection<TrashIdMapping> {new("id1000", "name1")}
}; };
var processor = new CustomFormatStep();
processor.Process(guideData, testConfig, testCache); processor.Process(guideData, testConfig, testCache);
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -174,8 +171,8 @@ public class CustomFormatStepTest
}); });
} }
[Test] [Test, AutoMockData]
public void Custom_format_is_deleted_if_not_in_config_but_in_cache_and_in_guide() public void Custom_format_is_deleted_if_not_in_config_but_in_cache_and_in_guide(CustomFormatStep processor)
{ {
var cache = new CustomFormatCache var cache = new CustomFormatCache
{ {
@ -187,7 +184,6 @@ public class CustomFormatStepTest
new("3D", "id1", null, new JObject()) new("3D", "id1", null, new JObject())
}; };
var processor = new CustomFormatStep();
processor.Process(guideCfs, Array.Empty<CustomFormatConfig>(), cache); processor.Process(guideCfs, Array.Empty<CustomFormatConfig>(), cache);
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -196,8 +192,8 @@ public class CustomFormatStepTest
processor.ProcessedCustomFormats.Should().BeEmpty(); processor.ProcessedCustomFormats.Should().BeEmpty();
} }
[Test] [Test, AutoMockData]
public void Custom_format_name_in_cache_is_updated_if_renamed_in_guide_and_config() public void Custom_format_name_in_cache_is_updated_if_renamed_in_guide_and_config(CustomFormatStep processor)
{ {
var guideData = new List<CustomFormatData> var guideData = new List<CustomFormatData>
{ {
@ -214,7 +210,6 @@ public class CustomFormatStepTest
TrashIdMappings = new Collection<TrashIdMapping> {new("id1", "name1")} TrashIdMappings = new Collection<TrashIdMapping> {new("id1", "name1")}
}; };
var processor = new CustomFormatStep();
processor.Process(guideData, testConfig, testCache); processor.Process(guideData, testConfig, testCache);
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -225,8 +220,8 @@ public class CustomFormatStepTest
.BeEquivalentTo(new TrashIdMapping("id1", "name2")); .BeEquivalentTo(new TrashIdMapping("id1", "name2"));
} }
[Test] [Test, AutoMockData]
public void Duplicates_are_recorded_and_removed_from_processed_custom_formats_list() public void Duplicates_are_recorded_and_removed_from_processed_custom_formats_list(CustomFormatStep processor)
{ {
var guideData = new List<CustomFormatData> var guideData = new List<CustomFormatData>
{ {
@ -239,7 +234,6 @@ public class CustomFormatStepTest
new() {Names = new List<string> {"name1"}} new() {Names = new List<string> {"name1"}}
}; };
var processor = new CustomFormatStep();
processor.Process(guideData, testConfig, null); processor.Process(guideData, testConfig, null);
//Dictionary<string, List<ProcessedCustomFormatData>> //Dictionary<string, List<ProcessedCustomFormatData>>
@ -255,8 +249,8 @@ public class CustomFormatStepTest
processor.ProcessedCustomFormats.Should().BeEmpty(); processor.ProcessedCustomFormats.Should().BeEmpty();
} }
[Test] [Test, AutoMockData]
public void Match_cf_names_regardless_of_case_in_config() public void Match_cf_names_regardless_of_case_in_config(CustomFormatStep processor)
{ {
var ctx = new Context(); var ctx = new Context();
var testConfig = new List<CustomFormatConfig> var testConfig = new List<CustomFormatConfig>
@ -264,7 +258,6 @@ public class CustomFormatStepTest
new() {Names = new List<string> {"name1", "NAME1"}} new() {Names = new List<string> {"name1", "NAME1"}}
}; };
var processor = new CustomFormatStep();
processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache());
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -277,8 +270,8 @@ public class CustomFormatStepTest
op => op.Using(new JsonEquivalencyStep())); op => op.Using(new JsonEquivalencyStep()));
} }
[Test] [Test, AutoMockData]
public void Match_custom_format_using_trash_id() public void Match_custom_format_using_trash_id(CustomFormatStep processor)
{ {
var guideData = new List<CustomFormatData> var guideData = new List<CustomFormatData>
{ {
@ -291,7 +284,6 @@ public class CustomFormatStepTest
new() {TrashIds = new List<string> {"id2"}} new() {TrashIds = new List<string> {"id2"}}
}; };
var processor = new CustomFormatStep();
processor.Process(guideData, testConfig, null); processor.Process(guideData, testConfig, null);
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -304,8 +296,8 @@ public class CustomFormatStepTest
}); });
} }
[Test] [Test, AutoMockData]
public void Non_existent_cfs_in_config_are_skipped() public void Non_existent_cfs_in_config_are_skipped(CustomFormatStep processor)
{ {
var ctx = new Context(); var ctx = new Context();
var testConfig = new List<CustomFormatConfig> var testConfig = new List<CustomFormatConfig>
@ -313,7 +305,6 @@ public class CustomFormatStepTest
new() {Names = new List<string> {"doesnt_exist"}} new() {Names = new List<string> {"doesnt_exist"}}
}; };
var processor = new CustomFormatStep();
processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache());
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();
@ -322,8 +313,8 @@ public class CustomFormatStepTest
processor.ProcessedCustomFormats.Should().BeEmpty(); processor.ProcessedCustomFormats.Should().BeEmpty();
} }
[Test] [Test, AutoMockData]
public void Score_from_json_takes_precedence_over_score_from_guide() public void Score_from_json_takes_precedence_over_score_from_guide(CustomFormatStep processor)
{ {
var guideData = new List<CustomFormatData> var guideData = new List<CustomFormatData>
{ {
@ -342,7 +333,6 @@ public class CustomFormatStepTest
} }
}; };
var processor = new CustomFormatStep();
processor.Process(guideData, testConfig, null); processor.Process(guideData, testConfig, null);
processor.DuplicatedCustomFormats.Should().BeEmpty(); processor.DuplicatedCustomFormats.Should().BeEmpty();

@ -1,20 +1,35 @@
using Common.Extensions; using Common.Extensions;
using Serilog;
using TrashLib.Radarr.Config; using TrashLib.Radarr.Config;
using TrashLib.Radarr.CustomFormat.Models; using TrashLib.Radarr.CustomFormat.Models;
namespace TrashLib.Radarr.CustomFormat.Processors.GuideSteps; namespace TrashLib.Radarr.CustomFormat.Processors.GuideSteps;
internal class ConfigStep : IConfigStep public class ConfigStep : IConfigStep
{ {
private readonly ILogger _log;
private readonly List<ProcessedConfigData> _configData = new(); private readonly List<ProcessedConfigData> _configData = new();
private readonly List<string> _customFormatsNotInGuide = new(); private readonly List<string> _customFormatsNotInGuide = new();
public IReadOnlyCollection<string> CustomFormatsNotInGuide => _customFormatsNotInGuide; public IReadOnlyCollection<string> CustomFormatsNotInGuide => _customFormatsNotInGuide;
public IReadOnlyCollection<ProcessedConfigData> ConfigData => _configData; public IReadOnlyCollection<ProcessedConfigData> ConfigData => _configData;
public void Process(IReadOnlyCollection<ProcessedCustomFormatData> processedCfs, public ConfigStep(ILogger log)
IEnumerable<CustomFormatConfig> config)
{ {
_log = log;
}
public void Process(
IReadOnlyCollection<ProcessedCustomFormatData> processedCfs,
IReadOnlyCollection<CustomFormatConfig> config)
{
if (config.SelectMany(x => x.Names).Any())
{
_log.Warning(
"`names` list for `custom_formats` is deprecated and will be removed in the future; use " +
"`trash_ids` instead");
}
foreach (var singleConfig in config) foreach (var singleConfig in config)
{ {
var validCfs = new List<ProcessedCustomFormatData>(); var validCfs = new List<ProcessedCustomFormatData>();

@ -5,7 +5,7 @@ using TrashLib.Radarr.CustomFormat.Models.Cache;
namespace TrashLib.Radarr.CustomFormat.Processors.GuideSteps; namespace TrashLib.Radarr.CustomFormat.Processors.GuideSteps;
internal class CustomFormatStep : ICustomFormatStep public class CustomFormatStep : ICustomFormatStep
{ {
private readonly List<(string, string)> _customFormatsWithOutdatedNames = new(); private readonly List<(string, string)> _customFormatsWithOutdatedNames = new();
private readonly List<ProcessedCustomFormatData> _processedCustomFormats = new(); private readonly List<ProcessedCustomFormatData> _processedCustomFormats = new();

@ -9,5 +9,5 @@ public interface IConfigStep
IReadOnlyCollection<ProcessedConfigData> ConfigData { get; } IReadOnlyCollection<ProcessedConfigData> ConfigData { get; }
void Process(IReadOnlyCollection<ProcessedCustomFormatData> processedCfs, void Process(IReadOnlyCollection<ProcessedCustomFormatData> processedCfs,
IEnumerable<CustomFormatConfig> config); IReadOnlyCollection<CustomFormatConfig> config);
} }

@ -210,35 +210,9 @@ Synchronization]] page.
Radarr **will not be deleted** if you enable this setting. Radarr **will not be deleted** if you enable this setting.
- `custom_formats` (Optional; *Default: No custom formats are synced*)<br> - `custom_formats` (Optional; *Default: No custom formats are synced*)<br>
A list of one or more sets of custom formats (by name and/or trash_id), each with an optional set A list of one or more sets of custom formats each with an optional set of quality profiles names
of quality profiles names that identify which quality profiles to assign the scores for those that identify which quality profiles to assign the scores for those custom formats to. The child
custom formats to. The child properties documented below apply to each element of this list. properties documented below apply to each element of this list.
> **Note:** Even though `names` and `trash_ids` below are marked *optional*, at least one of them
> is required. For example, if `names` is empty you must use `trash_ids` and vice versa. You can
> also use both together if you want.
>
> **Advice:** When would you use `names` or `trash_ids`? Rule of thumb: Stick to `trash_ids`. It's
> more robust and immune to breaking than using names. Names can change, Trash IDs never change.
- `names` (Optional; *`trash_ids` is required if not used*)<br>
A list of one or more custom format names to synchronize to Radarr. The names *must* be taken
from the JSON itself in the guide, for example:
```json
{
"trash_id": "496f355514737f7d83bf7aa4d24f8169",
"name": "TrueHD ATMOS",
"includeCustomFormatWhenRenaming": false
}
```
You take the value of `"name"` above and add it to the list of names like so:
```yml
names:
- TrueHD ATMOS
```
- `trash_ids` (Optional; *`names` is required if not used*)<br> - `trash_ids` (Optional; *`names` is required if not used*)<br>
A list of one or more Trash IDs of custom formats to synchronize to Radarr. The IDs *must* be A list of one or more Trash IDs of custom formats to synchronize to Radarr. The IDs *must* be
@ -264,7 +238,7 @@ Synchronization]] page.
> >
> - If `delete_old_custom_formats` is set to true, custom formats are **deleted** in Radarr if > - If `delete_old_custom_formats` is set to true, custom formats are **deleted** in Radarr if
> you remove them from this list. > you remove them from this list.
> - It's OK for the same custom format to exist in multiple lists of `names`. Recyclarr will > - It's OK for the same custom format to exist in multiple lists of `trash_ids`. Recyclarr will
> only ever synchronize it once. Allowing it to be specified multiple times allows you to > only ever synchronize it once. Allowing it to be specified multiple times allows you to
> assign it to different profiles with different scores. > assign it to different profiles with different scores.

Loading…
Cancel
Save