Swapped out the timer GET for a signalr connection.
This commit is contained in:
parent
8f35952f90
commit
21ad2ebfd6
14 changed files with 218 additions and 69 deletions
|
|
@ -2,5 +2,10 @@
|
|||
"/Api": {
|
||||
"target": "http://localhost:6500/",
|
||||
"secure": false
|
||||
},
|
||||
"/hub": {
|
||||
"target": "http://localhost:6500/",
|
||||
"secure": false,
|
||||
"ws": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
64
client/package-lock.json
generated
64
client/package-lock.json
generated
|
|
@ -1618,6 +1618,18 @@
|
|||
"schema-utils": "^2.7.0"
|
||||
}
|
||||
},
|
||||
"@microsoft/signalr": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-5.0.1.tgz",
|
||||
"integrity": "sha512-qk5xMEpEqvxmj2/7ZRkHpWyt33gGXiNTkM+iIFr0QYEaynsbwGUxyV5WhuxcOP9LyXgUx6IXBer2HVAGOC4zpw==",
|
||||
"requires": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"eventsource": "^1.0.7",
|
||||
"fetch-cookie": "^0.7.3",
|
||||
"node-fetch": "^2.6.0",
|
||||
"ws": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@ngtools/webpack": {
|
||||
"version": "11.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.0.5.tgz",
|
||||
|
|
@ -2002,6 +2014,14 @@
|
|||
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"abort-controller": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||
"requires": {
|
||||
"event-target-shim": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
|
|
@ -2333,8 +2353,7 @@
|
|||
"async-limiter": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
|
|
@ -4628,6 +4647,11 @@
|
|||
"next-tick": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"es6-denodeify": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/es6-denodeify/-/es6-denodeify-0.1.5.tgz",
|
||||
"integrity": "sha1-MdTV/pxVA+ElRgQ5MQ4WoqPznB8="
|
||||
},
|
||||
"es6-iterator": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||
|
|
@ -4733,6 +4757,11 @@
|
|||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
|
||||
"dev": true
|
||||
},
|
||||
"event-target-shim": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
|
|
@ -4749,7 +4778,6 @@
|
|||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
|
||||
"integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"original": "^1.0.0"
|
||||
}
|
||||
|
|
@ -5072,6 +5100,15 @@
|
|||
"websocket-driver": ">=0.5.1"
|
||||
}
|
||||
},
|
||||
"fetch-cookie": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.7.3.tgz",
|
||||
"integrity": "sha512-rZPkLnI8x5V+zYAiz8QonAHsTb4BY+iFowFBI1RFn0zrO343AVp9X7/yUj/9wL6Ef/8fLls8b/vGtzUvmyAUGA==",
|
||||
"requires": {
|
||||
"es6-denodeify": "^0.1.1",
|
||||
"tough-cookie": "^2.3.3"
|
||||
}
|
||||
},
|
||||
"figgy-pudding": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
|
||||
|
|
@ -7801,6 +7838,11 @@
|
|||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
},
|
||||
"node-fetch-npm": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz",
|
||||
|
|
@ -8311,7 +8353,6 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
|
||||
"integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"url-parse": "^1.4.3"
|
||||
}
|
||||
|
|
@ -9883,8 +9924,7 @@
|
|||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"public-encrypt": {
|
||||
"version": "4.0.3",
|
||||
|
|
@ -9944,8 +9984,7 @@
|
|||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"q": {
|
||||
"version": "1.5.1",
|
||||
|
|
@ -9980,8 +10019,7 @@
|
|||
"querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
|
|
@ -10281,8 +10319,7 @@
|
|||
"requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.15.1",
|
||||
|
|
@ -12004,7 +12041,6 @@
|
|||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
|
|
@ -12354,7 +12390,6 @@
|
|||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
|
||||
"integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
|
|
@ -13607,7 +13642,6 @@
|
|||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
"@angular/platform-browser-dynamic": "~11.0.5",
|
||||
"@angular/router": "~11.0.5",
|
||||
"@fortawesome/fontawesome-free": "^5.15.1",
|
||||
"@microsoft/signalr": "^5.0.1",
|
||||
"bulma": "^0.9.1",
|
||||
"curray": "^1.0.8",
|
||||
"ngx-filesize": "^2.0.16",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
{{ file.path }}
|
||||
</td>
|
||||
<td>{{ file.bytes | filesize }}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
{{ file | fileStatus }}
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
{{ torrent.downloads.length | number }}
|
||||
</td>
|
||||
<td class="auto">
|
||||
<i class="fas fa-download" *ngIf="!torrent.autoDownload" title="Auto download"></i>
|
||||
<i class="fas fa-box-open" *ngIf="!torrent.autoUnpack" title="Auto unpack"></i>
|
||||
<i class="fas fa-trash" *ngIf="!torrent.autoDelete" title="Auto delete"></i>
|
||||
<i class="fas fa-download" *ngIf="torrent.autoDownload" title="Auto download"></i>
|
||||
<i class="fas fa-box-open" *ngIf="torrent.autoUnpack" title="Auto unpack"></i>
|
||||
<i class="fas fa-trash" *ngIf="torrent.autoDelete" title="Auto delete"></i>
|
||||
</td>
|
||||
<td>
|
||||
{{ torrent | status }}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
<div class="table-container">
|
||||
<table class="table is-fullwidth is-hoverable">
|
||||
<colgroup>
|
||||
<col style="width: calc(65% - 550px)" />
|
||||
<col style="width: calc(40% - 550px)" />
|
||||
<col style="width: 15%" />
|
||||
<col style="width: 150px" />
|
||||
<col style="width: 150px" />
|
||||
<col style="width: 150px" />
|
||||
<col style="width: 20%" />
|
||||
<col style="width: 40%" />
|
||||
<col style="width: 100px" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
|
|
@ -32,12 +32,7 @@
|
|||
(click)="selectTorrent(torrent)"
|
||||
(delete)="showDeleteModal($event)"
|
||||
></tr>
|
||||
<ng-container *ngIf="showFiles[torrent.torrentId] && torrent?.files.length === 0">
|
||||
<tr>
|
||||
<td colspan="20">
|
||||
<i class="fas fa-spinner fa-pulse"></i>
|
||||
</td>
|
||||
</tr>
|
||||
<ng-container *ngIf="showFiles[torrent.torrentId]">
|
||||
<tr app-torrent-file [file]="file" *ngFor="let file of torrent.files"></tr>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
|
|
|||
|
|
@ -20,26 +20,27 @@ export class TorrentTableComponent implements OnInit, OnDestroy {
|
|||
public deleteRdTorrent: boolean;
|
||||
public deleteLocalFiles: boolean;
|
||||
|
||||
private timer: any;
|
||||
|
||||
constructor(private torrentService: TorrentService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.timer = setInterval(() => {
|
||||
this.torrentService.getList().subscribe(
|
||||
(result) => {
|
||||
this.torrents = result;
|
||||
},
|
||||
(err) => {
|
||||
this.error = err.error;
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
);
|
||||
}, 1000);
|
||||
this.torrentService.getList().subscribe(
|
||||
(result) => {
|
||||
this.torrents = result;
|
||||
|
||||
this.torrentService.connect();
|
||||
|
||||
this.torrentService.update$.subscribe((result2) => {
|
||||
this.torrents = result2;
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
this.error = err.error;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
clearInterval(this.timer);
|
||||
this.torrentService.disconnect();
|
||||
}
|
||||
|
||||
public selectTorrent(torrent: Torrent): void {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import * as signalR from '@microsoft/signalr';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { Torrent } from './models/torrent.model';
|
||||
|
||||
@Injectable({
|
||||
|
|
@ -9,6 +10,23 @@ import { Torrent } from './models/torrent.model';
|
|||
export class TorrentService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
public update$: Subject<Torrent[]> = new Subject();
|
||||
|
||||
private connection: signalR.HubConnection;
|
||||
|
||||
public connect(): void {
|
||||
this.connection = new signalR.HubConnectionBuilder().withUrl('/hub').withAutomaticReconnect().build();
|
||||
this.connection.start().catch((err) => console.error(err));
|
||||
|
||||
this.connection.on('update', (torrents: Torrent[]) => {
|
||||
this.update$.next(torrents);
|
||||
});
|
||||
}
|
||||
|
||||
public disconnect(): void {
|
||||
this.connection?.stop();
|
||||
}
|
||||
|
||||
public getList(): Observable<Torrent[]> {
|
||||
return this.http.get<Torrent[]>(`/Api/Torrents`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ namespace RdtClient.Service
|
|||
services.AddScoped<IAuthentication, Authentication>();
|
||||
services.AddScoped<IDownloads, Downloads>();
|
||||
services.AddScoped<IQBittorrent, QBittorrent>();
|
||||
services.AddScoped<IRemoteService, RemoteService>();
|
||||
services.AddScoped<ISettings, Settings>();
|
||||
services.AddScoped<ITorrents, Torrents>();
|
||||
services.AddScoped<ITorrentRunner, TorrentRunner>();
|
||||
|
|
|
|||
27
server/RdtClient.Service/Services/RdtHub.cs
Normal file
27
server/RdtClient.Service/Services/RdtHub.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace RdtClient.Service.Services
|
||||
{
|
||||
public class RdtHub : Hub
|
||||
{
|
||||
private static readonly ConcurrentDictionary<String, String> Users = new ConcurrentDictionary<String, String>();
|
||||
|
||||
public static Boolean HasConnections => Users.Any();
|
||||
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
Users.TryAdd(Context.ConnectionId, Context.ConnectionId);
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception exception)
|
||||
{
|
||||
Users.TryRemove(Context.ConnectionId, out _);
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
server/RdtClient.Service/Services/RemoteService.cs
Normal file
41
server/RdtClient.Service/Services/RemoteService.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace RdtClient.Service.Services
|
||||
{
|
||||
public interface IRemoteService
|
||||
{
|
||||
Task Update();
|
||||
}
|
||||
|
||||
public class RemoteService : IRemoteService
|
||||
{
|
||||
private readonly IHubContext<RdtHub> _hub;
|
||||
private readonly ITorrents _torrents;
|
||||
|
||||
public RemoteService(IHubContext<RdtHub> hub, ITorrents torrents)
|
||||
{
|
||||
_hub = hub;
|
||||
_torrents = torrents;
|
||||
}
|
||||
|
||||
public async Task Update()
|
||||
{
|
||||
var torrents = await _torrents.Get();
|
||||
|
||||
// Prevent infinite recursion when serializing
|
||||
foreach (var file in torrents.SelectMany(torrent => torrent.Downloads))
|
||||
{
|
||||
file.Torrent = null;
|
||||
}
|
||||
|
||||
await _hub.Clients.All.SendCoreAsync("update",
|
||||
new Object[]
|
||||
{
|
||||
torrents
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,23 +18,25 @@ namespace RdtClient.Service.Services
|
|||
|
||||
public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new ConcurrentDictionary<Guid, DownloadClient>();
|
||||
public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new ConcurrentDictionary<Guid, UnpackClient>();
|
||||
|
||||
private readonly IDownloads _downloads;
|
||||
private readonly IRemoteService _remoteService;
|
||||
|
||||
private readonly ISettings _settings;
|
||||
private readonly ITorrents _torrents;
|
||||
private readonly IDownloads _downloads;
|
||||
|
||||
public TorrentRunner(ISettings settings, ITorrents torrents, IDownloads downloads)
|
||||
public TorrentRunner(ISettings settings, ITorrents torrents, IDownloads downloads, IRemoteService remoteService)
|
||||
{
|
||||
_settings = settings;
|
||||
_torrents = torrents;
|
||||
_downloads = downloads;
|
||||
_remoteService = remoteService;
|
||||
}
|
||||
|
||||
public async Task Initialize()
|
||||
{
|
||||
// When starting up reset any pending downloads or unpackings so that they are restarted.
|
||||
var torrents = await _torrents.Get();
|
||||
|
||||
|
||||
var downloads = torrents.SelectMany(m => m.Downloads)
|
||||
.Where(m => m.DownloadQueued != null && m.DownloadStarted != null && m.DownloadFinished == null)
|
||||
.OrderBy(m => m.DownloadQueued);
|
||||
|
|
@ -43,7 +45,7 @@ namespace RdtClient.Service.Services
|
|||
{
|
||||
await _downloads.UpdateDownloadStarted(download.DownloadId, null);
|
||||
}
|
||||
|
||||
|
||||
var unpacks = torrents.SelectMany(m => m.Downloads)
|
||||
.Where(m => m.UnpackingQueued != null && m.UnpackingStarted != null && m.UnpackingFinished == null)
|
||||
.OrderBy(m => m.DownloadQueued);
|
||||
|
|
@ -53,7 +55,7 @@ namespace RdtClient.Service.Services
|
|||
await _downloads.UpdateUnpackingStarted(download.DownloadId, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task Tick()
|
||||
{
|
||||
var settingApiKey = await _settings.GetString("RealDebridApiKey");
|
||||
|
|
@ -62,7 +64,7 @@ namespace RdtClient.Service.Services
|
|||
{
|
||||
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();
|
||||
|
||||
|
|
@ -78,14 +80,14 @@ namespace RdtClient.Service.Services
|
|||
{
|
||||
await _downloads.UpdateDownloadFinished(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)
|
||||
|
|
@ -98,24 +100,30 @@ namespace RdtClient.Service.Services
|
|||
{
|
||||
await _downloads.UpdateUnpackingFinished(downloadId, DateTimeOffset.UtcNow);
|
||||
}
|
||||
|
||||
|
||||
ActiveUnpackClients.TryRemove(downloadId, out _);
|
||||
}
|
||||
}
|
||||
|
||||
// Only poll RealDebrid every 30 seconds
|
||||
|
||||
// Only poll RealDebrid every 5 when a hub is connected, otherwise ever 30 seconds
|
||||
if (_nextUpdate < DateTime.UtcNow)
|
||||
{
|
||||
_nextUpdate = DateTime.UtcNow.AddSeconds(5);
|
||||
|
||||
var updateTime = 30;
|
||||
|
||||
if (RdtHub.HasConnections)
|
||||
{
|
||||
updateTime = 5;
|
||||
}
|
||||
|
||||
_nextUpdate = DateTime.UtcNow.AddSeconds(updateTime);
|
||||
|
||||
await _torrents.Update();
|
||||
}
|
||||
|
||||
var 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.DownloadQueued != null && m.DownloadStarted == null)
|
||||
|
|
@ -125,7 +133,7 @@ namespace RdtClient.Service.Services
|
|||
{
|
||||
await _torrents.Download(download.DownloadId);
|
||||
}
|
||||
|
||||
|
||||
// Check if there are any unpacks that are queued and can be started.
|
||||
var queuedUnpacks = torrents.SelectMany(m => m.Downloads)
|
||||
.Where(m => m.UnpackingQueued != null && m.UnpackingStarted == null)
|
||||
|
|
@ -167,22 +175,23 @@ namespace RdtClient.Service.Services
|
|||
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.DownloadStarted == null &&
|
||||
.Where(m => m.DownloadStarted == null &&
|
||||
m.DownloadFinished == null)
|
||||
.ToList();
|
||||
|
||||
|
||||
if (downloadsPending.Count > 0)
|
||||
{
|
||||
foreach (var download in downloadsPending)
|
||||
{
|
||||
await _torrents.Download(download.DownloadId);
|
||||
}
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -191,22 +200,22 @@ namespace RdtClient.Service.Services
|
|||
{
|
||||
// If all files are finished downloading, move to the unpacking step.
|
||||
var unpackingPending = torrent.Downloads
|
||||
.Where(m => m.DownloadFinished != null &&
|
||||
m.UnpackingStarted == null &&
|
||||
.Where(m => 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)
|
||||
{
|
||||
|
|
@ -224,6 +233,8 @@ namespace RdtClient.Service.Services
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
await _remoteService.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,10 @@ namespace RdtClient.Service.Services
|
|||
|
||||
var torrentPath = Path.Combine(settingDownloadFolder, torrent.RdName);
|
||||
|
||||
Directory.Delete(torrentPath, true);
|
||||
if (Directory.Exists(torrentPath))
|
||||
{
|
||||
Directory.Delete(torrentPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteData)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Microsoft.Extensions.Logging;
|
|||
using RdtClient.Data.Data;
|
||||
using RdtClient.Data.Models.Internal;
|
||||
using RdtClient.Service.Middleware;
|
||||
using RdtClient.Service.Services;
|
||||
|
||||
namespace RdtClient.Web
|
||||
{
|
||||
|
|
@ -39,6 +40,11 @@ namespace RdtClient.Web
|
|||
|
||||
services.AddSpaStaticFiles(configuration => { configuration.RootPath = "wwwroot"; });
|
||||
|
||||
services.AddSignalR(options =>
|
||||
{
|
||||
options.EnableDetailedErrors = true;
|
||||
});
|
||||
|
||||
services.AddHttpContextAccessor();
|
||||
|
||||
services.AddCors(options =>
|
||||
|
|
@ -112,7 +118,11 @@ namespace RdtClient.Web
|
|||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapHub<RdtHub>("/hub");
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
app.MapWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue