Lidarr/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs

193 lines
7.7 KiB
C#
Raw Normal View History

2017-09-04 02:20:56 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.History;
2017-09-04 02:20:56 +00:00
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Download.TrackedDownloads
{
public interface ITrackedDownloadService
{
TrackedDownload Find(string downloadId);
2017-09-04 02:20:56 +00:00
void StopTracking(string downloadId);
void StopTracking(List<string> downloadIds);
TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem);
2017-09-04 02:20:56 +00:00
List<TrackedDownload> GetTrackedDownloads();
void UpdateTrackable(List<TrackedDownload> trackedDownloads);
}
public class TrackedDownloadService : ITrackedDownloadService
{
private readonly IParsingService _parsingService;
private readonly IHistoryService _historyService;
2017-09-04 02:20:56 +00:00
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger;
private readonly ICached<TrackedDownload> _cache;
public TrackedDownloadService(IParsingService parsingService,
2017-09-04 02:20:56 +00:00
ICacheManager cacheManager,
IHistoryService historyService,
IEventAggregator eventAggregator,
Logger logger)
{
_parsingService = parsingService;
_historyService = historyService;
2017-09-04 02:20:56 +00:00
_eventAggregator = eventAggregator;
_cache = cacheManager.GetCache<TrackedDownload>(GetType());
_logger = logger;
}
public TrackedDownload Find(string downloadId)
{
return _cache.Find(downloadId);
}
2017-09-04 02:20:56 +00:00
public void StopTracking(string downloadId)
{
var trackedDownload = _cache.Find(downloadId);
_cache.Remove(downloadId);
_eventAggregator.PublishEvent(new TrackedDownloadsRemovedEvent(new List<TrackedDownload> { trackedDownload }));
}
public void StopTracking(List<string> downloadIds)
{
var trackedDownloads = new List<TrackedDownload>();
foreach (var downloadId in downloadIds)
{
var trackedDownload = _cache.Find(downloadId);
_cache.Remove(downloadId);
trackedDownloads.Add(trackedDownload);
}
_eventAggregator.PublishEvent(new TrackedDownloadsRemovedEvent(trackedDownloads));
}
public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem)
{
var existingItem = Find(downloadItem.DownloadId);
if (existingItem != null && existingItem.State != TrackedDownloadStage.Downloading)
{
2017-09-04 02:20:56 +00:00
LogItemChange(existingItem, existingItem.DownloadItem, downloadItem);
existingItem.DownloadItem = downloadItem;
2017-09-04 02:20:56 +00:00
existingItem.IsTrackable = true;
return existingItem;
}
var trackedDownload = new TrackedDownload
{
DownloadClient = downloadClient.Id,
DownloadItem = downloadItem,
2017-09-04 02:20:56 +00:00
Protocol = downloadClient.Protocol,
IsTrackable = true
};
try
{
var parsedAlbumInfo = Parser.Parser.ParseAlbumTitle(trackedDownload.DownloadItem.Title);
var historyItems = _historyService.FindByDownloadId(downloadItem.DownloadId);
if (parsedAlbumInfo != null)
{
trackedDownload.RemoteAlbum = _parsingService.Map(parsedAlbumInfo);
}
if (historyItems.Any())
{
var firstHistoryItem = historyItems.OrderByDescending(h => h.Date).First();
trackedDownload.State = GetStateFromHistory(firstHistoryItem.EventType);
2017-09-04 02:20:56 +00:00
var grabbedEvent = historyItems.FirstOrDefault(v => v.EventType == HistoryEventType.Grabbed);
trackedDownload.Indexer = grabbedEvent?.Data["indexer"];
if (parsedAlbumInfo == null ||
trackedDownload.RemoteAlbum == null ||
trackedDownload.RemoteAlbum.Artist == null ||
trackedDownload.RemoteAlbum.Albums.Empty())
{
// Try parsing the original source title and if that fails, try parsing it as a special
// TODO: Pass the TVDB ID and TVRage IDs in as well so we have a better chance for finding the item
parsedAlbumInfo = Parser.Parser.ParseAlbumTitle(firstHistoryItem.SourceTitle);
if (parsedAlbumInfo != null)
{
trackedDownload.RemoteAlbum = _parsingService.Map(parsedAlbumInfo, firstHistoryItem.ArtistId, historyItems.Where(v => v.EventType == HistoryEventType.Grabbed).Select(h => h.AlbumId).Distinct());
}
}
}
if (trackedDownload.RemoteAlbum == null)
{
2017-09-04 02:20:56 +00:00
_logger.Trace("No Album found for download '{0}', not tracking.", trackedDownload.DownloadItem.Title);
return null;
}
}
catch (Exception e)
{
_logger.Debug(e, "Failed to find album for " + downloadItem.Title);
return null;
}
2017-09-04 02:20:56 +00:00
LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem);
_cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload);
return trackedDownload;
}
2017-09-04 02:20:56 +00:00
public List<TrackedDownload> GetTrackedDownloads()
{
return _cache.Values.ToList();
}
public void UpdateTrackable(List<TrackedDownload> trackedDownloads)
{
var untrackable = GetTrackedDownloads().ExceptBy(t => t.DownloadItem.DownloadId, trackedDownloads, t => t.DownloadItem.DownloadId, StringComparer.CurrentCulture).ToList();
foreach (var trackedDownload in untrackable)
{
trackedDownload.IsTrackable = false;
}
}
private void LogItemChange(TrackedDownload trackedDownload, DownloadClientItem existingItem, DownloadClientItem downloadItem)
{
if (existingItem == null ||
existingItem.Status != downloadItem.Status ||
existingItem.CanBeRemoved != downloadItem.CanBeRemoved ||
existingItem.CanMoveFiles != downloadItem.CanMoveFiles)
{
_logger.Debug("Tracking '{0}:{1}': ClientState={2}{3} SonarrStage={4} Episode='{5}' OutputPath={6}.",
downloadItem.DownloadClient, downloadItem.Title,
downloadItem.Status, downloadItem.CanBeRemoved ? "" :
downloadItem.CanMoveFiles ? " (busy)" : " (readonly)",
trackedDownload.State,
trackedDownload.RemoteAlbum?.ParsedAlbumInfo,
downloadItem.OutputPath);
}
}
private static TrackedDownloadStage GetStateFromHistory(HistoryEventType eventType)
{
switch (eventType)
{
case HistoryEventType.DownloadFolderImported:
return TrackedDownloadStage.Imported;
case HistoryEventType.DownloadFailed:
return TrackedDownloadStage.DownloadFailed;
default:
return TrackedDownloadStage.Downloading;
}
}
}
}