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 @@
-
+
+
+
-