@ctrl/qbittorrent 2.8.2 → 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 -8
- package/dist/{index.js → src/qbittorrent.js} +153 -123
- package/dist/{types.d.ts → src/types.d.ts} +2 -12
- package/dist/{types.js → src/types.js} +8 -11
- package/package.json +35 -34
@@ -1,7 +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,
|
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';
|
5
5
|
export declare class QBittorrent implements TorrentClient {
|
6
6
|
config: TorrentSettings;
|
7
7
|
/**
|
@@ -27,7 +27,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
27
27
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-build-info}
|
28
28
|
*/
|
29
29
|
getBuildInfo(): Promise<BuildInfo>;
|
30
|
-
getTorrent(hash: string): Promise<
|
30
|
+
getTorrent(hash: string): Promise<NormalizedTorrent>;
|
31
31
|
/**
|
32
32
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-application-preferences}
|
33
33
|
*/
|
@@ -43,8 +43,16 @@ export declare class QBittorrent implements TorrentClient {
|
|
43
43
|
* @param category Get torrents with the given category (empty string means "without category"; no "category" parameter means "any category")
|
44
44
|
* @returns list of torrents
|
45
45
|
*/
|
46
|
-
listTorrents(hashes
|
47
|
-
|
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>;
|
48
56
|
/**
|
49
57
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-torrent-generic-properties}
|
50
58
|
*/
|
@@ -94,7 +102,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
94
102
|
/**
|
95
103
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-all-categories}
|
96
104
|
*/
|
97
|
-
getCategories(): Promise<
|
105
|
+
getCategories(): Promise<TorrentCategories>;
|
98
106
|
/**
|
99
107
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#add-new-category}
|
100
108
|
*/
|
@@ -145,7 +153,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
145
153
|
*/
|
146
154
|
reannounceTorrent(hashes: string | string[] | 'all'): Promise<boolean>;
|
147
155
|
addTorrent(torrent: string | Buffer, options?: Partial<AddTorrentOptions>): Promise<boolean>;
|
148
|
-
normalizedAddTorrent(torrent: string | Buffer, options?: Partial<NormalizedAddTorrentOptions>): Promise<
|
156
|
+
normalizedAddTorrent(torrent: string | Buffer, options?: Partial<NormalizedAddTorrentOptions>): Promise<NormalizedTorrent>;
|
149
157
|
/**
|
150
158
|
* @param hash Hash for desired torrent
|
151
159
|
* @param id id of the file to be renamed
|
@@ -190,7 +198,7 @@ export declare class QBittorrent implements TorrentClient {
|
|
190
198
|
*/
|
191
199
|
login(): Promise<boolean>;
|
192
200
|
logout(): boolean;
|
193
|
-
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>>;
|
194
202
|
/**
|
195
203
|
* Normalizes hashes
|
196
204
|
* @returns hashes as string seperated by `|`
|
@@ -1,19 +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 = void 0;
|
7
1
|
/* eslint-disable @typescript-eslint/ban-types */
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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';
|
17
13
|
const defaults = {
|
18
14
|
baseUrl: 'http://localhost:9091/',
|
19
15
|
path: '/api/v2',
|
@@ -21,8 +17,32 @@ const defaults = {
|
|
21
17
|
password: '',
|
22
18
|
timeout: 5000,
|
23
19
|
};
|
24
|
-
class QBittorrent {
|
20
|
+
export class QBittorrent {
|
25
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
|
+
});
|
26
46
|
this.config = { ...defaults, ...options };
|
27
47
|
}
|
28
48
|
/**
|
@@ -36,11 +56,11 @@ class QBittorrent {
|
|
36
56
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#get-application-version}
|
37
57
|
*/
|
38
58
|
async getAppVersion() {
|
39
|
-
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);
|
40
60
|
return res.body;
|
41
61
|
}
|
42
62
|
async getApiVersion() {
|
43
|
-
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);
|
44
64
|
return res.body;
|
45
65
|
}
|
46
66
|
/**
|
@@ -51,7 +71,7 @@ class QBittorrent {
|
|
51
71
|
return res.body;
|
52
72
|
}
|
53
73
|
async getTorrent(hash) {
|
54
|
-
const torrentsResponse = await this.listTorrents(hash);
|
74
|
+
const torrentsResponse = await this.listTorrents({ hashes: hash });
|
55
75
|
const torrentData = torrentsResponse[0];
|
56
76
|
if (!torrentData) {
|
57
77
|
throw new Error('Torrent not found');
|
@@ -69,9 +89,9 @@ class QBittorrent {
|
|
69
89
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-application-preferences}
|
70
90
|
*/
|
71
91
|
async setPreferences(preferences) {
|
72
|
-
|
73
|
-
|
74
|
-
|
92
|
+
await this.request('/app/setPreferences', 'POST', undefined, undefined, {
|
93
|
+
json: JSON.stringify(preferences),
|
94
|
+
});
|
75
95
|
return true;
|
76
96
|
}
|
77
97
|
/**
|
@@ -81,8 +101,7 @@ class QBittorrent {
|
|
81
101
|
* @param category Get torrents with the given category (empty string means "without category"; no "category" parameter means "any category")
|
82
102
|
* @returns list of torrents
|
83
103
|
*/
|
84
|
-
|
85
|
-
async listTorrents(hashes, filter, category, sort, offset, reverse) {
|
104
|
+
async listTorrents({ hashes, filter, category, sort, offset, reverse, tag, } = {}) {
|
86
105
|
const params = {};
|
87
106
|
if (hashes) {
|
88
107
|
params.hashes = this._normalizeHashes(hashes);
|
@@ -93,6 +112,9 @@ class QBittorrent {
|
|
93
112
|
if (category) {
|
94
113
|
params.category = category;
|
95
114
|
}
|
115
|
+
if (tag) {
|
116
|
+
params.tag = tag;
|
117
|
+
}
|
96
118
|
if (offset !== undefined) {
|
97
119
|
params.offset = `${offset}`;
|
98
120
|
}
|
@@ -184,20 +206,20 @@ class QBittorrent {
|
|
184
206
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-torrent-location}
|
185
207
|
*/
|
186
208
|
async setTorrentLocation(hashes, location) {
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
209
|
+
await this.request('/torrents/setLocation', 'POST', undefined, undefined, {
|
210
|
+
location,
|
211
|
+
hashes: this._normalizeHashes(hashes),
|
212
|
+
});
|
191
213
|
return true;
|
192
214
|
}
|
193
215
|
/**
|
194
216
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-torrent-name}
|
195
217
|
*/
|
196
218
|
async setTorrentName(hash, name) {
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
219
|
+
await this.request('/torrents/rename', 'POST', undefined, undefined, {
|
220
|
+
hash,
|
221
|
+
name,
|
222
|
+
});
|
201
223
|
return true;
|
202
224
|
}
|
203
225
|
/**
|
@@ -212,9 +234,9 @@ class QBittorrent {
|
|
212
234
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#create-tags}
|
213
235
|
*/
|
214
236
|
async createTags(tags) {
|
215
|
-
|
216
|
-
|
217
|
-
|
237
|
+
await this.request('/torrents/createTags', 'POST', undefined, undefined, {
|
238
|
+
tags,
|
239
|
+
}, undefined, false);
|
218
240
|
return true;
|
219
241
|
}
|
220
242
|
/**
|
@@ -222,9 +244,7 @@ class QBittorrent {
|
|
222
244
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#delete-tags}
|
223
245
|
*/
|
224
246
|
async deleteTags(tags) {
|
225
|
-
|
226
|
-
form.append('tags', tags);
|
227
|
-
await this.request('/torrents/deleteTags', 'POST', undefined, form, undefined, false);
|
247
|
+
await this.request('/torrents/deleteTags', 'POST', undefined, undefined, { tags }, undefined, false);
|
228
248
|
return true;
|
229
249
|
}
|
230
250
|
/**
|
@@ -238,39 +258,39 @@ class QBittorrent {
|
|
238
258
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#add-new-category}
|
239
259
|
*/
|
240
260
|
async createCategory(category, savePath = '') {
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
261
|
+
await this.request('/torrents/createCategory', 'POST', undefined, undefined, {
|
262
|
+
category,
|
263
|
+
savePath,
|
264
|
+
}, undefined, false);
|
245
265
|
return true;
|
246
266
|
}
|
247
267
|
/**
|
248
268
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#edit-category}
|
249
269
|
*/
|
250
270
|
async editCategory(category, savePath = '') {
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
271
|
+
await this.request('/torrents/editCategory', 'POST', undefined, undefined, {
|
272
|
+
category,
|
273
|
+
savePath,
|
274
|
+
}, undefined, false);
|
255
275
|
return true;
|
256
276
|
}
|
257
277
|
/**
|
258
278
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#remove-categories}
|
259
279
|
*/
|
260
280
|
async removeCategory(categories) {
|
261
|
-
|
262
|
-
|
263
|
-
|
281
|
+
await this.request('/torrents/removeCategories', 'POST', undefined, undefined, {
|
282
|
+
categories,
|
283
|
+
}, undefined, false);
|
264
284
|
return true;
|
265
285
|
}
|
266
286
|
/**
|
267
287
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#add-torrent-tags}
|
268
288
|
*/
|
269
289
|
async addTorrentTags(hashes, tags) {
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
290
|
+
await this.request('/torrents/addTags', 'POST', undefined, undefined, {
|
291
|
+
hashes: this._normalizeHashes(hashes),
|
292
|
+
tags,
|
293
|
+
}, undefined, false);
|
274
294
|
return true;
|
275
295
|
}
|
276
296
|
/**
|
@@ -278,12 +298,11 @@ class QBittorrent {
|
|
278
298
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#remove-torrent-tags}
|
279
299
|
*/
|
280
300
|
async removeTorrentTags(hashes, tags) {
|
281
|
-
const form =
|
282
|
-
form.append('hashes', this._normalizeHashes(hashes));
|
301
|
+
const form = { hashes: this._normalizeHashes(hashes) };
|
283
302
|
if (tags) {
|
284
|
-
form.
|
303
|
+
form.tags = tags;
|
285
304
|
}
|
286
|
-
await this.request('/torrents/removeTags', 'POST', undefined, form, undefined, false);
|
305
|
+
await this.request('/torrents/removeTags', 'POST', undefined, undefined, form, undefined, false);
|
287
306
|
return true;
|
288
307
|
}
|
289
308
|
/**
|
@@ -296,10 +315,10 @@ class QBittorrent {
|
|
296
315
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#set-torrent-category}
|
297
316
|
*/
|
298
317
|
async setTorrentCategory(hashes, category = '') {
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
318
|
+
await this.request('/torrents/setCategory', 'POST', undefined, undefined, {
|
319
|
+
hashes: this._normalizeHashes(hashes),
|
320
|
+
category,
|
321
|
+
});
|
303
322
|
return true;
|
304
323
|
}
|
305
324
|
/**
|
@@ -354,26 +373,25 @@ class QBittorrent {
|
|
354
373
|
return true;
|
355
374
|
}
|
356
375
|
async addTorrent(torrent, options = {}) {
|
357
|
-
var _a;
|
358
|
-
const form = new
|
359
|
-
const fileOptions = {
|
360
|
-
contentType: 'application/x-bittorrent',
|
361
|
-
filename: (_a = options.filename) !== null && _a !== void 0 ? _a : 'torrent',
|
362
|
-
};
|
376
|
+
var _a, _b;
|
377
|
+
const form = new FormData();
|
363
378
|
// remove options.filename, not used in form
|
364
379
|
if (options.filename) {
|
365
380
|
delete options.filename;
|
366
381
|
}
|
382
|
+
const type = { type: 'application/x-bittorrent' };
|
367
383
|
if (typeof torrent === 'string') {
|
368
|
-
if (
|
369
|
-
|
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);
|
370
387
|
}
|
371
388
|
else {
|
372
|
-
form.
|
389
|
+
form.set('file', new File([Buffer.from(torrent, 'base64')], 'file.torrent', type));
|
373
390
|
}
|
374
391
|
}
|
375
392
|
else {
|
376
|
-
|
393
|
+
const file = new File([torrent], (_b = options.filename) !== null && _b !== void 0 ? _b : 'torrent', type);
|
394
|
+
form.set('file', file);
|
377
395
|
}
|
378
396
|
if (options) {
|
379
397
|
// disable savepath when autoTMM is defined
|
@@ -387,7 +405,7 @@ class QBittorrent {
|
|
387
405
|
form.append(key, value);
|
388
406
|
}
|
389
407
|
}
|
390
|
-
const res = await this.request('/torrents/add', 'POST', undefined, form,
|
408
|
+
const res = await this.request('/torrents/add', 'POST', undefined, form, undefined, undefined, false);
|
391
409
|
if (res.body === 'Fails.') {
|
392
410
|
throw new Error('Failed to add torrent');
|
393
411
|
}
|
@@ -401,11 +419,21 @@ class QBittorrent {
|
|
401
419
|
if (options.label) {
|
402
420
|
torrentOptions.category = options.label;
|
403
421
|
}
|
404
|
-
|
405
|
-
|
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);
|
406
436
|
}
|
407
|
-
const torrentHash = await torrent_file_1.hash(torrent);
|
408
|
-
await this.addTorrent(torrent, torrentOptions);
|
409
437
|
return this.getTorrent(torrentHash);
|
410
438
|
}
|
411
439
|
/**
|
@@ -414,11 +442,11 @@ class QBittorrent {
|
|
414
442
|
* @param name new name to be assigned to the file
|
415
443
|
*/
|
416
444
|
async renameFile(hash, id, name) {
|
417
|
-
const form = new
|
445
|
+
const form = new FormData();
|
418
446
|
form.append('hash', hash);
|
419
447
|
form.append('id', id);
|
420
448
|
form.append('name', name);
|
421
|
-
await this.request('/torrents/renameFile', 'POST', undefined, form,
|
449
|
+
await this.request('/torrents/renameFile', 'POST', undefined, form, undefined, false);
|
422
450
|
return true;
|
423
451
|
}
|
424
452
|
/**
|
@@ -426,7 +454,7 @@ class QBittorrent {
|
|
426
454
|
* @param options
|
427
455
|
*/
|
428
456
|
async addMagnet(urls, options = {}) {
|
429
|
-
const form = new
|
457
|
+
const form = new FormData();
|
430
458
|
form.append('urls', urls);
|
431
459
|
if (options) {
|
432
460
|
// disable savepath when autoTMM is defined
|
@@ -440,7 +468,7 @@ class QBittorrent {
|
|
440
468
|
form.append(key, value);
|
441
469
|
}
|
442
470
|
}
|
443
|
-
const res = await this.request('/torrents/add', 'POST', undefined, form,
|
471
|
+
const res = await this.request('/torrents/add', 'POST', undefined, form, undefined, undefined, false);
|
444
472
|
if (res.body === 'Fails.') {
|
445
473
|
throw new Error('Failed to add torrent');
|
446
474
|
}
|
@@ -514,23 +542,25 @@ class QBittorrent {
|
|
514
542
|
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#login}
|
515
543
|
*/
|
516
544
|
async login() {
|
517
|
-
|
518
|
-
const
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
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
|
+
},
|
524
554
|
followRedirect: false,
|
525
|
-
retry: 0,
|
555
|
+
retry: { limit: 0 },
|
556
|
+
timeout: { request: this.config.timeout },
|
526
557
|
// allow proxy agent
|
527
|
-
agent: this.config.agent,
|
528
|
-
timeout: this.config.timeout,
|
558
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
529
559
|
});
|
530
560
|
if (!res.headers['set-cookie'] || !res.headers['set-cookie'].length) {
|
531
561
|
throw new Error('Cookie not found. Auth Failed.');
|
532
562
|
}
|
533
|
-
const cookie =
|
563
|
+
const cookie = Cookie.parse(res.headers['set-cookie'][0]);
|
534
564
|
if (!cookie || cookie.key !== 'SID') {
|
535
565
|
throw new Error('Invalid cookie');
|
536
566
|
}
|
@@ -544,7 +574,7 @@ class QBittorrent {
|
|
544
574
|
return true;
|
545
575
|
}
|
546
576
|
// eslint-disable-next-line max-params
|
547
|
-
async request(path, method, params = {}, body, headers = {}, json = true) {
|
577
|
+
async request(path, method, params = {}, body, form, headers = {}, json = true) {
|
548
578
|
var _a;
|
549
579
|
if (!this._sid || !this._exp || this._exp.getTime() < new Date().getTime()) {
|
550
580
|
const authed = await this.login();
|
@@ -552,8 +582,8 @@ class QBittorrent {
|
|
552
582
|
throw new Error('Auth Failed');
|
553
583
|
}
|
554
584
|
}
|
555
|
-
const url =
|
556
|
-
const res = await
|
585
|
+
const url = urlJoin(this.config.baseUrl, this.config.path, path);
|
586
|
+
const res = await got(url, {
|
557
587
|
isStream: false,
|
558
588
|
resolveBodyOnly: false,
|
559
589
|
method,
|
@@ -561,13 +591,14 @@ class QBittorrent {
|
|
561
591
|
Cookie: `SID=${(_a = this._sid) !== null && _a !== void 0 ? _a : ''}`,
|
562
592
|
...headers,
|
563
593
|
},
|
564
|
-
retry: 0,
|
594
|
+
retry: { limit: 0 },
|
565
595
|
body,
|
566
|
-
|
596
|
+
form,
|
597
|
+
searchParams: new URLSearchParams(params),
|
567
598
|
// allow proxy agent
|
568
|
-
|
569
|
-
timeout: this.config.timeout,
|
599
|
+
timeout: { request: this.config.timeout },
|
570
600
|
responseType: json ? 'json' : 'text',
|
601
|
+
...(this.config.agent ? { agent: this.config.agent } : {}),
|
571
602
|
});
|
572
603
|
return res;
|
573
604
|
}
|
@@ -582,40 +613,40 @@ class QBittorrent {
|
|
582
613
|
return hashes;
|
583
614
|
}
|
584
615
|
_normalizeTorrentData(torrent) {
|
585
|
-
let state =
|
616
|
+
let state = NormalizedTorrentState.unknown;
|
586
617
|
switch (torrent.state) {
|
587
|
-
case
|
588
|
-
case
|
589
|
-
state =
|
618
|
+
case TorrentState.ForcedDL:
|
619
|
+
case TorrentState.MetaDL:
|
620
|
+
state = NormalizedTorrentState.downloading;
|
590
621
|
break;
|
591
|
-
case
|
622
|
+
case TorrentState.Allocating:
|
592
623
|
// state = 'stalledDL';
|
593
|
-
state =
|
624
|
+
state = NormalizedTorrentState.queued;
|
594
625
|
break;
|
595
|
-
case
|
596
|
-
state =
|
626
|
+
case TorrentState.ForcedUP:
|
627
|
+
state = NormalizedTorrentState.seeding;
|
597
628
|
break;
|
598
|
-
case
|
599
|
-
state =
|
629
|
+
case TorrentState.PausedDL:
|
630
|
+
state = NormalizedTorrentState.paused;
|
600
631
|
break;
|
601
|
-
case
|
632
|
+
case TorrentState.PausedUP:
|
602
633
|
// state = 'completed';
|
603
|
-
state =
|
634
|
+
state = NormalizedTorrentState.paused;
|
604
635
|
break;
|
605
|
-
case
|
606
|
-
case
|
607
|
-
state =
|
636
|
+
case TorrentState.QueuedDL:
|
637
|
+
case TorrentState.QueuedUP:
|
638
|
+
state = NormalizedTorrentState.queued;
|
608
639
|
break;
|
609
|
-
case
|
610
|
-
case
|
611
|
-
case
|
612
|
-
case
|
613
|
-
case
|
614
|
-
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;
|
615
646
|
break;
|
616
|
-
case
|
617
|
-
case
|
618
|
-
state =
|
647
|
+
case TorrentState.Unknown:
|
648
|
+
case TorrentState.MissingFiles:
|
649
|
+
state = NormalizedTorrentState.error;
|
619
650
|
break;
|
620
651
|
default:
|
621
652
|
break;
|
@@ -649,4 +680,3 @@ class QBittorrent {
|
|
649
680
|
return result;
|
650
681
|
}
|
651
682
|
}
|
652
|
-
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
|
-
"@
|
44
|
-
"
|
45
|
-
"
|
46
|
-
"
|
47
|
-
"
|
48
|
-
"
|
49
|
-
"
|
50
|
-
"typedoc": "0.21.0-beta.2",
|
51
|
-
"typescript": "4.3.2"
|
43
|
+
"@ctrl/eslint-config": "3.3.1",
|
44
|
+
"@sindresorhus/tsconfig": "2.0.0",
|
45
|
+
"@types/node": "17.0.21",
|
46
|
+
"@types/tough-cookie": "4.0.1",
|
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
|
}
|