Skip to content

Commit 8542ea7

Browse files
committed
feat: add normalized functions
1 parent f6cb13b commit 8542ea7

File tree

5 files changed

+120
-51
lines changed

5 files changed

+120
-51
lines changed

Diff for: .eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ module.exports = {
1414
'no-mixed-operators': 0,
1515
'no-await-in-loop': 0,
1616
'@typescript-eslint/camelcase': 0,
17+
'@typescript-eslint/promise-function-async': 0,
1718
},
1819
};

Diff for: package-lock.json

+13-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@
2525
"semantic-release": "cd dist && semantic-release"
2626
},
2727
"dependencies": {
28-
"@ctrl/shared-torrent": "^1.0.3",
28+
"@ctrl/shared-torrent": "^1.1.0",
2929
"form-data": "2.3.3",
3030
"got": "9.6.0",
31-
"tough-cookie": "3.0.1"
31+
"tough-cookie": "3.0.1",
32+
"url-join": "^4.0.0"
3233
},
3334
"devDependencies": {
3435
"@types/form-data": "2.2.1",
@@ -37,9 +38,10 @@
3738
"@types/node": "11.10.4",
3839
"@types/p-wait-for": "2.0.0",
3940
"@types/tough-cookie": "2.3.5",
41+
"@types/url-join": "4.0.0",
4042
"@typescript-eslint/eslint-plugin": "1.4.2",
4143
"@typescript-eslint/parser": "1.4.2",
42-
"eslint": "5.15.0",
44+
"eslint": "5.15.1",
4345
"eslint-config-prettier": "4.1.0",
4446
"eslint-config-xo-space": "0.21.0",
4547
"eslint-config-xo-typescript": "0.8.0",

Diff for: src/index.ts

+88-16
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
import { resolve } from 'url';
1+
import urljoin from 'url-join';
22
import got, { Response, GotJSONOptions } from 'got';
33
import { Cookie } from 'tough-cookie';
44
import FormData from 'form-data';
55
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';
713
import {
814
GetHostsResponse,
915
GetHostStatusResponse,
@@ -22,6 +28,7 @@ import {
2228
TorrentFiles,
2329
TorrentStatus,
2430
Tracker,
31+
Torrent,
2532
} from './types';
2633

2734
const defaults: TorrentSettings = {
@@ -31,7 +38,7 @@ const defaults: TorrentSettings = {
3138
timeout: 5000,
3239
};
3340

34-
export class Deluge {
41+
export class Deluge implements TorrentClient {
3542
config: TorrentSettings;
3643

3744
private _msgId = 0;
@@ -122,7 +129,7 @@ export class Deluge {
122129
if (check.body && check.body.result) {
123130
return true;
124131
}
125-
// tslint:disable-next-line:no-unused
132+
// tslint:disable-next-line:no-unused
126133
} catch {
127134
// do nothing
128135
}
@@ -193,7 +200,7 @@ export class Deluge {
193200
form.append('file', torrent);
194201
}
195202

196-
const url = resolve(this.config.baseUrl, '../upload');
203+
const url = urljoin(this.config.baseUrl, '/upload');
197204
const res = await got.post(url, {
198205
headers: form.getHeaders(),
199206
body: form,
@@ -222,14 +229,8 @@ export class Deluge {
222229
// move_completed_path: '/root/Downloads',
223230
...config,
224231
};
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+
233234
return res.body;
234235
}
235236

@@ -258,7 +259,32 @@ export class Deluge {
258259
return res.body;
259260
}
260261

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 } = {}) {
262288
const fields = [
263289
'distributed_copies',
264290
'download_payload_rate',
@@ -283,15 +309,22 @@ export class Deluge {
283309
'total_wanted',
284310
'tracker_host',
285311
'upload_payload_rate',
312+
// if they don't have the label plugin it shouldn't fail
313+
'label',
286314
...additionalFields,
287315
];
288316
const req = await this.request<TorrentListResponse>('web.update_ui', [
289317
[...new Set(fields)],
290-
{},
318+
filter,
291319
]);
292320
return req.body;
293321
}
294322

323+
async getTorrent(id: string) {
324+
const torrentResponse = await this.getTorrentStatus(id);
325+
return this._normalizeTorrentData(id, torrentResponse.result);
326+
}
327+
295328
/**
296329
* get torrent state/status
297330
* @param additionalFields fields ex - `['label']`
@@ -333,6 +366,7 @@ export class Deluge {
333366
'max_download_speed',
334367
'max_upload_speed',
335368
'seeds_peers_ratio',
369+
'label',
336370
...additionalFields,
337371
];
338372
const req = await this.request<TorrentStatus>('web.get_torrent_status', [torrentId, fields]);
@@ -452,7 +486,7 @@ export class Deluge {
452486
const headers: any = {
453487
Cookie: this._cookie && this._cookie.cookieString(),
454488
};
455-
const url = resolve(this.config.baseUrl, this.config.path);
489+
const url = urljoin(this.config.baseUrl, this.config.path);
456490
const options: GotJSONOptions = {
457491
body: {
458492
method,
@@ -476,6 +510,44 @@ export class Deluge {
476510
return got.post(url, options);
477511
}
478512

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+
479551
private async _validateAuth() {
480552
let validAuth = await this.checkSession();
481553
if (!validAuth) {

Diff for: src/types.ts

+13-24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
export interface DefaultResponse {
2+
/**
3+
* mostly usless id that increments with every request
4+
*/
25
id: number;
36
error: null | string;
47
result: any;
@@ -13,7 +16,13 @@ export interface ListMethods extends DefaultResponse {
1316
}
1417

1518
// {"files": ["/tmp/delugeweb-5Q9ttR/tmpL7xhth.torrent"], "success": true}
19+
/**
20+
* ex -
21+
*/
1622
export interface UploadResponse {
23+
/**
24+
* ex - `["/tmp/delugeweb-5Q9ttR/tmpL7xhth.torrent"]`
25+
*/
1726
files: string[];
1827
success: boolean;
1928
}
@@ -94,6 +103,9 @@ export interface TorrentList {
94103
filters: TorrentFilters;
95104
}
96105

106+
/**
107+
* ['label', 'id']
108+
*/
97109
export interface TorrentFilters {
98110
state: [string, number][];
99111
tracker_host: [string, number][];
@@ -173,30 +185,7 @@ export interface Tracker {
173185
}
174186

175187
export interface TorrentStatus extends DefaultResponse {
176-
result: {
177-
max_download_speed?: number;
178-
stop_ratio?: number;
179-
is_auto_managed?: true;
180-
move_completed_path?: string;
181-
private?: boolean;
182-
stop_at_ratio?: boolean;
183-
max_upload_speed?: number;
184-
remove_at_ratio?: boolean;
185-
max_upload_slots?: number;
186-
prioritize_first_last?: boolean;
187-
move_completed?: boolean;
188-
max_connections?: number;
189-
comment?: string;
190-
name?: string;
191-
total_size?: number;
192-
num_files?: number;
193-
tracker?: string;
194-
save_path?: string;
195-
message?: string;
196-
peers?: TorrentPeers;
197-
trackers?: Tracker;
198-
[key: string]: any;
199-
};
188+
result: Torrent;
200189
}
201190

202191
export interface TorrentPeers {

0 commit comments

Comments
 (0)