1
- import { resolve } from 'url' ;
1
+ import urljoin from 'url-join ' ;
2
2
import got , { Response , GotJSONOptions } from 'got' ;
3
3
import { Cookie } from 'tough-cookie' ;
4
4
import FormData from 'form-data' ;
5
5
import fs from 'fs' ;
6
- import { TorrentSettings } from '@ctrl/shared-torrent' ;
6
+ import {
7
+ TorrentSettings ,
8
+ TorrentClient ,
9
+ NormalizedTorrent ,
10
+ AllClientData ,
11
+ TorrentState ,
12
+ } from '@ctrl/shared-torrent' ;
7
13
import {
8
14
GetHostsResponse ,
9
15
GetHostStatusResponse ,
@@ -22,6 +28,7 @@ import {
22
28
TorrentFiles ,
23
29
TorrentStatus ,
24
30
Tracker ,
31
+ Torrent ,
25
32
} from './types' ;
26
33
27
34
const defaults : TorrentSettings = {
@@ -31,7 +38,7 @@ const defaults: TorrentSettings = {
31
38
timeout : 5000 ,
32
39
} ;
33
40
34
- export class Deluge {
41
+ export class Deluge implements TorrentClient {
35
42
config : TorrentSettings ;
36
43
37
44
private _msgId = 0 ;
@@ -122,7 +129,7 @@ export class Deluge {
122
129
if ( check . body && check . body . result ) {
123
130
return true ;
124
131
}
125
- // tslint:disable-next-line:no-unused
132
+ // tslint:disable-next-line:no-unused
126
133
} catch {
127
134
// do nothing
128
135
}
@@ -193,7 +200,7 @@ export class Deluge {
193
200
form . append ( 'file' , torrent ) ;
194
201
}
195
202
196
- const url = resolve ( this . config . baseUrl , '.. /upload' ) ;
203
+ const url = urljoin ( this . config . baseUrl , '/upload' ) ;
197
204
const res = await got . post ( url , {
198
205
headers : form . getHeaders ( ) ,
199
206
body : form ,
@@ -222,14 +229,8 @@ export class Deluge {
222
229
// move_completed_path: '/root/Downloads',
223
230
...config ,
224
231
} ;
225
- const res = await this . request < BooleanStatus > ( 'web.add_torrents' , [
226
- [
227
- {
228
- path,
229
- options,
230
- } ,
231
- ] ,
232
- ] ) ;
232
+ const res = await this . request < BooleanStatus > ( 'web.add_torrents' , [ [ { path, options } ] ] ) ;
233
+
233
234
return res . body ;
234
235
}
235
236
@@ -258,7 +259,32 @@ export class Deluge {
258
259
return res . body ;
259
260
}
260
261
261
- async listTorrents ( additionalFields : string [ ] = [ ] ) {
262
+ async getAllData ( ) : Promise < AllClientData > {
263
+ const listTorrents = await this . listTorrents ( ) ;
264
+ const results : AllClientData = {
265
+ torrents : [ ] ,
266
+ labels : [ ] ,
267
+ } ;
268
+ for ( const id of Object . keys ( listTorrents . result . torrents ) ) {
269
+ const torrent = listTorrents . result . torrents [ id ] ;
270
+ const torrentData : NormalizedTorrent = this . _normalizeTorrentData ( id , torrent ) ;
271
+ results . torrents . push ( torrentData ) ;
272
+ }
273
+
274
+ if ( listTorrents . result . filters . label ) {
275
+ for ( const label of listTorrents . result . filters . label ) {
276
+ results . labels . push ( {
277
+ id : label [ 0 ] ,
278
+ name : label [ 0 ] ,
279
+ count : label [ 1 ] ,
280
+ } ) ;
281
+ }
282
+ }
283
+
284
+ return results ;
285
+ }
286
+
287
+ async listTorrents ( additionalFields : string [ ] = [ ] , filter : { [ key : string ] : string } = { } ) {
262
288
const fields = [
263
289
'distributed_copies' ,
264
290
'download_payload_rate' ,
@@ -283,15 +309,22 @@ export class Deluge {
283
309
'total_wanted' ,
284
310
'tracker_host' ,
285
311
'upload_payload_rate' ,
312
+ // if they don't have the label plugin it shouldn't fail
313
+ 'label' ,
286
314
...additionalFields ,
287
315
] ;
288
316
const req = await this . request < TorrentListResponse > ( 'web.update_ui' , [
289
317
[ ...new Set ( fields ) ] ,
290
- { } ,
318
+ filter ,
291
319
] ) ;
292
320
return req . body ;
293
321
}
294
322
323
+ async getTorrent ( id : string ) {
324
+ const torrentResponse = await this . getTorrentStatus ( id ) ;
325
+ return this . _normalizeTorrentData ( id , torrentResponse . result ) ;
326
+ }
327
+
295
328
/**
296
329
* get torrent state/status
297
330
* @param additionalFields fields ex - `['label']`
@@ -333,6 +366,7 @@ export class Deluge {
333
366
'max_download_speed' ,
334
367
'max_upload_speed' ,
335
368
'seeds_peers_ratio' ,
369
+ 'label' ,
336
370
...additionalFields ,
337
371
] ;
338
372
const req = await this . request < TorrentStatus > ( 'web.get_torrent_status' , [ torrentId , fields ] ) ;
@@ -452,7 +486,7 @@ export class Deluge {
452
486
const headers : any = {
453
487
Cookie : this . _cookie && this . _cookie . cookieString ( ) ,
454
488
} ;
455
- const url = resolve ( this . config . baseUrl , this . config . path ) ;
489
+ const url = urljoin ( this . config . baseUrl , this . config . path ) ;
456
490
const options : GotJSONOptions = {
457
491
body : {
458
492
method,
@@ -476,6 +510,44 @@ export class Deluge {
476
510
return got . post ( url , options ) ;
477
511
}
478
512
513
+ private _normalizeTorrentData ( id : string , torrent : Torrent ) : NormalizedTorrent {
514
+ const dateAdded = new Date ( torrent . time_added * 1000 ) . toISOString ( ) ;
515
+
516
+ // normalize state to enum
517
+ let state = TorrentState . unknown ;
518
+ if ( Object . keys ( TorrentState ) . includes ( torrent . state . toLowerCase ( ) ) ) {
519
+ state = TorrentState [ torrent . state . toLowerCase ( ) as keyof typeof TorrentState ] ;
520
+ }
521
+
522
+ const isCompleted = torrent . progress >= 100 ;
523
+
524
+ const result : NormalizedTorrent = {
525
+ id,
526
+ name : torrent . name ,
527
+ state,
528
+ isCompleted,
529
+ stateMessage : torrent . state ,
530
+ progress : torrent . progress ,
531
+ ratio : torrent . ratio ,
532
+ dateAdded,
533
+ dateCompleted : undefined ,
534
+ label : torrent . label ,
535
+ savePath : torrent . save_path ,
536
+ uploadSpeed : torrent . upload_payload_rate ,
537
+ downloadSpeed : torrent . download_payload_rate ,
538
+ eta : torrent . eta ,
539
+ queuePosition : torrent . queue + 1 ,
540
+ connectedPeers : torrent . num_peers ,
541
+ connectedSeeds : torrent . num_seeds ,
542
+ totalPeers : torrent . total_peers ,
543
+ totalSeeds : torrent . total_seeds ,
544
+ totalSelected : torrent . total_wanted ,
545
+ totalUploaded : torrent . total_uploaded ,
546
+ totalDownloaded : torrent . total_done ,
547
+ } ;
548
+ return result ;
549
+ }
550
+
479
551
private async _validateAuth ( ) {
480
552
let validAuth = await this . checkSession ( ) ;
481
553
if ( ! validAuth ) {
0 commit comments