Fixed: Automatic import of releases when file is not matched to series
Closes #4935
This commit is contained in:
parent
bb02fc4668
commit
e280897bc7
|
@ -0,0 +1,14 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(168)]
|
||||||
|
public class add_additional_info_to_pending_releases : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("PendingReleases").AddColumn("AdditionalInfo").AsString().Nullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -177,6 +177,7 @@ namespace NzbDrone.Core.Datastore
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(List<LanguageProfileItem>), new EmbeddedDocumentConverter(new LanguageIntConverter()));
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<LanguageProfileItem>), new EmbeddedDocumentConverter(new LanguageIntConverter()));
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedEpisodeInfo), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedEpisodeInfo), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(ReleaseInfo), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(ReleaseInfo), new EmbeddedDocumentConverter());
|
||||||
|
MapRepository.Instance.RegisterTypeConverter(typeof(PendingReleaseAdditionalInfo), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(HashSet<int>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(HashSet<int>), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(OsPath), new OsPathConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(OsPath), new OsPathConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(Guid), new GuidConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(Guid), new GuidConverter());
|
||||||
|
|
|
@ -13,6 +13,7 @@ using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download
|
namespace NzbDrone.Core.Download
|
||||||
|
@ -97,9 +98,13 @@ namespace NzbDrone.Core.Download
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackedDownload.Warn("Found matching series via grab history, but release title doesn't match series title. Automatic import is not possible.");
|
Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.SERIES_MATCH_TYPE, SeriesMatchType.Unknown.ToString()), out SeriesMatchType seriesMatchType);
|
||||||
|
|
||||||
return;
|
if (seriesMatchType == SeriesMatchType.Id)
|
||||||
|
{
|
||||||
|
trackedDownload.Warn("Found matching series via grab history, but release was matched to series by ID. Automatic import is not possible.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackedDownload.State = TrackedDownloadState.ImportPending;
|
trackedDownload.State = TrackedDownloadState.ImportPending;
|
||||||
|
|
|
@ -12,8 +12,14 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
|
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
|
||||||
public ReleaseInfo Release { get; set; }
|
public ReleaseInfo Release { get; set; }
|
||||||
public PendingReleaseReason Reason { get; set; }
|
public PendingReleaseReason Reason { get; set; }
|
||||||
|
public PendingReleaseAdditionalInfo AdditionalInfo { get; set; }
|
||||||
|
|
||||||
//Not persisted
|
//Not persisted
|
||||||
public RemoteEpisode RemoteEpisode { get; set; }
|
public RemoteEpisode RemoteEpisode { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PendingReleaseAdditionalInfo
|
||||||
|
{
|
||||||
|
public SeriesMatchType SeriesMatchType { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,16 +291,15 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
// Just in case the series was removed, but wasn't cleaned up yet (housekeeper will clean it up)
|
// Just in case the series was removed, but wasn't cleaned up yet (housekeeper will clean it up)
|
||||||
if (series == null) return null;
|
if (series == null) return null;
|
||||||
|
|
||||||
|
|
||||||
release.RemoteEpisode = new RemoteEpisode
|
release.RemoteEpisode = new RemoteEpisode
|
||||||
{
|
{
|
||||||
Series = series,
|
Series = series,
|
||||||
|
SeriesMatchType = release.AdditionalInfo?.SeriesMatchType ?? SeriesMatchType.Unknown,
|
||||||
ParsedEpisodeInfo = release.ParsedEpisodeInfo,
|
ParsedEpisodeInfo = release.ParsedEpisodeInfo,
|
||||||
Release = release.Release
|
Release = release.Release
|
||||||
};
|
};
|
||||||
|
|
||||||
RemoteEpisode knownRemoteEpisode;
|
if (knownRemoteEpisodes != null && knownRemoteEpisodes.TryGetValue(release.Release.Title, out var knownRemoteEpisode))
|
||||||
if (knownRemoteEpisodes != null && knownRemoteEpisodes.TryGetValue(release.Release.Title, out knownRemoteEpisode))
|
|
||||||
{
|
{
|
||||||
release.RemoteEpisode.MappedSeasonNumber = knownRemoteEpisode.MappedSeasonNumber;
|
release.RemoteEpisode.MappedSeasonNumber = knownRemoteEpisode.MappedSeasonNumber;
|
||||||
release.RemoteEpisode.Episodes = knownRemoteEpisode.Episodes;
|
release.RemoteEpisode.Episodes = knownRemoteEpisode.Episodes;
|
||||||
|
@ -333,7 +332,11 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
Release = decision.RemoteEpisode.Release,
|
Release = decision.RemoteEpisode.Release,
|
||||||
Title = decision.RemoteEpisode.Release.Title,
|
Title = decision.RemoteEpisode.Release.Title,
|
||||||
Added = DateTime.UtcNow,
|
Added = DateTime.UtcNow,
|
||||||
Reason = reason
|
Reason = reason,
|
||||||
|
AdditionalInfo = new PendingReleaseAdditionalInfo
|
||||||
|
{
|
||||||
|
SeriesMatchType = decision.RemoteEpisode.SeriesMatchType
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent());
|
_eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent());
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace NzbDrone.Core.History
|
||||||
public class EpisodeHistory : ModelBase
|
public class EpisodeHistory : ModelBase
|
||||||
{
|
{
|
||||||
public const string DOWNLOAD_CLIENT = "downloadClient";
|
public const string DOWNLOAD_CLIENT = "downloadClient";
|
||||||
|
public const string SERIES_MATCH_TYPE = "seriesMatchType";
|
||||||
|
|
||||||
public EpisodeHistory()
|
public EpisodeHistory()
|
||||||
{
|
{
|
||||||
|
|
|
@ -169,6 +169,7 @@ namespace NzbDrone.Core.History
|
||||||
history.Data.Add("TvRageId", message.Episode.Release.TvRageId.ToString());
|
history.Data.Add("TvRageId", message.Episode.Release.TvRageId.ToString());
|
||||||
history.Data.Add("Protocol", ((int)message.Episode.Release.DownloadProtocol).ToString());
|
history.Data.Add("Protocol", ((int)message.Episode.Release.DownloadProtocol).ToString());
|
||||||
history.Data.Add("PreferredWordScore", message.Episode.PreferredWordScore.ToString());
|
history.Data.Add("PreferredWordScore", message.Episode.PreferredWordScore.ToString());
|
||||||
|
history.Data.Add("SeriesMatchType", message.Episode.SeriesMatchType.ToString());
|
||||||
|
|
||||||
if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
|
if (!message.Episode.ParsedEpisodeInfo.ReleaseHash.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Parser.Model
|
||||||
|
{
|
||||||
|
public class FindSeriesResult
|
||||||
|
{
|
||||||
|
public Series Series { get; set; }
|
||||||
|
public SeriesMatchType MatchType { get; set; }
|
||||||
|
|
||||||
|
public FindSeriesResult(Series series, SeriesMatchType matchType)
|
||||||
|
{
|
||||||
|
Series = series;
|
||||||
|
MatchType = matchType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SeriesMatchType
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
Title = 1,
|
||||||
|
Alias = 2,
|
||||||
|
Id = 3
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public bool DownloadAllowed { get; set; }
|
public bool DownloadAllowed { get; set; }
|
||||||
public TorrentSeedConfiguration SeedConfiguration { get; set; }
|
public TorrentSeedConfiguration SeedConfiguration { get; set; }
|
||||||
public int PreferredWordScore { get; set; }
|
public int PreferredWordScore { get; set; }
|
||||||
|
public SeriesMatchType SeriesMatchType { get; set; }
|
||||||
|
|
||||||
public RemoteEpisode()
|
public RemoteEpisode()
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,7 +164,13 @@ namespace NzbDrone.Core.Parser
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
series = GetSeries(parsedEpisodeInfo, tvdbId, tvRageId, sceneMapping, searchCriteria);
|
var seriesMatch = FindSeries(parsedEpisodeInfo, tvdbId, tvRageId, sceneMapping, searchCriteria);
|
||||||
|
|
||||||
|
if (seriesMatch != null)
|
||||||
|
{
|
||||||
|
series = seriesMatch.Series;
|
||||||
|
remoteEpisode.SeriesMatchType = seriesMatch.MatchType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series != null)
|
if (series != null)
|
||||||
|
@ -328,7 +334,7 @@ namespace NzbDrone.Core.Parser
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Series GetSeries(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SceneMapping sceneMapping, SearchCriteriaBase searchCriteria)
|
private FindSeriesResult FindSeries(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SceneMapping sceneMapping, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
Series series = null;
|
Series series = null;
|
||||||
|
|
||||||
|
@ -336,7 +342,7 @@ namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
if (searchCriteria != null && searchCriteria.Series.TvdbId == sceneMapping.TvdbId)
|
if (searchCriteria != null && searchCriteria.Series.TvdbId == sceneMapping.TvdbId)
|
||||||
{
|
{
|
||||||
return searchCriteria.Series;
|
return new FindSeriesResult(searchCriteria.Series, SeriesMatchType.Alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
series = _seriesService.FindByTvdbId(sceneMapping.TvdbId);
|
series = _seriesService.FindByTvdbId(sceneMapping.TvdbId);
|
||||||
|
@ -347,14 +353,14 @@ namespace NzbDrone.Core.Parser
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return series;
|
return new FindSeriesResult(series, SeriesMatchType.Alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchCriteria != null)
|
if (searchCriteria != null)
|
||||||
{
|
{
|
||||||
if (searchCriteria.Series.CleanTitle == parsedEpisodeInfo.SeriesTitle.CleanSeriesTitle())
|
if (searchCriteria.Series.CleanTitle == parsedEpisodeInfo.SeriesTitle.CleanSeriesTitle())
|
||||||
{
|
{
|
||||||
return searchCriteria.Series;
|
return new FindSeriesResult(searchCriteria.Series, SeriesMatchType.Title);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tvdbId > 0 && tvdbId == searchCriteria.Series.TvdbId)
|
if (tvdbId > 0 && tvdbId == searchCriteria.Series.TvdbId)
|
||||||
|
@ -366,7 +372,7 @@ namespace NzbDrone.Core.Parser
|
||||||
.WriteSentryWarn("TvdbIdMatch", tvdbId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
.WriteSentryWarn("TvdbIdMatch", tvdbId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||||
.Write();
|
.Write();
|
||||||
|
|
||||||
return searchCriteria.Series;
|
return new FindSeriesResult(searchCriteria.Series, SeriesMatchType.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tvRageId > 0 && tvRageId == searchCriteria.Series.TvRageId)
|
if (tvRageId > 0 && tvRageId == searchCriteria.Series.TvRageId)
|
||||||
|
@ -378,20 +384,28 @@ namespace NzbDrone.Core.Parser
|
||||||
.WriteSentryWarn("TvRageIdMatch", tvRageId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
.WriteSentryWarn("TvRageIdMatch", tvRageId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||||
.Write();
|
.Write();
|
||||||
|
|
||||||
return searchCriteria.Series;
|
return new FindSeriesResult(searchCriteria.Series, SeriesMatchType.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var matchType = SeriesMatchType.Unknown;
|
||||||
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
||||||
|
|
||||||
|
if (series != null)
|
||||||
|
{
|
||||||
|
matchType = SeriesMatchType.Title;
|
||||||
|
}
|
||||||
|
|
||||||
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.AllTitles != null)
|
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.AllTitles != null)
|
||||||
{
|
{
|
||||||
series = GetSeriesByAllTitles(parsedEpisodeInfo);
|
series = GetSeriesByAllTitles(parsedEpisodeInfo);
|
||||||
|
matchType = SeriesMatchType.Title;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.Year > 0)
|
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.Year > 0)
|
||||||
{
|
{
|
||||||
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear, parsedEpisodeInfo.SeriesTitleInfo.Year);
|
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear, parsedEpisodeInfo.SeriesTitleInfo.Year);
|
||||||
|
matchType = SeriesMatchType.Title;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series == null && tvdbId > 0)
|
if (series == null && tvdbId > 0)
|
||||||
|
@ -406,6 +420,8 @@ namespace NzbDrone.Core.Parser
|
||||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||||
.WriteSentryWarn("TvdbIdMatch", tvdbId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
.WriteSentryWarn("TvdbIdMatch", tvdbId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||||
.Write();
|
.Write();
|
||||||
|
|
||||||
|
matchType = SeriesMatchType.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,6 +437,8 @@ namespace NzbDrone.Core.Parser
|
||||||
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
.Property("ParsedEpisodeInfo", parsedEpisodeInfo)
|
||||||
.WriteSentryWarn("TvRageIdMatch", tvRageId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
.WriteSentryWarn("TvRageIdMatch", tvRageId.ToString(), parsedEpisodeInfo.SeriesTitle)
|
||||||
.Write();
|
.Write();
|
||||||
|
|
||||||
|
matchType = SeriesMatchType.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,7 +448,7 @@ namespace NzbDrone.Core.Parser
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return series;
|
return new FindSeriesResult(series, matchType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Episode GetDailyEpisode(Series series, string airDate, int? part, SearchCriteriaBase searchCriteria)
|
private Episode GetDailyEpisode(Series series, string airDate, int? part, SearchCriteriaBase searchCriteria)
|
||||||
|
|
Loading…
Reference in New Issue