diff --git a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs index 0ec53522c..8b66b4612 100644 --- a/src/NzbDrone.Core/Blocklisting/BlocklistService.cs +++ b/src/NzbDrone.Core/Blocklisting/BlocklistService.cs @@ -185,7 +185,7 @@ namespace NzbDrone.Core.Blocklisting Indexer = message.Data.GetValueOrDefault("indexer"), Protocol = (DownloadProtocol)Convert.ToInt32(message.Data.GetValueOrDefault("protocol")), Message = message.Message, - TorrentInfoHash = message.Data.GetValueOrDefault("torrentInfoHash"), + TorrentInfoHash = message.TorrentInfoHash, Languages = message.Languages }; diff --git a/src/NzbDrone.Core/Download/DownloadFailedEvent.cs b/src/NzbDrone.Core/Download/DownloadFailedEvent.cs index 7a42b7e18..4a9b65383 100644 --- a/src/NzbDrone.Core/Download/DownloadFailedEvent.cs +++ b/src/NzbDrone.Core/Download/DownloadFailedEvent.cs @@ -21,6 +21,7 @@ namespace NzbDrone.Core.Download public string DownloadClient { get; set; } public string DownloadId { get; set; } public string Message { get; set; } + public string TorrentInfoHash { get; set; } public Dictionary Data { get; set; } public TrackedDownload TrackedDownload { get; set; } public List Languages { get; set; } diff --git a/src/NzbDrone.Core/Download/FailedDownloadService.cs b/src/NzbDrone.Core/Download/FailedDownloadService.cs index d392f0ea4..a9bc84524 100644 --- a/src/NzbDrone.Core/Download/FailedDownloadService.cs +++ b/src/NzbDrone.Core/Download/FailedDownloadService.cs @@ -4,6 +4,7 @@ using System.Linq; using NzbDrone.Common.Extensions; using NzbDrone.Core.Download.TrackedDownloads; using NzbDrone.Core.History; +using NzbDrone.Core.Indexers; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Parser.Model; @@ -12,7 +13,7 @@ namespace NzbDrone.Core.Download public interface IFailedDownloadService { void MarkAsFailed(int historyId, bool skipRedownload = false); - void MarkAsFailed(string downloadId, bool skipRedownload = false); + void MarkAsFailed(TrackedDownload trackedDownload, bool skipRedownload = false); void Check(TrackedDownload trackedDownload); void ProcessFailed(TrackedDownload trackedDownload); } @@ -20,7 +21,6 @@ namespace NzbDrone.Core.Download public class FailedDownloadService : IFailedDownloadService { private readonly IHistoryService _historyService; - private readonly ITrackedDownloadService _trackedDownloadService; private readonly IEventAggregator _eventAggregator; public FailedDownloadService(IHistoryService historyService, @@ -28,7 +28,6 @@ namespace NzbDrone.Core.Download IEventAggregator eventAggregator) { _historyService = historyService; - _trackedDownloadService = trackedDownloadService; _eventAggregator = eventAggregator; } @@ -37,9 +36,10 @@ namespace NzbDrone.Core.Download var history = _historyService.Get(historyId); var downloadId = history.DownloadId; + if (downloadId.IsNullOrWhiteSpace()) { - PublishDownloadFailedEvent(new List { history }, "Manually marked as failed", skipRedownload: skipRedownload); + PublishDownloadFailedEvent(history, new List { history.EpisodeId }, "Manually marked as failed", skipRedownload: skipRedownload); return; } @@ -53,21 +53,19 @@ namespace NzbDrone.Core.Download } // Add any other history items for the download ID then filter out any duplicate history items. - grabbedHistory.AddRange(_historyService.Find(downloadId, EpisodeHistoryEventType.Grabbed)); + grabbedHistory.AddRange(GetGrabbedHistory(downloadId)); grabbedHistory = grabbedHistory.DistinctBy(h => h.Id).ToList(); - PublishDownloadFailedEvent(grabbedHistory, "Manually marked as failed"); + PublishDownloadFailedEvent(history, GetEpisodeIds(grabbedHistory), "Manually marked as failed"); } - public void MarkAsFailed(string downloadId, bool skipRedownload = false) + public void MarkAsFailed(TrackedDownload trackedDownload, bool skipRedownload = false) { - var history = _historyService.Find(downloadId, EpisodeHistoryEventType.Grabbed); + var history = GetGrabbedHistory(trackedDownload.DownloadItem.DownloadId); if (history.Any()) { - var trackedDownload = _trackedDownloadService.Find(downloadId); - - PublishDownloadFailedEvent(history, "Manually marked as failed", trackedDownload, skipRedownload: skipRedownload); + PublishDownloadFailedEvent(history.First(), GetEpisodeIds(history), "Manually marked as failed", trackedDownload, skipRedownload: skipRedownload); } } @@ -82,9 +80,7 @@ namespace NzbDrone.Core.Download if (trackedDownload.DownloadItem.IsEncrypted || trackedDownload.DownloadItem.Status == DownloadItemStatus.Failed) { - var grabbedItems = _historyService - .Find(trackedDownload.DownloadItem.DownloadId, EpisodeHistoryEventType.Grabbed) - .ToList(); + var grabbedItems = GetGrabbedHistory(trackedDownload.DownloadItem.DownloadId); if (grabbedItems.Empty()) { @@ -103,9 +99,7 @@ namespace NzbDrone.Core.Download return; } - var grabbedItems = _historyService - .Find(trackedDownload.DownloadItem.DownloadId, EpisodeHistoryEventType.Grabbed) - .ToList(); + var grabbedItems = GetGrabbedHistory(trackedDownload.DownloadItem.DownloadId); if (grabbedItems.Empty()) { @@ -124,18 +118,19 @@ namespace NzbDrone.Core.Download } trackedDownload.State = TrackedDownloadState.Failed; - PublishDownloadFailedEvent(grabbedItems, failure, trackedDownload); + PublishDownloadFailedEvent(grabbedItems.First(), GetEpisodeIds(grabbedItems), failure, trackedDownload); } - private void PublishDownloadFailedEvent(List historyItems, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false) + private void PublishDownloadFailedEvent(EpisodeHistory historyItem, List episodeIds, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false) { - var historyItem = historyItems.Last(); Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.RELEASE_SOURCE, ReleaseSourceType.Unknown.ToString()), out ReleaseSourceType releaseSource); + var torrentInfoHash = GetTorrentInfoHash(historyItem, trackedDownload); + var downloadFailedEvent = new DownloadFailedEvent { SeriesId = historyItem.SeriesId, - EpisodeIds = historyItems.Select(h => h.EpisodeId).Distinct().ToList(), + EpisodeIds = episodeIds, Quality = historyItem.Quality, SourceTitle = historyItem.SourceTitle, DownloadClient = historyItem.Data.GetValueOrDefault(EpisodeHistory.DOWNLOAD_CLIENT), @@ -145,10 +140,34 @@ namespace NzbDrone.Core.Download TrackedDownload = trackedDownload, Languages = historyItem.Languages, SkipRedownload = skipRedownload, - ReleaseSource = releaseSource + ReleaseSource = releaseSource, + TorrentInfoHash = torrentInfoHash }; _eventAggregator.PublishEvent(downloadFailedEvent); } + + private string GetTorrentInfoHash(EpisodeHistory historyItem, TrackedDownload trackedDownload) + { + if (trackedDownload == null) + { + return historyItem.Data.GetValueOrDefault("torrentInfoHash", null); + } + + return trackedDownload.Protocol == DownloadProtocol.Torrent ? trackedDownload.DownloadItem.DownloadId : null; + } + + private List GetEpisodeIds(List historyItems) + { + return historyItems.Select(h => h.EpisodeId).Distinct().ToList(); + } + + private List GetGrabbedHistory(string downloadId) + { + // Sort by date so items are always in the same order + return _historyService.Find(downloadId, EpisodeHistoryEventType.Grabbed) + .OrderByDescending(h => h.Date) + .ToList(); + } } } diff --git a/src/Sonarr.Api.V3/Queue/QueueController.cs b/src/Sonarr.Api.V3/Queue/QueueController.cs index 34622ad18..2e74dec94 100644 --- a/src/Sonarr.Api.V3/Queue/QueueController.cs +++ b/src/Sonarr.Api.V3/Queue/QueueController.cs @@ -323,7 +323,7 @@ namespace Sonarr.Api.V3.Queue if (blocklist) { - _failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId, skipRedownload); + _failedDownloadService.MarkAsFailed(trackedDownload, skipRedownload); } if (!removeFromClient && !blocklist && !changeCategory)