@ctrl/qbittorrent 2.10.0 → 3.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/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/{index.d.ts → src/qbittorrent.d.ts} +16 -9
- package/dist/{index.js → src/qbittorrent.js} +150 -129
- package/dist/{types.d.ts → src/types.d.ts} +2 -12
- package/dist/{types.js → src/types.js} +8 -11
- package/package.json +34 -33
@@ -1,8 +1,7 @@
|
|
1
1
|
/// <reference types="node" />
|
2
2
|
import { Options as GotOptions, Response } from 'got';
|
3
|
-
import { AddTorrentOptions as NormalizedAddTorrentOptions, TorrentClient, TorrentSettings } from '@ctrl/shared-torrent';
|
4
|
-
import { AddMagnetOptions, AddTorrentOptions,
|
5
|
-
export { TorrentState, TorrentTrackerStatus, TorrentFilePriority, TorrentPieceState };
|
3
|
+
import { AddTorrentOptions as NormalizedAddTorrentOptions, AllClientData, NormalizedTorrent, TorrentClient, TorrentSettings } from '@ctrl/shared-torrent';
|
4
|
+
import { AddMagnetOptions, AddTorrentOptions, BuildInfo, Preferences, Torrent, TorrentCategories, TorrentFile, TorrentFilePriority, TorrentFilters, TorrentPieceState, TorrentProperties, TorrentTrackers, WebSeed } from './types.js';
|
6
5
|
export declare class QBittorrent implements TorrentClient {
|
7
6
|
config: TorrentSettings;
|
8
7
|
/**
|
@@ -28,7 +27,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
28
27
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-build-info}
|
29
28
|
*/
|
30
29
|
getBuildInfo(): Promise<BuildInfo>;
|
31
|
-
getTorrent(hash: string): Promise<
|
30
|
+
getTorrent(hash: string): Promise<NormalizedTorrent>;
|
32
31
|
/**
|
33
32
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-application-preferences}
|
34
33
|
*/
|
@@ -44,8 +43,16 @@ export declare class QBittorrent implements TorrentClient {
|
|
44
43
|
* @param category Get torrents with the given category (empty string means "without category"; no "category" parameter means "any category")
|
45
44
|
* @returns list of torrents
|
46
45
|
*/
|
47
|
-
listTorrents(hashes
|
48
|
-
|
46
|
+
listTorrents({ hashes, filter, category, sort, offset, reverse, tag, }?: {
|
47
|
+
hashes?: string | string[];
|
48
|
+
filter?: TorrentFilters;
|
49
|
+
sort?: string;
|
50
|
+
tag?: string;
|
51
|
+
category?: string;
|
52
|
+
offset?: number;
|
53
|
+
reverse?: boolean;
|
54
|
+
}): Promise<Torrent[]>;
|
55
|
+
getAllData(): Promise<AllClientData>;
|
49
56
|
/**
|
50
57
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-torrent-generic-properties}
|
51
58
|
*/
|
@@ -95,7 +102,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
95
102
|
/**
|
96
103
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-all-categories}
|
97
104
|
*/
|
98
|
-
getCategories(): Promise<
|
105
|
+
getCategories(): Promise<TorrentCategories>;
|
99
106
|
/**
|
100
107
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#add-new-category}
|
101
108
|
*/
|
@@ -146,7 +153,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
146
153
|
*/
|
147
154
|
reannounceTorrent(hashes: string | string[] | 'all'): Promise<boolean>;
|
148
155
|
addTorrent(torrent: string | Buffer, options?: Partial<AddTorrentOptions>): Promise<boolean>;
|
149
|
-
normalizedAddTorrent(torrent: string | Buffer, options?: Partial<NormalizedAddTorrentOptions>): Promise<
|
156
|
+
normalizedAddTorrent(torrent: string | Buffer, options?: Partial<NormalizedAddTorrentOptions>): Promise<NormalizedTorrent>;
|
150
157
|
/**
|
151
158
|
* @param hash Hash for desired torrent
|
152
159
|
* @param id id of the file to be renamed
|
@@ -191,7 +198,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
191
198
|
*/
|
192
199
|
login(): Promise<boolean>;
|
193
200
|
logout(): boolean;
|
194
|
-
request<T extends object | string>(path: string, method: GotOptions['method'], params?: any, body?: GotOptions['body'], headers?: any, json?: boolean): Promise<Response<T>>;
|
201
|
+
request<T extends object | string>(path: string, method: GotOptions['method'], params?: any, body?: GotOptions['body'], form?: GotOptions['form'], headers?: any, json?: boolean): Promise<Response<T>>;
|
195
202
|
/**
|
196
203
|
* Normalizes hashes
|
197
204
|
* @returns hashes as string seperated by `|`
|
@@ -1,23 +1,15 @@
|
|
1
|
-
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.QBittorrent = exports.TorrentPieceState = exports.TorrentFilePriority = exports.TorrentTrackerStatus = exports.TorrentState = void 0;
|
7
1
|
/* eslint-disable @typescript-eslint/ban-types */
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Object.defineProperty(exports, "TorrentState", { enumerable: true, get: function () { return types_1.TorrentState; } });
|
20
|
-
Object.defineProperty(exports, "TorrentTrackerStatus", { enumerable: true, get: function () { return types_1.TorrentTrackerStatus; } });
|
2
|
+
import { existsSync } from 'fs';
|
3
|
+
import { URLSearchParams } from 'url';
|
4
|
+
import { File, FormData } from 'formdata-node';
|
5
|
+
import { fileFromPath } from 'formdata-node/file-from-path';
|
6
|
+
import got from 'got';
|
7
|
+
import { Cookie } from 'tough-cookie';
|
8
|
+
import { magnetDecode } from '@ctrl/magnet-link';
|
9
|
+
import { TorrentState as NormalizedTorrentState, } from '@ctrl/shared-torrent';
|
10
|
+
import { hash } from '@ctrl/torrent-file';
|
11
|
+
import { urlJoin } from '@ctrl/url-join';
|
12
|
+
import { TorrentState, } from './types.js';
|
21
13
|
const defaults = {
|
22
14
|
baseUrl: 'http://localhost:9091/',
|
23
15
|
path: '/api/v2',
|
@@ -25,8 +17,32 @@ const defaults = {
|
|
25
17
|
password: '',
|
26
18
|
timeout: 5000,
|
27
19
|
};
|
28
|
-
class QBittorrent {
|
20
|
+
export class QBittorrent {
|
29
21
|
constructor(options = {}) {
|
22
|
+
Object.defineProperty(this, "config", {
|
23
|
+
enumerable: true,
|
24
|
+
configurable: true,
|
25
|
+
writable: true,
|
26
|
+
value: void 0
|
27
|
+
});
|
28
|
+
/**
|
29
|
+
* auth cookie
|
30
|
+
*/
|
31
|
+
Object.defineProperty(this, "_sid", {
|
32
|
+
enumerable: true,
|
33
|
+
configurable: true,
|
34
|
+
writable: true,
|
35
|
+
value: void 0
|
36
|
+
});
|
37
|
+
/**
|
38
|
+
* cookie expiration
|
39
|
+
*/
|
40
|
+
Object.defineProperty(this, "_exp", {
|
41
|
+
enumerable: true,
|
42
|
+
configurable: true,
|
43
|
+
writable: true,
|
44
|
+
value: void 0
|
45
|
+
});
|
30
46
|
this.config = { ...defaults, ...options };
|
31
47
|
}
|
32
48
|
/**
|
@@ -40,11 +56,11 @@ class QBittorrent {
|
|
40
56
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-application-version}
|
41
57
|
*/
|
42
58
|
async getAppVersion() {
|
43
|
-
const res = await this.request('/app/version', 'GET', undefined, undefined, undefined, false);
|
59
|
+
const res = await this.request('/app/version', 'GET', undefined, undefined, undefined, undefined, false);
|
44
60
|
return res.body;
|
45
61
|
}
|
46
62
|
async getApiVersion() {
|
47
|
-
const res = await this.request('/app/webapiVersion', 'GET', undefined, undefined, undefined, false);
|
63
|
+
const res = await this.request('/app/webapiVersion', 'GET', undefined, undefined, undefined, undefined, false);
|
48
64
|
return res.body;
|
49
65
|
}
|
50
66
|
/**
|
@@ -55,7 +71,7 @@ class QBittorrent {
|
|
55
71
|
return res.body;
|
56
72
|
}
|
57
73
|
async getTorrent(hash) {
|
58
|
-
const torrentsResponse = await this.listTorrents(hash);
|
74
|
+
const torrentsResponse = await this.listTorrents({ hashes: hash });
|
59
75
|
const torrentData = torrentsResponse[0];
|
60
76
|
if (!torrentData) {
|
61
77
|
throw new Error('Torrent not found');
|
@@ -73,9 +89,9 @@ class QBittorrent {
|
|
73
89
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-application-preferences}
|
74
90
|
*/
|
75
91
|
async setPreferences(preferences) {
|
76
|
-
|
77
|
-
|
78
|
-
|
92
|
+
await this.request('/app/setPreferences', 'POST', undefined, undefined, {
|
93
|
+
json: JSON.stringify(preferences),
|
94
|
+
});
|
79
95
|
return true;
|
80
96
|
}
|
81
97
|
/**
|
@@ -85,10 +101,7 @@ class QBittorrent {
|
|
85
101
|
* @param category Get torrents with the given category (empty string means "without category"; no "category" parameter means "any category")
|
86
102
|
* @returns list of torrents
|
87
103
|
*/
|
88
|
-
|
89
|
-
async listTorrents(hashes, filter, category, sort, offset, reverse,
|
90
|
-
// TODO: refactor filters into an object with optional properties
|
91
|
-
tag) {
|
104
|
+
async listTorrents({ hashes, filter, category, sort, offset, reverse, tag, } = {}) {
|
92
105
|
const params = {};
|
93
106
|
if (hashes) {
|
94
107
|
params.hashes = this._normalizeHashes(hashes);
|
@@ -193,20 +206,20 @@ class QBittorrent {
|
|
193
206
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-torrent-location}
|
194
207
|
*/
|
195
208
|
async setTorrentLocation(hashes, location) {
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
209
|
+
await this.request('/torrents/setLocation', 'POST', undefined, undefined, {
|
210
|
+
location,
|
211
|
+
hashes: this._normalizeHashes(hashes),
|
212
|
+
});
|
200
213
|
return true;
|
201
214
|
}
|
202
215
|
/**
|
203
216
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-torrent-name}
|
204
217
|
*/
|
205
218
|
async setTorrentName(hash, name) {
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
219
|
+
await this.request('/torrents/rename', 'POST', undefined, undefined, {
|
220
|
+
hash,
|
221
|
+
name,
|
222
|
+
});
|
210
223
|
return true;
|
211
224
|
}
|
212
225
|
/**
|
@@ -221,9 +234,9 @@ class QBittorrent {
|
|
221
234
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#create-tags}
|
222
235
|
*/
|
223
236
|
async createTags(tags) {
|
224
|
-
|
225
|
-
|
226
|
-
|
237
|
+
await this.request('/torrents/createTags', 'POST', undefined, undefined, {
|
238
|
+
tags,
|
239
|
+
}, undefined, false);
|
227
240
|
return true;
|
228
241
|
}
|
229
242
|
/**
|
@@ -231,9 +244,7 @@ class QBittorrent {
|
|
231
244
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#delete-tags}
|
232
245
|
*/
|
233
246
|
async deleteTags(tags) {
|
234
|
-
|
235
|
-
form.append('tags', tags);
|
236
|
-
await this.request('/torrents/deleteTags', 'POST', undefined, form, undefined, false);
|
247
|
+
await this.request('/torrents/deleteTags', 'POST', undefined, undefined, { tags }, undefined, false);
|
237
248
|
return true;
|
238
249
|
}
|
239
250
|
/**
|
@@ -247,39 +258,39 @@ class QBittorrent {
|
|
247
258
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#add-new-category}
|
248
259
|
*/
|
249
260
|
async createCategory(category, savePath = '') {
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
261
|
+
await this.request('/torrents/createCategory', 'POST', undefined, undefined, {
|
262
|
+
category,
|
263
|
+
savePath,
|
264
|
+
}, undefined, false);
|
254
265
|
return true;
|
255
266
|
}
|
256
267
|
/**
|
257
268
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#edit-category}
|
258
269
|
*/
|
259
270
|
async editCategory(category, savePath = '') {
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
271
|
+
await this.request('/torrents/editCategory', 'POST', undefined, undefined, {
|
272
|
+
category,
|
273
|
+
savePath,
|
274
|
+
}, undefined, false);
|
264
275
|
return true;
|
265
276
|
}
|
266
277
|
/**
|
267
278
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#remove-categories}
|
268
279
|
*/
|
269
280
|
async removeCategory(categories) {
|
270
|
-
|
271
|
-
|
272
|
-
|
281
|
+
await this.request('/torrents/removeCategories', 'POST', undefined, undefined, {
|
282
|
+
categories,
|
283
|
+
}, undefined, false);
|
273
284
|
return true;
|
274
285
|
}
|
275
286
|
/**
|
276
287
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#add-torrent-tags}
|
277
288
|
*/
|
278
289
|
async addTorrentTags(hashes, tags) {
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
290
|
+
await this.request('/torrents/addTags', 'POST', undefined, undefined, {
|
291
|
+
hashes: this._normalizeHashes(hashes),
|
292
|
+
tags,
|
293
|
+
}, undefined, false);
|
283
294
|
return true;
|
284
295
|
}
|
285
296
|
/**
|
@@ -287,12 +298,11 @@ class QBittorrent {
|
|
287
298
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#remove-torrent-tags}
|
288
299
|
*/
|
289
300
|
async removeTorrentTags(hashes, tags) {
|
290
|
-
const form =
|
291
|
-
form.append('hashes', this._normalizeHashes(hashes));
|
301
|
+
const form = { hashes: this._normalizeHashes(hashes) };
|
292
302
|
if (tags) {
|
293
|
-
form.
|
303
|
+
form.tags = tags;
|
294
304
|
}
|
295
|
-
await this.request('/torrents/removeTags', 'POST', undefined, form, undefined, false);
|
305
|
+
await this.request('/torrents/removeTags', 'POST', undefined, undefined, form, undefined, false);
|
296
306
|
return true;
|
297
307
|
}
|
298
308
|
/**
|
@@ -305,10 +315,10 @@ class QBittorrent {
|
|
305
315
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-torrent-category}
|
306
316
|
*/
|
307
317
|
async setTorrentCategory(hashes, category = '') {
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
318
|
+
await this.request('/torrents/setCategory', 'POST', undefined, undefined, {
|
319
|
+
hashes: this._normalizeHashes(hashes),
|
320
|
+
category,
|
321
|
+
});
|
312
322
|
return true;
|
313
323
|
}
|
314
324
|
/**
|
@@ -363,26 +373,25 @@ class QBittorrent {
|
|
363
373
|
return true;
|
364
374
|
}
|
365
375
|
async addTorrent(torrent, options = {}) {
|
366
|
-
var _a;
|
367
|
-
const form = new
|
368
|
-
const fileOptions = {
|
369
|
-
contentType: 'application/x-bittorrent',
|
370
|
-
filename: (_a = options.filename) !== null && _a !== void 0 ? _a : 'torrent',
|
371
|
-
};
|
376
|
+
var _a, _b;
|
377
|
+
const form = new FormData();
|
372
378
|
// remove options.filename, not used in form
|
373
379
|
if (options.filename) {
|
374
380
|
delete options.filename;
|
375
381
|
}
|
382
|
+
const type = { type: 'application/x-bittorrent' };
|
376
383
|
if (typeof torrent === 'string') {
|
377
|
-
if (
|
378
|
-
|
384
|
+
if (existsSync(torrent)) {
|
385
|
+
const file = await fileFromPath(torrent, (_a = options.filename) !== null && _a !== void 0 ? _a : 'torrent', type);
|
386
|
+
form.set('file', file);
|
379
387
|
}
|
380
388
|
else {
|
381
|
-
form.
|
389
|
+
form.set('file', new File([Buffer.from(torrent, 'base64')], 'file.torrent', type));
|
382
390
|
}
|
383
391
|
}
|
384
392
|
else {
|
385
|
-
|
393
|
+
const file = new File([torrent], (_b = options.filename) !== null && _b !== void 0 ? _b : 'torrent', type);
|
394
|
+
form.set('file', file);
|
386
395
|
}
|
387
396
|
if (options) {
|
388
397
|
// disable savepath when autoTMM is defined
|
@@ -396,7 +405,7 @@ class QBittorrent {
|
|
396
405
|
form.append(key, value);
|
397
406
|
}
|
398
407
|
}
|
399
|
-
const res = await this.request('/torrents/add', 'POST', undefined, form,
|
408
|
+
const res = await this.request('/torrents/add', 'POST', undefined, form, undefined, undefined, false);
|
400
409
|
if (res.body === 'Fails.') {
|
401
410
|
throw new Error('Failed to add torrent');
|
402
411
|
}
|
@@ -410,11 +419,21 @@ class QBittorrent {
|
|
410
419
|
if (options.label) {
|
411
420
|
torrentOptions.category = options.label;
|
412
421
|
}
|
413
|
-
|
414
|
-
|
422
|
+
let torrentHash;
|
423
|
+
if (typeof torrent === 'string' && torrent.startsWith('magnet:')) {
|
424
|
+
torrentHash = magnetDecode(torrent).infoHash;
|
425
|
+
if (!torrentHash) {
|
426
|
+
throw new Error('Magnet did not contain hash');
|
427
|
+
}
|
428
|
+
await this.addMagnet(torrent, torrentOptions);
|
429
|
+
}
|
430
|
+
else {
|
431
|
+
if (!Buffer.isBuffer(torrent)) {
|
432
|
+
torrent = Buffer.from(torrent);
|
433
|
+
}
|
434
|
+
torrentHash = await hash(torrent);
|
435
|
+
await this.addTorrent(torrent, torrentOptions);
|
415
436
|
}
|
416
|
-
const torrentHash = await (0, torrent_file_1.hash)(torrent);
|
417
|
-
await this.addTorrent(torrent, torrentOptions);
|
418
437
|
return this.getTorrent(torrentHash);
|
419
438
|
}
|
420
439
|
/**
|
@@ -423,11 +442,11 @@ class QBittorrent {
|
|
423
442
|
* @param name new name to be assigned to the file
|
424
443
|
*/
|
425
444
|
async renameFile(hash, id, name) {
|
426
|
-
const form = new
|
445
|
+
const form = new FormData();
|
427
446
|
form.append('hash', hash);
|
428
447
|
form.append('id', id);
|
429
448
|
form.append('name', name);
|
430
|
-
await this.request('/torrents/renameFile', 'POST', undefined, form,
|
449
|
+
await this.request('/torrents/renameFile', 'POST', undefined, form, undefined, false);
|
431
450
|
return true;
|
432
451
|
}
|
433
452
|
/**
|
@@ -435,7 +454,7 @@ class QBittorrent {
|
|
435
454
|
* @param options
|
436
455
|
*/
|
437
456
|
async addMagnet(urls, options = {}) {
|
438
|
-
const form = new
|
457
|
+
const form = new FormData();
|
439
458
|
form.append('urls', urls);
|
440
459
|
if (options) {
|
441
460
|
// disable savepath when autoTMM is defined
|
@@ -449,7 +468,7 @@ class QBittorrent {
|
|
449
468
|
form.append(key, value);
|
450
469
|
}
|
451
470
|
}
|
452
|
-
const res = await this.request('/torrents/add', 'POST', undefined, form,
|
471
|
+
const res = await this.request('/torrents/add', 'POST', undefined, form, undefined, undefined, false);
|
453
472
|
if (res.body === 'Fails.') {
|
454
473
|
throw new Error('Failed to add torrent');
|
455
474
|
}
|
@@ -523,23 +542,25 @@ class QBittorrent {
|
|
523
542
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#login}
|
524
543
|
*/
|
525
544
|
async login() {
|
526
|
-
|
527
|
-
const
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
545
|
+
var _a, _b;
|
546
|
+
const url = urlJoin(this.config.baseUrl, this.config.path, '/auth/login');
|
547
|
+
const res = await got({
|
548
|
+
url,
|
549
|
+
method: 'POST',
|
550
|
+
form: {
|
551
|
+
username: (_a = this.config.username) !== null && _a !== void 0 ? _a : '',
|
552
|
+
password: (_b = this.config.password) !== null && _b !== void 0 ? _b : '',
|
553
|
+
},
|
533
554
|
followRedirect: false,
|
534
|
-
retry: 0,
|
555
|
+
retry: { limit: 0 },
|
556
|
+
timeout: { request: this.config.timeout },
|
535
557
|
// allow proxy agent
|
536
|
-
agent: this.config.agent,
|
537
|
-
timeout: this.config.timeout,
|
558
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
538
559
|
});
|
539
560
|
if (!res.headers['set-cookie'] || !res.headers['set-cookie'].length) {
|
540
561
|
throw new Error('Cookie not found. Auth Failed.');
|
541
562
|
}
|
542
|
-
const cookie =
|
563
|
+
const cookie = Cookie.parse(res.headers['set-cookie'][0]);
|
543
564
|
if (!cookie || cookie.key !== 'SID') {
|
544
565
|
throw new Error('Invalid cookie');
|
545
566
|
}
|
@@ -553,7 +574,7 @@ class QBittorrent {
|
|
553
574
|
return true;
|
554
575
|
}
|
555
576
|
// eslint-disable-next-line max-params
|
556
|
-
async request(path, method, params = {}, body, headers = {}, json = true) {
|
577
|
+
async request(path, method, params = {}, body, form, headers = {}, json = true) {
|
557
578
|
var _a;
|
558
579
|
if (!this._sid || !this._exp || this._exp.getTime() < new Date().getTime()) {
|
559
580
|
const authed = await this.login();
|
@@ -561,8 +582,8 @@ class QBittorrent {
|
|
561
582
|
throw new Error('Auth Failed');
|
562
583
|
}
|
563
584
|
}
|
564
|
-
const url =
|
565
|
-
const res = await (
|
585
|
+
const url = urlJoin(this.config.baseUrl, this.config.path, path);
|
586
|
+
const res = await got(url, {
|
566
587
|
isStream: false,
|
567
588
|
resolveBodyOnly: false,
|
568
589
|
method,
|
@@ -570,13 +591,14 @@ class QBittorrent {
|
|
570
591
|
Cookie: `SID=${(_a = this._sid) !== null && _a !== void 0 ? _a : ''}`,
|
571
592
|
...headers,
|
572
593
|
},
|
573
|
-
retry: 0,
|
594
|
+
retry: { limit: 0 },
|
574
595
|
body,
|
575
|
-
|
596
|
+
form,
|
597
|
+
searchParams: new URLSearchParams(params),
|
576
598
|
// allow proxy agent
|
577
|
-
|
578
|
-
timeout: this.config.timeout,
|
599
|
+
timeout: { request: this.config.timeout },
|
579
600
|
responseType: json ? 'json' : 'text',
|
601
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
580
602
|
});
|
581
603
|
return res;
|
582
604
|
}
|
@@ -591,40 +613,40 @@ class QBittorrent {
|
|
591
613
|
return hashes;
|
592
614
|
}
|
593
615
|
_normalizeTorrentData(torrent) {
|
594
|
-
let state =
|
616
|
+
let state = NormalizedTorrentState.unknown;
|
595
617
|
switch (torrent.state) {
|
596
|
-
case
|
597
|
-
case
|
598
|
-
state =
|
618
|
+
case TorrentState.ForcedDL:
|
619
|
+
case TorrentState.MetaDL:
|
620
|
+
state = NormalizedTorrentState.downloading;
|
599
621
|
break;
|
600
|
-
case
|
622
|
+
case TorrentState.Allocating:
|
601
623
|
// state = 'stalledDL';
|
602
|
-
state =
|
624
|
+
state = NormalizedTorrentState.queued;
|
603
625
|
break;
|
604
|
-
case
|
605
|
-
state =
|
626
|
+
case TorrentState.ForcedUP:
|
627
|
+
state = NormalizedTorrentState.seeding;
|
606
628
|
break;
|
607
|
-
case
|
608
|
-
state =
|
629
|
+
case TorrentState.PausedDL:
|
630
|
+
state = NormalizedTorrentState.paused;
|
609
631
|
break;
|
610
|
-
case
|
632
|
+
case TorrentState.PausedUP:
|
611
633
|
// state = 'completed';
|
612
|
-
state =
|
634
|
+
state = NormalizedTorrentState.paused;
|
613
635
|
break;
|
614
|
-
case
|
615
|
-
case
|
616
|
-
state =
|
636
|
+
case TorrentState.QueuedDL:
|
637
|
+
case TorrentState.QueuedUP:
|
638
|
+
state = NormalizedTorrentState.queued;
|
617
639
|
break;
|
618
|
-
case
|
619
|
-
case
|
620
|
-
case
|
621
|
-
case
|
622
|
-
case
|
623
|
-
state =
|
640
|
+
case TorrentState.CheckingDL:
|
641
|
+
case TorrentState.CheckingUP:
|
642
|
+
case TorrentState.QueuedForChecking:
|
643
|
+
case TorrentState.CheckingResumeData:
|
644
|
+
case TorrentState.Moving:
|
645
|
+
state = NormalizedTorrentState.checking;
|
624
646
|
break;
|
625
|
-
case
|
626
|
-
case
|
627
|
-
state =
|
647
|
+
case TorrentState.Unknown:
|
648
|
+
case TorrentState.MissingFiles:
|
649
|
+
state = NormalizedTorrentState.error;
|
628
650
|
break;
|
629
651
|
default:
|
630
652
|
break;
|
@@ -658,4 +680,3 @@ class QBittorrent {
|
|
658
680
|
return result;
|
659
681
|
}
|
660
682
|
}
|
661
|
-
exports.QBittorrent = QBittorrent;
|
@@ -1,13 +1,3 @@
|
|
1
|
-
import { AllClientData, NormalizedTorrent } from '@ctrl/shared-torrent';
|
2
|
-
/**
|
3
|
-
* refine the normalized torrent options for qbittorrent
|
4
|
-
*/
|
5
|
-
export interface NormalizedTorrentQbittorrent extends NormalizedTorrent {
|
6
|
-
id: string;
|
7
|
-
}
|
8
|
-
export interface AllClientDataQbittorrent extends AllClientData {
|
9
|
-
torrents: NormalizedTorrentQbittorrent[];
|
10
|
-
}
|
11
1
|
export interface BuildInfo {
|
12
2
|
/**
|
13
3
|
* QT version
|
@@ -176,8 +166,8 @@ export interface Torrent {
|
|
176
166
|
*/
|
177
167
|
category: string;
|
178
168
|
}
|
179
|
-
export declare type
|
180
|
-
|
169
|
+
export declare type TorrentCategories = Record<string, Category>;
|
170
|
+
interface Category {
|
181
171
|
name: string;
|
182
172
|
savePath: string;
|
183
173
|
}
|
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.TorrentPieceState = exports.TorrentFilePriority = exports.TorrentTrackerStatus = exports.TorrentState = void 0;
|
4
|
-
var TorrentState;
|
1
|
+
export var TorrentState;
|
5
2
|
(function (TorrentState) {
|
6
3
|
/**
|
7
4
|
* Some error occurred, applies to paused torrents
|
@@ -80,8 +77,8 @@ var TorrentState;
|
|
80
77
|
* Torrent data files is missing
|
81
78
|
*/
|
82
79
|
TorrentState["MissingFiles"] = "missingFiles";
|
83
|
-
})(TorrentState
|
84
|
-
var TorrentTrackerStatus;
|
80
|
+
})(TorrentState || (TorrentState = {}));
|
81
|
+
export var TorrentTrackerStatus;
|
85
82
|
(function (TorrentTrackerStatus) {
|
86
83
|
/**
|
87
84
|
* Tracker is disabled (used for DHT, PeX, and LSD)
|
@@ -103,8 +100,8 @@ var TorrentTrackerStatus;
|
|
103
100
|
* Tracker has not been contacted yet
|
104
101
|
*/
|
105
102
|
TorrentTrackerStatus[TorrentTrackerStatus["Waiting"] = 4] = "Waiting";
|
106
|
-
})(TorrentTrackerStatus
|
107
|
-
var TorrentFilePriority;
|
103
|
+
})(TorrentTrackerStatus || (TorrentTrackerStatus = {}));
|
104
|
+
export var TorrentFilePriority;
|
108
105
|
(function (TorrentFilePriority) {
|
109
106
|
/**
|
110
107
|
* Do not download
|
@@ -122,8 +119,8 @@ var TorrentFilePriority;
|
|
122
119
|
* Maximal priority
|
123
120
|
*/
|
124
121
|
TorrentFilePriority[TorrentFilePriority["MaxPriority"] = 7] = "MaxPriority";
|
125
|
-
})(TorrentFilePriority
|
126
|
-
var TorrentPieceState;
|
122
|
+
})(TorrentFilePriority || (TorrentFilePriority = {}));
|
123
|
+
export var TorrentPieceState;
|
127
124
|
(function (TorrentPieceState) {
|
128
125
|
/**
|
129
126
|
* Not downloaded yet
|
@@ -137,4 +134,4 @@ var TorrentPieceState;
|
|
137
134
|
* Already downloaded
|
138
135
|
*/
|
139
136
|
TorrentPieceState[TorrentPieceState["Downloaded"] = 2] = "Downloaded";
|
140
|
-
})(TorrentPieceState
|
137
|
+
})(TorrentPieceState || (TorrentPieceState = {}));
|
package/package.json
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ctrl/qbittorrent",
|
3
|
-
"version": "
|
3
|
+
"version": "3.0.0",
|
4
4
|
"description": "TypeScript api wrapper for qbittorrent using got",
|
5
5
|
"author": "Scott Cooper <scttcper@gmail.com>",
|
6
6
|
"license": "MIT",
|
7
7
|
"repository": "scttcper/qbittorrent",
|
8
|
-
"
|
9
|
-
"
|
8
|
+
"homepage": "https://qbittorrent.vercel.app",
|
9
|
+
"type": "module",
|
10
|
+
"main": "./dist/src/index.js",
|
11
|
+
"typings": "./dist/src/index.d.ts",
|
10
12
|
"files": [
|
11
|
-
"dist"
|
13
|
+
"dist/src"
|
12
14
|
],
|
13
15
|
"sideEffects": false,
|
14
16
|
"publishConfig": {
|
@@ -22,49 +24,48 @@
|
|
22
24
|
"lint": "eslint --ext .js,.ts, .",
|
23
25
|
"lint:fix": "eslint --fix --ext .js,.ts, .",
|
24
26
|
"prepare": "npm run build",
|
25
|
-
"build": "tsc
|
27
|
+
"build": "tsc",
|
26
28
|
"build:docs": "typedoc",
|
27
|
-
"test": "
|
28
|
-
"test:watch": "
|
29
|
-
"test:ci": "
|
29
|
+
"test": "ava",
|
30
|
+
"test:watch": "ava --watch",
|
31
|
+
"test:ci": "c8 --reporter=text --reporter=lcov ava"
|
30
32
|
},
|
31
33
|
"dependencies": {
|
32
|
-
"@ctrl/
|
33
|
-
"@ctrl/torrent
|
34
|
-
"@ctrl/
|
35
|
-
"
|
36
|
-
"
|
34
|
+
"@ctrl/magnet-link": "^3.1.0",
|
35
|
+
"@ctrl/shared-torrent": "^4.1.0",
|
36
|
+
"@ctrl/torrent-file": "^2.0.1",
|
37
|
+
"@ctrl/url-join": "^2.0.0",
|
38
|
+
"formdata-node": "^4.3.2",
|
39
|
+
"got": "^12.0.1",
|
37
40
|
"tough-cookie": "^4.0.0"
|
38
41
|
},
|
39
42
|
"devDependencies": {
|
40
|
-
"@
|
41
|
-
"@
|
42
|
-
"@
|
43
|
-
"@jest/globals": "27.3.1",
|
44
|
-
"@types/form-data": "2.5.0",
|
45
|
-
"@types/node": "16.11.6",
|
43
|
+
"@ctrl/eslint-config": "3.3.1",
|
44
|
+
"@sindresorhus/tsconfig": "2.0.0",
|
45
|
+
"@types/node": "17.0.21",
|
46
46
|
"@types/tough-cookie": "4.0.1",
|
47
|
-
"
|
48
|
-
"
|
49
|
-
"p-wait-for": "
|
50
|
-
"
|
51
|
-
"
|
47
|
+
"ava": "4.0.1",
|
48
|
+
"c8": "7.11.0",
|
49
|
+
"p-wait-for": "4.1.0",
|
50
|
+
"ts-node": "10.5.0",
|
51
|
+
"typedoc": "0.22.12",
|
52
|
+
"typescript": "4.5.5"
|
52
53
|
},
|
53
|
-
"
|
54
|
-
"
|
55
|
-
|
56
|
-
"babel": {
|
57
|
-
"presets": [
|
58
|
-
"@babel/preset-typescript"
|
54
|
+
"ava": {
|
55
|
+
"files": [
|
56
|
+
"test/**/*.spec.ts"
|
59
57
|
],
|
60
|
-
"
|
61
|
-
"
|
58
|
+
"extensions": {
|
59
|
+
"ts": "module"
|
60
|
+
},
|
61
|
+
"nodeArguments": [
|
62
|
+
"--loader=ts-node/esm"
|
62
63
|
]
|
63
64
|
},
|
64
65
|
"release": {
|
65
66
|
"branch": "master"
|
66
67
|
},
|
67
68
|
"engines": {
|
68
|
-
"node": ">=
|
69
|
+
"node": ">=14.16"
|
69
70
|
}
|
70
71
|
}
|