cross-seed 5.9.2 → 6.0.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/README.md +7 -1
- package/dist/Result.js +2 -0
- package/dist/Result.js.map +1 -1
- package/dist/action.js +127 -62
- package/dist/action.js.map +1 -1
- package/dist/auth.js +5 -5
- package/dist/auth.js.map +1 -1
- package/dist/clients/Deluge.js +104 -51
- package/dist/clients/Deluge.js.map +1 -1
- package/dist/clients/QBittorrent.js +205 -122
- package/dist/clients/QBittorrent.js.map +1 -1
- package/dist/clients/RTorrent.js +57 -23
- package/dist/clients/RTorrent.js.map +1 -1
- package/dist/clients/TorrentClient.js.map +1 -1
- package/dist/clients/Transmission.js +17 -9
- package/dist/clients/Transmission.js.map +1 -1
- package/dist/cmd.js +89 -77
- package/dist/cmd.js.map +1 -1
- package/dist/config.template.cjs +237 -144
- package/dist/config.template.cjs.map +1 -1
- package/dist/configSchema.js +177 -0
- package/dist/configSchema.js.map +1 -0
- package/dist/configuration.js +35 -9
- package/dist/configuration.js.map +1 -1
- package/dist/constants.js +28 -12
- package/dist/constants.js.map +1 -1
- package/dist/dataFiles.js +17 -8
- package/dist/dataFiles.js.map +1 -1
- package/dist/decide.js +118 -28
- package/dist/decide.js.map +1 -1
- package/dist/diff.js.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/indexers.js +3 -3
- package/dist/indexers.js.map +1 -1
- package/dist/jobs.js +15 -7
- package/dist/jobs.js.map +1 -1
- package/dist/logger.js +9 -9
- package/dist/logger.js.map +1 -1
- package/dist/migrations/00-initialSchema.js.map +1 -1
- package/dist/migrations/02-timestamps.js +3 -1
- package/dist/migrations/02-timestamps.js.map +1 -1
- package/dist/parseTorrent.js +11 -2
- package/dist/parseTorrent.js.map +1 -1
- package/dist/pipeline.js +34 -25
- package/dist/pipeline.js.map +1 -1
- package/dist/preFilter.js +17 -6
- package/dist/preFilter.js.map +1 -1
- package/dist/pushNotifier.js +29 -10
- package/dist/pushNotifier.js.map +1 -1
- package/dist/searchee.js +8 -1
- package/dist/searchee.js.map +1 -1
- package/dist/server.js.map +1 -1
- package/dist/startup.js +62 -23
- package/dist/startup.js.map +1 -1
- package/dist/torrent.js +14 -29
- package/dist/torrent.js.map +1 -1
- package/dist/torznab.js +56 -32
- package/dist/torznab.js.map +1 -1
- package/dist/utils.js +42 -5
- package/dist/utils.js.map +1 -1
- package/package.json +12 -12
- package/dist/config.template.docker.cjs +0 -236
- package/dist/config.template.docker.cjs.map +0 -1
package/README.md
CHANGED
@@ -17,9 +17,15 @@ files to a folder you specify. After that, I recommend using
|
|
17
17
|
[AutoTorrent2](https://github.com/JohnDoee/autotorrent2) to do the last-mile
|
18
18
|
delivery into your client.
|
19
19
|
|
20
|
+
## 🚨🚨🚨 Breaking changes in cross-seed v6 🚨🚨🚨
|
21
|
+
|
22
|
+
Head on over to the
|
23
|
+
[v6 migration guide](https://www.cross-seed.org/docs/v6-migration)
|
24
|
+
to see the steps required for migration.
|
25
|
+
|
20
26
|
## Requirements
|
21
27
|
|
22
|
-
- [Node
|
28
|
+
- [Node >= 20](https://nodejs.org/en/download)
|
23
29
|
- Any number of indexers that support Torznab (use Jackett or Prowlarr to
|
24
30
|
help)
|
25
31
|
|
package/dist/Result.js
CHANGED
package/dist/Result.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Result.js","sourceRoot":"","sources":["../src/Result.ts"],"names":[],"mappings":"AASA,MAAM,QAAQ;
|
1
|
+
{"version":3,"file":"Result.js","sourceRoot":"","sources":["../src/Result.ts"],"names":[],"mappings":"AASA,MAAM,QAAQ;IACI,QAAQ,CAAI;IAE7B,YAAY,QAAW;QACtB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;IAED,IAAI;QACH,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK;QACJ,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAI,MAAmB;QAC3B,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAI,MAAmB;QAC5B,OAAO,IAA+B,CAAC;IACxC,CAAC;IAED,6DAA6D;IAC7D,aAAa,CAAC,UAAkB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,gBAAgB;QACf,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACxD,CAAC;CACD;AAED,MAAM,SAAS;IACG,QAAQ,CAAI;IAE7B,YAAY,QAAW;QACtB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;IAED,IAAI;QACH,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK;QACJ,OAAO,IAAI,CAAC;IACb,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAI,MAAmB;QAC3B,OAAO,IAA+B,CAAC;IACxC,CAAC;IAED,MAAM,CAAI,MAAmB;QAC5B,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,aAAa,CAAC,UAAkB;QAC/B,MAAM,UAAU,IAAI,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACvE,CAAC;IAED,gBAAgB;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;CACD;AAED,MAAM,UAAU,QAAQ,CAAO,KAAQ;IACtC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,WAAW,CAAO,KAAQ;IACzC,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC"}
|
package/dist/action.js
CHANGED
@@ -1,67 +1,147 @@
|
|
1
1
|
import chalk from "chalk";
|
2
|
-
import { existsSync, linkSync, mkdirSync,
|
3
|
-
import { join, resolve
|
2
|
+
import { existsSync, linkSync, mkdirSync, statSync, symlinkSync } from "fs";
|
3
|
+
import { dirname, join, resolve } from "path";
|
4
4
|
import { getClient } from "./clients/TorrentClient.js";
|
5
5
|
import { Action, Decision, InjectionResult, LinkType, SaveResult, } from "./constants.js";
|
6
6
|
import { logger } from "./logger.js";
|
7
|
+
import { resultOf, resultOfErr } from "./Result.js";
|
7
8
|
import { getRuntimeConfig } from "./runtimeConfig.js";
|
9
|
+
import { hasVideo } from "./searchee.js";
|
8
10
|
import { saveTorrentFile } from "./torrent.js";
|
9
11
|
import { getTag } from "./utils.js";
|
10
|
-
|
11
|
-
|
12
|
-
const
|
13
|
-
|
14
|
-
|
12
|
+
function logInjectionResult(result, tracker, name, decision) {
|
13
|
+
const styledName = chalk.green.bold(name);
|
14
|
+
const styledTracker = chalk.bold(tracker);
|
15
|
+
switch (result) {
|
16
|
+
case InjectionResult.SUCCESS:
|
17
|
+
logger.info(`Found ${styledName} on ${styledTracker} by ${decision} - injected`);
|
18
|
+
break;
|
19
|
+
case InjectionResult.ALREADY_EXISTS:
|
20
|
+
logger.info(`Found ${styledName} on ${styledTracker} by ${decision} - exists`);
|
21
|
+
break;
|
22
|
+
case InjectionResult.TORRENT_NOT_COMPLETE:
|
23
|
+
logger.warn(`Found ${styledName} on ${styledTracker} by ${decision} - skipping incomplete torrent`);
|
24
|
+
break;
|
25
|
+
case InjectionResult.FAILURE:
|
26
|
+
default:
|
27
|
+
logger.error(`Found ${styledName} on ${styledTracker} by ${decision} - failed to inject, saving instead`);
|
28
|
+
break;
|
15
29
|
}
|
16
30
|
}
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
31
|
+
/**
|
32
|
+
* @return the root of linked files.
|
33
|
+
*/
|
34
|
+
function linkExactTree(newMeta, destinationDir, sourceRoot) {
|
35
|
+
if (newMeta.files.length === 1) {
|
36
|
+
return fuzzyLinkOneFile(newMeta, destinationDir, sourceRoot);
|
37
|
+
}
|
38
|
+
for (const newFile of newMeta.files) {
|
39
|
+
const srcFilePath = join(dirname(sourceRoot), newFile.path);
|
40
|
+
const destFilePath = join(destinationDir, newFile.path);
|
41
|
+
mkdirSync(dirname(destFilePath), { recursive: true });
|
42
|
+
linkFile(srcFilePath, destFilePath);
|
43
|
+
}
|
44
|
+
return join(destinationDir, newMeta.name);
|
45
|
+
}
|
46
|
+
/**
|
47
|
+
* @return the root of linked file.
|
48
|
+
*/
|
49
|
+
function fuzzyLinkOneFile(newMeta, destinationDir, sourceRoot) {
|
50
|
+
const srcFilePath = sourceRoot;
|
51
|
+
const destFilePath = join(destinationDir, newMeta.files[0].path);
|
52
|
+
mkdirSync(dirname(destFilePath), { recursive: true });
|
53
|
+
linkFile(srcFilePath, destFilePath);
|
54
|
+
return join(destinationDir, newMeta.name);
|
55
|
+
}
|
56
|
+
/**
|
57
|
+
* @return the root of linked files.
|
58
|
+
*/
|
59
|
+
function fuzzyLinkPartial(searchee, newMeta, destinationDir, sourceRoot) {
|
60
|
+
for (const newFile of newMeta.files) {
|
61
|
+
let matchedSearcheeFiles = searchee.files.filter((searcheeFile) => searcheeFile.length === newFile.length);
|
62
|
+
if (matchedSearcheeFiles.length > 1) {
|
63
|
+
matchedSearcheeFiles = matchedSearcheeFiles.filter((searcheeFile) => searcheeFile.name === newFile.name);
|
22
64
|
}
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
mkdirSync(join(linkDir, candidateParentDir), {
|
31
|
-
recursive: true,
|
32
|
-
});
|
33
|
-
correctedlinkDir = join(linkDir, candidateParentDir);
|
34
|
-
}
|
35
|
-
linkFile(searchee.path, join(correctedlinkDir, newMeta.files[0].name));
|
65
|
+
if (matchedSearcheeFiles.length) {
|
66
|
+
const srcFilePath = statSync(sourceRoot).isFile()
|
67
|
+
? sourceRoot
|
68
|
+
: join(dirname(sourceRoot), matchedSearcheeFiles[0].path);
|
69
|
+
const destFilePath = join(destinationDir, newFile.path);
|
70
|
+
mkdirSync(dirname(destFilePath), { recursive: true });
|
71
|
+
linkFile(srcFilePath, destFilePath);
|
36
72
|
}
|
37
73
|
}
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
break;
|
52
|
-
case InjectionResult.FAILURE:
|
53
|
-
default:
|
54
|
-
logger.error(`Found ${styledName} on ${styledTracker} - failed to inject, saving instead`);
|
55
|
-
saveTorrentFile(tracker, getTag(searchee.name), newMeta);
|
56
|
-
break;
|
74
|
+
return join(destinationDir, newMeta.name);
|
75
|
+
}
|
76
|
+
async function linkAllFilesInMetafile(searchee, newMeta, tracker, decision) {
|
77
|
+
const { linkDir, flatLinking } = getRuntimeConfig();
|
78
|
+
const fullLinkDir = flatLinking ? linkDir : join(linkDir, tracker);
|
79
|
+
let sourceRoot;
|
80
|
+
if (searchee.path) {
|
81
|
+
sourceRoot = searchee.path;
|
82
|
+
}
|
83
|
+
else {
|
84
|
+
const downloadDirResult = await getClient().getDownloadDir(searchee);
|
85
|
+
if (downloadDirResult.isErr()) {
|
86
|
+
return downloadDirResult.mapErr((e) => e === "NOT_FOUND" ? "TORRENT_NOT_FOUND" : e);
|
57
87
|
}
|
58
|
-
|
88
|
+
sourceRoot = join(downloadDirResult.unwrapOrThrow(), searchee.files.length === 1
|
89
|
+
? searchee.files[0].path
|
90
|
+
: searchee.name);
|
91
|
+
}
|
92
|
+
if (!existsSync(sourceRoot)) {
|
93
|
+
logger.error(`Linking failed, ${sourceRoot} not found. Make sure Docker volume mounts are set up properly.`);
|
94
|
+
return resultOfErr("MISSING_DATA");
|
95
|
+
}
|
96
|
+
if (decision === Decision.MATCH) {
|
97
|
+
return resultOf(linkExactTree(newMeta, fullLinkDir, sourceRoot));
|
98
|
+
}
|
99
|
+
else if (decision === Decision.MATCH_SIZE_ONLY) {
|
100
|
+
return resultOf(fuzzyLinkOneFile(newMeta, fullLinkDir, sourceRoot));
|
59
101
|
}
|
60
102
|
else {
|
61
|
-
|
62
|
-
|
103
|
+
return resultOf(fuzzyLinkPartial(searchee, newMeta, fullLinkDir, sourceRoot));
|
104
|
+
}
|
105
|
+
}
|
106
|
+
export async function performAction(newMeta, decision, searchee, tracker) {
|
107
|
+
const { action, linkDir } = getRuntimeConfig();
|
108
|
+
const isVideo = hasVideo(searchee);
|
109
|
+
if (action === Action.SAVE) {
|
110
|
+
await saveTorrentFile(tracker, getTag(searchee.name, isVideo), newMeta);
|
111
|
+
const styledName = chalk.green.bold(newMeta.name);
|
112
|
+
const styledTracker = chalk.bold(tracker);
|
113
|
+
logger.info(`Found ${styledName} on ${styledTracker} by ${decision} - saved`);
|
63
114
|
return SaveResult.SAVED;
|
64
115
|
}
|
116
|
+
let destinationDir;
|
117
|
+
if (linkDir) {
|
118
|
+
const linkedFilesRootResult = await linkAllFilesInMetafile(searchee, newMeta, tracker, decision);
|
119
|
+
if (linkedFilesRootResult.isOk()) {
|
120
|
+
destinationDir = dirname(linkedFilesRootResult.unwrapOrThrow());
|
121
|
+
}
|
122
|
+
else if (decision === Decision.MATCH &&
|
123
|
+
linkedFilesRootResult.unwrapErrOrThrow() === "MISSING_DATA") {
|
124
|
+
logger.warn("Falling back to non-linking.");
|
125
|
+
if (searchee.path) {
|
126
|
+
destinationDir = dirname(searchee.path);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
else {
|
130
|
+
logInjectionResult(InjectionResult.FAILURE, tracker, newMeta.name, decision);
|
131
|
+
await saveTorrentFile(tracker, getTag(searchee.name, isVideo), newMeta);
|
132
|
+
return InjectionResult.FAILURE;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
else if (searchee.path) {
|
136
|
+
// should be a MATCH, as risky requires a linkDir to be set
|
137
|
+
destinationDir = dirname(searchee.path);
|
138
|
+
}
|
139
|
+
const result = await getClient().inject(newMeta, searchee, decision, destinationDir);
|
140
|
+
logInjectionResult(result, tracker, newMeta.name, decision);
|
141
|
+
if (result === InjectionResult.FAILURE) {
|
142
|
+
await saveTorrentFile(tracker, getTag(searchee.name, isVideo), newMeta);
|
143
|
+
}
|
144
|
+
return result;
|
65
145
|
}
|
66
146
|
export async function performActions(searchee, matches) {
|
67
147
|
const results = [];
|
@@ -73,21 +153,6 @@ export async function performActions(searchee, matches) {
|
|
73
153
|
}
|
74
154
|
return results;
|
75
155
|
}
|
76
|
-
function linkExact(oldPath, newPath) {
|
77
|
-
if (!newPath) {
|
78
|
-
return;
|
79
|
-
}
|
80
|
-
if (statSync(oldPath).isFile()) {
|
81
|
-
if (!existsSync(join(newPath, basename(oldPath)))) {
|
82
|
-
linkFile(oldPath, join(newPath, basename(oldPath)));
|
83
|
-
}
|
84
|
-
return;
|
85
|
-
}
|
86
|
-
mkdirSync(join(newPath, basename(oldPath)), { recursive: true });
|
87
|
-
readdirSync(oldPath).forEach((file) => {
|
88
|
-
linkExact(join(oldPath, file), join(newPath, basename(oldPath)));
|
89
|
-
});
|
90
|
-
}
|
91
156
|
function linkFile(oldPath, newPath) {
|
92
157
|
const { linkType } = getRuntimeConfig();
|
93
158
|
try {
|
package/dist/action.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.js
CHANGED
@@ -9,17 +9,17 @@ export async function resetApiKey() {
|
|
9
9
|
await db("settings").update({ apikey });
|
10
10
|
return apikey;
|
11
11
|
}
|
12
|
-
export async function
|
12
|
+
export async function getApiKey() {
|
13
|
+
const { apiKey: runtimeConfigApiKey } = getRuntimeConfig();
|
14
|
+
if (runtimeConfigApiKey)
|
15
|
+
return runtimeConfigApiKey;
|
13
16
|
const { apikey } = await db("settings").select("apikey").first();
|
14
17
|
if (!apikey)
|
15
18
|
return resetApiKey();
|
16
19
|
return apikey;
|
17
20
|
}
|
18
21
|
export async function checkApiKey(keyToCheck) {
|
19
|
-
const
|
20
|
-
if (!apiAuth)
|
21
|
-
return true;
|
22
|
-
const apikey = await getApiKeyFromDatabase();
|
22
|
+
const apikey = await getApiKey();
|
23
23
|
return apikey === keyToCheck;
|
24
24
|
}
|
25
25
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,SAAS,cAAc;IACtB,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAChC,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,SAAS,cAAc;IACtB,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAChC,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC9B,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC3D,IAAI,mBAAmB;QAAE,OAAO,mBAAmB,CAAC;IAEpD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;IACjE,IAAI,CAAC,MAAM;QAAE,OAAO,WAAW,EAAE,CAAC;IAClC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB;IACnD,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IACjC,OAAO,MAAM,KAAK,UAAU,CAAC;AAC9B,CAAC"}
|
package/dist/clients/Deluge.js
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
import { InjectionResult } from "../constants.js";
|
1
|
+
import { InjectionResult, TORRENT_TAG, TORRENT_CATEGORY_SUFFIX, } from "../constants.js";
|
2
2
|
import { CrossSeedError } from "../errors.js";
|
3
3
|
import { Label, logger } from "../logger.js";
|
4
4
|
import { getRuntimeConfig } from "../runtimeConfig.js";
|
5
|
-
import { extractCredentialsFromUrl } from "../utils.js";
|
6
|
-
import
|
5
|
+
import { shouldRecheck, extractCredentialsFromUrl, wait } from "../utils.js";
|
6
|
+
import { resultOf, resultOfErr } from "../Result.js";
|
7
|
+
import ms from "ms";
|
7
8
|
var DelugeErrorCode;
|
8
9
|
(function (DelugeErrorCode) {
|
9
10
|
DelugeErrorCode[DelugeErrorCode["NO_AUTH"] = 1] = "NO_AUTH";
|
@@ -13,10 +14,11 @@ var DelugeErrorCode;
|
|
13
14
|
DelugeErrorCode[DelugeErrorCode["BAD_JSON"] = 5] = "BAD_JSON";
|
14
15
|
})(DelugeErrorCode || (DelugeErrorCode = {}));
|
15
16
|
export default class Deluge {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
delugeCookie = null;
|
18
|
+
delugeLabel = TORRENT_TAG;
|
19
|
+
delugeLabelSuffix = TORRENT_CATEGORY_SUFFIX;
|
20
|
+
isLabelEnabled;
|
21
|
+
delugeRequestId = 0;
|
20
22
|
/**
|
21
23
|
* validates the login and host for deluge webui
|
22
24
|
*/
|
@@ -65,26 +67,30 @@ export default class Deluge {
|
|
65
67
|
if (this.delugeCookie)
|
66
68
|
headers.set("Cookie", this.delugeCookie);
|
67
69
|
let response, json;
|
68
|
-
const
|
70
|
+
const abortController = new AbortController();
|
71
|
+
setTimeout(() => void abortController.abort(), ms("10 seconds")).unref();
|
69
72
|
try {
|
70
73
|
response = await fetch(href, {
|
71
74
|
body: JSON.stringify({
|
72
75
|
method,
|
73
76
|
params,
|
74
|
-
id
|
77
|
+
id: this.delugeRequestId++,
|
75
78
|
}),
|
76
79
|
method: "POST",
|
77
80
|
headers,
|
81
|
+
signal: abortController.signal,
|
78
82
|
});
|
79
83
|
}
|
80
84
|
catch (networkError) {
|
81
|
-
|
85
|
+
if (networkError.name === "AbortError") {
|
86
|
+
throw new Error(`Deluge method ${method} timed out after 10 seconds`);
|
87
|
+
}
|
82
88
|
throw new Error(`Failed to connect to Deluge at ${href}`, {
|
83
89
|
cause: networkError,
|
84
90
|
});
|
85
91
|
}
|
86
92
|
try {
|
87
|
-
json = await response.json();
|
93
|
+
json = (await response.json());
|
88
94
|
}
|
89
95
|
catch (jsonParseError) {
|
90
96
|
throw new Error(`Deluge method ${method} response was non-JSON ${jsonParseError}`);
|
@@ -96,7 +102,7 @@ export default class Deluge {
|
|
96
102
|
return this.call(method, params, 0);
|
97
103
|
}
|
98
104
|
else {
|
99
|
-
throw new Error("Connection lost with Deluge.
|
105
|
+
throw new Error("Connection lost with Deluge. Re-authentication failed.");
|
100
106
|
}
|
101
107
|
}
|
102
108
|
this.handleResponseHeaders(response.headers);
|
@@ -120,12 +126,32 @@ export default class Deluge {
|
|
120
126
|
? false
|
121
127
|
: enabledPlugins.result.includes("Label");
|
122
128
|
}
|
129
|
+
// generates the label (string) for injection based on searchee and torrentInfo
|
130
|
+
calculateLabel(searchee, torrentInfo) {
|
131
|
+
const { linkCategory, duplicateCategories } = getRuntimeConfig();
|
132
|
+
if (!searchee.infoHash || !torrentInfo.label) {
|
133
|
+
return this.delugeLabel;
|
134
|
+
}
|
135
|
+
const ogLabel = torrentInfo.label;
|
136
|
+
if (!duplicateCategories) {
|
137
|
+
return ogLabel;
|
138
|
+
}
|
139
|
+
const shouldSuffixLabel = !ogLabel.endsWith(this.delugeLabelSuffix) && // no .cross-seed
|
140
|
+
ogLabel !== linkCategory; // not data
|
141
|
+
return searchee.path
|
142
|
+
? linkCategory
|
143
|
+
: shouldSuffixLabel
|
144
|
+
? `${ogLabel}${this.delugeLabelSuffix}`
|
145
|
+
: ogLabel;
|
146
|
+
}
|
123
147
|
/**
|
124
148
|
* if Label plugin is loaded, adds (if necessary)
|
125
149
|
* and sets the label based on torrent hash.
|
126
150
|
*/
|
127
|
-
async setLabel(infoHash, label) {
|
128
|
-
if (this.isLabelEnabled)
|
151
|
+
async setLabel(name, infoHash, label) {
|
152
|
+
if (!this.isLabelEnabled)
|
153
|
+
return;
|
154
|
+
try {
|
129
155
|
const setResult = await this.call("label.set_torrent", [
|
130
156
|
infoHash,
|
131
157
|
label,
|
@@ -135,14 +161,19 @@ export default class Deluge {
|
|
135
161
|
await this.call("label.set_torrent", [infoHash, label]);
|
136
162
|
}
|
137
163
|
}
|
164
|
+
catch (e) {
|
165
|
+
logger.warn({
|
166
|
+
label: Label.DELUGE,
|
167
|
+
message: `Failed to label ${name} (${infoHash}) as ${label}`,
|
168
|
+
});
|
169
|
+
}
|
138
170
|
}
|
139
171
|
/**
|
140
172
|
* injects a torrent into deluge client
|
141
173
|
*/
|
142
|
-
async inject(newTorrent, searchee, path) {
|
174
|
+
async inject(newTorrent, searchee, decision, path) {
|
143
175
|
try {
|
144
176
|
let torrentInfo;
|
145
|
-
const { duplicateCategories } = getRuntimeConfig();
|
146
177
|
if (searchee.infoHash) {
|
147
178
|
torrentInfo = await this.getTorrentInfo(searchee);
|
148
179
|
if (!torrentInfo.complete) {
|
@@ -156,28 +187,33 @@ export default class Deluge {
|
|
156
187
|
});
|
157
188
|
return InjectionResult.FAILURE;
|
158
189
|
}
|
159
|
-
const
|
190
|
+
const torrentFileName = `${newTorrent.getFileSystemSafeName()}.cross-seed.torrent`;
|
191
|
+
const encodedTorrentData = newTorrent.encode().toString("base64");
|
192
|
+
const torrentPath = path ? path : torrentInfo.save_path;
|
193
|
+
const params = this.formatData(torrentFileName, encodedTorrentData, torrentPath, decision);
|
160
194
|
const addResult = await this.call("core.add_torrent_file", params);
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
195
|
+
const addResponse = typeof addResult.error?.message === "string"
|
196
|
+
? addResult.error
|
197
|
+
: addResult.result;
|
198
|
+
if (typeof addResponse === "string") {
|
199
|
+
await this.setLabel(newTorrent.name, newTorrent.infoHash, this.calculateLabel(searchee, torrentInfo));
|
200
|
+
if (shouldRecheck(decision)) {
|
201
|
+
// when paused, libtorrent doesnt start rechecking
|
202
|
+
// leaves torrent ready to download - ~99%
|
203
|
+
await wait(1000);
|
204
|
+
await this.call("core.force_recheck", [
|
205
|
+
[newTorrent.infoHash],
|
206
|
+
]);
|
207
|
+
}
|
172
208
|
return InjectionResult.SUCCESS;
|
173
209
|
}
|
174
|
-
else if (
|
210
|
+
else if (addResponse?.message.includes("already")) {
|
175
211
|
return InjectionResult.ALREADY_EXISTS;
|
176
212
|
}
|
177
|
-
else if (
|
213
|
+
else if (addResponse) {
|
178
214
|
logger.debug({
|
179
215
|
label: Label.DELUGE,
|
180
|
-
message: `Injection failed: ${
|
216
|
+
message: `Injection failed: ${addResponse}`,
|
181
217
|
});
|
182
218
|
return InjectionResult.FAILURE;
|
183
219
|
}
|
@@ -189,38 +225,56 @@ export default class Deluge {
|
|
189
225
|
return InjectionResult.FAILURE;
|
190
226
|
}
|
191
227
|
}
|
192
|
-
catch (
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
}
|
200
|
-
else {
|
201
|
-
logger.error({
|
202
|
-
label: Label.DELUGE,
|
203
|
-
message: `Injection failed: ${injectResult}`,
|
204
|
-
});
|
205
|
-
logger.debug(injectResult);
|
206
|
-
return InjectionResult.FAILURE;
|
207
|
-
}
|
228
|
+
catch (error) {
|
229
|
+
logger.error({
|
230
|
+
label: Label.DELUGE,
|
231
|
+
message: `Injection failed: ${error}`,
|
232
|
+
});
|
233
|
+
logger.debug(error);
|
234
|
+
return InjectionResult.FAILURE;
|
208
235
|
}
|
209
236
|
}
|
210
237
|
/**
|
211
238
|
* formats the json for rpc calls to inject
|
212
239
|
*/
|
213
|
-
formatData(filename, filedump, path,
|
240
|
+
formatData(filename, filedump, path, decision) {
|
241
|
+
const toRecheck = shouldRecheck(decision);
|
214
242
|
return [
|
215
243
|
filename,
|
216
244
|
filedump,
|
217
245
|
{
|
218
|
-
add_paused:
|
219
|
-
seed_mode:
|
246
|
+
add_paused: toRecheck,
|
247
|
+
seed_mode: !toRecheck,
|
220
248
|
download_location: path,
|
221
249
|
},
|
222
250
|
];
|
223
251
|
}
|
252
|
+
/**
|
253
|
+
* returns directory of an infohash in deluge as a string
|
254
|
+
*/
|
255
|
+
async getDownloadDir(searchee) {
|
256
|
+
let torrent, response;
|
257
|
+
const params = [["save_path", "progress"], { hash: searchee.infoHash }];
|
258
|
+
try {
|
259
|
+
response = await this.call("web.update_ui", params);
|
260
|
+
}
|
261
|
+
catch (e) {
|
262
|
+
return resultOfErr("UNKNOWN_ERROR");
|
263
|
+
}
|
264
|
+
if (response.result.torrents) {
|
265
|
+
torrent = response.result.torrents?.[searchee.infoHash];
|
266
|
+
}
|
267
|
+
else {
|
268
|
+
return resultOfErr("UNKNOWN_ERROR");
|
269
|
+
}
|
270
|
+
if (torrent === undefined) {
|
271
|
+
return resultOfErr("NOT_FOUND");
|
272
|
+
}
|
273
|
+
else if (response.result.torrents?.[searchee.infoHash].progress !== 100) {
|
274
|
+
return resultOfErr("TORRENT_NOT_COMPLETE");
|
275
|
+
}
|
276
|
+
return resultOf(torrent.save_path);
|
277
|
+
}
|
224
278
|
/**
|
225
279
|
* returns information needed to complete/validate injection
|
226
280
|
*/
|
@@ -260,7 +314,6 @@ export default class Deluge {
|
|
260
314
|
message: `Failed to fetch torrent data: ${searchee.name} - (${searchee.infoHash})`,
|
261
315
|
});
|
262
316
|
logger.debug(e);
|
263
|
-
// @ts-expect-error needs es2022 target (tsconfig)
|
264
317
|
throw new Error("web.update_ui: failed to fetch data from client", {
|
265
318
|
cause: e,
|
266
319
|
});
|