From 514027270582eb586137738504d54fcfd6150661 Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Wed, 18 May 2022 16:28:40 -0500 Subject: [PATCH] fix: strict_negative_scores works again The removal of the markdown parsing logic in v2.0 accidentally also deleted the logic responsible for handling this property. The code has been refactored to introduce a "filter pipeline" system that handles include/exclude filtering as well as strict negative score support. --- CHANGELOG.md | 4 ++ src/Directory.Build.targets | 1 + src/Recyclarr/CompositionRoot.cs | 4 ++ src/Recyclarr/Recyclarr.csproj | 5 +- .../Filters/StrictNegativeScoresFilterTest.cs | 59 +++++++++++++++++++ .../Filters/IReleaseProfileFilter.cs | 8 +++ .../Filters/IReleaseProfileFilterPipeline.cs | 8 +++ .../Filters/IncludeExcludeFilter.cs | 28 +++++++++ .../Filters/ReleaseProfileFilterPipeline.cs | 23 ++++++++ .../Filters/StrictNegativeScoresFilter.cs | 31 ++++++++++ .../ReleaseProfile/ReleaseProfileUpdater.cs | 19 +++--- src/TrashLib/Sonarr/SonarrAutofacModule.cs | 10 ++++ src/TrashLib/TrashLib.csproj | 5 +- 13 files changed, 189 insertions(+), 16 deletions(-) create mode 100644 src/TrashLib.Tests/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilterTest.cs create mode 100644 src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilter.cs create mode 100644 src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilterPipeline.cs create mode 100644 src/TrashLib/Sonarr/ReleaseProfile/Filters/IncludeExcludeFilter.cs create mode 100644 src/TrashLib/Sonarr/ReleaseProfile/Filters/ReleaseProfileFilterPipeline.cs create mode 100644 src/TrashLib/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilter.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index d1eb72b6..7ac1704b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Sonarr: `strict_negative_scores` works again (broke in v2.0 release) + ## [2.0.0] - 2022-05-13 This release contains **BREAKING CHANGES**. See the [Upgrade Guide] for required changes you need to diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index df69ad08..22f8c763 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -3,6 +3,7 @@ + diff --git a/src/Recyclarr/CompositionRoot.cs b/src/Recyclarr/CompositionRoot.cs index 70526f53..2fdaf55a 100644 --- a/src/Recyclarr/CompositionRoot.cs +++ b/src/Recyclarr/CompositionRoot.cs @@ -2,6 +2,7 @@ using System.Reflection; using Autofac; using Autofac.Core.Activators.Reflection; +using Autofac.Extras.Ordering; using CliFx; using CliFx.Infrastructure; using Common; @@ -79,6 +80,9 @@ public static class CompositionRoot public static IContainer Setup(ContainerBuilder builder) { + // Needed for Autofac.Extras.Ordering + builder.RegisterSource(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As().SingleInstance(); diff --git a/src/Recyclarr/Recyclarr.csproj b/src/Recyclarr/Recyclarr.csproj index fbb18338..319bde42 100644 --- a/src/Recyclarr/Recyclarr.csproj +++ b/src/Recyclarr/Recyclarr.csproj @@ -12,12 +12,13 @@ - + + + - diff --git a/src/TrashLib.Tests/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilterTest.cs b/src/TrashLib.Tests/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilterTest.cs new file mode 100644 index 00000000..e0e1435c --- /dev/null +++ b/src/TrashLib.Tests/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilterTest.cs @@ -0,0 +1,59 @@ +using FluentAssertions; +using NUnit.Framework; +using TestLibrary.AutoFixture; +using TrashLib.Sonarr.Config; +using TrashLib.Sonarr.ReleaseProfile; +using TrashLib.Sonarr.ReleaseProfile.Filters; + +namespace TrashLib.Tests.Sonarr.ReleaseProfile.Filters; + +[TestFixture] +[Parallelizable(ParallelScope.All)] +public class StrictNegativeScoresFilterTest +{ + private static readonly ReleaseProfileData TestProfile = new() + { + Preferred = new[] + { + new PreferredTermData + { + Score = -1, + Terms = new[] + { + new TermData + { + TrashId = "abc", + Term = "a" + } + } + } + } + }; + + [Test, AutoMockData] + public void Preferred_with_negative_scores_is_treated_as_ignored_when_strict_negative_scores_enabled( + StrictNegativeScoresFilter sut) + { + var config = new ReleaseProfileConfig + { + StrictNegativeScores = true + }; + + var result = sut.Transform(TestProfile, config); + + result.Preferred.Should().BeEmpty(); + result.Ignored.Should().BeEquivalentTo(TestProfile.Preferred.First().Terms); + } + + [Test, AutoMockData] + public void Preferred_and_ignored_untouched_when_strict_negative_scores_disabled(StrictNegativeScoresFilter sut) + { + var config = new ReleaseProfileConfig + { + StrictNegativeScores = false + }; + + var result = sut.Transform(TestProfile, config); + result.Should().BeSameAs(TestProfile); + } +} diff --git a/src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilter.cs b/src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilter.cs new file mode 100644 index 00000000..419873d7 --- /dev/null +++ b/src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilter.cs @@ -0,0 +1,8 @@ +using TrashLib.Sonarr.Config; + +namespace TrashLib.Sonarr.ReleaseProfile.Filters; + +public interface IReleaseProfileFilter +{ + ReleaseProfileData Transform(ReleaseProfileData profile, ReleaseProfileConfig config); +} diff --git a/src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilterPipeline.cs b/src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilterPipeline.cs new file mode 100644 index 00000000..8e9cd62b --- /dev/null +++ b/src/TrashLib/Sonarr/ReleaseProfile/Filters/IReleaseProfileFilterPipeline.cs @@ -0,0 +1,8 @@ +using TrashLib.Sonarr.Config; + +namespace TrashLib.Sonarr.ReleaseProfile.Filters; + +public interface IReleaseProfileFilterPipeline +{ + ReleaseProfileData Process(ReleaseProfileData profile, ReleaseProfileConfig config); +} diff --git a/src/TrashLib/Sonarr/ReleaseProfile/Filters/IncludeExcludeFilter.cs b/src/TrashLib/Sonarr/ReleaseProfile/Filters/IncludeExcludeFilter.cs new file mode 100644 index 00000000..c8ed83bd --- /dev/null +++ b/src/TrashLib/Sonarr/ReleaseProfile/Filters/IncludeExcludeFilter.cs @@ -0,0 +1,28 @@ +using Serilog; +using TrashLib.Sonarr.Config; + +namespace TrashLib.Sonarr.ReleaseProfile.Filters; + +public class IncludeExcludeFilter : IReleaseProfileFilter +{ + private readonly ILogger _log; + private readonly ReleaseProfileDataFilterer _filterer; + + public IncludeExcludeFilter(ILogger log) + { + _log = log; + _filterer = new ReleaseProfileDataFilterer(log); + } + + public ReleaseProfileData Transform(ReleaseProfileData profile, ReleaseProfileConfig config) + { + if (config.Filter == null) + { + return profile; + } + + _log.Debug("This profile will be filtered"); + var newProfile = _filterer.FilterProfile(profile, config.Filter); + return newProfile ?? profile; + } +} diff --git a/src/TrashLib/Sonarr/ReleaseProfile/Filters/ReleaseProfileFilterPipeline.cs b/src/TrashLib/Sonarr/ReleaseProfile/Filters/ReleaseProfileFilterPipeline.cs new file mode 100644 index 00000000..ca60bf76 --- /dev/null +++ b/src/TrashLib/Sonarr/ReleaseProfile/Filters/ReleaseProfileFilterPipeline.cs @@ -0,0 +1,23 @@ +using TrashLib.Sonarr.Config; + +namespace TrashLib.Sonarr.ReleaseProfile.Filters; + +public class ReleaseProfileFilterPipeline : IReleaseProfileFilterPipeline +{ + private readonly IOrderedEnumerable _filters; + + public ReleaseProfileFilterPipeline(IOrderedEnumerable filters) + { + _filters = filters; + } + + public ReleaseProfileData Process(ReleaseProfileData profile, ReleaseProfileConfig config) + { + foreach (var filter in _filters) + { + profile = filter.Transform(profile, config); + } + + return profile; + } +} diff --git a/src/TrashLib/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilter.cs b/src/TrashLib/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilter.cs new file mode 100644 index 00000000..142f90cc --- /dev/null +++ b/src/TrashLib/Sonarr/ReleaseProfile/Filters/StrictNegativeScoresFilter.cs @@ -0,0 +1,31 @@ +using Serilog; +using TrashLib.Sonarr.Config; + +namespace TrashLib.Sonarr.ReleaseProfile.Filters; + +public class StrictNegativeScoresFilter : IReleaseProfileFilter +{ + private readonly ILogger _log; + + public StrictNegativeScoresFilter(ILogger log) + { + _log = log; + } + + public ReleaseProfileData Transform(ReleaseProfileData profile, ReleaseProfileConfig config) + { + if (!config.StrictNegativeScores) + { + return profile; + } + + _log.Debug("Negative scores will be strictly ignored"); + var splitPreferred = profile.Preferred.ToLookup(x => x.Score < 0); + + return profile with + { + Ignored = profile.Ignored.Concat(splitPreferred[true].SelectMany(x => x.Terms)).ToList(), + Preferred = splitPreferred[false].ToList() + }; + } +} diff --git a/src/TrashLib/Sonarr/ReleaseProfile/ReleaseProfileUpdater.cs b/src/TrashLib/Sonarr/ReleaseProfile/ReleaseProfileUpdater.cs index badc3a60..580446b2 100644 --- a/src/TrashLib/Sonarr/ReleaseProfile/ReleaseProfileUpdater.cs +++ b/src/TrashLib/Sonarr/ReleaseProfile/ReleaseProfileUpdater.cs @@ -5,14 +5,16 @@ using TrashLib.ExceptionTypes; using TrashLib.Sonarr.Api; using TrashLib.Sonarr.Api.Objects; using TrashLib.Sonarr.Config; +using TrashLib.Sonarr.ReleaseProfile.Filters; using TrashLib.Sonarr.ReleaseProfile.Guide; namespace TrashLib.Sonarr.ReleaseProfile; -internal class ReleaseProfileUpdater : IReleaseProfileUpdater +public class ReleaseProfileUpdater : IReleaseProfileUpdater { private readonly ISonarrApi _api; private readonly ISonarrCompatibility _compatibility; + private readonly IReleaseProfileFilterPipeline _pipeline; private readonly ISonarrGuideService _guide; private readonly ILogger _log; @@ -20,12 +22,14 @@ internal class ReleaseProfileUpdater : IReleaseProfileUpdater ILogger logger, ISonarrGuideService guide, ISonarrApi api, - ISonarrCompatibility compatibility) + ISonarrCompatibility compatibility, + IReleaseProfileFilterPipeline pipeline) { _log = logger; _guide = guide; _api = api; _compatibility = compatibility; + _pipeline = pipeline; } public async Task Process(bool isPreview, SonarrConfiguration config) @@ -33,7 +37,6 @@ internal class ReleaseProfileUpdater : IReleaseProfileUpdater var profilesFromGuide = _guide.GetReleaseProfileData(); var filteredProfiles = new List<(ReleaseProfileData Profile, IReadOnlyCollection Tags)>(); - var filterer = new ReleaseProfileDataFilterer(_log); var configProfiles = config.ReleaseProfiles.SelectMany(x => x.TrashIds.Select(y => (TrashId: y, Config: x))); foreach (var (trashId, configProfile) in configProfiles) @@ -49,15 +52,7 @@ internal class ReleaseProfileUpdater : IReleaseProfileUpdater _log.Debug("Found Release Profile: {ProfileName} ({TrashId})", selectedProfile.Name, selectedProfile.TrashId); - if (configProfile.Filter != null) - { - _log.Debug("This profile will be filtered"); - var newProfile = filterer.FilterProfile(selectedProfile, configProfile.Filter); - if (newProfile is not null) - { - selectedProfile = newProfile; - } - } + selectedProfile = _pipeline.Process(selectedProfile, configProfile); if (isPreview) { diff --git a/src/TrashLib/Sonarr/SonarrAutofacModule.cs b/src/TrashLib/Sonarr/SonarrAutofacModule.cs index 607d0848..8b628704 100644 --- a/src/TrashLib/Sonarr/SonarrAutofacModule.cs +++ b/src/TrashLib/Sonarr/SonarrAutofacModule.cs @@ -1,8 +1,10 @@ using Autofac; +using Autofac.Extras.Ordering; using TrashLib.Sonarr.Api; using TrashLib.Sonarr.Config; using TrashLib.Sonarr.QualityDefinition; using TrashLib.Sonarr.ReleaseProfile; +using TrashLib.Sonarr.ReleaseProfile.Filters; using TrashLib.Sonarr.ReleaseProfile.Guide; namespace TrashLib.Sonarr; @@ -21,6 +23,14 @@ public class SonarrAutofacModule : Module builder.RegisterType().As(); builder.RegisterType() .As(); + builder.RegisterType().As(); + + // Release Profile Filters (ORDER MATTERS!) + builder.RegisterTypes( + typeof(IncludeExcludeFilter), + typeof(StrictNegativeScoresFilter)) + .As() + .OrderByRegistration(); // Quality Definition Support builder.RegisterType().As(); diff --git a/src/TrashLib/TrashLib.csproj b/src/TrashLib/TrashLib.csproj index 2f5275d9..13fa5bf7 100644 --- a/src/TrashLib/TrashLib.csproj +++ b/src/TrashLib/TrashLib.csproj @@ -1,18 +1,19 @@ - + + + -