@ctrl/qbittorrent 4.0.1 → 5.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/README.md +1 -1
- package/dist/src/qbittorrent.d.ts +7 -3
- package/dist/src/qbittorrent.js +51 -20
- package/dist/src/types.d.ts +12 -8
- package/dist/src/types.js +12 -8
- package/package.json +15 -14
package/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# qBittorrent [](https://www.npmjs.com/package/@ctrl/qbittorrent) [](https://circleci.com/gh/scttcper/qbittorrent) [](https://codecov.io/gh/scttcper/qbittorrent)
|
1
|
+
# qBittorrent [](https://www.npmjs.com/package/@ctrl/qbittorrent) [](https://circleci.com/gh/scttcper/qbittorrent) [](https://codecov.io/gh/scttcper/qbittorrent)
|
2
2
|
|
3
3
|
> TypeScript api wrapper for [qBittorrent](https://www.qbittorrent.org/) using [got](https://github.com/sindresorhus/got)
|
4
4
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
2
|
-
import { Options as GotOptions, Response } from 'got';
|
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';
|
2
|
+
import type { Options as GotOptions, Response } from 'got';
|
3
|
+
import type { AddTorrentOptions as NormalizedAddTorrentOptions, AllClientData, NormalizedTorrent, TorrentClient, TorrentSettings } from '@ctrl/shared-torrent';
|
4
|
+
import type { 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
|
/**
|
@@ -160,6 +160,10 @@ export declare class QBittorrent implements TorrentClient {
|
|
160
160
|
* @param name new name to be assigned to the file
|
161
161
|
*/
|
162
162
|
renameFile(hash: string, id: number, name: string): Promise<boolean>;
|
163
|
+
/**
|
164
|
+
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#rename-folder}
|
165
|
+
*/
|
166
|
+
renameFolder(hash: string, oldPath: string, newPath: string): Promise<boolean>;
|
163
167
|
/**
|
164
168
|
* @param urls URLs separated with newlines
|
165
169
|
* @param options
|
package/dist/src/qbittorrent.js
CHANGED
@@ -7,10 +7,10 @@ import { fileFromPath } from 'formdata-node/file-from-path';
|
|
7
7
|
import got from 'got';
|
8
8
|
import { Cookie } from 'tough-cookie';
|
9
9
|
import { magnetDecode } from '@ctrl/magnet-link';
|
10
|
-
import { TorrentState as NormalizedTorrentState
|
10
|
+
import { TorrentState as NormalizedTorrentState } from '@ctrl/shared-torrent';
|
11
11
|
import { hash } from '@ctrl/torrent-file';
|
12
12
|
import { urlJoin } from '@ctrl/url-join';
|
13
|
-
import { TorrentState
|
13
|
+
import { TorrentState } from './types.js';
|
14
14
|
const defaults = {
|
15
15
|
baseUrl: 'http://localhost:9091/',
|
16
16
|
path: '/api/v2',
|
@@ -449,6 +449,17 @@ export class QBittorrent {
|
|
449
449
|
await this.request('/torrents/renameFile', 'POST', undefined, form, undefined, false);
|
450
450
|
return true;
|
451
451
|
}
|
452
|
+
/**
|
453
|
+
* {@link https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)#rename-folder}
|
454
|
+
*/
|
455
|
+
async renameFolder(hash, oldPath, newPath) {
|
456
|
+
const form = new FormData();
|
457
|
+
form.append('hash', hash);
|
458
|
+
form.append('oldPath', oldPath);
|
459
|
+
form.append('newPath', newPath);
|
460
|
+
await this.request('/torrents/renameFolder', 'POST', undefined, form, undefined, false);
|
461
|
+
return true;
|
462
|
+
}
|
452
463
|
/**
|
453
464
|
* @param urls URLs separated with newlines
|
454
465
|
* @param options
|
@@ -612,39 +623,59 @@ export class QBittorrent {
|
|
612
623
|
}
|
613
624
|
_normalizeTorrentData(torrent) {
|
614
625
|
let state = NormalizedTorrentState.unknown;
|
626
|
+
let stateMessage = '';
|
627
|
+
let { eta } = torrent;
|
628
|
+
/**
|
629
|
+
* Good references https://github.com/qbittorrent/qBittorrent/blob/master/src/webui/www/private/scripts/dynamicTable.js#L933
|
630
|
+
* https://github.com/Radarr/Radarr/blob/develop/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs#L242
|
631
|
+
*/
|
615
632
|
switch (torrent.state) {
|
616
|
-
case TorrentState.
|
617
|
-
|
633
|
+
case TorrentState.Error:
|
634
|
+
state = NormalizedTorrentState.warning;
|
635
|
+
stateMessage = 'qBittorrent is reporting an error';
|
636
|
+
break;
|
637
|
+
case TorrentState.PausedDL:
|
638
|
+
state = NormalizedTorrentState.paused;
|
639
|
+
break;
|
640
|
+
case TorrentState.QueuedDL: // queuing is enabled and torrent is queued for download
|
641
|
+
case TorrentState.CheckingDL: // same as checkingUP, but torrent has NOT finished downloading
|
642
|
+
case TorrentState.CheckingUP: // torrent has finished downloading and is being checked. Set when `recheck torrent on completion` is enabled. In the event the check fails we shouldn't treat it as completed.
|
643
|
+
state = NormalizedTorrentState.queued;
|
644
|
+
break;
|
645
|
+
case TorrentState.MetaDL: // Metadl could be an error if DHT is not enabled
|
646
|
+
case TorrentState.ForcedDL: // torrent is being downloaded, and was forced started
|
647
|
+
case TorrentState.ForcedMetaDL: // torrent metadata is being forcibly downloaded
|
648
|
+
case TorrentState.Downloading: // torrent is being downloaded and data is being transferred
|
618
649
|
state = NormalizedTorrentState.downloading;
|
619
650
|
break;
|
620
651
|
case TorrentState.Allocating:
|
621
652
|
// state = 'stalledDL';
|
622
653
|
state = NormalizedTorrentState.queued;
|
623
654
|
break;
|
624
|
-
case TorrentState.
|
625
|
-
state = NormalizedTorrentState.
|
626
|
-
|
627
|
-
case TorrentState.PausedDL:
|
628
|
-
state = NormalizedTorrentState.paused;
|
655
|
+
case TorrentState.StalledDL:
|
656
|
+
state = NormalizedTorrentState.warning;
|
657
|
+
stateMessage = 'The download is stalled with no connection';
|
629
658
|
break;
|
630
|
-
case TorrentState.PausedUP:
|
659
|
+
case TorrentState.PausedUP: // torrent is paused and has finished downloading:
|
660
|
+
case TorrentState.Uploading: // torrent is being seeded and data is being transferred
|
661
|
+
case TorrentState.StalledUP: // torrent is being seeded, but no connection were made
|
662
|
+
case TorrentState.QueuedUP: // queuing is enabled and torrent is queued for upload
|
663
|
+
case TorrentState.ForcedUP: // torrent has finished downloading and is being forcibly seeded
|
631
664
|
// state = 'completed';
|
632
|
-
state = NormalizedTorrentState.
|
633
|
-
|
634
|
-
case TorrentState.QueuedDL:
|
635
|
-
case TorrentState.QueuedUP:
|
636
|
-
state = NormalizedTorrentState.queued;
|
665
|
+
state = NormalizedTorrentState.seeding;
|
666
|
+
eta = 0; // qBittorrent sends eta=8640000 for completed torrents
|
637
667
|
break;
|
638
|
-
case TorrentState.
|
639
|
-
case TorrentState.CheckingUP:
|
668
|
+
case TorrentState.Moving: // torrent is being moved from a folder
|
640
669
|
case TorrentState.QueuedForChecking:
|
641
670
|
case TorrentState.CheckingResumeData:
|
642
|
-
case TorrentState.Moving:
|
643
671
|
state = NormalizedTorrentState.checking;
|
644
672
|
break;
|
645
673
|
case TorrentState.Unknown:
|
674
|
+
state = NormalizedTorrentState.error;
|
675
|
+
break;
|
646
676
|
case TorrentState.MissingFiles:
|
647
677
|
state = NormalizedTorrentState.error;
|
678
|
+
stateMessage = 'The download is missing files';
|
648
679
|
break;
|
649
680
|
default:
|
650
681
|
break;
|
@@ -653,8 +684,9 @@ export class QBittorrent {
|
|
653
684
|
const result = {
|
654
685
|
id: torrent.hash,
|
655
686
|
name: torrent.name,
|
656
|
-
stateMessage
|
687
|
+
stateMessage,
|
657
688
|
state,
|
689
|
+
eta,
|
658
690
|
dateAdded: new Date(torrent.added_on * 1000).toISOString(),
|
659
691
|
isCompleted,
|
660
692
|
progress: torrent.progress,
|
@@ -663,7 +695,6 @@ export class QBittorrent {
|
|
663
695
|
savePath: torrent.save_path,
|
664
696
|
uploadSpeed: torrent.upspeed,
|
665
697
|
downloadSpeed: torrent.dlspeed,
|
666
|
-
eta: torrent.eta,
|
667
698
|
queuePosition: torrent.priority,
|
668
699
|
connectedPeers: torrent.num_leechs,
|
669
700
|
connectedSeeds: torrent.num_seeds,
|
package/dist/src/types.d.ts
CHANGED
@@ -220,6 +220,10 @@ export declare enum TorrentState {
|
|
220
220
|
* Torrent is forced to downloading to ignore queue limit
|
221
221
|
*/
|
222
222
|
ForcedDL = "forcedDL",
|
223
|
+
/**
|
224
|
+
* Forced Downloading Metadata
|
225
|
+
*/
|
226
|
+
ForcedMetaDL = "ForcedMetaDL",
|
223
227
|
/**
|
224
228
|
* Torrent is forced to uploading and ignore queue limit
|
225
229
|
*/
|
@@ -424,21 +428,21 @@ export declare enum TorrentTrackerStatus {
|
|
424
428
|
*/
|
425
429
|
Disabled = 0,
|
426
430
|
/**
|
427
|
-
* Tracker has been contacted
|
431
|
+
* Tracker has not been contacted yet
|
428
432
|
*/
|
429
|
-
|
433
|
+
Waiting = 1,
|
430
434
|
/**
|
431
|
-
* Tracker
|
435
|
+
* Tracker has been contacted and is working
|
432
436
|
*/
|
433
|
-
|
437
|
+
Working = 2,
|
434
438
|
/**
|
435
|
-
* Tracker
|
439
|
+
* Tracker is updating
|
436
440
|
*/
|
437
|
-
|
441
|
+
Updating = 3,
|
438
442
|
/**
|
439
|
-
* Tracker has
|
443
|
+
* Tracker has been contacted, but it is not working (or doesn't send proper replies)
|
440
444
|
*/
|
441
|
-
|
445
|
+
Errored = 4
|
442
446
|
}
|
443
447
|
export interface WebSeed {
|
444
448
|
/**
|
package/dist/src/types.js
CHANGED
@@ -48,6 +48,10 @@ export var TorrentState;
|
|
48
48
|
* Torrent is forced to downloading to ignore queue limit
|
49
49
|
*/
|
50
50
|
TorrentState["ForcedDL"] = "forcedDL";
|
51
|
+
/**
|
52
|
+
* Forced Downloading Metadata
|
53
|
+
*/
|
54
|
+
TorrentState["ForcedMetaDL"] = "ForcedMetaDL";
|
51
55
|
/**
|
52
56
|
* Torrent is forced to uploading and ignore queue limit
|
53
57
|
*/
|
@@ -85,21 +89,21 @@ export var TorrentTrackerStatus;
|
|
85
89
|
*/
|
86
90
|
TorrentTrackerStatus[TorrentTrackerStatus["Disabled"] = 0] = "Disabled";
|
87
91
|
/**
|
88
|
-
* Tracker has been contacted
|
92
|
+
* Tracker has not been contacted yet
|
89
93
|
*/
|
90
|
-
TorrentTrackerStatus[TorrentTrackerStatus["
|
94
|
+
TorrentTrackerStatus[TorrentTrackerStatus["Waiting"] = 1] = "Waiting";
|
91
95
|
/**
|
92
|
-
* Tracker
|
96
|
+
* Tracker has been contacted and is working
|
93
97
|
*/
|
94
|
-
TorrentTrackerStatus[TorrentTrackerStatus["
|
98
|
+
TorrentTrackerStatus[TorrentTrackerStatus["Working"] = 2] = "Working";
|
95
99
|
/**
|
96
|
-
* Tracker
|
100
|
+
* Tracker is updating
|
97
101
|
*/
|
98
|
-
TorrentTrackerStatus[TorrentTrackerStatus["
|
102
|
+
TorrentTrackerStatus[TorrentTrackerStatus["Updating"] = 3] = "Updating";
|
99
103
|
/**
|
100
|
-
* Tracker has
|
104
|
+
* Tracker has been contacted, but it is not working (or doesn't send proper replies)
|
101
105
|
*/
|
102
|
-
TorrentTrackerStatus[TorrentTrackerStatus["
|
106
|
+
TorrentTrackerStatus[TorrentTrackerStatus["Errored"] = 4] = "Errored";
|
103
107
|
})(TorrentTrackerStatus = TorrentTrackerStatus || (TorrentTrackerStatus = {}));
|
104
108
|
export var TorrentFilePriority;
|
105
109
|
(function (TorrentFilePriority) {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ctrl/qbittorrent",
|
3
|
-
"version": "
|
3
|
+
"version": "5.0.0",
|
4
4
|
"description": "TypeScript api wrapper for qbittorrent using got",
|
5
5
|
"author": "Scott Cooper <scttcper@gmail.com>",
|
6
6
|
"license": "MIT",
|
@@ -32,23 +32,24 @@
|
|
32
32
|
},
|
33
33
|
"dependencies": {
|
34
34
|
"@ctrl/magnet-link": "^3.1.1",
|
35
|
-
"@ctrl/shared-torrent": "^4.
|
36
|
-
"@ctrl/torrent-file": "^2.0.
|
37
|
-
"@ctrl/url-join": "^2.0.
|
38
|
-
"formdata-node": "^
|
39
|
-
"got": "^12.1
|
40
|
-
"tough-cookie": "^4.
|
35
|
+
"@ctrl/shared-torrent": "^4.2.0",
|
36
|
+
"@ctrl/torrent-file": "^2.0.2",
|
37
|
+
"@ctrl/url-join": "^2.0.2",
|
38
|
+
"formdata-node": "^5.0.0",
|
39
|
+
"got": "^12.3.1",
|
40
|
+
"tough-cookie": "^4.1.2"
|
41
41
|
},
|
42
42
|
"devDependencies": {
|
43
|
-
"@ctrl/eslint-config": "3.4.
|
43
|
+
"@ctrl/eslint-config": "3.4.10",
|
44
44
|
"@sindresorhus/tsconfig": "3.0.1",
|
45
|
-
"@types/node": "
|
45
|
+
"@types/node": "18.7.14",
|
46
46
|
"@types/tough-cookie": "4.0.2",
|
47
|
-
"c8": "
|
48
|
-
"
|
49
|
-
"
|
50
|
-
"
|
51
|
-
"
|
47
|
+
"@vitest/coverage-c8": "0.22.1",
|
48
|
+
"c8": "7.12.0",
|
49
|
+
"p-wait-for": "5.0.0",
|
50
|
+
"typedoc": "0.23.11",
|
51
|
+
"typescript": "4.8.2",
|
52
|
+
"vitest": "0.22.1"
|
52
53
|
},
|
53
54
|
"release": {
|
54
55
|
"branches": [
|