New: Don't block imports when release was matched by ID if they were grabbed via interactive search
Closes #5043
This commit is contained in:
parent
599ad86657
commit
bc2942c28d
|
@ -37,7 +37,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||||
|
|
||||||
results.Should().NotBeEmpty();
|
results.Should().NotBeEmpty();
|
||||||
Mocker.GetMock<IMakeDownloadDecision>()
|
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]
|
[Test]
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
public interface IMakeDownloadDecision
|
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);
|
List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,17 +45,17 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports)
|
public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports, bool pushedRelease = false)
|
||||||
{
|
{
|
||||||
return GetDecisions(reports).ToList();
|
return GetDecisions(reports).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
|
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())
|
if (reports.Any())
|
||||||
{
|
{
|
||||||
|
@ -156,6 +156,26 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
if (decision != null)
|
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())
|
if (decision.Rejections.Any())
|
||||||
{
|
{
|
||||||
_logger.Debug("Release rejected for the following reasons: {0}", string.Join(", ", decision.Rejections));
|
_logger.Debug("Release rejected for the following reasons: {0}", string.Join(", ", decision.Rejections));
|
||||||
|
|
|
@ -1,73 +1,71 @@
|
||||||
using System.Linq;
|
using NLog;
|
||||||
using NLog;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.DataAugmentation.Scene;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
{
|
||||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
public class SceneMappingSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
public class SceneMappingSpecification : IDecisionEngineSpecification
|
private readonly Logger _logger;
|
||||||
{
|
|
||||||
private readonly Logger _logger;
|
public SceneMappingSpecification(Logger logger)
|
||||||
|
{
|
||||||
public SceneMappingSpecification(Logger logger)
|
_logger = logger;
|
||||||
{
|
}
|
||||||
_logger = logger;
|
|
||||||
}
|
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||||
|
public RejectionType Type => RejectionType.Temporary; // Temporary till there's a mapping
|
||||||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
|
||||||
public RejectionType Type => RejectionType.Temporary; // Temporary till there's a mapping
|
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||||
|
{
|
||||||
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
if (remoteEpisode.SceneMapping == null)
|
||||||
{
|
{
|
||||||
if (remoteEpisode.SceneMapping == null)
|
_logger.Debug("No applicable scene mapping, skipping.");
|
||||||
{
|
return Decision.Accept();
|
||||||
_logger.Debug("No applicable scene mapping, skipping.");
|
}
|
||||||
return Decision.Accept();
|
|
||||||
}
|
if (remoteEpisode.SceneMapping.SceneOrigin.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
if (remoteEpisode.SceneMapping.SceneOrigin.IsNullOrWhiteSpace())
|
_logger.Debug("No explicit scene origin in scene mapping.");
|
||||||
{
|
return Decision.Accept();
|
||||||
_logger.Debug("No explicit scene origin in scene mapping.");
|
}
|
||||||
return Decision.Accept();
|
|
||||||
}
|
var split = remoteEpisode.SceneMapping.SceneOrigin.Split(':');
|
||||||
|
|
||||||
var split = remoteEpisode.SceneMapping.SceneOrigin.Split(':');
|
var isInteractive = searchCriteria != null && searchCriteria.InteractiveSearch;
|
||||||
|
|
||||||
var isInteractive = searchCriteria != null && searchCriteria.InteractiveSearch;
|
if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
|
_logger.Debug("SceneMapping has origin {0} with comment '{1}'.", remoteEpisode.SceneMapping.SceneOrigin, remoteEpisode.SceneMapping.Comment);
|
||||||
{
|
}
|
||||||
_logger.Debug("SceneMapping has origin {0} with comment '{1}'.", remoteEpisode.SceneMapping.SceneOrigin, remoteEpisode.SceneMapping.Comment);
|
else
|
||||||
}
|
{
|
||||||
else
|
_logger.Debug("SceneMapping has origin {0}.", remoteEpisode.SceneMapping.SceneOrigin);
|
||||||
{
|
}
|
||||||
_logger.Debug("SceneMapping has origin {0}.", remoteEpisode.SceneMapping.SceneOrigin);
|
|
||||||
}
|
if (split[0] == "mixed")
|
||||||
|
{
|
||||||
if (split[0] == "mixed")
|
_logger.Debug("SceneMapping origin is explicitly mixed, this means these were released with multiple unidentifiable numbering schemes.");
|
||||||
{
|
|
||||||
_logger.Debug("SceneMapping origin is explicitly mixed, this means these were released with multiple unidentifiable numbering schemes.");
|
if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
if (remoteEpisode.SceneMapping.Comment.IsNotNullOrWhiteSpace())
|
return Decision.Reject("{0} has ambiguous numbering");
|
||||||
{
|
}
|
||||||
return Decision.Reject("{0} has ambiguous numbering");
|
else
|
||||||
}
|
{
|
||||||
else
|
return Decision.Reject("Ambiguous numbering");
|
||||||
{
|
}
|
||||||
return Decision.Reject("Ambiguous numbering");
|
}
|
||||||
}
|
|
||||||
}
|
if (split[0] == "unknown")
|
||||||
|
{
|
||||||
if (split[0] == "unknown")
|
var type = split.Length >= 2 ? split[1] : "scene";
|
||||||
{
|
|
||||||
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);
|
||||||
|
}
|
||||||
_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();
|
||||||
|
}
|
||||||
return Decision.Accept();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
|
@ -99,8 +99,10 @@ namespace NzbDrone.Core.Download
|
||||||
}
|
}
|
||||||
|
|
||||||
Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.SERIES_MATCH_TYPE, SeriesMatchType.Unknown.ToString()), out SeriesMatchType seriesMatchType);
|
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.");
|
trackedDownload.Warn("Found matching series via grab history, but release was matched to series by ID. Automatic import is not possible.");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
@ -21,5 +21,6 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
public class PendingReleaseAdditionalInfo
|
public class PendingReleaseAdditionalInfo
|
||||||
{
|
{
|
||||||
public SeriesMatchType SeriesMatchType { get; set; }
|
public SeriesMatchType SeriesMatchType { get; set; }
|
||||||
|
public ReleaseSourceType ReleaseSource { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,6 +313,7 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
{
|
{
|
||||||
Series = series,
|
Series = series,
|
||||||
SeriesMatchType = release.AdditionalInfo?.SeriesMatchType ?? SeriesMatchType.Unknown,
|
SeriesMatchType = release.AdditionalInfo?.SeriesMatchType ?? SeriesMatchType.Unknown,
|
||||||
|
ReleaseSource = release.AdditionalInfo?.ReleaseSource ?? ReleaseSourceType.Unknown,
|
||||||
ParsedEpisodeInfo = release.ParsedEpisodeInfo,
|
ParsedEpisodeInfo = release.ParsedEpisodeInfo,
|
||||||
Release = release.Release
|
Release = release.Release
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace NzbDrone.Core.History
|
||||||
{
|
{
|
||||||
public const string DOWNLOAD_CLIENT = "downloadClient";
|
public const string DOWNLOAD_CLIENT = "downloadClient";
|
||||||
public const string SERIES_MATCH_TYPE = "seriesMatchType";
|
public const string SERIES_MATCH_TYPE = "seriesMatchType";
|
||||||
|
public const string RELEASE_SOURCE = "releaseSource";
|
||||||
|
|
||||||
public EpisodeHistory()
|
public EpisodeHistory()
|
||||||
{
|
{
|
||||||
|
|
|
@ -168,6 +168,7 @@ namespace NzbDrone.Core.History
|
||||||
history.Data.Add("Protocol", ((int)message.Episode.Release.DownloadProtocol).ToString());
|
history.Data.Add("Protocol", ((int)message.Episode.Release.DownloadProtocol).ToString());
|
||||||
history.Data.Add("CustomFormatScore", message.Episode.CustomFormatScore.ToString());
|
history.Data.Add("CustomFormatScore", message.Episode.CustomFormatScore.ToString());
|
||||||
history.Data.Add("SeriesMatchType", message.Episode.SeriesMatchType.ToString());
|
history.Data.Add("SeriesMatchType", message.Episode.SeriesMatchType.ToString());
|
||||||
|
history.Data.Add("ReleaseSource", message.Episode.ReleaseSource.ToString());
|
||||||
|
|
||||||
if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
|
if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,6 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
|
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
|
||||||
public SceneMapping SceneMapping { get; set; }
|
public SceneMapping SceneMapping { get; set; }
|
||||||
public int MappedSeasonNumber { get; set; }
|
public int MappedSeasonNumber { get; set; }
|
||||||
|
|
||||||
public Series Series { get; set; }
|
public Series Series { get; set; }
|
||||||
public List<Episode> Episodes { get; set; }
|
public List<Episode> Episodes { get; set; }
|
||||||
public bool EpisodeRequested { get; set; }
|
public bool EpisodeRequested { get; set; }
|
||||||
|
@ -25,6 +24,7 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public int CustomFormatScore { get; set; }
|
public int CustomFormatScore { get; set; }
|
||||||
public SeriesMatchType SeriesMatchType { get; set; }
|
public SeriesMatchType SeriesMatchType { get; set; }
|
||||||
public List<Language> Languages { get; set; }
|
public List<Language> Languages { get; set; }
|
||||||
|
public ReleaseSourceType ReleaseSource { get; set; }
|
||||||
|
|
||||||
public RemoteEpisode()
|
public RemoteEpisode()
|
||||||
{
|
{
|
||||||
|
@ -43,4 +43,14 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
return Release.Title;
|
return Release.Title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ReleaseSourceType
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
Rss = 1,
|
||||||
|
Search = 2,
|
||||||
|
UserInvokedSearch = 3,
|
||||||
|
InteractiveSearch = 4,
|
||||||
|
ReleasePush = 5
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue