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:
@@ -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
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user