cross-seed 5.5.4 → 5.7.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 +6 -13
- package/dist/Result.js +1 -1
- package/dist/Result.js.map +1 -1
- package/dist/action.js +32 -25
- package/dist/action.js.map +1 -1
- package/dist/clients/Deluge.js +208 -0
- package/dist/clients/Deluge.js.map +1 -0
- package/dist/clients/QBittorrent.js +9 -8
- package/dist/clients/QBittorrent.js.map +1 -1
- package/dist/clients/RTorrent.js +38 -28
- package/dist/clients/RTorrent.js.map +1 -1
- package/dist/clients/TorrentClient.js +5 -1
- package/dist/clients/TorrentClient.js.map +1 -1
- package/dist/cmd.js +1 -0
- package/dist/cmd.js.map +1 -1
- package/dist/config.template.cjs +23 -6
- package/dist/config.template.cjs.map +1 -1
- package/dist/config.template.docker.cjs +24 -6
- package/dist/config.template.docker.cjs.map +1 -1
- package/dist/configuration.js.map +1 -1
- package/dist/constants.js +3 -3
- package/dist/constants.js.map +1 -1
- package/dist/decide.js +1 -1
- package/dist/decide.js.map +1 -1
- package/dist/jobs.js +2 -3
- package/dist/jobs.js.map +1 -1
- package/dist/logger.js +1 -0
- package/dist/logger.js.map +1 -1
- package/dist/pipeline.js +14 -12
- package/dist/pipeline.js.map +1 -1
- package/dist/pushNotifier.js +1 -1
- package/dist/pushNotifier.js.map +1 -1
- package/dist/runtimeConfig.js.map +1 -1
- package/dist/server.js +17 -11
- package/dist/server.js.map +1 -1
- package/dist/startup.js +10 -5
- package/dist/startup.js.map +1 -1
- package/dist/torrent.js +1 -2
- package/dist/torrent.js.map +1 -1
- package/dist/torznab.js +23 -21
- package/dist/torznab.js.map +1 -1
- package/dist/utils.js +8 -6
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
@@ -5,25 +5,18 @@ seed based on your existing torrents. It is designed to match conservatively to
|
|
5
5
|
minimize manual intervention.
|
6
6
|
|
7
7
|
`cross-seed` can inject the torrents it finds directly into your torrent client.
|
8
|
-
Currently the supported clients are
|
8
|
+
Currently, the supported clients are
|
9
9
|
|
10
10
|
- rTorrent
|
11
11
|
- qBittorrent
|
12
12
|
- Transmission
|
13
|
-
|
14
|
-
[Request your client here.](https://github.com/cross-seed/cross-seed/issues/new)
|
13
|
+
- Deluge
|
15
14
|
|
16
15
|
If your client isn't supported, `cross-seed` will download a bunch of torrent
|
17
16
|
files to a folder you specify. After that, I recommend using
|
18
17
|
[AutoTorrent2](https://github.com/JohnDoee/autotorrent2) to do the last-mile
|
19
18
|
delivery into your client.
|
20
19
|
|
21
|
-
## 🚨🚨🚨 Breaking changes in cross-seed v4 🚨🚨🚨
|
22
|
-
|
23
|
-
Head on over to the
|
24
|
-
[v4 migration guide](https://www.cross-seed.org/docs/tutorials/v4-migration-guide)
|
25
|
-
to see the steps required for migration.
|
26
|
-
|
27
20
|
## Requirements
|
28
21
|
|
29
22
|
- [Node 16+](https://nodejs.org/en/download)
|
@@ -33,11 +26,11 @@ to see the steps required for migration.
|
|
33
26
|
## Tutorial
|
34
27
|
|
35
28
|
Head on over to
|
36
|
-
[cross-seed.org](https://www.cross-seed.org/docs/basics/getting-started)
|
29
|
+
[cross-seed.org](https://www.cross-seed.org/docs/basics/getting-started) to get
|
30
|
+
started.
|
37
31
|
|
38
32
|
## Troubleshooting
|
39
33
|
|
40
34
|
Feel free to
|
41
|
-
[start a discussion](https://github.com/cross-seed/cross-seed/discussions/new)
|
42
|
-
or
|
43
|
-
reach out on [Discord](https://discord.gg/jpbUFzS5Wb).
|
35
|
+
[start a discussion](https://github.com/cross-seed/cross-seed/discussions/new),
|
36
|
+
or reach out on [Discord](https://discord.gg/jpbUFzS5Wb).
|
package/dist/Result.js
CHANGED
@@ -41,7 +41,7 @@ class ErrResult {
|
|
41
41
|
return new ErrResult(mapper(this.contents));
|
42
42
|
}
|
43
43
|
unwrapOrThrow(errToThrow) {
|
44
|
-
throw errToThrow
|
44
|
+
throw errToThrow ?? new Error("Tried to unwrap an ErrResult's error");
|
45
45
|
}
|
46
46
|
unwrapErrOrThrow() {
|
47
47
|
return this.contents;
|
package/dist/Result.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Result.js","sourceRoot":"","sources":["../src/Result.ts"],"names":[],"mappings":"AASA,MAAM,QAAQ;IAGb,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;IAGd,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,
|
1
|
+
{"version":3,"file":"Result.js","sourceRoot":"","sources":["../src/Result.ts"],"names":[],"mappings":"AASA,MAAM,QAAQ;IAGb,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;IAGd,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,12 +1,19 @@
|
|
1
1
|
import chalk from "chalk";
|
2
2
|
import { existsSync, linkSync, mkdirSync, readdirSync, statSync, symlinkSync, } from "fs";
|
3
|
-
import
|
3
|
+
import { join, resolve, dirname, basename } 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
7
|
import { getRuntimeConfig } from "./runtimeConfig.js";
|
8
8
|
import { saveTorrentFile } from "./torrent.js";
|
9
9
|
import { getTag } from "./utils.js";
|
10
|
+
import { CrossSeedError } from "./errors.js";
|
11
|
+
export async function validateAction() {
|
12
|
+
const { action } = getRuntimeConfig();
|
13
|
+
if (action !== Action.INJECT && action !== Action.SAVE) {
|
14
|
+
throw new CrossSeedError(`Action method "${action}" is invalid. Allowed choices are "save" and "inject".`);
|
15
|
+
}
|
16
|
+
}
|
10
17
|
export async function performAction(newMeta, decision, searchee, tracker) {
|
11
18
|
const { action, linkDir } = getRuntimeConfig();
|
12
19
|
if (searchee.path) {
|
@@ -16,18 +23,16 @@ export async function performAction(newMeta, decision, searchee, tracker) {
|
|
16
23
|
else if (decision == Decision.MATCH_SIZE_ONLY) {
|
17
24
|
// Size only matching is only supported for single file or
|
18
25
|
// single, nested file torrents.
|
19
|
-
const candidateParentDir =
|
26
|
+
const candidateParentDir = dirname(newMeta.files[0].path);
|
20
27
|
let correctedlinkDir = linkDir;
|
21
28
|
// Candidate is single, nested file
|
22
|
-
if (candidateParentDir
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
28
|
-
correctedlinkDir = path.join(linkDir, candidateParentDir);
|
29
|
+
if (candidateParentDir !== ".") {
|
30
|
+
mkdirSync(join(linkDir, candidateParentDir), {
|
31
|
+
recursive: true,
|
32
|
+
});
|
33
|
+
correctedlinkDir = join(linkDir, candidateParentDir);
|
29
34
|
}
|
30
|
-
linkFile(searchee.path,
|
35
|
+
linkFile(searchee.path, join(correctedlinkDir, newMeta.files[0].name));
|
31
36
|
}
|
32
37
|
}
|
33
38
|
const styledName = chalk.green.bold(newMeta.name);
|
@@ -73,30 +78,32 @@ function linkExact(oldPath, newPath) {
|
|
73
78
|
return;
|
74
79
|
}
|
75
80
|
if (statSync(oldPath).isFile()) {
|
76
|
-
if (!existsSync(
|
77
|
-
linkFile(oldPath,
|
81
|
+
if (!existsSync(join(newPath, basename(oldPath)))) {
|
82
|
+
linkFile(oldPath, join(newPath, basename(oldPath)));
|
78
83
|
}
|
79
84
|
return;
|
80
85
|
}
|
81
|
-
|
82
|
-
mkdirSync(path.join(newPath, path.basename(oldPath)));
|
83
|
-
}
|
84
|
-
catch (e) {
|
85
|
-
// skip if it already exists
|
86
|
-
}
|
86
|
+
mkdirSync(join(newPath, basename(oldPath)), { recursive: true });
|
87
87
|
readdirSync(oldPath).forEach((file) => {
|
88
|
-
linkExact(
|
88
|
+
linkExact(join(oldPath, file), join(newPath, basename(oldPath)));
|
89
89
|
});
|
90
90
|
}
|
91
91
|
function linkFile(oldPath, newPath) {
|
92
92
|
const { linkType } = getRuntimeConfig();
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
try {
|
94
|
+
if (linkType === LinkType.HARDLINK) {
|
95
|
+
linkSync(oldPath, newPath);
|
96
|
+
}
|
97
|
+
else {
|
98
|
+
// we need to resolve because symlinks are resolved outside
|
99
|
+
// the context of cross-seed's working directory
|
100
|
+
symlinkSync(oldPath, resolve(newPath));
|
101
|
+
}
|
97
102
|
}
|
98
|
-
|
99
|
-
|
103
|
+
catch (e) {
|
104
|
+
if (e.code === "EEXIST")
|
105
|
+
return;
|
106
|
+
throw e;
|
100
107
|
}
|
101
108
|
}
|
102
109
|
//# sourceMappingURL=action.js.map
|
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,EACN,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,QAAQ,EACR,WAAW,GACX,MAAM,IAAI,CAAC;AACZ,OAAO,IAAI,MAAM,MAAM,CAAC;
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,208 @@
|
|
1
|
+
import { InjectionResult } from "../constants.js";
|
2
|
+
import { CrossSeedError } from "../errors.js";
|
3
|
+
import { Label, logger } from "../logger.js";
|
4
|
+
import { getRuntimeConfig } from "../runtimeConfig.js";
|
5
|
+
import { extractCredentialsFromUrl } from "../utils.js";
|
6
|
+
import fetch, { Headers } from "node-fetch";
|
7
|
+
var DelugeErrorCode;
|
8
|
+
(function (DelugeErrorCode) {
|
9
|
+
DelugeErrorCode[DelugeErrorCode["NO_AUTH"] = 1] = "NO_AUTH";
|
10
|
+
DelugeErrorCode[DelugeErrorCode["BAD_METHOD"] = 2] = "BAD_METHOD";
|
11
|
+
DelugeErrorCode[DelugeErrorCode["CALL_ERR"] = 3] = "CALL_ERR";
|
12
|
+
DelugeErrorCode[DelugeErrorCode["RPC_FAIL"] = 4] = "RPC_FAIL";
|
13
|
+
DelugeErrorCode[DelugeErrorCode["BAD_JSON"] = 5] = "BAD_JSON";
|
14
|
+
})(DelugeErrorCode || (DelugeErrorCode = {}));
|
15
|
+
export default class Deluge {
|
16
|
+
constructor() {
|
17
|
+
this.delugeCookie = null;
|
18
|
+
this.delugeLabel = "cross-seed";
|
19
|
+
}
|
20
|
+
/**
|
21
|
+
* validates the login and host for deluge webui
|
22
|
+
*/
|
23
|
+
async validateConfig() {
|
24
|
+
await this.authenticate();
|
25
|
+
this.isLabelEnabled = await this.labelEnabled();
|
26
|
+
}
|
27
|
+
/**
|
28
|
+
* connects and authenticates to the webui
|
29
|
+
*/
|
30
|
+
async authenticate() {
|
31
|
+
const { delugeRpcUrl } = getRuntimeConfig();
|
32
|
+
const { href, password } = extractCredentialsFromUrl(delugeRpcUrl).unwrapOrThrow(new CrossSeedError("delugeRpcUrl must be percent-encoded"));
|
33
|
+
if (!password) {
|
34
|
+
throw new CrossSeedError("You need to define a password in the delugeRpcUrl. (e.g. http://:<PASSWORD>@localhost:8112)");
|
35
|
+
}
|
36
|
+
const response = await this.call("auth.login", [password], 0);
|
37
|
+
if (!response.result) {
|
38
|
+
throw new CrossSeedError(`Reached Deluge, but failed to authenticate: ${href}`);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
/**
|
42
|
+
* ensures authentication and sends JSON-RPC calls to deluge
|
43
|
+
*/
|
44
|
+
async call(method, params, retries = 1) {
|
45
|
+
const { delugeRpcUrl } = getRuntimeConfig();
|
46
|
+
const { href } = extractCredentialsFromUrl(delugeRpcUrl).unwrapOrThrow();
|
47
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
48
|
+
if (this.delugeCookie)
|
49
|
+
headers.set("Cookie", this.delugeCookie);
|
50
|
+
let response, json;
|
51
|
+
try {
|
52
|
+
response = await fetch(href, {
|
53
|
+
body: JSON.stringify({
|
54
|
+
...{ method: method, params: params },
|
55
|
+
id: Math.floor(Math.random() * 0x7fffffff),
|
56
|
+
}),
|
57
|
+
method: "POST",
|
58
|
+
headers: headers,
|
59
|
+
});
|
60
|
+
}
|
61
|
+
catch (networkError) {
|
62
|
+
// @ts-expect-error needs es2022 target (tsconfig)
|
63
|
+
throw new Error(`Failed to connect to Deluge at ${href}`, {
|
64
|
+
cause: networkError,
|
65
|
+
});
|
66
|
+
}
|
67
|
+
try {
|
68
|
+
json = await response.json();
|
69
|
+
}
|
70
|
+
catch (jsonParseError) {
|
71
|
+
throw new Error(`Deluge method ${method} response was non-JSON ${jsonParseError}`);
|
72
|
+
}
|
73
|
+
if (json?.error?.code === DelugeErrorCode.NO_AUTH && retries > 0) {
|
74
|
+
this.delugeCookie = null;
|
75
|
+
await this.authenticate();
|
76
|
+
if (this.delugeCookie) {
|
77
|
+
return this.call(method, params, 0);
|
78
|
+
}
|
79
|
+
else {
|
80
|
+
throw new Error("Connection lost with Deluge. Reauthentication failed.");
|
81
|
+
}
|
82
|
+
}
|
83
|
+
this.handleResponseHeaders(response.headers);
|
84
|
+
return json;
|
85
|
+
}
|
86
|
+
/**
|
87
|
+
* parses the set-cookie header and updates stored value
|
88
|
+
*/
|
89
|
+
handleResponseHeaders(headers) {
|
90
|
+
if (headers.has("Set-Cookie")) {
|
91
|
+
this.delugeCookie = headers.get("Set-Cookie").split(";")[0];
|
92
|
+
}
|
93
|
+
}
|
94
|
+
/**
|
95
|
+
* checks enabled plugins for "Label"
|
96
|
+
* returns true if successful.
|
97
|
+
*/
|
98
|
+
async labelEnabled() {
|
99
|
+
const enabledLabels = await this.call("core.get_enabled_plugins", []);
|
100
|
+
return enabledLabels?.result?.includes?.("Label");
|
101
|
+
}
|
102
|
+
/**
|
103
|
+
* if Label plugin is loaded, adds (if necessary)
|
104
|
+
* and sets the label based on torrent hash.
|
105
|
+
*/
|
106
|
+
async setLabel(infoHash, label) {
|
107
|
+
if (this.isLabelEnabled) {
|
108
|
+
const setResult = await this.call("label.set_torrent", [
|
109
|
+
infoHash,
|
110
|
+
label,
|
111
|
+
]);
|
112
|
+
if (setResult?.error?.code == DelugeErrorCode.RPC_FAIL) {
|
113
|
+
await this.call("label.add", [label]);
|
114
|
+
await this.call("label.set_torrent", [infoHash, label]);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
/**
|
119
|
+
* injects a torrent into deluge client
|
120
|
+
*/
|
121
|
+
async inject(newTorrent, searchee, path) {
|
122
|
+
try {
|
123
|
+
let torrentInfo;
|
124
|
+
if (searchee.infoHash) {
|
125
|
+
torrentInfo = await this.getTorrentInfo(searchee);
|
126
|
+
if (!torrentInfo.complete) {
|
127
|
+
if (torrentInfo.save_path == "missing" &&
|
128
|
+
!path &&
|
129
|
+
!searchee.path) {
|
130
|
+
return InjectionResult.FAILURE;
|
131
|
+
}
|
132
|
+
return InjectionResult.TORRENT_NOT_COMPLETE;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
const params = this.formatData(`${newTorrent.name}.cross-seed.torrent`, newTorrent.encode().toString("base64"), path ? path : torrentInfo.save_path, !!searchee.infoHash);
|
136
|
+
const addResult = await this.call("core.add_torrent_file", params);
|
137
|
+
if (addResult?.result) {
|
138
|
+
const { dataCategory } = getRuntimeConfig();
|
139
|
+
await this.setLabel(newTorrent.infoHash, searchee.path ? dataCategory : this.delugeLabel);
|
140
|
+
return InjectionResult.SUCCESS;
|
141
|
+
}
|
142
|
+
else if (addResult?.error?.message?.includes("already")) {
|
143
|
+
return InjectionResult.ALREADY_EXISTS;
|
144
|
+
}
|
145
|
+
else if (addResult?.error?.message) {
|
146
|
+
logger.debug({
|
147
|
+
label: Label.DELUGE,
|
148
|
+
message: `Injection failed: ${addResult.error.message}`,
|
149
|
+
});
|
150
|
+
return InjectionResult.FAILURE;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
catch (injectResult) {
|
154
|
+
logger.error({
|
155
|
+
label: Label.DELUGE,
|
156
|
+
message: `Injection failed: ${injectResult}`,
|
157
|
+
});
|
158
|
+
logger.debug(injectResult);
|
159
|
+
return InjectionResult.FAILURE;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
/**
|
163
|
+
* formats the json for rpc calls to inject
|
164
|
+
*/
|
165
|
+
formatData(filename, filedump, path, isTorrent) {
|
166
|
+
return [
|
167
|
+
filename,
|
168
|
+
filedump,
|
169
|
+
{
|
170
|
+
add_paused: isTorrent ? false : !getRuntimeConfig().skipRecheck,
|
171
|
+
seed_mode: isTorrent ? true : getRuntimeConfig().skipRecheck,
|
172
|
+
download_location: path,
|
173
|
+
},
|
174
|
+
];
|
175
|
+
}
|
176
|
+
/**
|
177
|
+
* returns information needed to complete/validate injection
|
178
|
+
*/
|
179
|
+
async getTorrentInfo(searchee) {
|
180
|
+
try {
|
181
|
+
const params = [
|
182
|
+
["state", "progress", "save_path"],
|
183
|
+
{ hash: searchee.infoHash },
|
184
|
+
];
|
185
|
+
const response = await this.call("web.update_ui", params);
|
186
|
+
if (response?.result?.torrents?.[searchee.infoHash] === undefined) {
|
187
|
+
throw new Error(`Torrent not found in client (${searchee.infoHash})`);
|
188
|
+
}
|
189
|
+
const completedTorrent = response?.result?.torrents?.[searchee.infoHash]?.state ===
|
190
|
+
"Seeding" ||
|
191
|
+
response?.result?.torrents?.[searchee.infoHash]?.progress ===
|
192
|
+
100;
|
193
|
+
return {
|
194
|
+
complete: completedTorrent,
|
195
|
+
save_path: response?.result?.torrents?.[searchee.infoHash]?.save_path,
|
196
|
+
};
|
197
|
+
}
|
198
|
+
catch (e) {
|
199
|
+
logger.error({
|
200
|
+
label: Label.DELUGE,
|
201
|
+
message: `Failed to fetch torrent data: ${searchee.name} - (${searchee.infoHash})`,
|
202
|
+
});
|
203
|
+
logger.debug(e);
|
204
|
+
return { complete: false, save_path: "missing" };
|
205
|
+
}
|
206
|
+
}
|
207
|
+
}
|
208
|
+
//# sourceMappingURL=Deluge.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"Deluge.js","sourceRoot":"","sources":["../../src/clients/Deluge.ts"],"names":[],"mappings":"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"}
|
@@ -13,12 +13,15 @@ const X_WWW_FORM_URLENCODED = {
|
|
13
13
|
"Content-Type": "application/x-www-form-urlencoded",
|
14
14
|
};
|
15
15
|
export default class QBittorrent {
|
16
|
-
|
16
|
+
constructor() {
|
17
17
|
const { qbittorrentUrl } = getRuntimeConfig();
|
18
|
-
|
18
|
+
this.url = extractCredentialsFromUrl(qbittorrentUrl, "/api/v2").unwrapOrThrow(new CrossSeedError("qBittorrent url must be percent-encoded"));
|
19
|
+
}
|
20
|
+
async login() {
|
19
21
|
let response;
|
22
|
+
const { href, username, password } = this.url;
|
20
23
|
try {
|
21
|
-
response = await fetch(`${href}
|
24
|
+
response = await fetch(`${href}/auth/login`, {
|
22
25
|
method: "POST",
|
23
26
|
body: new URLSearchParams({ username, password }),
|
24
27
|
});
|
@@ -46,9 +49,7 @@ export default class QBittorrent {
|
|
46
49
|
label: Label.QBITTORRENT,
|
47
50
|
message: `Making request to ${path} with body ${body.toString()}`,
|
48
51
|
});
|
49
|
-
const
|
50
|
-
const { href } = extractCredentialsFromUrl(qbittorrentUrl).unwrapOrThrow();
|
51
|
-
const response = await fetch(`${href}api/v2${path}`, {
|
52
|
+
const response = await fetch(`${this.url.href}${path}`, {
|
52
53
|
method: "post",
|
53
54
|
headers: { Cookie: this.cookie, ...headers },
|
54
55
|
body,
|
@@ -78,7 +79,7 @@ export default class QBittorrent {
|
|
78
79
|
logger.warn(`qBittorrent category "${ogCategoryName}" has no save path. Set a save path to prevent Missing Files errors.`);
|
79
80
|
});
|
80
81
|
}
|
81
|
-
if (
|
82
|
+
if (maybeNewCategory?.savePath === ogCategory.savePath) {
|
82
83
|
// setup is already complete
|
83
84
|
}
|
84
85
|
else if (maybeNewCategory) {
|
@@ -123,7 +124,7 @@ export default class QBittorrent {
|
|
123
124
|
return files.length === 1 && name !== posix.basename(name);
|
124
125
|
}
|
125
126
|
async inject(newTorrent, searchee, path) {
|
126
|
-
const { duplicateCategories,
|
127
|
+
const { duplicateCategories, skipRecheck, dataCategory } = getRuntimeConfig();
|
127
128
|
try {
|
128
129
|
if (await this.isInfoHashInClient(newTorrent.infoHash)) {
|
129
130
|
return InjectionResult.ALREADY_EXISTS;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"QBittorrent.js","sourceRoot":"","sources":["../../src/clients/QBittorrent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAA6B,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAGxD,MAAM,qBAAqB,GAAG;IAC7B,cAAc,EAAE,mCAAmC;CACnD,CAAC;AAsEF,MAAM,CAAC,OAAO,OAAO,WAAW;
|
1
|
+
{"version":3,"file":"QBittorrent.js","sourceRoot":"","sources":["../../src/clients/QBittorrent.ts"],"names":[],"mappings":"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"}
|
package/dist/clients/RTorrent.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { promises as fs } from "fs";
|
2
|
-
import { dirname, resolve } from "path";
|
2
|
+
import { dirname, join, resolve, sep } from "path";
|
3
3
|
import { inspect } from "util";
|
4
4
|
import xmlrpc from "xmlrpc";
|
5
5
|
import { InjectionResult } from "../constants.js";
|
@@ -9,16 +9,20 @@ import { Metafile } from "../parseTorrent.js";
|
|
9
9
|
import { resultOf, resultOfErr } from "../Result.js";
|
10
10
|
import { getRuntimeConfig } from "../runtimeConfig.js";
|
11
11
|
import { extractCredentialsFromUrl, wait } from "../utils.js";
|
12
|
-
async function createLibTorrentResumeTree(meta,
|
12
|
+
async function createLibTorrentResumeTree(meta, basePath) {
|
13
13
|
async function getFileResumeData(file) {
|
14
|
-
const
|
14
|
+
const filePathWithoutFirstSegment = file.path
|
15
|
+
.split(sep)
|
16
|
+
.slice(1)
|
17
|
+
.join(sep);
|
18
|
+
const resolvedFilePath = resolve(basePath, filePathWithoutFirstSegment);
|
15
19
|
const fileStat = await fs
|
16
|
-
.
|
20
|
+
.stat(resolvedFilePath)
|
17
21
|
.catch(() => ({ isFile: () => false }));
|
18
22
|
if (!fileStat.isFile() || fileStat.size !== file.length) {
|
19
23
|
logger.debug({
|
20
24
|
label: Label.RTORRENT,
|
21
|
-
message: `File ${
|
25
|
+
message: `File ${resolvedFilePath} either doesn't exist or is the wrong size.`,
|
22
26
|
});
|
23
27
|
return {
|
24
28
|
completed: 0,
|
@@ -37,10 +41,10 @@ async function createLibTorrentResumeTree(meta, dataDir) {
|
|
37
41
|
files: await Promise.all(meta.files.map(getFileResumeData)),
|
38
42
|
};
|
39
43
|
}
|
40
|
-
async function saveWithLibTorrentResume(meta, savePath,
|
44
|
+
async function saveWithLibTorrentResume(meta, savePath, basePath) {
|
41
45
|
const rawWithLibtorrentResume = {
|
42
46
|
...meta.raw,
|
43
|
-
libtorrent_resume: await createLibTorrentResumeTree(meta,
|
47
|
+
libtorrent_resume: await createLibTorrentResumeTree(meta, basePath),
|
44
48
|
};
|
45
49
|
await fs.writeFile(savePath, new Metafile(rawWithLibtorrentResume).encode());
|
46
50
|
}
|
@@ -85,10 +89,6 @@ export default class RTorrent {
|
|
85
89
|
try {
|
86
90
|
result = await this.methodCallP("system.multicall", [
|
87
91
|
[
|
88
|
-
{
|
89
|
-
methodName: "d.is_multi_file",
|
90
|
-
params: [infoHash],
|
91
|
-
},
|
92
92
|
{
|
93
93
|
methodName: "d.directory",
|
94
94
|
params: [infoHash],
|
@@ -106,14 +106,12 @@ export default class RTorrent {
|
|
106
106
|
}
|
107
107
|
// temp diag for #154
|
108
108
|
try {
|
109
|
-
const [[
|
109
|
+
const [[directoryBase], [isCompleteStr]] = result;
|
110
110
|
const isComplete = Boolean(Number(isCompleteStr));
|
111
111
|
if (!isComplete) {
|
112
112
|
return resultOfErr(InjectionResult.TORRENT_NOT_COMPLETE);
|
113
113
|
}
|
114
|
-
return resultOf({
|
115
|
-
downloadDir: Number(isMultiFileStr) ? dirname(dir) : dir,
|
116
|
-
});
|
114
|
+
return resultOf({ directoryBase });
|
117
115
|
}
|
118
116
|
catch (e) {
|
119
117
|
logger.error(e);
|
@@ -122,6 +120,25 @@ export default class RTorrent {
|
|
122
120
|
return resultOfErr(InjectionResult.FAILURE);
|
123
121
|
}
|
124
122
|
}
|
123
|
+
async getDownloadLocation(meta, searchee, path) {
|
124
|
+
if (path) {
|
125
|
+
const basePath = join(path, searchee.name);
|
126
|
+
const directoryBase = meta.isSingleFileTorrent ? path : basePath;
|
127
|
+
return resultOf({ downloadDir: path, basePath, directoryBase });
|
128
|
+
}
|
129
|
+
else {
|
130
|
+
const result = await this.checkOriginalTorrent(searchee);
|
131
|
+
return result.mapOk(({ directoryBase }) => ({
|
132
|
+
directoryBase,
|
133
|
+
downloadDir: meta.isSingleFileTorrent
|
134
|
+
? directoryBase
|
135
|
+
: dirname(directoryBase),
|
136
|
+
basePath: meta.isSingleFileTorrent
|
137
|
+
? join(directoryBase, searchee.name)
|
138
|
+
: directoryBase,
|
139
|
+
}));
|
140
|
+
}
|
141
|
+
}
|
125
142
|
async validateConfig() {
|
126
143
|
const { rtorrentRpcUrl } = getRuntimeConfig();
|
127
144
|
// no validation to do
|
@@ -140,25 +157,18 @@ export default class RTorrent {
|
|
140
157
|
if (await this.checkForInfoHashInClient(meta.infoHash)) {
|
141
158
|
return InjectionResult.ALREADY_EXISTS;
|
142
159
|
}
|
143
|
-
|
144
|
-
if (
|
145
|
-
|
146
|
-
}
|
147
|
-
else {
|
148
|
-
const result = await this.checkOriginalTorrent(searchee);
|
149
|
-
if (result.isErr()) {
|
150
|
-
return result.unwrapErrOrThrow();
|
151
|
-
}
|
152
|
-
downloadDir = result.unwrapOrThrow().downloadDir;
|
153
|
-
}
|
160
|
+
const result = await this.getDownloadLocation(meta, searchee, path);
|
161
|
+
if (result.isErr())
|
162
|
+
return result.unwrapErrOrThrow();
|
163
|
+
const { directoryBase, basePath } = result.unwrapOrThrow();
|
154
164
|
const torrentFilePath = resolve(outputDir, `${meta.name}.tmp.${Date.now()}.torrent`);
|
155
|
-
await saveWithLibTorrentResume(meta, torrentFilePath,
|
165
|
+
await saveWithLibTorrentResume(meta, torrentFilePath, basePath);
|
156
166
|
for (let i = 0; i < 5; i++) {
|
157
167
|
try {
|
158
168
|
await this.methodCallP("load.start", [
|
159
169
|
"",
|
160
170
|
torrentFilePath,
|
161
|
-
`d.
|
171
|
+
`d.directory_base.set="${directoryBase}"`,
|
162
172
|
`d.custom1.set="cross-seed"`,
|
163
173
|
`d.custom.set=addtime,${Math.round(Date.now() / 1000)}`,
|
164
174
|
]);
|