1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-27 22:57:09 -04:00

Use DownloadClientIds to find matching series/episodes instead of relying solely on release name

Fixed: Show a warning in Queue when drone is unable to import due to a name mismatch
Fixed: Better UI messages for Queue when there is an error or warning
This commit is contained in:
Mark McDowall
2014-09-13 16:13:00 -07:00
parent 3f11fcf2e1
commit caa6a3858b
26 changed files with 292 additions and 149 deletions
@@ -201,9 +201,6 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
if (downloadClientItem.Category == Settings.TvCategory)
{
downloadClientItem.RemoteEpisode = GetRemoteEpisode(downloadClientItem.Title);
if (downloadClientItem.RemoteEpisode == null) continue;
yield return downloadClientItem;
}
}
@@ -103,9 +103,6 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
historyItem.Status = DownloadItemStatus.Completed;
}
historyItem.RemoteEpisode = GetRemoteEpisode(historyItem.Title);
if (historyItem.RemoteEpisode == null) continue;
yield return historyItem;
}
}
@@ -188,9 +188,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{
if (downloadClientItem.Category == Settings.TvCategory)
{
downloadClientItem.RemoteEpisode = GetRemoteEpisode(downloadClientItem.Title);
if (downloadClientItem.RemoteEpisode == null) continue;
yield return downloadClientItem;
}
}
@@ -90,9 +90,6 @@ namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
historyItem.RemainingTime = TimeSpan.Zero;
}
historyItem.RemoteEpisode = GetRemoteEpisode(historyItem.Title);
if (historyItem.RemoteEpisode == null) continue;
yield return historyItem;
}
@@ -121,9 +118,6 @@ namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
historyItem.RemainingTime = TimeSpan.Zero;
}
historyItem.RemoteEpisode = GetRemoteEpisode(historyItem.Title);
if (historyItem.RemoteEpisode == null) continue;
yield return historyItem;
}
}
@@ -8,7 +8,6 @@ using NzbDrone.Core.Configuration;
using NzbDrone.Core.History;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.EpisodeImport;
using NzbDrone.Core.Messaging.Events;
using System.IO;
namespace NzbDrone.Core.Download
@@ -20,21 +19,18 @@ namespace NzbDrone.Core.Download
public class CompletedDownloadService : ICompletedDownloadService
{
private readonly IEventAggregator _eventAggregator;
private readonly IConfigService _configService;
private readonly IDiskProvider _diskProvider;
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
private readonly IHistoryService _historyService;
private readonly Logger _logger;
public CompletedDownloadService(IEventAggregator eventAggregator,
IConfigService configService,
IDiskProvider diskProvider,
IDownloadedEpisodesImportService downloadedEpisodesImportService,
IHistoryService historyService,
Logger logger)
public CompletedDownloadService(IConfigService configService,
IDiskProvider diskProvider,
IDownloadedEpisodesImportService downloadedEpisodesImportService,
IHistoryService historyService,
Logger logger)
{
_eventAggregator = eventAggregator;
_configService = configService;
_diskProvider = diskProvider;
_downloadedEpisodesImportService = downloadedEpisodesImportService;
@@ -61,7 +57,7 @@ namespace NzbDrone.Core.Download
if (!grabbedItems.Any() && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace())
{
UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Download wasn't grabbed by drone or not in a category, ignoring download.");
UpdateStatusMessage(trackedDownload, LogLevel.Warn, "Download wasn't grabbed by drone or not in a category, ignoring download.");
return;
}
@@ -73,10 +69,16 @@ namespace NzbDrone.Core.Download
UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Already added to history as imported.");
}
else if (trackedDownload.Status != TrackedDownloadStatus.Ok)
{
_logger.Debug("Tracked download status is: {0}, skipping import.", trackedDownload.Status);
return;
}
else
{
string downloadedEpisodesFolder = _configService.DownloadedEpisodesFolder;
string downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath;
var downloadedEpisodesFolder = _configService.DownloadedEpisodesFolder;
var downloadItemOutputPath = trackedDownload.DownloadItem.OutputPath;
if (downloadItemOutputPath.IsNullOrWhiteSpace())
{
UpdateStatusMessage(trackedDownload, LogLevel.Warn, "Download doesn't contain intermediate path, ignoring download.");
@@ -105,7 +107,7 @@ namespace NzbDrone.Core.Download
{
if (grabbedItems.Any())
{
var episodeIds = trackedDownload.DownloadItem.RemoteEpisode.Episodes.Select(v => v.Id).ToList();
var episodeIds = trackedDownload.RemoteEpisode.Episodes.Select(v => v.Id).ToList();
// Check if we can associate it with a previous drone factory import.
importedItems = importedHistory.Where(v => v.Data.GetValueOrDefault(DownloadTrackingService.DOWNLOAD_CLIENT_ID) == null &&
@@ -171,7 +173,7 @@ namespace NzbDrone.Core.Download
if (trackedDownload.StatusMessage != statusMessage)
{
trackedDownload.HasError = logLevel >= LogLevel.Warn;
trackedDownload.SetStatusLevel(logLevel);
trackedDownload.StatusMessage = statusMessage;
_logger.Log(logLevel, logMessage);
}
@@ -200,6 +202,9 @@ namespace NzbDrone.Core.Download
.Select(v => v.Errors.Aggregate(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), (a, r) => a + "\r\n- " + r))
.Aggregate("Failed to import:", (a, r) => a + "\r\n" + r);
trackedDownload.StatusMessages = importResults.Where(v => v.Result == ImportResultType.Skipped || v.Result == ImportResultType.Rejected)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors)).ToList();
UpdateStatusMessage(trackedDownload, LogLevel.Error, errors);
}
}
@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
@@ -21,7 +20,6 @@ namespace NzbDrone.Core.Download
{
protected readonly IConfigService _configService;
protected readonly IDiskProvider _diskProvider;
protected readonly IParsingService _parsingService;
protected readonly IRemotePathMappingService _remotePathMappingService;
protected readonly Logger _logger;
@@ -55,7 +53,6 @@ namespace NzbDrone.Core.Download
{
_configService = configService;
_diskProvider = diskProvider;
_parsingService = parsingService;
_remotePathMappingService = remotePathMappingService;
_logger = logger;
}
@@ -76,17 +73,6 @@ namespace NzbDrone.Core.Download
public abstract String RetryDownload(string id);
public abstract DownloadClientStatus GetStatus();
protected RemoteEpisode GetRemoteEpisode(String title)
{
var parsedEpisodeInfo = Parser.Parser.ParseTitle(title);
if (parsedEpisodeInfo == null) return null;
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
if (remoteEpisode.Series == null) return null;
return remoteEpisode;
}
public ValidationResult Test()
{
var failures = new List<ValidationFailure>();
@@ -1,5 +1,4 @@
using NzbDrone.Core.Parser.Model;
using System;
using System;
namespace NzbDrone.Core.Download
{
@@ -21,7 +20,5 @@ namespace NzbDrone.Core.Download
public DownloadItemStatus Status { get; set; }
public Boolean IsEncrypted { get; set; }
public Boolean IsReadOnly { get; set; }
public RemoteEpisode RemoteEpisode { get; set; }
}
}
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Download
namespace NzbDrone.Core.Download
{
public enum DownloadItemStatus
{
@@ -9,6 +9,7 @@ using NzbDrone.Core.History;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Queue;
namespace NzbDrone.Core.Download
@@ -22,7 +23,10 @@ namespace NzbDrone.Core.Download
void MarkAsFailed(Int32 historyId);
}
public class DownloadTrackingService : IDownloadTrackingService, IExecute<CheckForFinishedDownloadCommand>, IHandleAsync<ApplicationStartedEvent>, IHandle<EpisodeGrabbedEvent>
public class DownloadTrackingService : IDownloadTrackingService,
IExecute<CheckForFinishedDownloadCommand>,
IHandleAsync<ApplicationStartedEvent>,
IHandle<EpisodeGrabbedEvent>
{
private readonly IProvideDownloadClient _downloadClientProvider;
private readonly IHistoryService _historyService;
@@ -30,6 +34,7 @@ namespace NzbDrone.Core.Download
private readonly IConfigService _configService;
private readonly IFailedDownloadService _failedDownloadService;
private readonly ICompletedDownloadService _completedDownloadService;
private readonly IParsingService _parsingService;
private readonly Logger _logger;
private readonly ICached<TrackedDownload[]> _trackedDownloadCache;
@@ -44,6 +49,7 @@ namespace NzbDrone.Core.Download
ICacheManager cacheManager,
IFailedDownloadService failedDownloadService,
ICompletedDownloadService completedDownloadService,
IParsingService parsingService,
Logger logger)
{
_downloadClientProvider = downloadClientProvider;
@@ -52,6 +58,7 @@ namespace NzbDrone.Core.Download
_configService = configService;
_failedDownloadService = failedDownloadService;
_completedDownloadService = completedDownloadService;
_parsingService = parsingService;
_logger = logger;
_trackedDownloadCache = cacheManager.GetCache<TrackedDownload[]>(GetType());
@@ -73,7 +80,7 @@ namespace NzbDrone.Core.Download
{
return _trackedDownloadCache.Get("queued", () =>
{
UpdateTrackedDownloads();
UpdateTrackedDownloads(_historyService.Grabbed());
return FilterQueuedDownloads(GetTrackedDownloads());
@@ -119,7 +126,7 @@ namespace NzbDrone.Core.Download
.ToList();
}
private Boolean UpdateTrackedDownloads()
private Boolean UpdateTrackedDownloads(List<History.History> grabbedHistory)
{
var downloadClients = _downloadClientProvider.GetDownloadClients();
@@ -140,13 +147,9 @@ namespace NzbDrone.Core.Download
if (!oldTrackedDownloads.TryGetValue(trackingId, out trackedDownload))
{
trackedDownload = new TrackedDownload
{
TrackingId = trackingId,
DownloadClient = downloadClient.Definition.Id,
StartedTracking = DateTime.UtcNow,
State = TrackedDownloadState.Unknown
};
trackedDownload = GetTrackedDownload(trackingId, downloadClient.Definition.Id, downloadItem, grabbedHistory);
if (trackedDownload == null) continue;
_logger.Debug("[{0}] Started tracking download with id {1}.", downloadItem.Title, trackingId);
stateChanged = true;
@@ -182,9 +185,9 @@ namespace NzbDrone.Core.Download
var failedHistory = _historyService.Failed();
var importedHistory = _historyService.Imported();
var stateChanged = UpdateTrackedDownloads();
var stateChanged = UpdateTrackedDownloads(grabbedHistory);
var downloadClients = _downloadClientProvider.GetDownloadClients();
var downloadClients = _downloadClientProvider.GetDownloadClients().ToList();
var trackedDownloads = GetTrackedDownloads();
foreach (var trackedDownload in trackedDownloads)
@@ -215,6 +218,50 @@ namespace NzbDrone.Core.Download
}
}
private TrackedDownload GetTrackedDownload(String trackingId, Int32 downloadClient, DownloadClientItem downloadItem, List<History.History> grabbedHistory)
{
var trackedDownload = new TrackedDownload
{
TrackingId = trackingId,
DownloadClient = downloadClient,
DownloadItem = downloadItem,
StartedTracking = DateTime.UtcNow,
State = TrackedDownloadState.Unknown,
Status = TrackedDownloadStatus.Ok,
};
var historyItems = grabbedHistory.Where(h =>
{
var downloadClientId = h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID);
if (downloadClientId == null) return false;
return downloadClientId.Equals(trackedDownload.DownloadItem.DownloadClientId);
}).ToList();
var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
if (parsedEpisodeInfo == null) return null;
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0);
if (remoteEpisode.Series == null)
{
if (historyItems.Empty()) return null;
trackedDownload.Status = TrackedDownloadStatus.Warning;
trackedDownload.StatusMessages.Add(new TrackedDownloadStatusMessage(
trackedDownload.DownloadItem.Title,
"Series title mismatch, automatic import is not possible")
);
remoteEpisode = _parsingService.Map(parsedEpisodeInfo, historyItems.First().SeriesId, historyItems.Select(h => h.EpisodeId));
}
trackedDownload.RemoteEpisode = remoteEpisode;
return trackedDownload;
}
public void Execute(CheckForFinishedDownloadCommand message)
{
ProcessTrackedDownloads();
@@ -3,10 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Cache;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.History;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Download
@@ -68,7 +66,7 @@ namespace NzbDrone.Core.Download
if (!grabbedItems.Any())
{
UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Download was not grabbed by drone, ignoring download");
UpdateStatusMessage(trackedDownload, LogLevel.Warn, "Download was not grabbed by drone, ignoring download");
return;
}
@@ -92,7 +90,7 @@ namespace NzbDrone.Core.Download
if (!grabbedItems.Any())
{
UpdateStatusMessage(trackedDownload, LogLevel.Debug, "Download wasn't grabbed by drone or not in a category, ignoring download.");
UpdateStatusMessage(trackedDownload, LogLevel.Warn, "Download wasn't grabbed by drone or not in a category, ignoring download.");
return;
}
@@ -244,8 +242,12 @@ namespace NzbDrone.Core.Download
if (trackedDownload.StatusMessage != statusMessage)
{
trackedDownload.HasError = logLevel >= LogLevel.Warn;
trackedDownload.SetStatusLevel(logLevel);
trackedDownload.StatusMessage = statusMessage;
trackedDownload.StatusMessages = new List<TrackedDownloadStatusMessage>
{
new TrackedDownloadStatusMessage(trackedDownload.DownloadItem.Title, statusMessage)
};
_logger.Log(logLevel, logMessage);
}
else
+32 -2
View File
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using NLog;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download
{
@@ -9,12 +11,33 @@ namespace NzbDrone.Core.Download
public Int32 DownloadClient { get; set; }
public DownloadClientItem DownloadItem { get; set; }
public TrackedDownloadState State { get; set; }
public TrackedDownloadStatus Status { get; set; }
public DateTime StartedTracking { get; set; }
public DateTime LastRetry { get; set; }
public Int32 RetryCount { get; set; }
public Boolean HasError { get; set; }
public String StatusMessage { get; set; }
public List<String> StatusMessages { get; set; }
public RemoteEpisode RemoteEpisode { get; set; }
public List<TrackedDownloadStatusMessage> StatusMessages { get; set; }
public TrackedDownload()
{
StatusMessages = new List<TrackedDownloadStatusMessage>();
}
public void SetStatusLevel(LogLevel logLevel)
{
if (logLevel == LogLevel.Warn)
{
Status = TrackedDownloadStatus.Warning;
}
if (logLevel >= LogLevel.Error)
{
Status = TrackedDownloadStatus.Error;
}
else Status = TrackedDownloadStatus.Ok;
}
}
public enum TrackedDownloadState
@@ -25,4 +48,11 @@ namespace NzbDrone.Core.Download
DownloadFailed,
Removed
}
public enum TrackedDownloadStatus
{
Ok,
Warning,
Error
}
}
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Download
{
public class TrackedDownloadStatusMessage
{
public String Title { get; set; }
public List<String> Messages { get; set; }
public TrackedDownloadStatusMessage(String title, List<String> messages)
{
Title = title;
Messages = messages;
}
public TrackedDownloadStatusMessage(String title, String message)
{
Title = title;
Messages = new List<String>{ message };
}
}
}