Skip to content

Commit

Permalink
New: Don't block imports when release was matched by ID if they were …
Browse files Browse the repository at this point in the history
…grabbed via interactive search

Closes #5043
  • Loading branch information
markus101 committed Jan 14, 2023
1 parent 599ad86 commit bc2942c
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void should_not_ignore_pending_items_from_available_indexer()

results.Should().NotBeEmpty();
Mocker.GetMock<IMakeDownloadDecision>()
.Verify(v => v.GetRssDecision(It.Is<List<ReleaseInfo>>(d => d.Count == 0)), Times.Never());
.Verify(v => v.GetRssDecision(It.Is<List<ReleaseInfo>>(d => d.Count == 0), It.IsAny<bool>()), Times.Never());
}

[Test]
Expand Down
28 changes: 24 additions & 4 deletions src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace NzbDrone.Core.DecisionEngine
{
public interface IMakeDownloadDecision
{
List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports);
List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports, bool pushedRelease = false);
List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase);
}

Expand Down Expand Up @@ -45,17 +45,17 @@ public class DownloadDecisionMaker : IMakeDownloadDecision
_logger = logger;
}

public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports)
public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports, bool pushedRelease = false)
{
return GetDecisions(reports).ToList();
}

public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
{
return GetDecisions(reports, searchCriteriaBase).ToList();
return GetDecisions(reports, false, searchCriteriaBase).ToList();
}

private IEnumerable<DownloadDecision> GetDecisions(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null)
private IEnumerable<DownloadDecision> GetDecisions(List<ReleaseInfo> reports, bool pushedRelease = false, SearchCriteriaBase searchCriteria = null)
{
if (reports.Any())
{
Expand Down Expand Up @@ -156,6 +156,26 @@ private IEnumerable<DownloadDecision> GetDecisions(List<ReleaseInfo> reports, Se

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 rejected for the following reasons: {0}", string.Join(", ", decision.Rejections));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,73 +1,71 @@
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;

namespace NzbDrone.Core.DecisionEngine.Specifications.Search
{
public class SceneMappingSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;

public SceneMappingSpecification(Logger logger)
{
_logger = logger;
}

public SpecificationPriority Priority => SpecificationPriority.Default;
public RejectionType Type => RejectionType.Temporary; // Temporary till there's a mapping

public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
{
if (remoteEpisode.SceneMapping == null)
{
_logger.Debug("No applicable scene mapping, skipping.");
return Decision.Accept();
}

if (remoteEpisode.SceneMapping.SceneOrigin.IsNullOrWhiteSpace())
{
_logger.Debug("No explicit scene origin in scene mapping.");
return Decision.Accept();
}

var split = remoteEpisode.SceneMapping.SceneOrigin.Split(':');

var isInteractive = searchCriteria != null && searchCriteria.InteractiveSearch;

if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
{
_logger.Debug("SceneMapping has origin {0} with comment '{1}'.", remoteEpisode.SceneMapping.SceneOrigin, remoteEpisode.SceneMapping.Comment);
}
else
{
_logger.Debug("SceneMapping has origin {0}.", remoteEpisode.SceneMapping.SceneOrigin);
}

if (split[0] == "mixed")
{
_logger.Debug("SceneMapping origin is explicitly mixed, this means these were released with multiple unidentifiable numbering schemes.");

if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
{
return Decision.Reject("{0} has ambiguous numbering");
}
else
{
return Decision.Reject("Ambiguous numbering");
}
}

if (split[0] == "unknown")
{
var type = split.Length >= 2 ? split[1] : "scene";

_logger.Debug("SceneMapping origin is explicitly unknown, unsure what numbering scheme it uses but '{0}' will be assumed. Provide full release title to Sonarr/TheXEM team.", type);
}

return Decision.Accept();
}
}
}
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;

namespace NzbDrone.Core.DecisionEngine.Specifications
{
public class SceneMappingSpecification : IDecisionEngineSpecification
{
private readonly Logger _logger;

public SceneMappingSpecification(Logger logger)
{
_logger = logger;
}

public SpecificationPriority Priority => SpecificationPriority.Default;
public RejectionType Type => RejectionType.Temporary; // Temporary till there's a mapping

public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
{
if (remoteEpisode.SceneMapping == null)
{
_logger.Debug("No applicable scene mapping, skipping.");
return Decision.Accept();
}

if (remoteEpisode.SceneMapping.SceneOrigin.IsNullOrWhiteSpace())
{
_logger.Debug("No explicit scene origin in scene mapping.");
return Decision.Accept();
}

var split = remoteEpisode.SceneMapping.SceneOrigin.Split(':');

var isInteractive = searchCriteria != null && searchCriteria.InteractiveSearch;

if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
{
_logger.Debug("SceneMapping has origin {0} with comment '{1}'.", remoteEpisode.SceneMapping.SceneOrigin, remoteEpisode.SceneMapping.Comment);
}
else
{
_logger.Debug("SceneMapping has origin {0}.", remoteEpisode.SceneMapping.SceneOrigin);
}

if (split[0] == "mixed")
{
_logger.Debug("SceneMapping origin is explicitly mixed, this means these were released with multiple unidentifiable numbering schemes.");

if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
{
return Decision.Reject("{0} has ambiguous numbering");
}
else
{
return Decision.Reject("Ambiguous numbering");
}
}

if (split[0] == "unknown")
{
var type = split.Length >= 2 ? split[1] : "scene";

_logger.Debug("SceneMapping origin is explicitly unknown, unsure what numbering scheme it uses but '{0}' will be assumed. Provide full release title to Sonarr/TheXEM team.", type);
}

return Decision.Accept();
}
}
}
4 changes: 3 additions & 1 deletion src/NzbDrone.Core/Download/CompletedDownloadService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ public void Check(TrackedDownload trackedDownload)
}

Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.SERIES_MATCH_TYPE, SeriesMatchType.Unknown.ToString()), out SeriesMatchType seriesMatchType);
Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.RELEASE_SOURCE, ReleaseSourceType.Unknown.ToString()), out ReleaseSourceType releaseSource);

