@ctrl/deluge 3.3.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index.d.ts → src/deluge.d.ts} +8 -1
- package/dist/{index.js → src/deluge.js} +90 -46
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/{types.d.ts → src/types.d.ts} +0 -0
- package/dist/src/types.js +1 -0
- package/package.json +34 -32
- package/dist/types.js +0 -2
@@ -1,7 +1,7 @@
|
|
1
1
|
/// <reference types="node" />
|
2
2
|
import { Response } from 'got';
|
3
3
|
import { AddTorrentOptions as NormalizedAddTorrentOptions, AllClientData, NormalizedTorrent, TorrentClient, TorrentSettings } from '@ctrl/shared-torrent';
|
4
|
-
import { AddTorrentOptions, BooleanStatus, ConfigResponse, DefaultResponse, DelugeSettings, GetHostsResponse, GetHostStatusResponse, ListMethods, PluginInfo, PluginsListResponse, StringStatus, TorrentFiles, TorrentInfo, TorrentListResponse, TorrentOptions, TorrentStatus, Tracker, UploadResponse
|
4
|
+
import { AddTorrentOptions, AddTorrentResponse, BooleanStatus, ConfigResponse, DefaultResponse, DelugeSettings, GetHostsResponse, GetHostStatusResponse, ListMethods, PluginInfo, PluginsListResponse, StringStatus, TorrentFiles, TorrentInfo, TorrentListResponse, TorrentOptions, TorrentStatus, Tracker, UploadResponse } from './types.js';
|
5
5
|
export declare class Deluge implements TorrentClient {
|
6
6
|
config: TorrentSettings;
|
7
7
|
private _msgId;
|
@@ -57,6 +57,13 @@ export declare class Deluge implements TorrentClient {
|
|
57
57
|
*/
|
58
58
|
listMethods(auth?: boolean): Promise<ListMethods>;
|
59
59
|
upload(torrent: string | Buffer): Promise<UploadResponse>;
|
60
|
+
/**
|
61
|
+
* Download a torrent from url, pass the result to {@link Deluge.addTorrent}
|
62
|
+
* @param url
|
63
|
+
* @param cookies
|
64
|
+
* @returns file path
|
65
|
+
*/
|
66
|
+
downloadFromUrl(url: string, cookies?: string): Promise<string>;
|
60
67
|
addTorrent(torrent: string | Buffer, config?: Partial<AddTorrentOptions>): Promise<AddTorrentResponse>;
|
61
68
|
normalizedAddTorrent(torrent: string | Buffer, options?: Partial<NormalizedAddTorrentOptions>): Promise<NormalizedTorrent>;
|
62
69
|
addTorrentMagnet(magnet: string, config?: Partial<AddTorrentOptions>): Promise<BooleanStatus>;
|
@@ -1,24 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
const got_1 = __importDefault(require("got"));
|
10
|
-
const tough_cookie_1 = require("tough-cookie");
|
11
|
-
const url_join_1 = require("@ctrl/url-join");
|
12
|
-
const shared_torrent_1 = require("@ctrl/shared-torrent");
|
1
|
+
import { existsSync } from 'fs';
|
2
|
+
import { File, FormData } from 'formdata-node';
|
3
|
+
import { fileFromPath } from 'formdata-node/file-from-path';
|
4
|
+
import got from 'got';
|
5
|
+
import { Cookie } from 'tough-cookie';
|
6
|
+
import { magnetDecode } from '@ctrl/magnet-link';
|
7
|
+
import { TorrentState, } from '@ctrl/shared-torrent';
|
8
|
+
import { urlJoin } from '@ctrl/url-join';
|
13
9
|
const defaults = {
|
14
10
|
baseUrl: 'http://localhost:8112/',
|
15
11
|
path: '/json',
|
16
12
|
password: 'deluge',
|
17
13
|
timeout: 5000,
|
18
14
|
};
|
19
|
-
class Deluge {
|
15
|
+
export class Deluge {
|
20
16
|
constructor(options = {}) {
|
21
|
-
this
|
17
|
+
Object.defineProperty(this, "config", {
|
18
|
+
enumerable: true,
|
19
|
+
configurable: true,
|
20
|
+
writable: true,
|
21
|
+
value: void 0
|
22
|
+
});
|
23
|
+
Object.defineProperty(this, "_msgId", {
|
24
|
+
enumerable: true,
|
25
|
+
configurable: true,
|
26
|
+
writable: true,
|
27
|
+
value: 0
|
28
|
+
});
|
29
|
+
Object.defineProperty(this, "_cookie", {
|
30
|
+
enumerable: true,
|
31
|
+
configurable: true,
|
32
|
+
writable: true,
|
33
|
+
value: void 0
|
34
|
+
});
|
22
35
|
this.config = { ...defaults, ...options };
|
23
36
|
}
|
24
37
|
resetSession() {
|
@@ -93,7 +106,7 @@ class Deluge {
|
|
93
106
|
return true;
|
94
107
|
}
|
95
108
|
}
|
96
|
-
catch
|
109
|
+
catch {
|
97
110
|
// do nothing
|
98
111
|
}
|
99
112
|
}
|
@@ -110,7 +123,7 @@ class Deluge {
|
|
110
123
|
if (!res.body.result || !res.headers || !res.headers['set-cookie']) {
|
111
124
|
throw new Error('Auth failed, incorrect password');
|
112
125
|
}
|
113
|
-
this._cookie =
|
126
|
+
this._cookie = Cookie.parse(res.headers['set-cookie'][0]);
|
114
127
|
return true;
|
115
128
|
}
|
116
129
|
/**
|
@@ -152,36 +165,58 @@ class Deluge {
|
|
152
165
|
if (!isConnected) {
|
153
166
|
await this.connect();
|
154
167
|
}
|
155
|
-
const form = new
|
168
|
+
const form = new FormData();
|
169
|
+
const type = { type: 'application/x-bittorrent' };
|
156
170
|
if (typeof torrent === 'string') {
|
157
|
-
if (
|
158
|
-
|
171
|
+
if (existsSync(torrent)) {
|
172
|
+
const file = await fileFromPath(torrent, 'temp.torrent', type);
|
173
|
+
form.set('file', file);
|
159
174
|
}
|
160
175
|
else {
|
161
|
-
form.
|
176
|
+
form.set('file', new File([Buffer.from(torrent, 'base64')], 'file.torrent', type));
|
162
177
|
}
|
163
178
|
}
|
164
179
|
else {
|
165
|
-
|
180
|
+
const file = new File([torrent], 'torrent', type);
|
181
|
+
form.set('file', file);
|
166
182
|
}
|
167
|
-
const url =
|
168
|
-
const res = await
|
169
|
-
headers: form.getHeaders(),
|
183
|
+
const url = urlJoin(this.config.baseUrl, '/upload');
|
184
|
+
const res = await got.post(url, {
|
170
185
|
body: form,
|
171
|
-
retry: 0,
|
186
|
+
retry: { limit: 0 },
|
187
|
+
timeout: { request: this.config.timeout },
|
172
188
|
// allow proxy agent
|
173
|
-
agent: this.config.agent,
|
174
|
-
timeout: this.config.timeout,
|
189
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
175
190
|
});
|
176
191
|
// repsonse is json but in a string, cannot use native got.json()
|
177
192
|
return JSON.parse(res.body);
|
178
193
|
}
|
194
|
+
/**
|
195
|
+
* Download a torrent from url, pass the result to {@link Deluge.addTorrent}
|
196
|
+
* @param url
|
197
|
+
* @param cookies
|
198
|
+
* @returns file path
|
199
|
+
*/
|
200
|
+
async downloadFromUrl(url, cookies = '') {
|
201
|
+
const res = await this.request('web.download_torrent_from_url', [url, cookies]);
|
202
|
+
if (!res.body.result) {
|
203
|
+
throw new Error('Failed to download torrent');
|
204
|
+
}
|
205
|
+
return res.body.result;
|
206
|
+
}
|
179
207
|
async addTorrent(torrent, config = {}) {
|
180
|
-
|
181
|
-
if (
|
182
|
-
|
208
|
+
let path;
|
209
|
+
if (Buffer.isBuffer(torrent) || !torrent.startsWith('/tmp/')) {
|
210
|
+
const upload = await this.upload(torrent);
|
211
|
+
if (!upload.success || !upload.files.length) {
|
212
|
+
throw new Error('Failed to upload');
|
213
|
+
}
|
214
|
+
path = upload.files[0];
|
215
|
+
}
|
216
|
+
else {
|
217
|
+
/** Assume paths starting with /tmp/ are from {@link Deluge.addTorrent} */
|
218
|
+
path = torrent;
|
183
219
|
}
|
184
|
-
const path = upload.files[0];
|
185
220
|
const options = {
|
186
221
|
file_priorities: [],
|
187
222
|
add_paused: false,
|
@@ -212,11 +247,21 @@ class Deluge {
|
|
212
247
|
if (options.startPaused) {
|
213
248
|
torrentOptions.add_paused = true;
|
214
249
|
}
|
215
|
-
|
216
|
-
|
250
|
+
let torrentHash;
|
251
|
+
if (typeof torrent === 'string' && torrent.startsWith('magnet:')) {
|
252
|
+
torrentHash = magnetDecode(torrent).infoHash;
|
253
|
+
if (!torrentHash) {
|
254
|
+
throw new Error('Magnet did not contain hash');
|
255
|
+
}
|
256
|
+
await this.addTorrentMagnet(torrent, torrentOptions);
|
257
|
+
}
|
258
|
+
else {
|
259
|
+
if (!Buffer.isBuffer(torrent)) {
|
260
|
+
torrent = Buffer.from(torrent);
|
261
|
+
}
|
262
|
+
const res = await this.addTorrent(torrent, torrentOptions);
|
263
|
+
torrentHash = res.result[0][1];
|
217
264
|
}
|
218
|
-
const res = await this.addTorrent(torrent, torrentOptions);
|
219
|
-
const torrentHash = res.result[0][1];
|
220
265
|
if (options.label) {
|
221
266
|
// sets the label but it might not set the label right away
|
222
267
|
// sometimes takes a few seconds for label to reflect in results
|
@@ -266,7 +311,7 @@ class Deluge {
|
|
266
311
|
}
|
267
312
|
// update current password to new password
|
268
313
|
this.config.password = password;
|
269
|
-
this._cookie =
|
314
|
+
this._cookie = Cookie.parse(res.headers['set-cookie'][0]);
|
270
315
|
return res.body;
|
271
316
|
}
|
272
317
|
async getAllData() {
|
@@ -495,19 +540,19 @@ class Deluge {
|
|
495
540
|
const headers = {
|
496
541
|
Cookie: (_b = (_a = this._cookie) === null || _a === void 0 ? void 0 : _a.cookieString) === null || _b === void 0 ? void 0 : _b.call(_a),
|
497
542
|
};
|
498
|
-
const url =
|
499
|
-
const res = await
|
543
|
+
const url = urlJoin(this.config.baseUrl, this.config.path);
|
544
|
+
const res = await got.post(url, {
|
500
545
|
json: {
|
501
546
|
method,
|
502
547
|
params,
|
503
548
|
id: this._msgId++,
|
504
549
|
},
|
505
550
|
headers,
|
506
|
-
retry: 0,
|
507
|
-
|
508
|
-
agent: this.config.agent,
|
509
|
-
timeout: this.config.timeout,
|
551
|
+
retry: { limit: 0 },
|
552
|
+
timeout: { request: this.config.timeout },
|
510
553
|
responseType: 'json',
|
554
|
+
// allow proxy agent
|
555
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
511
556
|
});
|
512
557
|
const err = (_d = (_c = res.body) === null || _c === void 0 ? void 0 : _c.error) !== null && _d !== void 0 ? _d : (typeof res.body === 'string' && res.body);
|
513
558
|
if (err) {
|
@@ -518,9 +563,9 @@ class Deluge {
|
|
518
563
|
_normalizeTorrentData(id, torrent) {
|
519
564
|
const dateAdded = new Date(torrent.time_added * 1000).toISOString();
|
520
565
|
// normalize state to enum
|
521
|
-
let state =
|
522
|
-
if (Object.keys(
|
523
|
-
state =
|
566
|
+
let state = TorrentState.unknown;
|
567
|
+
if (Object.keys(TorrentState).includes(torrent.state.toLowerCase())) {
|
568
|
+
state = TorrentState[torrent.state.toLowerCase()];
|
524
569
|
}
|
525
570
|
const isCompleted = torrent.progress >= 100;
|
526
571
|
const result = {
|
@@ -560,4 +605,3 @@ class Deluge {
|
|
560
605
|
}
|
561
606
|
}
|
562
607
|
}
|
563
|
-
exports.Deluge = Deluge;
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ctrl/deluge",
|
3
|
-
"version": "
|
3
|
+
"version": "4.0.0",
|
4
4
|
"description": "TypeScript api wrapper for deluge using got",
|
5
5
|
"author": "Scott Cooper <scttcper@gmail.com>",
|
6
6
|
"license": "MIT",
|
@@ -10,50 +10,52 @@
|
|
10
10
|
"deluge",
|
11
11
|
"typescript"
|
12
12
|
],
|
13
|
-
"
|
14
|
-
"
|
13
|
+
"type": "module",
|
14
|
+
"main": "./dist/src/index.js",
|
15
|
+
"typings": "./dist/src/index.d.ts",
|
15
16
|
"files": [
|
16
|
-
"dist"
|
17
|
+
"dist/src"
|
17
18
|
],
|
18
19
|
"sideEffects": false,
|
19
20
|
"scripts": {
|
20
21
|
"lint": "eslint --ext .js,.ts, .",
|
21
22
|
"lint:fix": "eslint --fix --ext .js,.ts, .",
|
22
23
|
"prepare": "npm run build",
|
23
|
-
"build": "tsc
|
24
|
-
"build:docs": "typedoc
|
25
|
-
"test": "
|
26
|
-
"test:watch": "
|
27
|
-
"test:ci": "
|
24
|
+
"build": "tsc",
|
25
|
+
"build:docs": "typedoc",
|
26
|
+
"test": "ava",
|
27
|
+
"test:watch": "ava --watch",
|
28
|
+
"test:ci": "c8 --reporter=text --reporter=lcov ava"
|
28
29
|
},
|
29
30
|
"dependencies": {
|
30
|
-
"@ctrl/
|
31
|
-
"@ctrl/
|
32
|
-
"
|
33
|
-
"
|
31
|
+
"@ctrl/magnet-link": "^3.1.0",
|
32
|
+
"@ctrl/shared-torrent": "^4.1.0",
|
33
|
+
"@ctrl/url-join": "^2.0.0",
|
34
|
+
"formdata-node": "^4.3.2",
|
35
|
+
"got": "^12.0.1",
|
34
36
|
"tough-cookie": "^4.0.0"
|
35
37
|
},
|
36
38
|
"devDependencies": {
|
37
|
-
"@
|
38
|
-
"@
|
39
|
-
"@
|
40
|
-
"@
|
41
|
-
"
|
42
|
-
"
|
43
|
-
"
|
44
|
-
"p-wait-for": "
|
45
|
-
"typedoc": "0.
|
46
|
-
"typescript": "4.
|
39
|
+
"@ctrl/eslint-config": "3.3.1",
|
40
|
+
"@sindresorhus/tsconfig": "2.0.0",
|
41
|
+
"@types/node": "17.0.21",
|
42
|
+
"@types/tough-cookie": "4.0.1",
|
43
|
+
"ava": "4.0.1",
|
44
|
+
"c8": "7.11.0",
|
45
|
+
"ts-node": "10.5.0",
|
46
|
+
"p-wait-for": "4.1.0",
|
47
|
+
"typedoc": "0.22.12",
|
48
|
+
"typescript": "4.5.5"
|
47
49
|
},
|
48
|
-
"
|
49
|
-
"
|
50
|
-
|
51
|
-
"babel": {
|
52
|
-
"presets": [
|
53
|
-
"@babel/preset-typescript"
|
50
|
+
"ava": {
|
51
|
+
"files": [
|
52
|
+
"test/**/*.spec.ts"
|
54
53
|
],
|
55
|
-
"
|
56
|
-
"
|
54
|
+
"extensions": {
|
55
|
+
"ts": "module"
|
56
|
+
},
|
57
|
+
"nodeArguments": [
|
58
|
+
"--loader=ts-node/esm"
|
57
59
|
]
|
58
60
|
},
|
59
61
|
"publishConfig": {
|
@@ -63,6 +65,6 @@
|
|
63
65
|
"branch": "master"
|
64
66
|
},
|
65
67
|
"engines": {
|
66
|
-
"node": ">=
|
68
|
+
"node": ">=14.16"
|
67
69
|
}
|
68
70
|
}
|
package/dist/types.js
DELETED