public async Task Tick() { var settings = await _settings.GetAll(); var settingApiKey = settings.GetString("RealDebridApiKey"); if (String.IsNullOrWhiteSpace(settingApiKey)) { return; } var settingMinFileSize = settings.GetNumber("MinFileSize"); if (settingMinFileSize <= 0) { settingMinFileSize = 0; } settingMinFileSize = settingMinFileSize * 1024 * 1024; var settingDownloadLimit = settings.GetNumber("DownloadLimit"); if (settingDownloadLimit < 1) { settingDownloadLimit = 1; } var settingUnpackLimit = settings.GetNumber("UnpackLimit"); if (settingUnpackLimit < 1) { settingUnpackLimit = 1; } var settingDownloadPath = settings.GetString("DownloadPath"); if (String.IsNullOrWhiteSpace(settingDownloadPath)) { return; } // Check if any torrents are finished downloading to the host, remove them from the active download list. var completedActiveDownloads = ActiveDownloadClients.Where(m => m.Value.Finished).ToList(); if (completedActiveDownloads.Count > 0) { foreach (var(downloadId, downloadClient) in completedActiveDownloads) { if (downloadClient.Error != null) { await _downloads.UpdateError(downloadId, downloadClient.Error); await _downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow); } else { await _downloads.UpdateDownloadFinished(downloadId, DateTimeOffset.UtcNow); await _downloads.UpdateUnpackingQueued(downloadId, DateTimeOffset.UtcNow); } ActiveDownloadClients.TryRemove(downloadId, out _); } } // Check if any torrents are finished unpacking, remove them from the active unpack list. var completedUnpacks = ActiveUnpackClients.Where(m => m.Value.Finished).ToList(); if (completedUnpacks.Count > 0) { foreach (var(downloadId, unpackClient) in completedUnpacks) { if (unpackClient.Error != null) { await _downloads.UpdateError(downloadId, unpackClient.Error); await _downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow); } else { await _downloads.UpdateUnpackingFinished(downloadId, DateTimeOffset.UtcNow); await _downloads.UpdateCompleted(downloadId, DateTimeOffset.UtcNow); } ActiveUnpackClients.TryRemove(downloadId, out _); } } var torrents = await _torrents.Get(); // Only poll RealDebrid every second when a hub is connected, otherwise every 30 seconds if (_nextUpdate < DateTime.UtcNow && torrents.Count > 0) { var updateTime = 30; if (RdtHub.HasConnections) { updateTime = 1; } _nextUpdate = DateTime.UtcNow.AddSeconds(updateTime); await _torrents.Update(); // Re-get torrents to account for updated info torrents = await _torrents.Get(); } torrents = torrents.Where(m => m.Completed == null).ToList(); // Check if there are any downloads that are queued and can be started. var queuedDownloads = torrents.SelectMany(m => m.Downloads) .Where(m => m.Completed == null && m.DownloadQueued != null && m.DownloadStarted == null) .OrderBy(m => m.DownloadQueued); foreach (var download in queuedDownloads) { if (TorrentRunner.ActiveDownloadClients.Count >= settingDownloadLimit) { return; } if (TorrentRunner.ActiveDownloadClients.ContainsKey(download.DownloadId)) { return; } download.DownloadStarted = DateTime.UtcNow; await _downloads.UpdateDownloadStarted(download.DownloadId, download.DownloadStarted); var downloadPath = settingDownloadPath; if (!String.IsNullOrWhiteSpace(download.Torrent.Category)) { downloadPath = Path.Combine(downloadPath, download.Torrent.Category); } // Start the download process var downloadClient = new DownloadClient(download, downloadPath); if (TorrentRunner.ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient)) { await downloadClient.Start(settings); } } // Check if there are any unpacks that are queued and can be started. var queuedUnpacks = torrents.SelectMany(m => m.Downloads) .Where(m => m.Completed == null && m.UnpackingQueued != null && m.UnpackingStarted == null) .OrderBy(m => m.DownloadQueued); foreach (var download in queuedUnpacks) { // Check if the unpacking process is even needed var uri = new Uri(download.Link); var fileName = uri.Segments.Last(); var extension = Path.GetExtension(fileName); if (extension != ".rar") { download.UnpackingStarted = DateTimeOffset.UtcNow; download.UnpackingFinished = DateTimeOffset.UtcNow; download.Completed = DateTimeOffset.UtcNow; await _downloads.UpdateUnpackingStarted(download.DownloadId, download.UnpackingStarted); await _downloads.UpdateUnpackingFinished(download.DownloadId, download.UnpackingFinished); await _downloads.UpdateCompleted(download.DownloadId, download.Completed); continue; } // Check if we have reached the download limit, if so queue the download, but don't start it. if (TorrentRunner.ActiveUnpackClients.Count >= settingUnpackLimit) { return; } if (TorrentRunner.ActiveUnpackClients.ContainsKey(download.DownloadId)) { return; } download.UnpackingStarted = DateTimeOffset.UtcNow; await _downloads.UpdateUnpackingStarted(download.DownloadId, download.UnpackingStarted); var downloadPath = settingDownloadPath; if (!String.IsNullOrWhiteSpace(download.Torrent.Category)) { downloadPath = Path.Combine(downloadPath, download.Torrent.Category); } // Start the unpacking process var unpackClient = new UnpackClient(download, downloadPath); if (TorrentRunner.ActiveUnpackClients.TryAdd(download.DownloadId, unpackClient)) { await unpackClient.Start(); } } foreach (var torrent in torrents) { // If torrent is erroring out on the RealDebrid side, skip processing this torrent. if (torrent.RdStatus == RealDebridStatus.Error) { continue; } // RealDebrid is waiting for file selection, select which files to download. if (torrent.AutoDownload && torrent.RdStatus == RealDebridStatus.WaitingForFileSelection) { var fileIds = torrent.Files .Select(m => m.Id.ToString()) .ToArray(); if (settingMinFileSize > 0) { fileIds = torrent.Files .Where(m => m.Bytes > settingMinFileSize) .Select(m => m.Id.ToString()) .ToArray(); } await _torrents.SelectFiles(torrent.RdId, fileIds); } // If the torrent doesn't have any files at this point, don't process it further. if (torrent.Files.Count == 0) { continue; } // RealDebrid finished downloading the torrent, process the file to host. if (torrent.AutoDownload && torrent.RdStatus == RealDebridStatus.Finished) { // If the torrent doesn't have any Downloads, unrestrict the links and add them to the database. if (torrent.Downloads.Count == 0) { await _torrents.Unrestrict(torrent.TorrentId); continue; } // If the torrent has any files that need starting to be downloaded, download them. var downloadsPending = torrent.Downloads .Where(m => m.Completed == null && m.DownloadStarted == null && m.DownloadFinished == null) .ToList(); if (downloadsPending.Count > 0) { foreach (var download in downloadsPending) { await _torrents.Download(download.DownloadId); } continue; } } if (torrent.AutoUnpack && torrent.RdStatus == RealDebridStatus.Finished) { // If all files are finished downloading, move to the unpacking step. var unpackingPending = torrent.Downloads .Where(m => m.Completed == null && m.DownloadFinished != null && m.UnpackingStarted == null && m.UnpackingFinished == null) .ToList(); if (unpackingPending.Count > 0) { foreach (var download in unpackingPending) { await _torrents.Unpack(download.DownloadId); } continue; } } // Check if torrent is complete if (torrent.Downloads.Count > 0) { var allComplete = torrent.Downloads.All(m => m.Completed != null); if (allComplete) { await _torrents.UpdateComplete(torrent.TorrentId, DateTimeOffset.UtcNow); // Remove the torrent from RealDebrid if (torrent.AutoDelete) { await _torrents.Delete(torrent.TorrentId, true, true, false); } } } } await _remoteService.Update(); }
public async Task <ActionResult> Download(Guid id) { await _torrents.Unrestrict(id); return(Ok()); }