diff --git a/CHANGELOG.md b/CHANGELOG.md index 97d473e2..21a0ca19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - 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 diff --git a/schemas/config-schema.json b/schemas/config-schema.json index 0a83be04..a9c8e579 100644 --- a/schemas/config-schema.json +++ b/schemas/config-schema.json @@ -127,7 +127,7 @@ "items": { "type": "object", "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": [ {"required": ["trash_ids"]}, {"required": ["names"]} diff --git a/src/Recyclarr/config-template.yml b/src/Recyclarr/config-template.yml index f68e91f1..2dbc62b4 100644 --- a/src/Recyclarr/config-template.yml +++ b/src/Recyclarr/config-template.yml @@ -11,7 +11,7 @@ # Configuration specific to 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 api_key: f7e74ba6c80046e39e076a27af5a8444 @@ -46,19 +46,17 @@ radarr: delete_old_custom_formats: false custom_formats: - # A list of custom formats to sync to Radarr. Must match the "name" in the importable JSON. - # Do NOT use the heading names here, those do not work! These are case-insensitive. - - names: - - BR-DISK - - EVO (no WEBDL) - - LQ - - x265 (720/1080p) - - 3D + # A list of custom formats to sync to Radarr. Must match the "trash_id" in the guide JSON. + - trash_ids: + - ed38b889b31be83fda192888e2286d83 # BR-DISK + - 90cedc1fea7ea5d11298bebd3d1d3223 # EVO (no WEBDL) + - 90a6f9a284dff5103f6346090e6280c8 # LQ + - dc98083864ea246d05a42df0d05f81cc # x265 (720/1080p) + - b8cd450cbfa689c0259a01d9e29ba3d6 # 3D # 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 # are synced to Radarr but no scores are set in any quality profiles. - # quality_profiles: # - name: Quality Profile 1 # - name: Quality Profile 2 diff --git a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideProcessorTest.cs b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideProcessorTest.cs index 6b2f995d..bc9041b4 100644 --- a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideProcessorTest.cs +++ b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideProcessorTest.cs @@ -4,6 +4,7 @@ using FluentAssertions; using Newtonsoft.Json.Linq; using NSubstitute; using NUnit.Framework; +using Serilog; using TestLibrary.FluentAssertions; using TrashLib.Radarr.Config; using TrashLib.Radarr.CustomFormat.Guide; @@ -21,7 +22,7 @@ public class GuideProcessorTest private class TestGuideProcessorSteps : IGuideProcessorSteps { public ICustomFormatStep CustomFormat { get; } = new CustomFormatStep(); - public IConfigStep Config { get; } = new ConfigStep(); + public IConfigStep Config { get; } = new ConfigStep(Substitute.For()); public IQualityProfileStep QualityProfile { get; } = new QualityProfileStep(); } diff --git a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/ConfigStepTest.cs b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/ConfigStepTest.cs index fd8d7ee7..e9049242 100644 --- a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/ConfigStepTest.cs +++ b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/ConfigStepTest.cs @@ -1,6 +1,7 @@ using FluentAssertions; using Newtonsoft.Json.Linq; using NUnit.Framework; +using TestLibrary.AutoFixture; using TrashLib.Radarr.Config; using TrashLib.Radarr.CustomFormat.Models; using TrashLib.Radarr.CustomFormat.Models.Cache; @@ -13,8 +14,8 @@ namespace TrashLib.Tests.Radarr.CustomFormat.Processors.GuideSteps; [Parallelizable(ParallelScope.All)] public class ConfigStepTest { - [Test] - public void Cache_names_are_used_instead_of_name_in_json_data() + [Test, AutoMockData] + public void Cache_names_are_used_instead_of_name_in_json_data(ConfigStep processor) { var testProcessedCfs = new List { @@ -30,7 +31,6 @@ public class ConfigStepTest } }; - var processor = new ConfigStep(); processor.Process(testProcessedCfs, testConfig); processor.CustomFormatsNotInGuide.Should().BeEmpty(); @@ -46,8 +46,8 @@ public class ConfigStepTest .WhenTypeIs()); } - [Test] - public void Custom_formats_missing_from_config_are_skipped() + [Test, AutoMockData] + public void Custom_formats_missing_from_config_are_skipped(ConfigStep processor) { var testProcessedCfs = new List { @@ -63,7 +63,6 @@ public class ConfigStepTest } }; - var processor = new ConfigStep(); processor.Process(testProcessedCfs, testConfig); processor.CustomFormatsNotInGuide.Should().BeEmpty(); @@ -81,8 +80,8 @@ public class ConfigStepTest .WhenTypeIs()); } - [Test] - public void Custom_formats_missing_from_guide_are_added_to_not_in_guide_list() + [Test, AutoMockData] + public void Custom_formats_missing_from_guide_are_added_to_not_in_guide_list(ConfigStep processor) { var testProcessedCfs = new List { @@ -98,7 +97,6 @@ public class ConfigStepTest } }; - var processor = new ConfigStep(); processor.Process(testProcessedCfs, testConfig); processor.CustomFormatsNotInGuide.Should().BeEquivalentTo(new List {"name3"}, op => op @@ -118,8 +116,8 @@ public class ConfigStepTest .WhenTypeIs()); } - [Test] - public void Duplicate_config_name_and_id_are_ignored() + [Test, AutoMockData] + public void Duplicate_config_name_and_id_are_ignored(ConfigStep processor) { var testProcessedCfs = new List { @@ -135,7 +133,6 @@ public class ConfigStepTest } }; - var processor = new ConfigStep(); processor.Process(testProcessedCfs, testConfig); processor.CustomFormatsNotInGuide.Should().BeEmpty(); @@ -148,8 +145,8 @@ public class ConfigStepTest }); } - [Test] - public void Duplicate_config_names_are_ignored() + [Test, AutoMockData] + public void Duplicate_config_names_are_ignored(ConfigStep processor) { var testProcessedCfs = new List { @@ -161,7 +158,6 @@ public class ConfigStepTest new() {Names = new List {"name1", "name1"}} }; - var processor = new ConfigStep(); processor.Process(testProcessedCfs, testConfig); processor.CustomFormatsNotInGuide.Should().BeEmpty(); @@ -174,8 +170,8 @@ public class ConfigStepTest }); } - [Test] - public void Find_custom_formats_by_name_and_trash_id() + [Test, AutoMockData] + public void Find_custom_formats_by_name_and_trash_id(ConfigStep processor) { var testProcessedCfs = new List { @@ -197,7 +193,6 @@ public class ConfigStepTest } }; - var processor = new ConfigStep(); processor.Process(testProcessedCfs, testConfig); processor.CustomFormatsNotInGuide.Should().BeEmpty(); diff --git a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStepTest.cs b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStepTest.cs index 7f277e25..498a4c6b 100644 --- a/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStepTest.cs +++ b/src/TrashLib.Tests/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStepTest.cs @@ -2,6 +2,7 @@ using System.Collections.ObjectModel; using FluentAssertions; using Newtonsoft.Json.Linq; using NUnit.Framework; +using TestLibrary.AutoFixture; using TestLibrary.FluentAssertions; using TrashLib.Radarr.Config; using TrashLib.Radarr.CustomFormat.Models; @@ -61,8 +62,8 @@ public class CustomFormatStepTest }); } - [Test] - public void Cache_entry_is_not_set_when_id_is_different() + [Test, AutoMockData] + public void Cache_entry_is_not_set_when_id_is_different(CustomFormatStep processor) { var guideData = new List { @@ -82,7 +83,6 @@ public class CustomFormatStepTest } }; - var processor = new CustomFormatStep(); processor.Process(guideData, testConfig, testCache); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -95,8 +95,8 @@ public class CustomFormatStepTest }); } - [Test] - public void Cfs_not_in_config_are_skipped() + [Test, AutoMockData] + public void Cfs_not_in_config_are_skipped(CustomFormatStep processor) { var ctx = new Context(); var testConfig = new List @@ -104,7 +104,6 @@ public class CustomFormatStepTest new() {Names = new List {"name1", "name3"}} }; - var processor = new CustomFormatStep(); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -118,8 +117,8 @@ public class CustomFormatStepTest }); } - [Test] - public void Config_cfs_in_different_sections_are_processed() + [Test, AutoMockData] + public void Config_cfs_in_different_sections_are_processed(CustomFormatStep processor) { var ctx = new Context(); var testConfig = new List @@ -128,7 +127,6 @@ public class CustomFormatStepTest new() {Names = new List {"name2"}} }; - var processor = new CustomFormatStep(); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -143,8 +141,8 @@ public class CustomFormatStepTest op => op.Using(new JsonEquivalencyStep())); } - [Test] - public void Custom_format_is_deleted_if_in_config_and_cache_but_not_in_guide() + [Test, AutoMockData] + public void Custom_format_is_deleted_if_in_config_and_cache_but_not_in_guide(CustomFormatStep processor) { var guideData = new List { @@ -161,7 +159,6 @@ public class CustomFormatStepTest TrashIdMappings = new Collection {new("id1000", "name1")} }; - var processor = new CustomFormatStep(); processor.Process(guideData, testConfig, testCache); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -174,8 +171,8 @@ public class CustomFormatStepTest }); } - [Test] - public void Custom_format_is_deleted_if_not_in_config_but_in_cache_and_in_guide() + [Test, AutoMockData] + public void Custom_format_is_deleted_if_not_in_config_but_in_cache_and_in_guide(CustomFormatStep processor) { var cache = new CustomFormatCache { @@ -187,7 +184,6 @@ public class CustomFormatStepTest new("3D", "id1", null, new JObject()) }; - var processor = new CustomFormatStep(); processor.Process(guideCfs, Array.Empty(), cache); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -196,8 +192,8 @@ public class CustomFormatStepTest processor.ProcessedCustomFormats.Should().BeEmpty(); } - [Test] - public void Custom_format_name_in_cache_is_updated_if_renamed_in_guide_and_config() + [Test, AutoMockData] + public void Custom_format_name_in_cache_is_updated_if_renamed_in_guide_and_config(CustomFormatStep processor) { var guideData = new List { @@ -214,7 +210,6 @@ public class CustomFormatStepTest TrashIdMappings = new Collection {new("id1", "name1")} }; - var processor = new CustomFormatStep(); processor.Process(guideData, testConfig, testCache); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -225,8 +220,8 @@ public class CustomFormatStepTest .BeEquivalentTo(new TrashIdMapping("id1", "name2")); } - [Test] - public void Duplicates_are_recorded_and_removed_from_processed_custom_formats_list() + [Test, AutoMockData] + public void Duplicates_are_recorded_and_removed_from_processed_custom_formats_list(CustomFormatStep processor) { var guideData = new List { @@ -239,7 +234,6 @@ public class CustomFormatStepTest new() {Names = new List {"name1"}} }; - var processor = new CustomFormatStep(); processor.Process(guideData, testConfig, null); //Dictionary> @@ -255,8 +249,8 @@ public class CustomFormatStepTest processor.ProcessedCustomFormats.Should().BeEmpty(); } - [Test] - public void Match_cf_names_regardless_of_case_in_config() + [Test, AutoMockData] + public void Match_cf_names_regardless_of_case_in_config(CustomFormatStep processor) { var ctx = new Context(); var testConfig = new List @@ -264,7 +258,6 @@ public class CustomFormatStepTest new() {Names = new List {"name1", "NAME1"}} }; - var processor = new CustomFormatStep(); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -277,8 +270,8 @@ public class CustomFormatStepTest op => op.Using(new JsonEquivalencyStep())); } - [Test] - public void Match_custom_format_using_trash_id() + [Test, AutoMockData] + public void Match_custom_format_using_trash_id(CustomFormatStep processor) { var guideData = new List { @@ -291,7 +284,6 @@ public class CustomFormatStepTest new() {TrashIds = new List {"id2"}} }; - var processor = new CustomFormatStep(); processor.Process(guideData, testConfig, null); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -304,8 +296,8 @@ public class CustomFormatStepTest }); } - [Test] - public void Non_existent_cfs_in_config_are_skipped() + [Test, AutoMockData] + public void Non_existent_cfs_in_config_are_skipped(CustomFormatStep processor) { var ctx = new Context(); var testConfig = new List @@ -313,7 +305,6 @@ public class CustomFormatStepTest new() {Names = new List {"doesnt_exist"}} }; - var processor = new CustomFormatStep(); processor.Process(ctx.TestGuideData, testConfig, new CustomFormatCache()); processor.DuplicatedCustomFormats.Should().BeEmpty(); @@ -322,8 +313,8 @@ public class CustomFormatStepTest processor.ProcessedCustomFormats.Should().BeEmpty(); } - [Test] - public void Score_from_json_takes_precedence_over_score_from_guide() + [Test, AutoMockData] + public void Score_from_json_takes_precedence_over_score_from_guide(CustomFormatStep processor) { var guideData = new List { @@ -342,7 +333,6 @@ public class CustomFormatStepTest } }; - var processor = new CustomFormatStep(); processor.Process(guideData, testConfig, null); processor.DuplicatedCustomFormats.Should().BeEmpty(); diff --git a/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/ConfigStep.cs b/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/ConfigStep.cs index 951911c2..cced548e 100644 --- a/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/ConfigStep.cs +++ b/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/ConfigStep.cs @@ -1,20 +1,35 @@ using Common.Extensions; +using Serilog; using TrashLib.Radarr.Config; using TrashLib.Radarr.CustomFormat.Models; namespace TrashLib.Radarr.CustomFormat.Processors.GuideSteps; -internal class ConfigStep : IConfigStep +public class ConfigStep : IConfigStep { + private readonly ILogger _log; private readonly List _configData = new(); private readonly List _customFormatsNotInGuide = new(); public IReadOnlyCollection CustomFormatsNotInGuide => _customFormatsNotInGuide; public IReadOnlyCollection ConfigData => _configData; - public void Process(IReadOnlyCollection processedCfs, - IEnumerable config) + public ConfigStep(ILogger log) { + _log = log; + } + + public void Process( + IReadOnlyCollection processedCfs, + IReadOnlyCollection 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) { var validCfs = new List(); diff --git a/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStep.cs b/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStep.cs index f1f1e85c..c80cd199 100644 --- a/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStep.cs +++ b/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/CustomFormatStep.cs @@ -5,7 +5,7 @@ using TrashLib.Radarr.CustomFormat.Models.Cache; namespace TrashLib.Radarr.CustomFormat.Processors.GuideSteps; -internal class CustomFormatStep : ICustomFormatStep +public class CustomFormatStep : ICustomFormatStep { private readonly List<(string, string)> _customFormatsWithOutdatedNames = new(); private readonly List _processedCustomFormats = new(); diff --git a/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/IConfigStep.cs b/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/IConfigStep.cs index 21afb726..d6e7f2c8 100644 --- a/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/IConfigStep.cs +++ b/src/TrashLib/Radarr/CustomFormat/Processors/GuideSteps/IConfigStep.cs @@ -9,5 +9,5 @@ public interface IConfigStep IReadOnlyCollection ConfigData { get; } void Process(IReadOnlyCollection processedCfs, - IEnumerable config); + IReadOnlyCollection config); } diff --git a/wiki/Configuration-Reference.md b/wiki/Configuration-Reference.md index 288a2155..47215658 100644 --- a/wiki/Configuration-Reference.md +++ b/wiki/Configuration-Reference.md @@ -210,35 +210,9 @@ Synchronization]] page. Radarr **will not be deleted** if you enable this setting. - `custom_formats` (Optional; *Default: No custom formats are synced*)
- 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. The child 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*)
- 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 - ``` + 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. The child + properties documented below apply to each element of this list. - `trash_ids` (Optional; *`names` is required if not used*)
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 > 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 > assign it to different profiles with different scores.