if (seriesMatchType == SeriesMatchType.Id)
// Show a warning if the release was matched by ID and the source is not interactive search
if (seriesMatchType == SeriesMatchType.Id && releaseSource != ReleaseSourceType.InteractiveSearch)
{
trackedDownload.Warn("Found matching series via grab history, but release was matched to series by ID. Automatic import is not possible.");
return;
Expand Down
3 changes: 2 additions & 1 deletion src/NzbDrone.Core/Download/Pending/PendingRelease.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Parser.Model;

Expand All @@ -21,5 +21,6 @@ public class PendingRelease : ModelBase
public class PendingReleaseAdditionalInfo
{
public SeriesMatchType SeriesMatchType { get; set; }
public ReleaseSourceType ReleaseSource { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ private List<PendingRelease> IncludeRemoteEpisodes(List<PendingRelease> releases
{
Series = series,
SeriesMatchType = release.AdditionalInfo?.SeriesMatchType ?? SeriesMatchType.Unknown,
ReleaseSource = release.AdditionalInfo?.ReleaseSource ?? ReleaseSourceType.Unknown,
ParsedEpisodeInfo = release.ParsedEpisodeInfo,
Release = release.Release
};
Expand Down
1 change: 1 addition & 0 deletions src/NzbDrone.Core/History/EpisodeHistory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class EpisodeHistory : ModelBase
{
public const string DOWNLOAD_CLIENT = "downloadClient";
public const string SERIES_MATCH_TYPE = "seriesMatchType";
public const string RELEASE_SOURCE = "releaseSource";

public EpisodeHistory()
{
Expand Down
1 change: 1 addition & 0 deletions src/NzbDrone.Core/History/HistoryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ public void Handle(EpisodeGrabbedEvent message)
history.Data.Add("Protocol", ((int)message.Episode.Release.DownloadProtocol).ToString());
history.Data.Add("CustomFormatScore", message.Episode.CustomFormatScore.ToString());
history.Data.Add("SeriesMatchType", message.Episode.SeriesMatchType.ToString());
history.Data.Add("ReleaseSource", message.Episode.ReleaseSource.ToString());

if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
{
Expand Down
12 changes: 11 additions & 1 deletion src/NzbDrone.Core/Parser/Model/RemoteEpisode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public class RemoteEpisode
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
public SceneMapping SceneMapping { get; set; }
public int MappedSeasonNumber { get; set; }

public Series Series { get; set; }
public List<Episode> Episodes { get; set; }
public bool EpisodeRequested { get; set; }
Expand All @@ -25,6 +24,7 @@ public class RemoteEpisode
public int CustomFormatScore { get; set; }
public SeriesMatchType SeriesMatchType { get; set; }
public List<Language> Languages { get; set; }
public ReleaseSourceType ReleaseSource { get; set; }

public RemoteEpisode()
{
Expand All @@ -43,4 +43,14 @@ public override string ToString()
return Release.Title;
}
}

public enum ReleaseSourceType
{
Unknown = 0,
Rss = 1,
Search = 2,
UserInvokedSearch = 3,
InteractiveSearch = 4,
ReleasePush = 5
}
}

0 comments on commit bc2942c

Please sign in to comment.