mirror of
https://github.com/Radarr/Radarr.git
synced 2025-04-19 12:14:45 -04:00
Add reason enum to decision engine rejections
Co-authored-by: Mark McDowall <mark@mcdowall.ca>
This commit is contained in:
parent
cd836fef38
commit
7977e0be05
70 changed files with 560 additions and 430 deletions
|
@ -20,32 +20,32 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
private List<ReleaseInfo> _reports;
|
||||
private RemoteMovie _remoteEpisode;
|
||||
|
||||
private Mock<IDecisionEngineSpecification> _pass1;
|
||||
private Mock<IDecisionEngineSpecification> _pass2;
|
||||
private Mock<IDecisionEngineSpecification> _pass3;
|
||||
private Mock<IDownloadDecisionEngineSpecification> _pass1;
|
||||
private Mock<IDownloadDecisionEngineSpecification> _pass2;
|
||||
private Mock<IDownloadDecisionEngineSpecification> _pass3;
|
||||
|
||||
private Mock<IDecisionEngineSpecification> _fail1;
|
||||
private Mock<IDecisionEngineSpecification> _fail2;
|
||||
private Mock<IDecisionEngineSpecification> _fail3;
|
||||
private Mock<IDownloadDecisionEngineSpecification> _fail1;
|
||||
private Mock<IDownloadDecisionEngineSpecification> _fail2;
|
||||
private Mock<IDownloadDecisionEngineSpecification> _fail3;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_pass1 = new Mock<IDecisionEngineSpecification>();
|
||||
_pass2 = new Mock<IDecisionEngineSpecification>();
|
||||
_pass3 = new Mock<IDecisionEngineSpecification>();
|
||||
_pass1 = new Mock<IDownloadDecisionEngineSpecification>();
|
||||
_pass2 = new Mock<IDownloadDecisionEngineSpecification>();
|
||||
_pass3 = new Mock<IDownloadDecisionEngineSpecification>();
|
||||
|
||||
_fail1 = new Mock<IDecisionEngineSpecification>();
|
||||
_fail2 = new Mock<IDecisionEngineSpecification>();
|
||||
_fail3 = new Mock<IDecisionEngineSpecification>();
|
||||
_fail1 = new Mock<IDownloadDecisionEngineSpecification>();
|
||||
_fail2 = new Mock<IDownloadDecisionEngineSpecification>();
|
||||
_fail3 = new Mock<IDownloadDecisionEngineSpecification>();
|
||||
|
||||
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(Decision.Accept);
|
||||
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(Decision.Accept);
|
||||
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(Decision.Accept);
|
||||
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(DownloadSpecDecision.Accept);
|
||||
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(DownloadSpecDecision.Accept);
|
||||
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(DownloadSpecDecision.Accept);
|
||||
|
||||
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(Decision.Reject("fail1"));
|
||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(Decision.Reject("fail2"));
|
||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(Decision.Reject("fail3"));
|
||||
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(DownloadSpecDecision.Reject(DownloadRejectionReason.Unknown, "fail1"));
|
||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(DownloadSpecDecision.Reject(DownloadRejectionReason.Unknown, "fail2"));
|
||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null)).Returns(DownloadSpecDecision.Reject(DownloadRejectionReason.Unknown, "fail3"));
|
||||
|
||||
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "Trolls.2016.720p.WEB-DL.DD5.1.H264-FGT" } };
|
||||
_remoteEpisode = new RemoteMovie
|
||||
|
@ -58,9 +58,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
.Setup(c => c.Map(It.IsAny<ParsedMovieInfo>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<SearchCriteriaBase>())).Returns(_remoteEpisode);
|
||||
}
|
||||
|
||||
private void GivenSpecifications(params Mock<IDecisionEngineSpecification>[] mocks)
|
||||
private void GivenSpecifications(params Mock<IDownloadDecisionEngineSpecification>[] mocks)
|
||||
{
|
||||
Mocker.SetConstant<IEnumerable<IDecisionEngineSpecification>>(mocks.Select(c => c.Object));
|
||||
Mocker.SetConstant<IEnumerable<IDownloadDecisionEngineSpecification>>(mocks.Select(c => c.Object));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -4,7 +4,6 @@ using FluentAssertions;
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.History;
|
||||
|
@ -107,11 +106,11 @@ namespace NzbDrone.Core.Test.Download
|
|||
{
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1998.mkv" }, new Rejection("Rejected!")), "Test Failure"),
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1998.mkv" }, new ImportRejection(ImportRejectionReason.Unknown, "Rejected!")), "Test Failure"),
|
||||
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1999.mkv" }, new Rejection("Rejected!")), "Test Failure")
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1999.mkv" }, new ImportRejection(ImportRejectionReason.Unknown, "Rejected!")), "Test Failure")
|
||||
});
|
||||
|
||||
Subject.Import(_trackedDownload);
|
||||
|
@ -131,11 +130,11 @@ namespace NzbDrone.Core.Test.Download
|
|||
{
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1998.mkv" }, new Rejection("Rejected!")), "Test Failure"),
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1998.mkv" }, new ImportRejection(ImportRejectionReason.Unknown, "Rejected!")), "Test Failure"),
|
||||
|
||||
new ImportResult(
|
||||
new ImportDecision(
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1998.mkv" }, new Rejection("Rejected!")), "Test Failure")
|
||||
new LocalMovie { Path = @"C:\TestPath\Droned.1998.mkv" }, new ImportRejection(ImportRejectionReason.Unknown, "Rejected!")), "Test Failure")
|
||||
});
|
||||
|
||||
_trackedDownload.RemoteMovie.Movie = new Movie();
|
||||
|
|
|
@ -189,8 +189,8 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
|||
{
|
||||
var decisions = new List<DownloadDecision>();
|
||||
RemoteMovie remoteMovie = null;
|
||||
decisions.Add(new DownloadDecision(remoteMovie, new Rejection("Failure!")));
|
||||
decisions.Add(new DownloadDecision(remoteMovie, new Rejection("Failure!")));
|
||||
decisions.Add(new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.Unknown, "Failure!")));
|
||||
decisions.Add(new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.Unknown, "Failure!")));
|
||||
|
||||
Subject.GetQualifiedReports(decisions).Should().BeEmpty();
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
|||
var remoteMovie = GetRemoteMovie(new QualityModel(Quality.HDTV720p));
|
||||
|
||||
var decisions = new List<DownloadDecision>();
|
||||
decisions.Add(new DownloadDecision(remoteMovie, new Rejection("Failure!", RejectionType.Temporary)));
|
||||
decisions.Add(new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.Unknown, "Failure!", RejectionType.Temporary)));
|
||||
|
||||
await Subject.ProcessDecisions(decisions);
|
||||
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>(), null), Times.Never());
|
||||
|
@ -214,7 +214,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
|||
|
||||
var decisions = new List<DownloadDecision>();
|
||||
decisions.Add(new DownloadDecision(removeMovie));
|
||||
decisions.Add(new DownloadDecision(removeMovie, new Rejection("Failure!", RejectionType.Temporary)));
|
||||
decisions.Add(new DownloadDecision(removeMovie, new DownloadRejection(DownloadRejectionReason.Unknown, "Failure!", RejectionType.Temporary)));
|
||||
|
||||
await Subject.ProcessDecisions(decisions);
|
||||
Mocker.GetMock<IPendingReleaseService>().Verify(v => v.AddMany(It.IsAny<List<Tuple<DownloadDecision, PendingReleaseReason>>>()), Times.Never());
|
||||
|
@ -226,8 +226,8 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
|||
var remoteEpisode = GetRemoteMovie(new QualityModel(Quality.HDTV720p));
|
||||
|
||||
var decisions = new List<DownloadDecision>();
|
||||
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
|
||||
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
|
||||
decisions.Add(new DownloadDecision(remoteEpisode, new DownloadRejection(DownloadRejectionReason.Unknown, "Failure!", RejectionType.Temporary)));
|
||||
decisions.Add(new DownloadDecision(remoteEpisode, new DownloadRejection(DownloadRejectionReason.Unknown, "Failure!", RejectionType.Temporary)));
|
||||
|
||||
await Subject.ProcessDecisions(decisions);
|
||||
Mocker.GetMock<IPendingReleaseService>().Verify(v => v.AddMany(It.IsAny<List<Tuple<DownloadDecision, PendingReleaseReason>>>()), Times.Once());
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
|||
_remoteMovie.ParsedMovieInfo = _parsedMovieInfo;
|
||||
_remoteMovie.Release = _release;
|
||||
|
||||
_temporarilyRejected = new DownloadDecision(_remoteMovie, new Rejection("Temp Rejected", RejectionType.Temporary));
|
||||
_temporarilyRejected = new DownloadDecision(_remoteMovie, new DownloadRejection(DownloadRejectionReason.MinimumAgeDelay, "Temp Rejected", RejectionType.Temporary));
|
||||
|
||||
_heldReleases = new List<PendingRelease>();
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
|||
_remoteMovie.ParsedMovieInfo = _parsedMovieInfo;
|
||||
_remoteMovie.Release = _release;
|
||||
|
||||
_temporarilyRejected = new DownloadDecision(_remoteMovie, new Rejection("Temp Rejected", RejectionType.Temporary));
|
||||
_temporarilyRejected = new DownloadDecision(_remoteMovie, new DownloadRejection(DownloadRejectionReason.MinimumAgeDelay, "Temp Rejected", RejectionType.Temporary));
|
||||
|
||||
_heldReleases = new List<PendingRelease>();
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
|||
_remoteMovie.ParsedMovieInfo = _parsedMovieInfo;
|
||||
_remoteMovie.Release = _release;
|
||||
|
||||
_temporarilyRejected = new DownloadDecision(_remoteMovie, new Rejection("Temp Rejected", RejectionType.Temporary));
|
||||
_temporarilyRejected = new DownloadDecision(_remoteMovie, new DownloadRejection(DownloadRejectionReason.MinimumAgeDelay, "Temp Rejected", RejectionType.Temporary));
|
||||
|
||||
Mocker.GetMock<IPendingReleaseRepository>()
|
||||
.Setup(s => s.All())
|
||||
|
|
|
@ -7,7 +7,6 @@ using Moq;
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
|
@ -46,9 +45,9 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
|
|||
.With(s => s.Path = @"C:\Test\TV\30 Rock".AsOsAgnostic())
|
||||
.Build();
|
||||
|
||||
_rejectedDecisions.Add(new ImportDecision(new LocalMovie(), new Rejection("Rejected!")));
|
||||
_rejectedDecisions.Add(new ImportDecision(new LocalMovie(), new Rejection("Rejected!")));
|
||||
_rejectedDecisions.Add(new ImportDecision(new LocalMovie(), new Rejection("Rejected!")));
|
||||
_rejectedDecisions.Add(new ImportDecision(new LocalMovie(), new ImportRejection(ImportRejectionReason.Unknown, "Rejected!")));
|
||||
_rejectedDecisions.Add(new ImportDecision(new LocalMovie(), new ImportRejection(ImportRejectionReason.Unknown, "Rejected!")));
|
||||
_rejectedDecisions.Add(new ImportDecision(new LocalMovie(), new ImportRejection(ImportRejectionReason.Unknown, "Rejected!")));
|
||||
|
||||
_approvedDecisions.Add(new ImportDecision(
|
||||
new LocalMovie
|
||||
|
|
|
@ -4,7 +4,6 @@ using FizzWare.NBuilder;
|
|||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.MovieImport;
|
||||
|
@ -49,13 +48,13 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
|
|||
_fail2 = new Mock<IImportDecisionEngineSpecification>();
|
||||
_fail3 = new Mock<IImportDecisionEngineSpecification>();
|
||||
|
||||
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Accept());
|
||||
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Accept());
|
||||
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Accept());
|
||||
_pass1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(ImportSpecDecision.Accept());
|
||||
_pass2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(ImportSpecDecision.Accept());
|
||||
_pass3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(ImportSpecDecision.Accept());
|
||||
|
||||
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Reject("_fail1"));
|
||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Reject("_fail2"));
|
||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(Decision.Reject("_fail3"));
|
||||
_fail1.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(ImportSpecDecision.Reject(ImportRejectionReason.Unknown, "_fail1"));
|
||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(ImportSpecDecision.Reject(ImportRejectionReason.Unknown, "_fail2"));
|
||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<LocalMovie>(), It.IsAny<DownloadClientItem>())).Returns(ImportSpecDecision.Reject(ImportRejectionReason.Unknown, "_fail3"));
|
||||
|
||||
_movie = Builder<Movie>.CreateNew()
|
||||
.With(e => e.Path = @"C:\Test\Movie".AsOsAgnostic())
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public class Decision
|
||||
{
|
||||
public bool Accepted { get; private set; }
|
||||
public string Reason { get; private set; }
|
||||
|
||||
private static readonly Decision AcceptDecision = new Decision { Accepted = true };
|
||||
private Decision()
|
||||
{
|
||||
}
|
||||
|
||||
public static Decision Accept()
|
||||
{
|
||||
return AcceptDecision;
|
||||
}
|
||||
|
||||
public static Decision Reject(string reason, params object[] args)
|
||||
{
|
||||
return Reject(string.Format(reason, args));
|
||||
}
|
||||
|
||||
public static Decision Reject(string reason)
|
||||
{
|
||||
return new Decision
|
||||
{
|
||||
Accepted = false,
|
||||
Reason = reason
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
{
|
||||
public RemoteMovie RemoteMovie { get; private set; }
|
||||
|
||||
public IEnumerable<Rejection> Rejections { get; private set; }
|
||||
public IEnumerable<DownloadRejection> Rejections { get; private set; }
|
||||
|
||||
public bool Approved => !Rejections.Any();
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
}
|
||||
}
|
||||
|
||||
public DownloadDecision(RemoteMovie movie, params Rejection[] rejections)
|
||||
public DownloadDecision(RemoteMovie movie, params DownloadRejection[] rejections)
|
||||
{
|
||||
RemoteMovie = movie;
|
||||
Rejections = rejections.ToList();
|
||||
|
|
|
@ -23,14 +23,14 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
public class DownloadDecisionMaker : IMakeDownloadDecision
|
||||
{
|
||||
private readonly IEnumerable<IDecisionEngineSpecification> _specifications;
|
||||
private readonly IEnumerable<IDownloadDecisionEngineSpecification> _specifications;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly ICustomFormatCalculationService _formatCalculator;
|
||||
private readonly IRemoteMovieAggregationService _aggregationService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DownloadDecisionMaker(IEnumerable<IDecisionEngineSpecification> specifications,
|
||||
public DownloadDecisionMaker(IEnumerable<IDownloadDecisionEngineSpecification> specifications,
|
||||
IParsingService parsingService,
|
||||
IConfigService configService,
|
||||
ICustomFormatCalculationService formatCalculator,
|
||||
|
@ -85,9 +85,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
if (remoteMovie.Movie == null)
|
||||
{
|
||||
var reason = "Unknown Movie";
|
||||
|
||||
decision = new DownloadDecision(remoteMovie, new Rejection(reason));
|
||||
decision = new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.UnknownMovie, "Unknown Movie"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -123,7 +121,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
Languages = parsedMovieInfo.Languages
|
||||
};
|
||||
|
||||
decision = new DownloadDecision(remoteMovie, new Rejection("Unable to parse release"));
|
||||
decision = new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.UnableToParse, "Unable to parse release"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +130,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
_logger.Error(e, "Couldn't process release.");
|
||||
|
||||
var remoteMovie = new RemoteMovie { Release = report };
|
||||
decision = new DownloadDecision(remoteMovie, new Rejection("Unexpected error processing release"));
|
||||
decision = new DownloadDecision(remoteMovie, new DownloadRejection(DownloadRejectionReason.Error, "Unexpected error processing release"));
|
||||
}
|
||||
|
||||
reportNumber++;
|
||||
|
@ -175,7 +173,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
private DownloadDecision GetDecisionForReport(RemoteMovie remoteMovie, SearchCriteriaBase searchCriteria = null)
|
||||
{
|
||||
var reasons = Array.Empty<Rejection>();
|
||||
var reasons = Array.Empty<DownloadRejection>();
|
||||
|
||||
foreach (var specifications in _specifications.GroupBy(v => v.Priority).OrderBy(v => v.Key))
|
||||
{
|
||||
|
@ -192,7 +190,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
return new DownloadDecision(remoteMovie, reasons.ToArray());
|
||||
}
|
||||
|
||||
private Rejection EvaluateSpec(IDecisionEngineSpecification spec, RemoteMovie remoteMovie, SearchCriteriaBase searchCriteriaBase = null)
|
||||
private DownloadRejection EvaluateSpec(IDownloadDecisionEngineSpecification spec, RemoteMovie remoteMovie, SearchCriteriaBase searchCriteriaBase = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -200,7 +198,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
if (!result.Accepted)
|
||||
{
|
||||
return new Rejection(result.Reason, spec.Type);
|
||||
return new DownloadRejection(result.Reason, result.Message, spec.Type);
|
||||
}
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
|
@ -212,7 +210,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
e.Data.Add("report", remoteMovie.Release.ToJson());
|
||||
e.Data.Add("parsed", remoteMovie.ParsedMovieInfo.ToJson());
|
||||
_logger.Error(e, "Couldn't evaluate decision on {0}, with spec: {1}", remoteMovie.Release.Title, spec.GetType().Name);
|
||||
return new Rejection($"{spec.GetType().Name}: {e.Message}");
|
||||
return new DownloadRejection(DownloadRejectionReason.DecisionError, $"{spec.GetType().Name}: {e.Message}");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
9
src/NzbDrone.Core/DecisionEngine/DownloadRejection.cs
Normal file
9
src/NzbDrone.Core/DecisionEngine/DownloadRejection.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace NzbDrone.Core.DecisionEngine;
|
||||
|
||||
public class DownloadRejection : Rejection<DownloadRejectionReason>
|
||||
{
|
||||
public DownloadRejection(DownloadRejectionReason reason, string message, RejectionType type = RejectionType.Permanent)
|
||||
: base(reason, message, type)
|
||||
{
|
||||
}
|
||||
}
|
67
src/NzbDrone.Core/DecisionEngine/DownloadRejectionReason.cs
Normal file
67
src/NzbDrone.Core/DecisionEngine/DownloadRejectionReason.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
namespace NzbDrone.Core.DecisionEngine;
|
||||
|
||||
public enum DownloadRejectionReason
|
||||
{
|
||||
Unknown,
|
||||
UnknownMovie,
|
||||
UnableToParse,
|
||||
Error,
|
||||
DecisionError,
|
||||
Availability,
|
||||
MinimumAgeDelay,
|
||||
MovieNotMonitored,
|
||||
HistoryRecentCutoffMet,
|
||||
HistoryCdhDisabledCutoffMet,
|
||||
HistoryHigherPreference,
|
||||
HistoryHigherRevision,
|
||||
HistoryCutoffMet,
|
||||
HistoryCustomFormatCutoffMet,
|
||||
HistoryCustomFormatScore,
|
||||
HistoryCustomFormatScoreIncrement,
|
||||
HistoryUpgradesNotAllowed,
|
||||
NoMatchingTag,
|
||||
PropersDisabled,
|
||||
ProperForOldFile,
|
||||
WrongMovie,
|
||||
UnknownRuntime,
|
||||
BelowMinimumSize,
|
||||
AboveMaximumSize,
|
||||
AlreadyImportedSameHash,
|
||||
AlreadyImportedSameName,
|
||||
IndexerDisabled,
|
||||
Blocklisted,
|
||||
CustomFormatMinimumScore,
|
||||
MinimumFreeSpace,
|
||||
HardcodeSubtitles,
|
||||
WantedLanguage,
|
||||
MaximumSizeExceeded,
|
||||
MinimumAge,
|
||||
MaximumAge,
|
||||
Sample,
|
||||
ProtocolDisabled,
|
||||
QualityNotWanted,
|
||||
QualityUpgradesDisabled,
|
||||
QueueHigherPreference,
|
||||
QueueHigherRevision,
|
||||
QueueCutoffMet,
|
||||
QueueCustomFormatCutoffMet,
|
||||
QueueCustomFormatScore,
|
||||
QueueCustomFormatScoreIncrement,
|
||||
QueueUpgradesNotAllowed,
|
||||
QueuePropersDisabled,
|
||||
Raw,
|
||||
MustContainMissing,
|
||||
MustNotContainPresent,
|
||||
RepackDisabled,
|
||||
RepackUnknownReleaseGroup,
|
||||
RepackReleaseGroupDoesNotMatch,
|
||||
RequiredFlags,
|
||||
MinimumSeeders,
|
||||
DiskHigherPreference,
|
||||
DiskHigherRevision,
|
||||
DiskCutoffMet,
|
||||
DiskCustomFormatCutoffMet,
|
||||
DiskCustomFormatScore,
|
||||
DiskCustomFormatScoreIncrement,
|
||||
DiskUpgradesNotAllowed
|
||||
}
|
34
src/NzbDrone.Core/DecisionEngine/DownloadSpecDecision.cs
Normal file
34
src/NzbDrone.Core/DecisionEngine/DownloadSpecDecision.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public class DownloadSpecDecision
|
||||
{
|
||||
public bool Accepted { get; private set; }
|
||||
public DownloadRejectionReason Reason { get; set; }
|
||||
public string Message { get; private set; }
|
||||
|
||||
private static readonly DownloadSpecDecision AcceptDownloadSpecDecision = new () { Accepted = true };
|
||||
private DownloadSpecDecision()
|
||||
{
|
||||
}
|
||||
|
||||
public static DownloadSpecDecision Accept()
|
||||
{
|
||||
return AcceptDownloadSpecDecision;
|
||||
}
|
||||
|
||||
public static DownloadSpecDecision Reject(DownloadRejectionReason reason, string message, params object[] args)
|
||||
{
|
||||
return Reject(reason, string.Format(message, args));
|
||||
}
|
||||
|
||||
public static DownloadSpecDecision Reject(DownloadRejectionReason reason, string message)
|
||||
{
|
||||
return new DownloadSpecDecision
|
||||
{
|
||||
Accepted = false,
|
||||
Reason = reason,
|
||||
Message = message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +1,21 @@
|
|||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public class Rejection
|
||||
public class Rejection<TRejectionReason>
|
||||
{
|
||||
public string Reason { get; set; }
|
||||
public TRejectionReason Reason { get; set; }
|
||||
public string Message { get; set; }
|
||||
public RejectionType Type { get; set; }
|
||||
|
||||
public Rejection(string reason, RejectionType type = RejectionType.Permanent)
|
||||
public Rejection(TRejectionReason reason, string message, RejectionType type = RejectionType.Permanent)
|
||||
{
|
||||
Reason = reason;
|
||||
Message = message;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0}] {1}", Type, Reason);
|
||||
return string.Format("[{0}] {1}", Type, Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using NzbDrone.Core.Qualities;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class AcceptableSizeSpecification : IDecisionEngineSpecification
|
||||
public class AcceptableSizeSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -20,7 +20,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
_logger.Debug("Beginning size check for: {0}", subject);
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (subject.Release.Size == 0)
|
||||
{
|
||||
_logger.Debug("Release has unknown size, skipping size check");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var qualityDefinition = _qualityDefinitionService.Get(quality);
|
||||
|
@ -53,7 +53,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
var runtimeMessage = subject.Movie.Title;
|
||||
|
||||
_logger.Debug("Item: {0}, Size: {1} is smaller than minimum allowed size ({2} bytes for {3}), rejecting.", subject, subject.Release.Size, minSize, runtimeMessage);
|
||||
return Decision.Reject("{0} is smaller than minimum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix(), runtimeMessage);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.BelowMinimumSize, "{0} is smaller than minimum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix(), runtimeMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
else if (subject.Movie.MovieMetadata.Value.Runtime == 0)
|
||||
{
|
||||
_logger.Debug("Movie runtime is 0, unable to validate size until it is available, rejecting");
|
||||
return Decision.Reject("Movie runtime is 0, unable to validate size until it is available");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.UnknownRuntime, "Movie runtime is 0, unable to validate size until it is available");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -77,12 +77,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (subject.Release.Size > maxSize)
|
||||
{
|
||||
_logger.Debug("Item: {0}, Size: {1} is greater than maximum allowed size ({2} for {3}), rejecting", subject, subject.Release.Size, maxSize, subject.Movie.Title);
|
||||
return Decision.Reject("{0} is larger than maximum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix(), subject.Movie.Title);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.AboveMaximumSize, "{0} is larger than maximum allowed {1} (for {2})", subject.Release.Size.SizeSuffix(), maxSize.SizeSuffix(), subject.Movie.Title);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug("Item: {0}, meets size constraints", subject);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class AlreadyImportedSpecification : IDecisionEngineSpecification
|
||||
public class AlreadyImportedSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IHistoryService _historyService;
|
||||
private readonly IConfigService _configService;
|
||||
|
@ -27,14 +27,14 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cdhEnabled = _configService.EnableCompletedDownloadHandling;
|
||||
|
||||
if (!cdhEnabled)
|
||||
{
|
||||
_logger.Debug("Skipping already imported check because CDH is disabled");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var movie = subject.Movie;
|
||||
|
@ -45,7 +45,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (!movie.HasFile)
|
||||
{
|
||||
_logger.Debug("Skipping already imported check for movie without file");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var historyForMovie = _historyService.GetByMovieId(movie.Id, null);
|
||||
|
@ -53,7 +53,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
if (lastGrabbed == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var imported = historyForMovie.FirstOrDefault(h =>
|
||||
|
@ -62,7 +62,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
if (imported == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
// This is really only a guard against redownloading the same release over
|
||||
|
@ -70,7 +70,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
// match skip this check.
|
||||
if (lastGrabbed.Quality.Equals(imported.Quality))
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var release = subject.Release;
|
||||
|
@ -82,7 +82,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (torrentInfo?.InfoHash != null && torrentInfo.InfoHash.ToUpper() == lastGrabbed.DownloadId)
|
||||
{
|
||||
_logger.Debug("Has same torrent hash as a grabbed and imported release");
|
||||
return Decision.Reject("Has same torrent hash as a grabbed and imported release");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.AlreadyImportedSameHash, "Has same torrent hash as a grabbed and imported release");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,11 +91,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (release.Title.Equals(lastGrabbed.SourceTitle, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
_logger.Debug("Has same release name as a grabbed and imported release");
|
||||
return Decision.Reject("Has same release name as a grabbed and imported release");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.AlreadyImportedSameName, "Has same release name as a grabbed and imported release");
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class BlockedIndexerSpecification : IDecisionEngineSpecification
|
||||
public class BlockedIndexerSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IIndexerStatusService _indexerStatusService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -27,15 +27,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
public RejectionType Type => RejectionType.Temporary;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var status = _blockedIndexerCache.Find(subject.Release.IndexerId.ToString());
|
||||
if (status != null)
|
||||
{
|
||||
return Decision.Reject($"Indexer {subject.Release.Indexer} is blocked till {status.DisabledTill} due to failures, cannot grab release.");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.IndexerDisabled, $"Indexer {subject.Release.Indexer} is blocked till {status.DisabledTill} due to failures, cannot grab release.");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
private IDictionary<string, IndexerStatus> FetchBlockedIndexer()
|
||||
|
|
|
@ -5,7 +5,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class BlocklistSpecification : IDecisionEngineSpecification
|
||||
public class BlocklistSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IBlocklistService _blocklistService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -19,15 +19,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (_blocklistService.Blocklisted(subject.Movie.Id, subject.Release))
|
||||
{
|
||||
_logger.Debug("{0} is blocklisted, rejecting.", subject.Release.Title);
|
||||
return Decision.Reject("Release is blocklisted");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.Blocklisted, "Release is blocklisted");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class CustomFormatAllowedbyProfileSpecification : IDecisionEngineSpecification
|
||||
public class CustomFormatAllowedbyProfileSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
|
@ -17,19 +17,19 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var minScore = subject.Movie.QualityProfile.MinFormatScore;
|
||||
var score = subject.CustomFormatScore;
|
||||
|
||||
if (score < minScore)
|
||||
{
|
||||
return Decision.Reject("Custom Formats {0} have score {1} below Movie's profile minimum {2}", subject.CustomFormats.ConcatToString(), score, minScore);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.CustomFormatMinimumScore, "Custom Formats {0} have score {1} below Movie's profile minimum {2}", subject.CustomFormats.ConcatToString(), score, minScore);
|
||||
}
|
||||
|
||||
_logger.Trace("Custom Format Score of {0} [{1}] above Movie's profile minimum {2}", score, subject.CustomFormats.ConcatToString(), minScore);
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class FreeSpaceSpecification : IDecisionEngineSpecification
|
||||
public class FreeSpaceSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
|
@ -24,12 +24,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (_configService.SkipFreeSpaceCheckWhenImporting)
|
||||
{
|
||||
_logger.Debug("Skipping free space check");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var size = subject.Release.Size;
|
||||
|
@ -49,7 +49,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
{
|
||||
_logger.Debug("Unable to get available space for {0}. Skipping", path);
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var minimumSpace = _configService.MinimumFreeSpaceWhenImporting.Megabytes();
|
||||
|
@ -60,7 +60,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
var message = "Importing after download will exceed available disk space";
|
||||
|
||||
_logger.Debug(message);
|
||||
return Decision.Reject(message);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MinimumFreeSpace, message);
|
||||
}
|
||||
|
||||
if (remainingSpace < minimumSpace)
|
||||
|
@ -68,10 +68,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
var message = $"Not enough free space ({minimumSpace.SizeSuffix()}) to import after download: {remainingSpace.SizeSuffix()}. (Settings: Media Management: Minimum Free Space)";
|
||||
|
||||
_logger.Debug(message);
|
||||
return Decision.Reject(message);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MinimumFreeSpace, message);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class HardcodeSubsSpecification : IDecisionEngineSpecification
|
||||
public class HardcodeSubsSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -21,13 +21,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var hardcodeSubs = subject.ParsedMovieInfo.HardcodedSubs;
|
||||
|
||||
if (_configService.AllowHardcodedSubs || hardcodeSubs.IsNullOrWhiteSpace())
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var whitelisted = _configService.WhitelistedHardcodedSubs.Split(',');
|
||||
|
@ -35,12 +35,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (whitelisted != null && whitelisted.Any(t => (hardcodeSubs.ToLower().Contains(t.ToLower()) && t.IsNotNullOrWhiteSpace())))
|
||||
{
|
||||
_logger.Debug("Release hardcode subs ({0}) are in allowed values ({1})", hardcodeSubs, whitelisted);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Hardcode subs found: {0}", hardcodeSubs);
|
||||
return Decision.Reject("Hardcode subs found: {0}", hardcodeSubs);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HardcodeSubtitles, "Hardcode subs found: {0}", hardcodeSubs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public interface IDecisionEngineSpecification
|
||||
public interface IDownloadDecisionEngineSpecification
|
||||
{
|
||||
RejectionType Type { get; }
|
||||
|
||||
SpecificationPriority Priority { get; }
|
||||
|
||||
Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria);
|
||||
DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class LanguageSpecification : IDecisionEngineSpecification
|
||||
public class LanguageSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
|
@ -17,14 +17,14 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var wantedLanguage = subject.Movie.QualityProfile.Language;
|
||||
|
||||
if (wantedLanguage == Language.Any)
|
||||
{
|
||||
_logger.Debug("Profile allows any language, accepting release.");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var originalLanguage = subject.Movie.MovieMetadata.Value.OriginalLanguage;
|
||||
|
@ -34,10 +34,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (!subject.Languages.Contains(originalLanguage))
|
||||
{
|
||||
_logger.Debug("Original Language({0}) is wanted, but found {1}", originalLanguage, subject.Languages.ToExtendedString());
|
||||
return Decision.Reject("Original Language ({0}) is wanted, but found {1}", originalLanguage, subject.Languages.ToExtendedString());
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.WantedLanguage, "Original Language ({0}) is wanted, but found {1}", originalLanguage, subject.Languages.ToExtendedString());
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if report meets language requirements. {0}", subject.ParsedMovieInfo.Languages.ToExtendedString());
|
||||
|
@ -45,10 +45,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (!subject.Languages.Contains(wantedLanguage))
|
||||
{
|
||||
_logger.Debug("Report Language: {0} rejected because it is not wanted, wanted {1}", subject.Languages.ToExtendedString(), wantedLanguage);
|
||||
return Decision.Reject("{0} is wanted, but found {1}", wantedLanguage, subject.Languages.ToExtendedString());
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.WantedLanguage, "{0} is wanted, but found {1}", wantedLanguage, subject.Languages.ToExtendedString());
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class MaximumSizeSpecification : IDecisionEngineSpecification
|
||||
public class MaximumSizeSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -20,7 +20,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var size = subject.Release.Size;
|
||||
var maximumSize = _configService.MaximumSize.Megabytes();
|
||||
|
@ -28,13 +28,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (maximumSize == 0)
|
||||
{
|
||||
_logger.Debug("Maximum size is not set.");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
_logger.Debug("Release has unknown size, skipping size check.");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if release meets maximum size requirements. {0}", size.SizeSuffix());
|
||||
|
@ -44,10 +44,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
var message = $"{size.SizeSuffix()} is too big, maximum size is {maximumSize.SizeSuffix()} (Settings->Indexers->Maximum Size)";
|
||||
|
||||
_logger.Debug(message);
|
||||
return Decision.Reject(message);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MaximumSizeExceeded, message);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class MinimumAgeSpecification : IDecisionEngineSpecification
|
||||
public class MinimumAgeSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -20,12 +20,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Temporary;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (subject.Release.DownloadProtocol != Indexers.DownloadProtocol.Usenet)
|
||||
{
|
||||
_logger.Debug("Not checking minimum age requirement for non-usenet report");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var age = subject.Release.AgeMinutes;
|
||||
|
@ -35,7 +35,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (minimumAge == 0)
|
||||
{
|
||||
_logger.Debug("Minimum age is not set.");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if report meets minimum age requirements. {0}", ageRounded);
|
||||
|
@ -43,12 +43,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (age < minimumAge)
|
||||
{
|
||||
_logger.Debug("Only {0} minutes old, minimum age is {1} minutes", ageRounded, minimumAge);
|
||||
return Decision.Reject("Only {0} minutes old, minimum age is {1} minutes", ageRounded, minimumAge);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MinimumAge, "Only {0} minutes old, minimum age is {1} minutes", ageRounded, minimumAge);
|
||||
}
|
||||
|
||||
_logger.Debug("Release is {0} minutes old, greater than minimum age of {1} minutes", ageRounded, minimumAge);
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class NotSampleSpecification : IDecisionEngineSpecification
|
||||
public class NotSampleSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
|
@ -17,15 +17,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (subject.Release.Title.ToLower().Contains("sample") && subject.Release.Size < 70.Megabytes())
|
||||
{
|
||||
_logger.Debug("Sample release, rejecting.");
|
||||
return Decision.Reject("Sample");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.Sample, "Sample");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using NzbDrone.Core.Profiles.Delay;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class ProtocolSpecification : IDecisionEngineSpecification
|
||||
public class ProtocolSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IDelayProfileService _delayProfileService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -21,23 +21,23 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var delayProfile = _delayProfileService.BestForTags(subject.Movie.Tags);
|
||||
|
||||
if (subject.Release.DownloadProtocol == DownloadProtocol.Usenet && !delayProfile.EnableUsenet)
|
||||
{
|
||||
_logger.Debug("[{0}] Usenet is not enabled for this movie", subject.Release.Title);
|
||||
return Decision.Reject("Usenet is not enabled for this movie");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.ProtocolDisabled, "Usenet is not enabled for this movie");
|
||||
}
|
||||
|
||||
if (subject.Release.DownloadProtocol == DownloadProtocol.Torrent && !delayProfile.EnableTorrent)
|
||||
{
|
||||
_logger.Debug("[{0}] Torrent is not enabled for this movie", subject.Release.Title);
|
||||
return Decision.Reject("Torrent is not enabled for this movie");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.ProtocolDisabled, "Torrent is not enabled for this movie");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class QualityAllowedByProfileSpecification : IDecisionEngineSpecification
|
||||
public class QualityAllowedByProfileSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
|
@ -16,7 +16,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
_logger.Debug("Checking if report meets quality requirements. {0}", subject.ParsedMovieInfo.Quality);
|
||||
|
||||
|
@ -27,10 +27,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (!qualityOrGroup.Allowed)
|
||||
{
|
||||
_logger.Debug("Quality {0} rejected by Movie's quality profile", subject.ParsedMovieInfo.Quality);
|
||||
return Decision.Reject("{0} is not wanted in profile", subject.ParsedMovieInfo.Quality.Quality);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QualityNotWanted, "{0} is not wanted in profile", subject.ParsedMovieInfo.Quality.Quality);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ using NzbDrone.Core.Queue;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class QueueSpecification : IDecisionEngineSpecification
|
||||
public class QueueSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IQueueService _queueService;
|
||||
private readonly UpgradableSpecification _upgradableSpecification;
|
||||
|
@ -35,7 +35,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var queue = _queueService.GetQueue();
|
||||
var matchingMovies = queue.Where(q => q.RemoteMovie?.Movie != null &&
|
||||
|
@ -66,7 +66,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
queuedItemCustomFormats,
|
||||
subject.ParsedMovieInfo.Quality))
|
||||
{
|
||||
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteMovie.ParsedMovieInfo.Quality);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueCutoffMet, "Quality for release in queue already meets cutoff: {0}", remoteMovie.ParsedMovieInfo.Quality);
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteMovie.ParsedMovieInfo.Quality);
|
||||
|
@ -80,25 +80,25 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
switch (upgradeableRejectReason)
|
||||
{
|
||||
case UpgradeableRejectReason.BetterQuality:
|
||||
return Decision.Reject("Release in queue is of equal or higher preference: {0}", remoteMovie.ParsedMovieInfo.Quality);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueHigherPreference, "Release in queue is of equal or higher preference: {0}", remoteMovie.ParsedMovieInfo.Quality);
|
||||
|
||||
case UpgradeableRejectReason.BetterRevision:
|
||||
return Decision.Reject("Release in queue is of equal or higher revision: {0}", remoteMovie.ParsedMovieInfo.Quality.Revision);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueHigherRevision, "Release in queue is of equal or higher revision: {0}", remoteMovie.ParsedMovieInfo.Quality.Revision);
|
||||
|
||||
case UpgradeableRejectReason.QualityCutoff:
|
||||
return Decision.Reject("Release in queue meets quality cutoff: {0}", qualityProfile.Items[qualityProfile.GetIndex(qualityProfile.Cutoff).Index]);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueCutoffMet, "Release in queue meets quality cutoff: {0}", qualityProfile.Items[qualityProfile.GetIndex(qualityProfile.Cutoff).Index]);
|
||||
|
||||
case UpgradeableRejectReason.CustomFormatCutoff:
|
||||
return Decision.Reject("Release in queue meets Custom Format cutoff: {0}", qualityProfile.CutoffFormatScore);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueCustomFormatCutoffMet, "Release in queue meets Custom Format cutoff: {0}", qualityProfile.CutoffFormatScore);
|
||||
|
||||
case UpgradeableRejectReason.CustomFormatScore:
|
||||
return Decision.Reject("Release in queue has an equal or higher Custom Format score: {0}", qualityProfile.CalculateCustomFormatScore(queuedItemCustomFormats));
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueCustomFormatScore, "Release in queue has an equal or higher Custom Format score: {0}", qualityProfile.CalculateCustomFormatScore(queuedItemCustomFormats));
|
||||
|
||||
case UpgradeableRejectReason.MinCustomFormatScore:
|
||||
return Decision.Reject("Release in queue has Custom Format score within Custom Format score increment: {0}", qualityProfile.MinUpgradeFormatScore);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueCustomFormatScoreIncrement, "Release in queue has Custom Format score within Custom Format score increment: {0}", qualityProfile.MinUpgradeFormatScore);
|
||||
|
||||
case UpgradeableRejectReason.UpgradesNotAllowed:
|
||||
return Decision.Reject("Release in queue and Quality Profile '{0}' does not allow upgrades", qualityProfile.Name);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueueUpgradesNotAllowed, "Release in queue and Quality Profile '{0}' does not allow upgrades", qualityProfile.Name);
|
||||
}
|
||||
|
||||
if (_upgradableSpecification.IsRevisionUpgrade(remoteMovie.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
|
||||
|
@ -106,12 +106,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (_configService.DownloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade)
|
||||
{
|
||||
_logger.Debug("Auto downloading of propers is disabled");
|
||||
return Decision.Reject("Proper downloading is disabled");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QueuePropersDisabled, "Proper downloading is disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class RawDiskSpecification : IDecisionEngineSpecification
|
||||
public class RawDiskSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private static readonly Regex[] DiscRegex = new[]
|
||||
{
|
||||
|
@ -29,11 +29,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (subject.Release == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
foreach (var regex in DiscRegex)
|
||||
|
@ -41,28 +41,28 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (regex.IsMatch(subject.Release.Title))
|
||||
{
|
||||
_logger.Debug("Release contains raw Bluray/DVD, rejecting.");
|
||||
return Decision.Reject("Raw Bluray/DVD release");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.Raw, "Raw Bluray/DVD release");
|
||||
}
|
||||
}
|
||||
|
||||
if (subject.Release.Container.IsNullOrWhiteSpace())
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (_dvdContainerTypes.Contains(subject.Release.Container.ToLower()))
|
||||
{
|
||||
_logger.Debug("Release contains raw DVD, rejecting.");
|
||||
return Decision.Reject("Raw DVD release");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.Raw, "Raw DVD release");
|
||||
}
|
||||
|
||||
if (_blurayContainerTypes.Contains(subject.Release.Container.ToLower()))
|
||||
{
|
||||
_logger.Debug("Release contains raw Bluray, rejecting.");
|
||||
return Decision.Reject("Raw Bluray release");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.Raw, "Raw Bluray release");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ using NzbDrone.Core.Profiles.Releases;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class ReleaseRestrictionsSpecification : IDecisionEngineSpecification
|
||||
public class ReleaseRestrictionsSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly IReleaseProfileService _releaseProfileService;
|
||||
|
@ -24,7 +24,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
_logger.Debug("Checking if release meets restrictions: {0}", subject);
|
||||
|
||||
|
@ -43,7 +43,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
{
|
||||
var terms = string.Join(", ", requiredTerms);
|
||||
_logger.Debug("[{0}] does not contain one of the required terms: {1}", title, terms);
|
||||
return Decision.Reject("Does not contain one of the required terms: {0}", terms);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MustContainMissing, "Does not contain one of the required terms: {0}", terms);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,12 +56,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
{
|
||||
var terms = string.Join(", ", foundTerms);
|
||||
_logger.Debug("[{0}] contains these ignored terms: {1}", title, terms);
|
||||
return Decision.Reject("Contains these ignored terms: {0}", terms);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MustNotContainPresent, "Contains these ignored terms: {0}", terms);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Debug("[{0}] No restrictions apply, allowing", subject);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
private List<string> ContainsAny(List<string> terms, string title)
|
||||
|
|
|
@ -8,7 +8,7 @@ using NzbDrone.Core.Qualities;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class RepackSpecification : IDecisionEngineSpecification
|
||||
public class RepackSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly UpgradableSpecification _upgradableSpecification;
|
||||
private readonly IConfigService _configService;
|
||||
|
@ -24,19 +24,19 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks;
|
||||
|
||||
if (!subject.ParsedMovieInfo.Quality.Revision.IsRepack)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotPrefer)
|
||||
{
|
||||
_logger.Debug("Repacks are not preferred, skipping check");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (subject.Movie.MovieFileId != 0)
|
||||
|
@ -51,17 +51,17 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade)
|
||||
{
|
||||
_logger.Debug("Auto downloading of repacks is disabled");
|
||||
return Decision.Reject("Repack downloading is disabled");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.RepackDisabled, "Repack downloading is disabled");
|
||||
}
|
||||
|
||||
if (fileReleaseGroup.IsNullOrWhiteSpace())
|
||||
{
|
||||
return Decision.Reject("Unable to determine release group for the existing file");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.RepackUnknownReleaseGroup, "Unable to determine release group for the existing file");
|
||||
}
|
||||
|
||||
if (releaseGroup.IsNullOrWhiteSpace())
|
||||
{
|
||||
return Decision.Reject("Unable to determine release group for this release");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.RepackUnknownReleaseGroup, "Unable to determine release group for this release");
|
||||
}
|
||||
|
||||
if (!fileReleaseGroup.Equals(releaseGroup, StringComparison.InvariantCultureIgnoreCase))
|
||||
|
@ -70,7 +70,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
"Release is a repack for a different release group. Release Group: {0}. File release group: {1}",
|
||||
releaseGroup,
|
||||
fileReleaseGroup);
|
||||
return Decision.Reject(
|
||||
return DownloadSpecDecision.Reject(
|
||||
DownloadRejectionReason.RepackReleaseGroupDoesNotMatch,
|
||||
"Release is a repack for a different release group. Release Group: {0}. File release group: {1}",
|
||||
releaseGroup,
|
||||
fileReleaseGroup);
|
||||
|
@ -78,7 +79,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class RequiredIndexerFlagsSpecification : IDecisionEngineSpecification
|
||||
public class RequiredIndexerFlagsSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly Logger _logger;
|
||||
|
@ -21,7 +21,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var torrentInfo = subject.Release;
|
||||
|
||||
|
@ -37,34 +37,35 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
if (torrentInfo == null || indexerSettings == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (indexerSettings is ITorrentIndexerSettings torrentIndexerSettings)
|
||||
{
|
||||
var requiredFlags = torrentIndexerSettings.RequiredFlags;
|
||||
var requiredFlag = (IndexerFlags)0;
|
||||
|
||||
if (requiredFlags == null || !requiredFlags.Any())
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var requiredFlag = (IndexerFlags)0;
|
||||
|
||||
foreach (var flag in requiredFlags)
|
||||
{
|
||||
if (torrentInfo.IndexerFlags.HasFlag((IndexerFlags)flag))
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
requiredFlag |= (IndexerFlags)flag;
|
||||
}
|
||||
|
||||
_logger.Debug("None of the required indexer flags {0} where found. Found flags: {1}", requiredFlag, torrentInfo.IndexerFlags);
|
||||
return Decision.Reject("None of the required indexer flags {0} where found. Found flags: {1}", requiredFlag, torrentInfo.IndexerFlags);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.RequiredFlags, "None of the required indexer flags {0} where found. Found flags: {1}", requiredFlag, torrentInfo.IndexerFlags);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class RetentionSpecification : IDecisionEngineSpecification
|
||||
public class RetentionSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -19,12 +19,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (subject.Release.DownloadProtocol != Indexers.DownloadProtocol.Usenet)
|
||||
{
|
||||
_logger.Debug("Not checking retention requirement for non-usenet report");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var age = subject.Release.Age;
|
||||
|
@ -34,10 +34,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (retention > 0 && age > retention)
|
||||
{
|
||||
_logger.Debug("Report age: {0} rejected by user's retention limit", age);
|
||||
return Decision.Reject("Older than configured retention");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MaximumAge, "Older than configured retention");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class AvailabilitySpecification : IDecisionEngineSpecification
|
||||
public class AvailabilitySpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
@ -19,22 +19,22 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria is { UserInvokedSearch: true })
|
||||
{
|
||||
_logger.Debug("Skipping availability check during search");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var availabilityDelay = _configService.AvailabilityDelay;
|
||||
|
||||
if (!subject.Movie.IsAvailable(availabilityDelay))
|
||||
{
|
||||
return Decision.Reject("Movie {0} will only be considered available {1} days after {2}", subject.Movie, availabilityDelay, subject.Movie.MinimumAvailability.ToString());
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.Availability, "Movie {0} will only be considered available {1} days after {2}", subject.Movie, availabilityDelay, subject.Movie.MinimumAvailability.ToString());
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ using NzbDrone.Core.Qualities;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class DelaySpecification : IDecisionEngineSpecification
|
||||
public class DelaySpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IPendingReleaseService _pendingReleaseService;
|
||||
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
||||
|
@ -32,12 +32,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
public RejectionType Type => RejectionType.Temporary;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria != null && searchCriteria.UserInvokedSearch)
|
||||
{
|
||||
_logger.Debug("Ignoring delay for user invoked search");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var profile = subject.Movie.QualityProfile;
|
||||
|
@ -48,7 +48,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
if (delay == 0)
|
||||
{
|
||||
_logger.Debug("Delay Profile does not require a waiting period before download for {0}.", subject.Release.DownloadProtocol);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
_logger.Debug("Delay Profile requires a waiting period of {0} minutes for {1}", delay, subject.Release.DownloadProtocol);
|
||||
|
@ -73,7 +73,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
if (revisionUpgrade)
|
||||
{
|
||||
_logger.Debug("New quality is a better revision for existing quality, skipping delay");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
if (isBestInProfile && isPreferredProtocol)
|
||||
{
|
||||
_logger.Debug("Quality is highest in profile for preferred protocol, will not delay.");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
if (score >= minimum && isPreferredProtocol)
|
||||
{
|
||||
_logger.Debug("Custom format score ({0}) meets minimum ({1}) for preferred protocol, will not delay", score, minimum);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,16 +109,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
if (oldest != null && oldest.Release.AgeMinutes > delay)
|
||||
{
|
||||
_logger.Debug("Oldest pending release {0} has been delayed for {1}, longer than the set delay of {2}. Release will be accepted", oldest.Release.Title, oldest.Release.AgeMinutes, delay);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (subject.Release.AgeMinutes < delay)
|
||||
{
|
||||
_logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol);
|
||||
return Decision.Reject("Waiting for better quality release");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MinimumAgeDelay, "Waiting for better quality release");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class HistorySpecification : IDecisionEngineSpecification
|
||||
public class HistorySpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IHistoryService _historyService;
|
||||
private readonly UpgradableSpecification _upgradableSpecification;
|
||||
|
@ -33,12 +33,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
_logger.Debug("Skipping history check during search");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var cdhEnabled = _configService.EnableCompletedDownloadHandling;
|
||||
|
@ -55,7 +55,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
|
||||
if (!recent && cdhEnabled)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var customFormats = _formatService.ParseCustomFormat(mostRecent, subject.Movie);
|
||||
|
@ -77,10 +77,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
{
|
||||
if (recent)
|
||||
{
|
||||
return Decision.Reject("Recent grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryRecentCutoffMet, "Recent grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
||||
}
|
||||
|
||||
return Decision.Reject("CDH is disabled and grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryCdhDisabledCutoffMet, "CDH is disabled and grab event in history already meets cutoff: {0}", mostRecent.Quality);
|
||||
}
|
||||
|
||||
var rejectionSubject = recent ? "Recent" : "CDH is disabled and";
|
||||
|
@ -88,32 +88,32 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
switch (upgradeableRejectReason)
|
||||
{
|
||||
case UpgradeableRejectReason.None:
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
|
||||
case UpgradeableRejectReason.BetterQuality:
|
||||
return Decision.Reject("{0} grab event in history is of equal or higher preference: {1}", rejectionSubject, mostRecent.Quality);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryHigherPreference, "{0} grab event in history is of equal or higher preference: {1}", rejectionSubject, mostRecent.Quality);
|
||||
|
||||
case UpgradeableRejectReason.BetterRevision:
|
||||
return Decision.Reject("{0} grab event in history is of equal or higher revision: {1}", rejectionSubject, mostRecent.Quality.Revision);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryHigherRevision, "{0} grab event in history is of equal or higher revision: {1}", rejectionSubject, mostRecent.Quality.Revision);
|
||||
|
||||
case UpgradeableRejectReason.QualityCutoff:
|
||||
return Decision.Reject("{0} grab event in history meets quality cutoff: {1}", rejectionSubject, qualityProfile.Items[qualityProfile.GetIndex(qualityProfile.Cutoff).Index]);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryCutoffMet, "{0} grab event in history meets quality cutoff: {1}", rejectionSubject, qualityProfile.Items[qualityProfile.GetIndex(qualityProfile.Cutoff).Index]);
|
||||
|
||||
case UpgradeableRejectReason.CustomFormatCutoff:
|
||||
return Decision.Reject("{0} grab event in history meets Custom Format cutoff: {1}", rejectionSubject, qualityProfile.CutoffFormatScore);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryCustomFormatCutoffMet, "{0} grab event in history meets Custom Format cutoff: {1}", rejectionSubject, qualityProfile.CutoffFormatScore);
|
||||
|
||||
case UpgradeableRejectReason.CustomFormatScore:
|
||||
return Decision.Reject("{0} grab event in history has an equal or higher Custom Format score: {1}", rejectionSubject, qualityProfile.CalculateCustomFormatScore(customFormats));
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryCustomFormatScore, "{0} grab event in history has an equal or higher Custom Format score: {1}", rejectionSubject, qualityProfile.CalculateCustomFormatScore(customFormats));
|
||||
|
||||
case UpgradeableRejectReason.MinCustomFormatScore:
|
||||
return Decision.Reject("{0} grab event in history has Custom Format score within Custom Format score increment: {1}", rejectionSubject, qualityProfile.MinUpgradeFormatScore);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryCustomFormatScoreIncrement, "{0} grab event in history has Custom Format score within Custom Format score increment: {1}", rejectionSubject, qualityProfile.MinUpgradeFormatScore);
|
||||
|
||||
case UpgradeableRejectReason.UpgradesNotAllowed:
|
||||
return Decision.Reject("{0} grab event in history and Quality Profile '{1}' does not allow upgrades", rejectionSubject, qualityProfile.Name);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.HistoryUpgradesNotAllowed, "{0} grab event in history and Quality Profile '{1}' does not allow upgrades", rejectionSubject, qualityProfile.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class IndexerTagSpecification : IDecisionEngineSpecification
|
||||
public class IndexerTagSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
|
@ -22,11 +22,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (subject.Release == null || subject.Movie?.Tags == null || subject.Release.IndexerId == 0)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
IndexerDefinition indexer;
|
||||
|
@ -37,7 +37,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
catch (ModelNotFoundException)
|
||||
{
|
||||
_logger.Debug("Indexer with id {0} does not exist, skipping indexer tags check", subject.Release.IndexerId);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
// If indexer has tags, check that at least one of them is present on the series
|
||||
|
@ -47,10 +47,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
{
|
||||
_logger.Debug("Indexer {0} has tags. None of these are present on movie {1}. Rejecting", subject.Release.Indexer, subject.Movie);
|
||||
|
||||
return Decision.Reject("Movie tags do not match any of the indexer tags");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.NoMatchingTag, "Movie tags do not match any of the indexer tags");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class MonitoredMovieSpecification : IDecisionEngineSpecification
|
||||
public class MonitoredMovieSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
|
@ -16,23 +16,24 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
if (searchCriteria.UserInvokedSearch)
|
||||
{
|
||||
_logger.Debug("Skipping monitored check during search");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
|
||||
if (!subject.Movie.Monitored)
|
||||
{
|
||||
return Decision.Reject("Movie is not monitored");
|
||||
_logger.Debug("{0} is present in the DB but not tracked. Rejecting", subject.Movie);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MovieNotMonitored, "Movie is not monitored");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ using NzbDrone.Core.Qualities;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
public class ProperSpecification : IDecisionEngineSpecification
|
||||
public class ProperSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly UpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly IConfigService _configService;
|
||||
|
@ -23,11 +23,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks;
|
||||
|
@ -35,12 +35,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotPrefer)
|
||||
{
|
||||
_logger.Debug("Propers are not preferred, skipping check");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (subject.Movie.MovieFile == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var file = subject.Movie.MovieFile;
|
||||
|
@ -50,17 +50,17 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
if (downloadPropersAndRepacks == ProperDownloadTypes.DoNotUpgrade)
|
||||
{
|
||||
_logger.Debug("Auto downloading of propers is disabled");
|
||||
return Decision.Reject("Proper downloading is disabled");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.PropersDisabled, "Proper downloading is disabled");
|
||||
}
|
||||
|
||||
if (file.DateAdded < DateTime.Today.AddDays(-7))
|
||||
{
|
||||
_logger.Debug("Proper for old file, rejecting: {0}", subject);
|
||||
return Decision.Reject("Proper for old file");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.ProperForOldFile, "Proper for old file");
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
{
|
||||
public class MovieSpecification : IDecisionEngineSpecification
|
||||
public class MovieSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
|
@ -16,11 +16,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
if (searchCriteria == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if movie matches searched movie");
|
||||
|
@ -28,10 +28,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
|||
if (subject.Movie.Id != searchCriteria.Movie.Id)
|
||||
{
|
||||
_logger.Debug("Movie {0} does not match {1}", subject.Movie, searchCriteria.Movie);
|
||||
return Decision.Reject("Wrong movie");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.WrongMovie, "Wrong movie");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class TorrentSeedingSpecification : IDecisionEngineSpecification
|
||||
public class TorrentSeedingSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly Logger _logger;
|
||||
|
@ -20,13 +20,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var torrentInfo = subject.Release as TorrentInfo;
|
||||
|
||||
if (torrentInfo == null || torrentInfo.IndexerId == 0)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
IndexerDefinition indexer;
|
||||
|
@ -37,7 +37,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
catch (ModelNotFoundException)
|
||||
{
|
||||
_logger.Debug("Indexer with id {0} does not exist, skipping seeders check", torrentInfo.IndexerId);
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var torrentIndexerSettings = indexer.Settings as ITorrentIndexerSettings;
|
||||
|
@ -49,11 +49,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (torrentInfo.Seeders.HasValue && torrentInfo.Seeders.Value < minimumSeeders)
|
||||
{
|
||||
_logger.Debug("Not enough seeders: {0}. Minimum seeders: {1}", torrentInfo.Seeders, minimumSeeders);
|
||||
return Decision.Reject("Not enough seeders: {0}. Minimum seeders: {1}", torrentInfo.Seeders, minimumSeeders);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.MinimumSeeders, "Not enough seeders: {0}. Minimum seeders: {1}", torrentInfo.Seeders, minimumSeeders);
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class UpgradeAllowedSpecification : IDecisionEngineSpecification
|
||||
public class UpgradeAllowedSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly UpgradableSpecification _upgradableSpecification;
|
||||
private readonly ICustomFormatCalculationService _formatService;
|
||||
|
@ -24,7 +24,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var qualityProfile = subject.Movie.QualityProfile;
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (file == null)
|
||||
{
|
||||
_logger.Debug("File is no longer available, skipping this file.");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
file.Movie = subject.Movie;
|
||||
|
@ -50,11 +50,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
{
|
||||
_logger.Debug("Upgrading is not allowed by the quality profile");
|
||||
|
||||
return Decision.Reject("Existing file and the Quality profile does not allow upgrades");
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.QualityUpgradesDisabled, "Existing file and the Quality profile does not allow upgrades");
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using NzbDrone.Core.Parser.Model;
|
|||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class UpgradeDiskSpecification : IDecisionEngineSpecification
|
||||
public class UpgradeDiskSpecification : IDownloadDecisionEngineSpecification
|
||||
{
|
||||
private readonly UpgradableSpecification _upgradableSpecification;
|
||||
private readonly ICustomFormatCalculationService _formatService;
|
||||
|
@ -24,7 +24,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
public virtual DownloadSpecDecision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var qualityProfile = subject.Movie.QualityProfile;
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
if (file == null)
|
||||
{
|
||||
_logger.Debug("File is no longer available, skipping this file.");
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
|
||||
file.Movie = subject.Movie;
|
||||
|
@ -52,7 +52,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
var cutoff = qualityProfile.UpgradeAllowed ? qualityProfile.Cutoff : qualityProfile.FirststAllowedQuality().Id;
|
||||
var qualityCutoff = qualityProfile.Items[qualityProfile.GetIndex(cutoff).Index];
|
||||
|
||||
return Decision.Reject("Existing file meets cutoff: {0} [{1}]", qualityCutoff, customFormats.ConcatToString());
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskCutoffMet, "Existing file meets cutoff: {0} [{1}]", qualityCutoff, customFormats.ConcatToString());
|
||||
}
|
||||
|
||||
var upgradeableRejectReason = _upgradableSpecification.IsUpgradable(qualityProfile,
|
||||
|
@ -64,31 +64,31 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
switch (upgradeableRejectReason)
|
||||
{
|
||||
case UpgradeableRejectReason.None:
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
|
||||
case UpgradeableRejectReason.BetterQuality:
|
||||
return Decision.Reject("Existing file on disk is of equal or higher preference: {0}", file.Quality);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskHigherPreference, "Existing file on disk is of equal or higher preference: {0}", file.Quality);
|
||||
|
||||
case UpgradeableRejectReason.BetterRevision:
|
||||
return Decision.Reject("Existing file on disk is of equal or higher revision: {0}", file.Quality.Revision);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskHigherRevision, "Existing file on disk is of equal or higher revision: {0}", file.Quality.Revision);
|
||||
|
||||
case UpgradeableRejectReason.QualityCutoff:
|
||||
return Decision.Reject("Existing file on disk meets quality cutoff: {0}", qualityProfile.Items[qualityProfile.GetIndex(qualityProfile.Cutoff).Index]);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskCutoffMet, "Existing file on disk meets quality cutoff: {0}", qualityProfile.Items[qualityProfile.GetIndex(qualityProfile.Cutoff).Index]);
|
||||
|
||||
case UpgradeableRejectReason.CustomFormatCutoff:
|
||||
return Decision.Reject("Existing file on disk meets Custom Format cutoff: {0}", qualityProfile.CutoffFormatScore);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskCustomFormatCutoffMet, "Existing file on disk meets Custom Format cutoff: {0}", qualityProfile.CutoffFormatScore);
|
||||
|
||||
case UpgradeableRejectReason.CustomFormatScore:
|
||||
return Decision.Reject("Existing file on disk has a equal or higher Custom Format score: {0}", qualityProfile.CalculateCustomFormatScore(customFormats));
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskCustomFormatScore, "Existing file on disk has a equal or higher Custom Format score: {0}", qualityProfile.CalculateCustomFormatScore(customFormats));
|
||||
|
||||
case UpgradeableRejectReason.MinCustomFormatScore:
|
||||
return Decision.Reject("Existing file on disk has Custom Format score within Custom Format score increment: {0}", qualityProfile.MinUpgradeFormatScore);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskCustomFormatScoreIncrement, "Existing file on disk has Custom Format score within Custom Format score increment: {0}", qualityProfile.MinUpgradeFormatScore);
|
||||
|
||||
case UpgradeableRejectReason.UpgradesNotAllowed:
|
||||
return Decision.Reject("Existing file on disk and Quality Profile '{0}' does not allow upgrades", qualityProfile.Name);
|
||||
return DownloadSpecDecision.Reject(DownloadRejectionReason.DiskUpgradesNotAllowed, "Existing file on disk and Quality Profile '{0}' does not allow upgrades", qualityProfile.Name);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return DownloadSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ using NzbDrone.Common.Disk;
|
|||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.MediaFiles.MovieImport;
|
||||
|
@ -186,7 +185,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
_logger.Warn("Unable to process folder that is mapped to an existing movie");
|
||||
return new List<ImportResult>
|
||||
{
|
||||
RejectionResult("Import path is mapped to a movie folder")
|
||||
RejectionResult(ImportRejectionReason.MovieFolder, "Import path is mapped to a movie folder")
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -272,7 +271,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
|
||||
return new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalMovie { Path = fileInfo.FullName }, new Rejection("Invalid video file, filename starts with '._'")), "Invalid video file, filename starts with '._'")
|
||||
new ImportResult(new ImportDecision(new LocalMovie { Path = fileInfo.FullName }, new ImportRejection(ImportRejectionReason.InvalidFilePath, "Invalid video file, filename starts with '._'")), "Invalid video file, filename starts with '._'")
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -285,7 +284,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||
return new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalMovie { Path = fileInfo.FullName },
|
||||
new Rejection($"Invalid video file, unsupported extension: '{extension}'")),
|
||||
new ImportRejection(ImportRejectionReason.UnsupportedExtension, $"Invalid video file, unsupported extension: '{extension}'")),
|
||||
$"Invalid video file, unsupported extension: '{extension}'")
|
||||
};
|
||||
}
|
||||
|
@ -317,19 +316,19 @@ namespace NzbDrone.Core.MediaFiles
|
|||
private ImportResult FileIsLockedResult(string videoFile)
|
||||
{
|
||||
_logger.Debug("[{0}] is currently locked by another process, skipping", videoFile);
|
||||
return new ImportResult(new ImportDecision(new LocalMovie { Path = videoFile }, new Rejection("Locked file, try again later")), "Locked file, try again later");
|
||||
return new ImportResult(new ImportDecision(new LocalMovie { Path = videoFile }, new ImportRejection(ImportRejectionReason.FileLocked, "Locked file, try again later")), "Locked file, try again later");
|
||||
}
|
||||
|
||||
private ImportResult UnknownMovieResult(string message, string videoFile = null)
|
||||
{
|
||||
var localMovie = videoFile == null ? null : new LocalMovie { Path = videoFile };
|
||||
|
||||
return new ImportResult(new ImportDecision(localMovie, new Rejection("Unknown Movie")), message);
|
||||
return new ImportResult(new ImportDecision(localMovie, new ImportRejection(ImportRejectionReason.UnknownMovie, "Unknown Movie")), message);
|
||||
}
|
||||
|
||||
private ImportResult RejectionResult(string message)
|
||||
private ImportResult RejectionResult(ImportRejectionReason reason, string message)
|
||||
{
|
||||
return new ImportResult(new ImportDecision(null, new Rejection(message)), message);
|
||||
return new ImportResult(new ImportDecision(null, new ImportRejection(reason, message)), message);
|
||||
}
|
||||
|
||||
private ImportResult CheckEmptyResultForIssue(string folder)
|
||||
|
@ -338,12 +337,12 @@ namespace NzbDrone.Core.MediaFiles
|
|||
|
||||
if (files.Any(file => FileExtensions.ExecutableExtensions.Contains(Path.GetExtension(file))))
|
||||
{
|
||||
return RejectionResult("Caution: Found executable file");
|
||||
return RejectionResult(ImportRejectionReason.ExecutableFile, "Caution: Found executable file");
|
||||
}
|
||||
|
||||
if (files.Any(file => FileExtensions.ArchiveExtensions.Contains(Path.GetExtension(file))))
|
||||
{
|
||||
return RejectionResult("Found archive file, might need to be extracted");
|
||||
return RejectionResult(ImportRejectionReason.ArchiveFile, "Found archive file, might need to be extracted");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -6,6 +5,6 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
{
|
||||
public interface IImportDecisionEngineSpecification
|
||||
{
|
||||
Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem);
|
||||
ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
|
||||
// Adding all the rejected decisions
|
||||
importResults.AddRange(decisions.Where(c => !c.Approved)
|
||||
.Select(d => new ImportResult(d, d.Rejections.Select(r => r.Reason).ToArray())));
|
||||
.Select(d => new ImportResult(d, d.Rejections.Select(r => r.Message).ToArray())));
|
||||
|
||||
return importResults;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.MovieImport
|
||||
|
@ -9,24 +8,14 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
public class ImportDecision
|
||||
{
|
||||
public LocalMovie LocalMovie { get; private set; }
|
||||
public IEnumerable<Rejection> Rejections { get; private set; }
|
||||
public IEnumerable<ImportRejection> Rejections { get; private set; }
|
||||
|
||||
public bool Approved => Rejections.Empty();
|
||||
|
||||
public ImportDecision(LocalMovie localMovie, params Rejection[] rejections)
|
||||
public ImportDecision(LocalMovie localMovie, params ImportRejection[] rejections)
|
||||
{
|
||||
LocalMovie = localMovie;
|
||||
Rejections = rejections.ToList();
|
||||
|
||||
// LocalMovie = new LocalMovie
|
||||
// {
|
||||
// Quality = localMovie.Quality,
|
||||
// ExistingFile = localMovie.ExistingFile,
|
||||
// MediaInfo = localMovie.MediaInfo,
|
||||
// ParsedMovieInfo = localMovie.ParsedMovieInfo,
|
||||
// Path = localMovie.Path,
|
||||
// Size = localMovie.Size
|
||||
// };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ using NLog;
|
|||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.MediaFiles.MovieImport.Aggregation;
|
||||
|
@ -128,7 +127,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
|
||||
if (localMovie.Movie == null)
|
||||
{
|
||||
decision = new ImportDecision(localMovie, new Rejection("Invalid movie"));
|
||||
decision = new ImportDecision(localMovie, new ImportRejection(ImportRejectionReason.InvalidMovie, "Invalid movie"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -150,13 +149,13 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
}
|
||||
catch (AugmentingFailedException)
|
||||
{
|
||||
decision = new ImportDecision(localMovie, new Rejection("Unable to parse file"));
|
||||
decision = new ImportDecision(localMovie, new ImportRejection(ImportRejectionReason.UnableToParse, "Unable to parse file"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Couldn't import file. {0}", localMovie.Path);
|
||||
|
||||
decision = new ImportDecision(localMovie, new Rejection("Unexpected error processing file"));
|
||||
decision = new ImportDecision(localMovie, new ImportRejection(ImportRejectionReason.Error, "Unexpected error processing file"));
|
||||
}
|
||||
|
||||
if (decision == null)
|
||||
|
@ -175,7 +174,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
return decision;
|
||||
}
|
||||
|
||||
private Rejection EvaluateSpec(IImportDecisionEngineSpecification spec, LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
private ImportRejection EvaluateSpec(IImportDecisionEngineSpecification spec, LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -183,7 +182,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
|
||||
if (!result.Accepted)
|
||||
{
|
||||
return new Rejection(result.Reason);
|
||||
return new ImportRejection(result.Reason, result.Message);
|
||||
}
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
|
@ -194,7 +193,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
|
|||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Couldn't evaluate decision on {0}", localMovie.Path);
|
||||
return new Rejection($"{spec.GetType().Name}: {ex.Message}");
|
||||
return new ImportRejection(ImportRejectionReason.DecisionError, $"{spec.GetType().Name}: {ex.Message}");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
11
src/NzbDrone.Core/MediaFiles/MovieImport/ImportRejection.cs
Normal file
11
src/NzbDrone.Core/MediaFiles/MovieImport/ImportRejection.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using NzbDrone.Core.DecisionEngine;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.MovieImport;
|
||||
|
||||
public class ImportRejection : Rejection<ImportRejectionReason>
|
||||
{
|
||||
public ImportRejection(ImportRejectionReason reason, string message, RejectionType type = RejectionType.Permanent)
|
||||
: base(reason, message, type)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
namespace NzbDrone.Core.MediaFiles.MovieImport;
|
||||
|
||||
public enum ImportRejectionReason
|
||||
{
|
||||
Unknown,
|
||||
FileLocked,
|
||||
UnknownMovie,
|
||||
ExecutableFile,
|
||||
ArchiveFile,
|
||||
MovieFolder,
|
||||
InvalidFilePath,
|
||||
UnsupportedExtension,
|
||||
InvalidMovie,
|
||||
UnableToParse,
|
||||
Error,
|
||||
DecisionError,
|
||||
MovieAlreadyImported,
|
||||
MinimumFreeSpace,
|
||||
NoAudio,
|
||||
MovieNotFoundInRelease,
|
||||
Sample,
|
||||
SampleIndeterminate,
|
||||
Unpacking,
|
||||
MultiPartMovie,
|
||||
NotQualityUpgrade,
|
||||
NotRevisionUpgrade,
|
||||
NotCustomFormatUpgrade
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
namespace NzbDrone.Core.MediaFiles.MovieImport
|
||||
{
|
||||
public class ImportSpecDecision
|
||||
{
|
||||
public bool Accepted { get; private set; }
|
||||
public ImportRejectionReason Reason { get; set; }
|
||||
public string Message { get; private set; }
|
||||
|
||||
private static readonly ImportSpecDecision AcceptDecision = new () { Accepted = true };
|
||||
private ImportSpecDecision()
|
||||
{
|
||||
}
|
||||
|
||||
public static ImportSpecDecision Accept()
|
||||
{
|
||||
return AcceptDecision;
|
||||
}
|
||||
|
||||
public static ImportSpecDecision Reject(ImportRejectionReason reason, string message, params object[] args)
|
||||
{
|
||||
return Reject(reason, string.Format(message, args));
|
||||
}
|
||||
|
||||
public static ImportSpecDecision Reject(ImportRejectionReason reason, string message)
|
||||
{
|
||||
return new ImportSpecDecision
|
||||
{
|
||||
Accepted = false,
|
||||
Reason = reason,
|
||||
Message = message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
@ -21,7 +20,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
|
|||
public List<CustomFormat> CustomFormats { get; set; }
|
||||
public int CustomFormatScore { get; set; }
|
||||
public int IndexerFlags { get; set; }
|
||||
public IEnumerable<Rejection> Rejections { get; set; }
|
||||
public IEnumerable<ImportRejection> Rejections { get; set; }
|
||||
public Movie Movie { get; set; }
|
||||
|
||||
public ManualImportItem()
|
||||
|
|
|
@ -7,7 +7,6 @@ using NzbDrone.Common.Disk;
|
|||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation.Extensions;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Languages;
|
||||
|
@ -255,7 +254,11 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
|
|||
localMovie.Languages = LanguageParser.ParseLanguages(file);
|
||||
localMovie.Size = _diskProvider.GetFileSize(file);
|
||||
|
||||
return MapItem(new ImportDecision(localMovie, new Rejection("Unknown Movie")), rootFolder, downloadId, null);
|
||||
return MapItem(new ImportDecision(localMovie,
|
||||
new ImportRejection(ImportRejectionReason.UnknownMovie, "Unknown Movie")),
|
||||
rootFolder,
|
||||
downloadId,
|
||||
null);
|
||||
}
|
||||
|
||||
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> { file }, movie, trackedDownload?.DownloadItem, null, SceneSource(movie, baseFolder));
|
||||
|
@ -277,7 +280,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
|
|||
RelativePath = rootFolder.GetRelativePath(file),
|
||||
Name = Path.GetFileNameWithoutExtension(file),
|
||||
Size = _diskProvider.GetFileSize(file),
|
||||
Rejections = new List<Rejection>()
|
||||
Rejections = new List<ImportRejection>()
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
|
||||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
_logger.Debug("No download client information is available, skipping");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var movie = localMovie.Movie;
|
||||
|
@ -35,7 +35,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (!movie.HasFile)
|
||||
{
|
||||
_logger.Debug("Skipping already imported check for movie without file");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var movieImportedHistory = _historyService.GetByMovieId(movie.Id, null);
|
||||
|
@ -48,7 +48,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (lastImported == null)
|
||||
{
|
||||
_logger.Trace("Movie file has not been imported");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (lastGrabbed != null)
|
||||
|
@ -57,23 +57,23 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (lastGrabbed.Date.After(lastImported.Date))
|
||||
{
|
||||
_logger.Trace("Movie file was grabbed again after importing");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
// If the release was imported after the last grab reject it
|
||||
if (lastImported.Date.After(lastGrabbed.Date))
|
||||
{
|
||||
_logger.Debug("Movie file previously imported at {0}", lastImported.Date);
|
||||
return Decision.Reject("Movie file already imported at {0}", lastImported.Date.ToLocalTime());
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.MovieAlreadyImported, "Movie file already imported at {0}", lastImported.Date.ToLocalTime());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("Movie file previously imported at {0}", lastImported.Date);
|
||||
return Decision.Reject("Movie file already imported at {0}", lastImported.Date.ToLocalTime());
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.MovieAlreadyImported, "Movie file already imported at {0}", lastImported.Date.ToLocalTime());
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ using NLog;
|
|||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -23,12 +22,12 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (_configService.SkipFreeSpaceCheckWhenImporting)
|
||||
{
|
||||
_logger.Debug("Skipping free space check when importing");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
try
|
||||
|
@ -36,7 +35,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (localMovie.ExistingFile)
|
||||
{
|
||||
_logger.Debug("Skipping free space check for existing movie");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var path = Directory.GetParent(localMovie.Movie.Path);
|
||||
|
@ -45,13 +44,13 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (!freeSpace.HasValue)
|
||||
{
|
||||
_logger.Debug("Free space check returned an invalid result for: {0}", path);
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (freeSpace < localMovie.Size + _configService.MinimumFreeSpaceWhenImporting.Megabytes())
|
||||
{
|
||||
_logger.Warn("Not enough free space ({0}) to import: {1} ({2})", freeSpace, localMovie, localMovie.Size);
|
||||
return Decision.Reject("Not enough free space");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.MinimumFreeSpace, "Not enough free space");
|
||||
}
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
|
@ -63,7 +62,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger.Error(ex, "Unable to check free disk space while importing: {0}", localMovie.Path);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
@ -21,11 +20,11 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_historyService = historyService;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var grabbedHistory = _historyService.FindByDownloadId(downloadClientItem.DownloadId)
|
||||
|
@ -35,7 +34,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (grabbedHistory.Empty())
|
||||
{
|
||||
_logger.Debug("No grabbed history for this download client item");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
foreach (var item in grabbedHistory)
|
||||
|
@ -47,7 +46,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -14,22 +13,22 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (localMovie.MediaInfo == null)
|
||||
{
|
||||
_logger.Debug("Failed to get media info from the file, make sure ffprobe is available, skipping check");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (localMovie.MediaInfo.AudioStreamCount == 0)
|
||||
{
|
||||
_logger.Debug("No audio tracks found in file");
|
||||
|
||||
return Decision.Reject("No audio tracks detected");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.NoAudio, "No audio tracks detected");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -15,18 +14,18 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (localMovie.ExistingFile)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var dirInfo = new FileInfo(localMovie.Path).Directory;
|
||||
|
||||
if (dirInfo == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
// TODO: Actually implement this!!!!
|
||||
|
@ -37,7 +36,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
return Decision.Accept();
|
||||
}*/
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -16,28 +15,28 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (localMovie.ExistingFile)
|
||||
{
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var releaseInfo = localMovie.Release;
|
||||
|
||||
if (releaseInfo == null || releaseInfo.MovieIds.Empty())
|
||||
{
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
if (releaseInfo.MovieIds.All(o => o != localMovie.Movie.Id))
|
||||
{
|
||||
_logger.Debug("Unexpected movie(s) in file: {0}", localMovie.Movie.ToString());
|
||||
|
||||
return Decision.Reject("Movie {0} was not found in the grabbed release: {1}", localMovie.Movie.ToString(), releaseInfo.Title);
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.MovieNotFoundInRelease, "Movie {0} was not found in the grabbed release: {1}", localMovie.Movie.ToString(), releaseInfo.Title);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Text.RegularExpressions;
|
|||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -11,8 +10,14 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
{
|
||||
public class NotMultiPartSpecification : IImportDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private static readonly Regex[] MovieMultiPartRegex = new[]
|
||||
{
|
||||
new Regex(@"(?<!^)(?<identifier>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"(?<!^)(?<identifier>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[a-d]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
};
|
||||
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public NotMultiPartSpecification(IDiskProvider diskProvider, Logger logger)
|
||||
{
|
||||
|
@ -20,33 +25,24 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
private static readonly Regex[] MovieMultiPartRegex = new Regex[]
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
new Regex(@"(?<!^)(?<identifier>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"(?<!^)(?<identifier>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[a-d]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
};
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var regexReplace = MovieMultiPartRegex.First().Replace(localMovie.Path, "");
|
||||
|
||||
if (MovieMultiPartRegex.Any(v => v.IsMatch(localMovie.Path)))
|
||||
{
|
||||
var parentPath = localMovie.Path.GetParentPath();
|
||||
var filesInDirectory = _diskProvider.GetFiles(localMovie.Path.GetParentPath(), false);
|
||||
var filesInDirectory = _diskProvider.GetFiles(localMovie.Path.GetParentPath(), false).ToList();
|
||||
|
||||
foreach (var regex in MovieMultiPartRegex)
|
||||
{
|
||||
if (filesInDirectory.Where(file => regex.Replace(file, "") == regex.Replace(localMovie.Path, "")).Count() > 1)
|
||||
if (filesInDirectory.Count(file => regex.Replace(file, "") == regex.Replace(localMovie.Path, "")) > 1)
|
||||
{
|
||||
_logger.Debug("Rejected Multi-Part File: {0}", localMovie.Path);
|
||||
|
||||
return Decision.Reject("File is suspected multi-part file, Radarr doesn't support this");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.MultiPartMovie, "File is suspected multi-part file, Radarr doesn't support this");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -17,26 +16,26 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (localMovie.ExistingFile)
|
||||
{
|
||||
_logger.Debug("Existing file, skipping sample check");
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var sample = _detectSample.IsSample(localMovie.Movie.MovieMetadata, localMovie.Path);
|
||||
|
||||
if (sample == DetectSampleResult.Sample)
|
||||
{
|
||||
return Decision.Reject("Sample");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.Sample, "Sample");
|
||||
}
|
||||
else if (sample == DetectSampleResult.Indeterminate)
|
||||
{
|
||||
return Decision.Reject("Unable to determine if file is a sample");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.SampleIndeterminate, "Unable to determine if file is a sample");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ using NLog;
|
|||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -23,12 +22,12 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (localMovie.ExistingFile)
|
||||
{
|
||||
_logger.Debug("{0} is in movie folder, skipping unpacking check", localMovie.Path);
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
foreach (var workingFolder in _configService.DownloadClientWorkingFolders.Split('|'))
|
||||
|
@ -41,13 +40,13 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (OsInfo.IsNotWindows)
|
||||
{
|
||||
_logger.Debug("{0} is still being unpacked", localMovie.Path);
|
||||
return Decision.Reject("File is still being unpacked");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.Unpacking, "File is still being unpacked");
|
||||
}
|
||||
|
||||
if (_diskProvider.FileGetLastWrite(localMovie.Path) > DateTime.UtcNow.AddMinutes(-5))
|
||||
{
|
||||
_logger.Debug("{0} appears to be unpacking still", localMovie.Path);
|
||||
return Decision.Reject("File is still being unpacked");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.Unpacking, "File is still being unpacked");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
||||
{
|
||||
public class UnverifiedSceneNumberingSpecification : IImportDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public UnverifiedSceneNumberingSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ using NLog;
|
|||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
@ -24,7 +23,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
public ImportSpecDecision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var downloadPropersAndRepacks = _configService.DownloadPropersAndRepacks;
|
||||
var qualityProfile = localMovie.Movie.QualityProfile;
|
||||
|
@ -38,7 +37,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
{
|
||||
_logger.Trace("Unable to get movie file details from the DB. MovieId: {0} MovieFileId: {1}", localMovie.Movie.Id, localMovie.Movie.MovieFileId);
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
|
||||
var qualityCompare = qualityComparer.Compare(localMovie.Quality.Quality, movieFile.Quality.Quality);
|
||||
|
@ -46,7 +45,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
if (qualityCompare < 0)
|
||||
{
|
||||
_logger.Debug("This file isn't a quality upgrade for movie. Existing quality: {0}. New Quality {1}. Skipping {2}", movieFile.Quality.Quality, localMovie.Quality.Quality, localMovie.Path);
|
||||
return Decision.Reject("Not an upgrade for existing movie file. Existing quality: {0}. New Quality {1}.", movieFile.Quality.Quality, localMovie.Quality.Quality);
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.NotQualityUpgrade, "Not an upgrade for existing movie file. Existing quality: {0}. New Quality {1}.", movieFile.Quality.Quality, localMovie.Quality.Quality);
|
||||
}
|
||||
|
||||
// Same quality, propers/repacks are preferred and it is not a revision update. Reject revision downgrade.
|
||||
|
@ -56,7 +55,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
localMovie.Quality.Revision.CompareTo(movieFile.Quality.Revision) < 0)
|
||||
{
|
||||
_logger.Debug("This file isn't a quality revision upgrade for movie. Skipping {0}", localMovie.Path);
|
||||
return Decision.Reject("Not a quality revision upgrade for existing movie file(s)");
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.NotRevisionUpgrade, "Not a quality revision upgrade for existing movie file(s)");
|
||||
}
|
||||
|
||||
movieFile.Movie = localMovie.Movie;
|
||||
|
@ -73,7 +72,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
currentCustomFormats != null ? currentCustomFormats.ConcatToString() : "",
|
||||
currentFormatScore);
|
||||
|
||||
return Decision.Reject("Not a Custom Format upgrade for existing movie file(s). New: [{0}] ({1}) do not improve on Existing: [{2}] ({3})",
|
||||
return ImportSpecDecision.Reject(ImportRejectionReason.NotCustomFormatUpgrade,
|
||||
"Not a Custom Format upgrade for existing movie file(s). New: [{0}] ({1}) do not improve on Existing: [{2}] ({3})",
|
||||
newCustomFormats != null ? newCustomFormats.ConcatToString() : "",
|
||||
newFormatScore,
|
||||
currentCustomFormats != null ? currentCustomFormats.ConcatToString() : "",
|
||||
|
@ -87,7 +87,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
|||
currentFormatScore);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
return ImportSpecDecision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace Radarr.Api.V3.Indexers
|
|||
Rejected = model.Rejected,
|
||||
TmdbId = releaseInfo.TmdbId,
|
||||
ImdbId = releaseInfo.ImdbId,
|
||||
Rejections = model.Rejections.Select(r => r.Reason).ToList(),
|
||||
Rejections = model.Rejections.Select(r => r.Message).ToList(),
|
||||
PublishDate = releaseInfo.PublishDate,
|
||||
CommentUrl = releaseInfo.CommentUrl,
|
||||
DownloadUrl = releaseInfo.DownloadUrl,
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Radarr.Api.V3.ManualImport
|
|||
|
||||
item.Movie = processedItem.Movie.ToResource(0);
|
||||
item.IndexerFlags = processedItem.IndexerFlags;
|
||||
item.Rejections = processedItem.Rejections;
|
||||
item.Rejections = processedItem.Rejections.Select(r => r.ToResource());
|
||||
item.CustomFormats = processedItem.CustomFormats.ToResource(false);
|
||||
item.CustomFormatScore = processedItem.CustomFormatScore;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Radarr.Api.V3.CustomFormats;
|
||||
|
@ -20,6 +19,6 @@ namespace Radarr.Api.V3.ManualImport
|
|||
public List<CustomFormatResource> CustomFormats { get; set; }
|
||||
public int CustomFormatScore { get; set; }
|
||||
public int IndexerFlags { get; set; }
|
||||
public IEnumerable<Rejection> Rejections { get; set; }
|
||||
public IEnumerable<ImportRejectionResource> Rejections { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
|||
using NzbDrone.Common.Crypto;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles.MovieImport;
|
||||
using NzbDrone.Core.MediaFiles.MovieImport.Manual;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using Radarr.Api.V3.CustomFormats;
|
||||
|
@ -27,7 +28,7 @@ namespace Radarr.Api.V3.ManualImport
|
|||
public List<CustomFormatResource> CustomFormats { get; set; }
|
||||
public int CustomFormatScore { get; set; }
|
||||
public int IndexerFlags { get; set; }
|
||||
public IEnumerable<Rejection> Rejections { get; set; }
|
||||
public IEnumerable<ImportRejectionResource> Rejections { get; set; }
|
||||
}
|
||||
|
||||
public static class ManualImportResourceMapper
|
||||
|
@ -60,7 +61,7 @@ namespace Radarr.Api.V3.ManualImport
|
|||
// QualityWeight
|
||||
DownloadId = model.DownloadId,
|
||||
IndexerFlags = model.IndexerFlags,
|
||||
Rejections = model.Rejections
|
||||
Rejections = model.Rejections.Select(r => r.ToResource())
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -69,4 +70,27 @@ namespace Radarr.Api.V3.ManualImport
|
|||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public class ImportRejectionResource
|
||||
{
|
||||
public string Reason { get; set; }
|
||||
public RejectionType Type { get; set; }
|
||||
}
|
||||
|
||||
public static class ImportRejectionResourceMapper
|
||||
{
|
||||
public static ImportRejectionResource ToResource(this ImportRejection rejection)
|
||||
{
|
||||
if (rejection == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ImportRejectionResource
|
||||
{
|
||||
Reason = rejection.Message,
|
||||
Type = rejection.Type
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue