|
|
@ -1,6 +1,7 @@
|
|
|
|
using System;
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
using Marr.Data;
|
|
|
|
using NLog;
|
|
|
|
using NLog;
|
|
|
|
using NzbDrone.Common.Crypto;
|
|
|
|
using NzbDrone.Common.Crypto;
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
@ -66,35 +67,30 @@ namespace NzbDrone.Core.Download.Pending
|
|
|
|
_logger = logger;
|
|
|
|
_logger = logger;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Add(DownloadDecision decision, PendingReleaseReason reason)
|
|
|
|
public void Add(DownloadDecision decision, PendingReleaseReason reason)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var alreadyPending = _repository.AllBySeriesId(decision.RemoteEpisode.Series.Id);
|
|
|
|
AddMany(new List<Tuple<DownloadDecision, PendingReleaseReason>> { Tuple.Create(decision, reason) });
|
|
|
|
|
|
|
|
|
|
|
|
alreadyPending = IncludeRemoteEpisodes(alreadyPending);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Add(alreadyPending, decision, reason);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void AddMany(List<Tuple<DownloadDecision, PendingReleaseReason>> decisions)
|
|
|
|
public void AddMany(List<Tuple<DownloadDecision, PendingReleaseReason>> decisions)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var alreadyPending = decisions.Select(v => v.Item1.RemoteEpisode.Series.Id).Distinct().SelectMany(_repository.AllBySeriesId).ToList();
|
|
|
|
foreach (var seriesDecisions in decisions.GroupBy(v => v.Item1.RemoteEpisode.Series.Id))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var series = seriesDecisions.First().Item1.RemoteEpisode.Series;
|
|
|
|
|
|
|
|
var alreadyPending = _repository.AllBySeriesId(series.Id);
|
|
|
|
|
|
|
|
|
|
|
|
alreadyPending = IncludeRemoteEpisodes(alreadyPending);
|
|
|
|
alreadyPending = IncludeRemoteEpisodes(alreadyPending, seriesDecisions.ToDictionaryIgnoreDuplicates(v => v.Item1.RemoteEpisode.Release.Title, v => v.Item1.RemoteEpisode));
|
|
|
|
|
|
|
|
var alreadyPendingByEpisode = CreateEpisodeLookup(alreadyPending);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var pair in decisions)
|
|
|
|
foreach (var pair in seriesDecisions)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Add(alreadyPending, pair.Item1, pair.Item2);
|
|
|
|
var decision = pair.Item1;
|
|
|
|
}
|
|
|
|
var reason = pair.Item2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void Add(List<PendingRelease> alreadyPending, DownloadDecision decision, PendingReleaseReason reason)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var episodeIds = decision.RemoteEpisode.Episodes.Select(e => e.Id);
|
|
|
|
var episodeIds = decision.RemoteEpisode.Episodes.Select(e => e.Id);
|
|
|
|
|
|
|
|
|
|
|
|
var existingReports = alreadyPending.Where(r => r.RemoteEpisode.Episodes.Select(e => e.Id)
|
|
|
|
var existingReports = episodeIds.SelectMany(v => alreadyPendingByEpisode[v] ?? Enumerable.Empty<PendingRelease>())
|
|
|
|
.Intersect(episodeIds)
|
|
|
|
.Distinct().ToList();
|
|
|
|
.Any());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var matchingReports = existingReports.Where(MatchingReleasePredicate(decision.RemoteEpisode.Release)).ToList();
|
|
|
|
var matchingReports = existingReports.Where(MatchingReleasePredicate(decision.RemoteEpisode.Release)).ToList();
|
|
|
|
|
|
|
|
|
|
|
@ -121,15 +117,25 @@ namespace NzbDrone.Core.Download.Pending
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_repository.Delete(duplicate.Id);
|
|
|
|
_repository.Delete(duplicate.Id);
|
|
|
|
alreadyPending.Remove(duplicate);
|
|
|
|
alreadyPending.Remove(duplicate);
|
|
|
|
|
|
|
|
alreadyPendingByEpisode = CreateEpisodeLookup(alreadyPending);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_logger.Debug("Adding release {0} to pending releases with reason {1}", decision.RemoteEpisode, reason);
|
|
|
|
_logger.Debug("Adding release {0} to pending releases with reason {1}", decision.RemoteEpisode, reason);
|
|
|
|
Insert(decision, reason);
|
|
|
|
Insert(decision, reason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private ILookup<int, PendingRelease> CreateEpisodeLookup(IEnumerable<PendingRelease> alreadyPending)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return alreadyPending.SelectMany(v => v.RemoteEpisode.Episodes
|
|
|
|
|
|
|
|
.Select(d => new { Episode = d, PendingRelease = v }))
|
|
|
|
|
|
|
|
.ToLookup(v => v.Episode.Id, v => v.PendingRelease);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<ReleaseInfo> GetPending()
|
|
|
|
public List<ReleaseInfo> GetPending()
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -254,11 +260,27 @@ namespace NzbDrone.Core.Download.Pending
|
|
|
|
return IncludeRemoteEpisodes(_repository.AllBySeriesId(seriesId).ToList());
|
|
|
|
return IncludeRemoteEpisodes(_repository.AllBySeriesId(seriesId).ToList());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<PendingRelease> IncludeRemoteEpisodes(List<PendingRelease> releases)
|
|
|
|
private List<PendingRelease> IncludeRemoteEpisodes(List<PendingRelease> releases, Dictionary<string, RemoteEpisode> knownRemoteEpisodes = null)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var result = new List<PendingRelease>();
|
|
|
|
var result = new List<PendingRelease>();
|
|
|
|
var seriesMap = _seriesService.GetSeries(releases.Select(v => v.SeriesId).Distinct())
|
|
|
|
|
|
|
|
.ToDictionary(v => v.Id);
|
|
|
|
var seriesMap = new Dictionary<int, Series>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (knownRemoteEpisodes != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
foreach (var series in knownRemoteEpisodes.Values.Select(v => v.Series))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!seriesMap.ContainsKey(series.Id))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
seriesMap[series.Id] = series;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var series in _seriesService.GetSeries(releases.Select(v => v.SeriesId).Distinct().Where(v => !seriesMap.ContainsKey(v))))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
seriesMap[series.Id] = series;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var release in releases)
|
|
|
|
foreach (var release in releases)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -267,7 +289,17 @@ 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;
|
|
|
|
|
|
|
|
|
|
|
|
var episodes = _parsingService.GetEpisodes(release.ParsedEpisodeInfo, series, true);
|
|
|
|
List<Episode> episodes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RemoteEpisode knownRemoteEpisode;
|
|
|
|
|
|
|
|
if (knownRemoteEpisodes != null && knownRemoteEpisodes.TryGetValue(release.Release.Title, out knownRemoteEpisode))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
episodes = knownRemoteEpisode.Episodes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
episodes = _parsingService.GetEpisodes(release.ParsedEpisodeInfo, series, true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
release.RemoteEpisode = new RemoteEpisode
|
|
|
|
release.RemoteEpisode = new RemoteEpisode
|
|
|
|
{
|
|
|
|
{
|
|
|
|