1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-24 22:36:19 -04:00

Fixed: Don't allow pushed releases to bypass pending releases that recently expired

Closes #7725
This commit is contained in:
Mark McDowall
2025-03-23 18:11:24 -07:00
parent 83b2c9e97a
commit da29de4cfe
72 changed files with 632 additions and 369 deletions
@@ -92,6 +92,7 @@ namespace NzbDrone.Core.DecisionEngine
{
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvdbId, report.TvRageId, report.ImdbId, searchCriteria);
remoteEpisode.Release = report;
remoteEpisode.ReleaseSource = GetReleaseSource(pushedRelease, searchCriteria);
if (remoteEpisode.Series == null)
{
@@ -120,7 +121,7 @@ namespace NzbDrone.Core.DecisionEngine
_logger.Trace("Custom Format Score of '{0}' [{1}] calculated for '{2}'", remoteEpisode.CustomFormatScore, remoteEpisode.CustomFormats?.ConcatToString(), report.Title);
remoteEpisode.DownloadAllowed = remoteEpisode.Episodes.Any();
decision = GetDecisionForReport(remoteEpisode, searchCriteria);
decision = GetDecisionForReport(remoteEpisode, new ReleaseDecisionInformation(pushedRelease, searchCriteria));
}
}
@@ -140,8 +141,9 @@ namespace NzbDrone.Core.DecisionEngine
var remoteEpisode = new RemoteEpisode
{
Release = report,
ReleaseSource = GetReleaseSource(pushedRelease, searchCriteria),
ParsedEpisodeInfo = parsedEpisodeInfo,
Languages = parsedEpisodeInfo.Languages
Languages = parsedEpisodeInfo.Languages,
};
decision = new DownloadDecision(remoteEpisode, new DownloadRejection(DownloadRejectionReason.UnableToParse, "Unable to parse release"));
@@ -152,7 +154,8 @@ namespace NzbDrone.Core.DecisionEngine
{
_logger.Error(e, "Couldn't process release.");
var remoteEpisode = new RemoteEpisode { Release = report };
var remoteEpisode = new RemoteEpisode { Release = report, ReleaseSource = GetReleaseSource(pushedRelease, searchCriteria) };
decision = new DownloadDecision(remoteEpisode, new DownloadRejection(DownloadRejectionReason.Error, "Unexpected error processing release"));
}
@@ -160,26 +163,6 @@ namespace NzbDrone.Core.DecisionEngine
if (decision != null)
{
var source = pushedRelease ? ReleaseSourceType.ReleasePush : ReleaseSourceType.Rss;
if (searchCriteria != null)
{
if (searchCriteria.InteractiveSearch)
{
source = ReleaseSourceType.InteractiveSearch;
}
else if (searchCriteria.UserInvokedSearch)
{
source = ReleaseSourceType.UserInvokedSearch;
}
else
{
source = ReleaseSourceType.Search;
}
}
decision.RemoteEpisode.ReleaseSource = source;
if (decision.Rejections.Any())
{
_logger.Debug("Release '{0}' from '{1}' rejected for the following reasons: {2}", report.Title, report.Indexer, string.Join(", ", decision.Rejections));
@@ -194,13 +177,13 @@ namespace NzbDrone.Core.DecisionEngine
}
}
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria = null)
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, ReleaseDecisionInformation information)
{
var reasons = Array.Empty<DownloadRejection>();
foreach (var specifications in _specifications.GroupBy(v => v.Priority).OrderBy(v => v.Key))
{
reasons = specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchCriteria))
reasons = specifications.Select(c => EvaluateSpec(c, remoteEpisode, information))
.Where(c => c != null)
.ToArray();
@@ -213,11 +196,11 @@ namespace NzbDrone.Core.DecisionEngine
return new DownloadDecision(remoteEpisode, reasons.ToArray());
}
private DownloadRejection EvaluateSpec(IDownloadDecisionEngineSpecification spec, RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteriaBase = null)
private DownloadRejection EvaluateSpec(IDownloadDecisionEngineSpecification spec, RemoteEpisode remoteEpisode, ReleaseDecisionInformation information)
{
try
{
var result = spec.IsSatisfiedBy(remoteEpisode, searchCriteriaBase);
var result = spec.IsSatisfiedBy(remoteEpisode, information);
if (!result.Accepted)
{
@@ -234,5 +217,26 @@ namespace NzbDrone.Core.DecisionEngine
return null;
}
private ReleaseSourceType GetReleaseSource(bool pushedRelease, SearchCriteriaBase searchCriteria = null)
{
if (searchCriteria == null)
{
return pushedRelease ? ReleaseSourceType.ReleasePush : ReleaseSourceType.Rss;
}
if (searchCriteria.InteractiveSearch)
{
return ReleaseSourceType.InteractiveSearch;
}
else if (searchCriteria.UserInvokedSearch)
{
return ReleaseSourceType.UserInvokedSearch;
}
else
{
return ReleaseSourceType.Search;
}
}
}
}