-
-
Notifications
You must be signed in to change notification settings - Fork 242
/
DownloadService.cs
143 lines (124 loc) · 5.94 KB
/
DownloadService.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Common.TPL;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Download.Pending;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download
{
public interface IDownloadService
{
Task DownloadReport(RemoteAlbum remoteAlbum);
}
public class DownloadService : IDownloadService
{
private readonly IProvideDownloadClient _downloadClientProvider;
private readonly IDownloadClientStatusService _downloadClientStatusService;
private readonly IIndexerFactory _indexerFactory;
private readonly IIndexerStatusService _indexerStatusService;
private readonly IRateLimitService _rateLimitService;
private readonly IEventAggregator _eventAggregator;
private readonly ISeedConfigProvider _seedConfigProvider;
private readonly Logger _logger;
public DownloadService(IProvideDownloadClient downloadClientProvider,
IDownloadClientStatusService downloadClientStatusService,
IIndexerFactory indexerFactory,
IIndexerStatusService indexerStatusService,
IRateLimitService rateLimitService,
IEventAggregator eventAggregator,
ISeedConfigProvider seedConfigProvider,
Logger logger)
{
_downloadClientProvider = downloadClientProvider;
_downloadClientStatusService = downloadClientStatusService;
_indexerFactory = indexerFactory;
_indexerStatusService = indexerStatusService;
_rateLimitService = rateLimitService;
_eventAggregator = eventAggregator;
_seedConfigProvider = seedConfigProvider;
_logger = logger;
}
public async Task DownloadReport(RemoteAlbum remoteAlbum)
{
var filterBlockedClients = remoteAlbum.Release.PendingReleaseReason == PendingReleaseReason.DownloadClientUnavailable;
var tags = remoteAlbum.Artist?.Tags;
var downloadClient = _downloadClientProvider.GetDownloadClient(remoteAlbum.Release.DownloadProtocol, remoteAlbum.Release.IndexerId, filterBlockedClients, tags);
await DownloadReport(remoteAlbum, downloadClient);
}
private async Task DownloadReport(RemoteAlbum remoteAlbum, IDownloadClient downloadClient)
{
Ensure.That(remoteAlbum.Artist, () => remoteAlbum.Artist).IsNotNull();
Ensure.That(remoteAlbum.Albums, () => remoteAlbum.Albums).HasItems();
var downloadTitle = remoteAlbum.Release.Title;
if (downloadClient == null)
{
throw new DownloadClientUnavailableException($"{remoteAlbum.Release.DownloadProtocol} Download client isn't configured yet");
}
// Get the seed configuration for this release.
remoteAlbum.SeedConfiguration = _seedConfigProvider.GetSeedConfiguration(remoteAlbum);
// Limit grabs to 2 per second.
if (remoteAlbum.Release.DownloadUrl.IsNotNullOrWhiteSpace() && !remoteAlbum.Release.DownloadUrl.StartsWith("magnet:"))
{
var url = new HttpUri(remoteAlbum.Release.DownloadUrl);
await _rateLimitService.WaitAndPulseAsync(url.Host, TimeSpan.FromSeconds(2));
}
IIndexer indexer = null;
if (remoteAlbum.Release.IndexerId > 0)
{
indexer = _indexerFactory.GetInstance(_indexerFactory.Get(remoteAlbum.Release.IndexerId));
}
string downloadClientId;
try
{
downloadClientId = await downloadClient.Download(remoteAlbum, indexer);
_downloadClientStatusService.RecordSuccess(downloadClient.Definition.Id);
_indexerStatusService.RecordSuccess(remoteAlbum.Release.IndexerId);
}
catch (ReleaseUnavailableException)
{
_logger.Trace("Release {0} no longer available on indexer.", remoteAlbum);
throw;
}
catch (ReleaseBlockedException)
{
_logger.Trace("Release {0} previously added to blocklist, not sending to download client again.", remoteAlbum);
throw;
}
catch (DownloadClientRejectedReleaseException)
{
_logger.Trace("Release {0} rejected by download client, possible duplicate.", remoteAlbum);
throw;
}
catch (ReleaseDownloadException ex)
{
if (ex.InnerException is TooManyRequestsException http429)
{
_indexerStatusService.RecordFailure(remoteAlbum.Release.IndexerId, http429.RetryAfter);
}
else
{
_indexerStatusService.RecordFailure(remoteAlbum.Release.IndexerId);
}
throw;
}
var albumGrabbedEvent = new AlbumGrabbedEvent(remoteAlbum);
albumGrabbedEvent.DownloadClient = downloadClient.Name;
albumGrabbedEvent.DownloadClientId = downloadClient.Definition.Id;
albumGrabbedEvent.DownloadClientName = downloadClient.Definition.Name;
if (downloadClientId.IsNotNullOrWhiteSpace())
{
albumGrabbedEvent.DownloadId = downloadClientId;
}
_logger.ProgressInfo("Report sent to {0} from indexer {1}. {2}", downloadClient.Definition.Name, remoteAlbum.Release.Indexer, downloadTitle);
_eventAggregator.PublishEvent(albumGrabbedEvent);
}
}
}