@ctrl/deluge 3.4.0 → 4.0.1
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} +2 -2
- package/dist/{index.js → src/deluge.js} +80 -51
- 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 +27 -35
- package/dist/types.js +0 -2
@@ -1,7 +1,7 @@
|
|
1
|
-
/// <reference types="node" />
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
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;
|
@@ -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() {
|
@@ -76,7 +89,6 @@ class Deluge {
|
|
76
89
|
* @returns true if valid
|
77
90
|
*/
|
78
91
|
async checkSession() {
|
79
|
-
var _a;
|
80
92
|
// cookie is missing or expires in x seconds
|
81
93
|
if (this._cookie) {
|
82
94
|
// eslint-disable-next-line new-cap
|
@@ -89,11 +101,11 @@ class Deluge {
|
|
89
101
|
if (this._cookie) {
|
90
102
|
try {
|
91
103
|
const check = await this.request('auth.check_session', undefined, false);
|
92
|
-
if (
|
104
|
+
if (check?.body?.result) {
|
93
105
|
return true;
|
94
106
|
}
|
95
107
|
}
|
96
|
-
catch
|
108
|
+
catch {
|
97
109
|
// do nothing
|
98
110
|
}
|
99
111
|
}
|
@@ -110,7 +122,7 @@ class Deluge {
|
|
110
122
|
if (!res.body.result || !res.headers || !res.headers['set-cookie']) {
|
111
123
|
throw new Error('Auth failed, incorrect password');
|
112
124
|
}
|
113
|
-
this._cookie =
|
125
|
+
this._cookie = Cookie.parse(res.headers['set-cookie'][0]);
|
114
126
|
return true;
|
115
127
|
}
|
116
128
|
/**
|
@@ -152,26 +164,28 @@ class Deluge {
|
|
152
164
|
if (!isConnected) {
|
153
165
|
await this.connect();
|
154
166
|
}
|
155
|
-
const form = new
|
167
|
+
const form = new FormData();
|
168
|
+
const type = { type: 'application/x-bittorrent' };
|
156
169
|
if (typeof torrent === 'string') {
|
157
|
-
if (
|
158
|
-
|
170
|
+
if (existsSync(torrent)) {
|
171
|
+
const file = await fileFromPath(torrent, 'temp.torrent', type);
|
172
|
+
form.set('file', file);
|
159
173
|
}
|
160
174
|
else {
|
161
|
-
form.
|
175
|
+
form.set('file', new File([Buffer.from(torrent, 'base64')], 'file.torrent', type));
|
162
176
|
}
|
163
177
|
}
|
164
178
|
else {
|
165
|
-
|
179
|
+
const file = new File([torrent], 'torrent', type);
|
180
|
+
form.set('file', file);
|
166
181
|
}
|
167
|
-
const url =
|
168
|
-
const res = await
|
169
|
-
headers: form.getHeaders(),
|
182
|
+
const url = urlJoin(this.config.baseUrl, '/upload');
|
183
|
+
const res = await got.post(url, {
|
170
184
|
body: form,
|
171
|
-
retry: 0,
|
185
|
+
retry: { limit: 0 },
|
186
|
+
timeout: { request: this.config.timeout },
|
172
187
|
// allow proxy agent
|
173
|
-
agent: this.config.agent,
|
174
|
-
timeout: this.config.timeout,
|
188
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
175
189
|
});
|
176
190
|
// repsonse is json but in a string, cannot use native got.json()
|
177
191
|
return JSON.parse(res.body);
|
@@ -190,11 +204,18 @@ class Deluge {
|
|
190
204
|
return res.body.result;
|
191
205
|
}
|
192
206
|
async addTorrent(torrent, config = {}) {
|
193
|
-
|
194
|
-
if (
|
195
|
-
|
207
|
+
let path;
|
208
|
+
if (Buffer.isBuffer(torrent) || !torrent.startsWith('/tmp/')) {
|
209
|
+
const upload = await this.upload(torrent);
|
210
|
+
if (!upload.success || !upload.files.length) {
|
211
|
+
throw new Error('Failed to upload');
|
212
|
+
}
|
213
|
+
path = upload.files[0];
|
214
|
+
}
|
215
|
+
else {
|
216
|
+
/** Assume paths starting with /tmp/ are from {@link Deluge.addTorrent} */
|
217
|
+
path = torrent;
|
196
218
|
}
|
197
|
-
const path = upload.files[0];
|
198
219
|
const options = {
|
199
220
|
file_priorities: [],
|
200
221
|
add_paused: false,
|
@@ -225,11 +246,21 @@ class Deluge {
|
|
225
246
|
if (options.startPaused) {
|
226
247
|
torrentOptions.add_paused = true;
|
227
248
|
}
|
228
|
-
|
229
|
-
|
249
|
+
let torrentHash;
|
250
|
+
if (typeof torrent === 'string' && torrent.startsWith('magnet:')) {
|
251
|
+
torrentHash = magnetDecode(torrent).infoHash;
|
252
|
+
if (!torrentHash) {
|
253
|
+
throw new Error('Magnet did not contain hash');
|
254
|
+
}
|
255
|
+
await this.addTorrentMagnet(torrent, torrentOptions);
|
256
|
+
}
|
257
|
+
else {
|
258
|
+
if (!Buffer.isBuffer(torrent)) {
|
259
|
+
torrent = Buffer.from(torrent);
|
260
|
+
}
|
261
|
+
const res = await this.addTorrent(torrent, torrentOptions);
|
262
|
+
torrentHash = res.result[0][1];
|
230
263
|
}
|
231
|
-
const res = await this.addTorrent(torrent, torrentOptions);
|
232
|
-
const torrentHash = res.result[0][1];
|
233
264
|
if (options.label) {
|
234
265
|
// sets the label but it might not set the label right away
|
235
266
|
// sometimes takes a few seconds for label to reflect in results
|
@@ -279,7 +310,7 @@ class Deluge {
|
|
279
310
|
}
|
280
311
|
// update current password to new password
|
281
312
|
this.config.password = password;
|
282
|
-
this._cookie =
|
313
|
+
this._cookie = Cookie.parse(res.headers['set-cookie'][0]);
|
283
314
|
return res.body;
|
284
315
|
}
|
285
316
|
async getAllData() {
|
@@ -492,7 +523,6 @@ class Deluge {
|
|
492
523
|
}
|
493
524
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
494
525
|
async request(method, params = [], needsAuth = true, autoConnect = true) {
|
495
|
-
var _a, _b, _c, _d;
|
496
526
|
if (this._msgId === 4096) {
|
497
527
|
this._msgId = 0;
|
498
528
|
}
|
@@ -506,23 +536,23 @@ class Deluge {
|
|
506
536
|
}
|
507
537
|
}
|
508
538
|
const headers = {
|
509
|
-
Cookie:
|
539
|
+
Cookie: this._cookie?.cookieString?.(),
|
510
540
|
};
|
511
|
-
const url =
|
512
|
-
const res = await
|
541
|
+
const url = urlJoin(this.config.baseUrl, this.config.path);
|
542
|
+
const res = await got.post(url, {
|
513
543
|
json: {
|
514
544
|
method,
|
515
545
|
params,
|
516
546
|
id: this._msgId++,
|
517
547
|
},
|
518
548
|
headers,
|
519
|
-
retry: 0,
|
520
|
-
|
521
|
-
agent: this.config.agent,
|
522
|
-
timeout: this.config.timeout,
|
549
|
+
retry: { limit: 0 },
|
550
|
+
timeout: { request: this.config.timeout },
|
523
551
|
responseType: 'json',
|
552
|
+
// allow proxy agent
|
553
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
524
554
|
});
|
525
|
-
const err =
|
555
|
+
const err = res.body?.error ?? (typeof res.body === 'string' && res.body);
|
526
556
|
if (err) {
|
527
557
|
throw new Error(err.message || err);
|
528
558
|
}
|
@@ -531,9 +561,9 @@ class Deluge {
|
|
531
561
|
_normalizeTorrentData(id, torrent) {
|
532
562
|
const dateAdded = new Date(torrent.time_added * 1000).toISOString();
|
533
563
|
// normalize state to enum
|
534
|
-
let state =
|
535
|
-
if (Object.keys(
|
536
|
-
state =
|
564
|
+
let state = TorrentState.unknown;
|
565
|
+
if (Object.keys(TorrentState).includes(torrent.state.toLowerCase())) {
|
566
|
+
state = TorrentState[torrent.state.toLowerCase()];
|
537
567
|
}
|
538
568
|
const isCompleted = torrent.progress >= 100;
|
539
569
|
const result = {
|
@@ -573,4 +603,3 @@ class Deluge {
|
|
573
603
|
}
|
574
604
|
}
|
575
605
|
}
|
576
|
-
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.1",
|
4
4
|
"description": "TypeScript api wrapper for deluge using got",
|
5
5
|
"author": "Scott Cooper <scttcper@gmail.com>",
|
6
6
|
"license": "MIT",
|
@@ -10,59 +10,51 @@
|
|
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": "tsc",
|
24
25
|
"build:docs": "typedoc",
|
25
|
-
"test": "
|
26
|
-
"test:watch": "
|
27
|
-
"test:ci": "
|
26
|
+
"test": "vitest run",
|
27
|
+
"test:watch": "vitest",
|
28
|
+
"test:ci": "vitest run --coverage"
|
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.1.0",
|
34
36
|
"tough-cookie": "^4.0.0"
|
35
37
|
},
|
36
38
|
"devDependencies": {
|
37
|
-
"@
|
38
|
-
"@
|
39
|
-
"@
|
40
|
-
"@
|
41
|
-
"
|
42
|
-
"
|
43
|
-
"
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"typescript": "4.2.4"
|
47
|
-
},
|
48
|
-
"jest": {
|
49
|
-
"testEnvironment": "node"
|
50
|
-
},
|
51
|
-
"babel": {
|
52
|
-
"presets": [
|
53
|
-
"@babel/preset-typescript"
|
54
|
-
],
|
55
|
-
"plugins": [
|
56
|
-
"@babel/plugin-transform-modules-commonjs"
|
57
|
-
]
|
39
|
+
"@ctrl/eslint-config": "3.4.4",
|
40
|
+
"@sindresorhus/tsconfig": "3.0.1",
|
41
|
+
"@types/node": "17.0.38",
|
42
|
+
"@types/tough-cookie": "4.0.2",
|
43
|
+
"c8": "7.11.3",
|
44
|
+
"p-wait-for": "4.1.0",
|
45
|
+
"typedoc": "0.22.17",
|
46
|
+
"typescript": "4.7.2",
|
47
|
+
"vitest": "0.13.1"
|
58
48
|
},
|
59
49
|
"publishConfig": {
|
60
50
|
"access": "public"
|
61
51
|
},
|
62
52
|
"release": {
|
63
|
-
"
|
53
|
+
"branches": [
|
54
|
+
"master"
|
55
|
+
]
|
64
56
|
},
|
65
57
|
"engines": {
|
66
|
-
"node": ">=
|
58
|
+
"node": ">=14.16"
|
67
59
|
}
|
68
60
|
}
|
package/dist/types.js
DELETED