cross-seed 2.9.3 → 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/clients → clients}/QBittorrent.js +31 -37
- package/dist/clients/QBittorrent.js.map +1 -0
- package/dist/{src/clients → clients}/RTorrent.js +42 -48
- package/dist/clients/RTorrent.js.map +1 -0
- package/dist/clients/TorrentClient.js +20 -0
- package/dist/clients/TorrentClient.js.map +1 -0
- package/dist/{src/cmd.js → cmd.js} +54 -57
- package/dist/cmd.js.map +1 -0
- package/dist/{src/config.template.js → config.template.cjs} +1 -2
- package/dist/config.template.cjs.map +1 -0
- package/dist/{src/config.template.docker.js → config.template.docker.cjs} +1 -3
- package/dist/config.template.docker.cjs.map +1 -0
- package/dist/configuration.js +39 -0
- package/dist/configuration.js.map +1 -0
- package/dist/constants.js +33 -0
- package/dist/constants.js.map +1 -0
- package/dist/db.js +28 -0
- package/dist/db.js.map +1 -0
- package/dist/decide.js +132 -0
- package/dist/decide.js.map +1 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/jackett.js +68 -0
- package/dist/jackett.js.map +1 -0
- package/dist/{src/logger.js → logger.js} +22 -25
- package/dist/logger.js.map +1 -0
- package/dist/pipeline.js +134 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/preFilter.js +66 -0
- package/dist/preFilter.js.map +1 -0
- package/dist/pushNotifier.js +27 -0
- package/dist/pushNotifier.js.map +1 -0
- package/dist/runtimeConfig.js +12 -0
- package/dist/runtimeConfig.js.map +1 -0
- package/dist/searchee.js +49 -0
- package/dist/searchee.js.map +1 -0
- package/dist/{src/server.js → server.js} +23 -30
- package/dist/server.js.map +1 -0
- package/dist/{src/signalHandlers.js → signalHandlers.js} +0 -0
- package/dist/signalHandlers.js.map +1 -0
- package/dist/startup.js +24 -0
- package/dist/startup.js.map +1 -0
- package/dist/torrent.js +128 -0
- package/dist/torrent.js.map +1 -0
- package/dist/utils.js +28 -0
- package/dist/utils.js.map +1 -0
- package/package.json +21 -25
- package/dist/package.json +0 -68
- package/dist/src/clients/QBittorrent.js.map +0 -1
- package/dist/src/clients/RTorrent.js.map +0 -1
- package/dist/src/clients/TorrentClient.js +0 -27
- package/dist/src/clients/TorrentClient.js.map +0 -1
- package/dist/src/cmd.js.map +0 -1
- package/dist/src/config.template.docker.js.map +0 -1
- package/dist/src/config.template.js.map +0 -1
- package/dist/src/configuration.js +0 -66
- package/dist/src/configuration.js.map +0 -1
- package/dist/src/constants.js +0 -39
- package/dist/src/constants.js.map +0 -1
- package/dist/src/db.js +0 -34
- package/dist/src/db.js.map +0 -1
- package/dist/src/decide.js +0 -143
- package/dist/src/decide.js.map +0 -1
- package/dist/src/errors.js +0 -15
- package/dist/src/errors.js.map +0 -1
- package/dist/src/jackett.js +0 -76
- package/dist/src/jackett.js.map +0 -1
- package/dist/src/logger.js.map +0 -1
- package/dist/src/pipeline.js +0 -140
- package/dist/src/pipeline.js.map +0 -1
- package/dist/src/preFilter.js +0 -77
- package/dist/src/preFilter.js.map +0 -1
- package/dist/src/pushNotifier.js +0 -35
- package/dist/src/pushNotifier.js.map +0 -1
- package/dist/src/runtimeConfig.js +0 -17
- package/dist/src/runtimeConfig.js.map +0 -1
- package/dist/src/searchee.js +0 -72
- package/dist/src/searchee.js.map +0 -1
- package/dist/src/server.js.map +0 -1
- package/dist/src/signalHandlers.js.map +0 -1
- package/dist/src/startup.js +0 -28
- package/dist/src/startup.js.map +0 -1
- package/dist/src/torrent.js +0 -169
- package/dist/src/torrent.js.map +0 -1
- package/dist/src/utils.js +0 -39
- package/dist/src/utils.js.map +0 -1
@@ -1,57 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
const querystring_1 = __importDefault(require("querystring"));
|
10
|
-
const constants_1 = require("../constants");
|
11
|
-
const errors_1 = require("../errors");
|
12
|
-
const logger_1 = require("../logger");
|
13
|
-
const runtimeConfig_1 = require("../runtimeConfig");
|
1
|
+
import FormData from "form-data";
|
2
|
+
import fetch from "node-fetch";
|
3
|
+
import parseTorrent from "parse-torrent";
|
4
|
+
import querystring from "querystring";
|
5
|
+
import { InjectionResult } from "../constants.js";
|
6
|
+
import { CrossSeedError } from "../errors.js";
|
7
|
+
import { Label, logger } from "../logger.js";
|
8
|
+
import { getRuntimeConfig } from "../runtimeConfig.js";
|
14
9
|
const X_WWW_FORM_URLENCODED = {
|
15
10
|
"Content-Type": "application/x-www-form-urlencoded",
|
16
11
|
};
|
17
|
-
class QBittorrent {
|
12
|
+
export default class QBittorrent {
|
18
13
|
constructor() {
|
19
|
-
const { qbittorrentUrl } =
|
14
|
+
const { qbittorrentUrl } = getRuntimeConfig();
|
20
15
|
try {
|
21
16
|
this.url = new URL(`${qbittorrentUrl}/api/v2`);
|
22
17
|
}
|
23
18
|
catch (e) {
|
24
|
-
throw new
|
19
|
+
throw new CrossSeedError("qBittorrent url must be percent-encoded");
|
25
20
|
}
|
26
21
|
}
|
27
22
|
async login() {
|
28
23
|
const { origin, pathname, username, password } = this.url;
|
29
24
|
let qs;
|
30
25
|
try {
|
31
|
-
qs =
|
26
|
+
qs = querystring.encode({
|
32
27
|
username: decodeURIComponent(username),
|
33
28
|
password: decodeURIComponent(password),
|
34
29
|
});
|
35
30
|
}
|
36
31
|
catch (e) {
|
37
|
-
throw new
|
32
|
+
throw new CrossSeedError("qBittorrent url must be percent-encoded");
|
38
33
|
}
|
39
34
|
let response;
|
40
35
|
try {
|
41
|
-
response = await
|
36
|
+
response = await fetch(`${origin}${pathname}/auth/login?${qs}`);
|
42
37
|
}
|
43
38
|
catch (e) {
|
44
|
-
throw new
|
39
|
+
throw new CrossSeedError(`qBittorrent login failed: ${e.message}`);
|
45
40
|
}
|
46
41
|
if (response.status !== 200) {
|
47
|
-
throw new
|
42
|
+
throw new CrossSeedError(`qBittorrent login failed with code ${response.status}`);
|
48
43
|
}
|
49
44
|
const cookieArray = response.headers.raw()["set-cookie"];
|
50
45
|
if (cookieArray) {
|
51
46
|
this.cookie = cookieArray[0].split(";")[0];
|
52
47
|
}
|
53
48
|
else {
|
54
|
-
throw new
|
49
|
+
throw new CrossSeedError(`qBittorrent login failed: Invalid username or password`);
|
55
50
|
}
|
56
51
|
}
|
57
52
|
async validateConfig() {
|
@@ -59,19 +54,19 @@ class QBittorrent {
|
|
59
54
|
await this.createTag();
|
60
55
|
}
|
61
56
|
async request(path, body, headers = {}, retries = 1) {
|
62
|
-
|
63
|
-
label:
|
57
|
+
logger.verbose({
|
58
|
+
label: Label.QBITTORRENT,
|
64
59
|
message: `Making request to ${path} with body ${body.toString()}`,
|
65
60
|
});
|
66
61
|
const { origin, pathname } = this.url;
|
67
|
-
const response = await
|
62
|
+
const response = await fetch(`${origin}${pathname}${path}`, {
|
68
63
|
method: "post",
|
69
64
|
headers: { Cookie: this.cookie, ...headers },
|
70
65
|
body,
|
71
66
|
});
|
72
67
|
if (response.status === 403 && retries > 0) {
|
73
|
-
|
74
|
-
label:
|
68
|
+
logger.verbose({
|
69
|
+
label: Label.QBITTORRENT,
|
75
70
|
message: "received 403 from API. Logging in again and retrying",
|
76
71
|
});
|
77
72
|
await this.login();
|
@@ -103,14 +98,14 @@ class QBittorrent {
|
|
103
98
|
}
|
104
99
|
async inject(newTorrent, searchee, nonceOptions) {
|
105
100
|
if (await this.isInfoHashInClient(newTorrent.infoHash)) {
|
106
|
-
return
|
101
|
+
return InjectionResult.ALREADY_EXISTS;
|
107
102
|
}
|
108
|
-
const buf =
|
103
|
+
const buf = parseTorrent.toTorrentFile(newTorrent);
|
109
104
|
try {
|
110
|
-
const { save_path, category, isComplete
|
105
|
+
const { save_path, category, isComplete } = await this.getTorrentConfiguration(searchee);
|
111
106
|
if (!isComplete)
|
112
|
-
return
|
113
|
-
const formData = new
|
107
|
+
return InjectionResult.TORRENT_NOT_COMPLETE;
|
108
|
+
const formData = new FormData();
|
114
109
|
formData.append("torrents", buf, {
|
115
110
|
filename: `${newTorrent.name}.cross-seed.torrent`,
|
116
111
|
contentType: "application/x-bittorrent",
|
@@ -120,16 +115,15 @@ class QBittorrent {
|
|
120
115
|
formData.append("tags", "cross-seed");
|
121
116
|
formData.append("autoTMM", "false");
|
122
117
|
await this.request("/torrents/add", formData);
|
123
|
-
return
|
118
|
+
return InjectionResult.SUCCESS;
|
124
119
|
}
|
125
120
|
catch (e) {
|
126
|
-
|
127
|
-
label:
|
121
|
+
logger.debug({
|
122
|
+
label: Label.QBITTORRENT,
|
128
123
|
message: `injection failed: ${e.message}`,
|
129
124
|
});
|
130
|
-
return
|
125
|
+
return InjectionResult.FAILURE;
|
131
126
|
}
|
132
127
|
}
|
133
128
|
}
|
134
|
-
exports.default = QBittorrent;
|
135
129
|
//# sourceMappingURL=QBittorrent.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"QBittorrent.js","sourceRoot":"","sources":["../../src/clients/QBittorrent.ts"],"names":[],"mappings":"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"}
|
@@ -1,28 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
};
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
const constants_1 = require("../constants");
|
13
|
-
const errors_1 = require("../errors");
|
14
|
-
const logger_1 = require("../logger");
|
15
|
-
const runtimeConfig_1 = require("../runtimeConfig");
|
16
|
-
const utils_1 = require("../utils");
|
1
|
+
import bencode from "bencode";
|
2
|
+
import { promises as fs } from "fs";
|
3
|
+
import parseTorrent from "parse-torrent";
|
4
|
+
import { dirname, resolve } from "path";
|
5
|
+
import { inspect } from "util";
|
6
|
+
import xmlrpc from "xmlrpc";
|
7
|
+
import { InjectionResult } from "../constants.js";
|
8
|
+
import { CrossSeedError } from "../errors.js";
|
9
|
+
import { Label, logger } from "../logger.js";
|
10
|
+
import { getRuntimeConfig } from "../runtimeConfig.js";
|
11
|
+
import { wait } from "../utils.js";
|
17
12
|
async function createLibTorrentResumeTree(meta, dataDir) {
|
18
13
|
async function getFileResumeData(file) {
|
19
|
-
const filePath =
|
20
|
-
const fileStat = await
|
14
|
+
const filePath = resolve(dataDir, file.path);
|
15
|
+
const fileStat = await fs
|
21
16
|
.lstat(filePath)
|
22
17
|
.catch(() => ({ isFile: () => false }));
|
23
18
|
if (!fileStat.isFile() || fileStat.size !== file.length) {
|
24
|
-
|
25
|
-
label:
|
19
|
+
logger.debug({
|
20
|
+
label: Label.RTORRENT,
|
26
21
|
message: `File ${filePath} either doesn't exist or is the wrong size.`,
|
27
22
|
});
|
28
23
|
return {
|
@@ -43,18 +38,18 @@ async function createLibTorrentResumeTree(meta, dataDir) {
|
|
43
38
|
};
|
44
39
|
}
|
45
40
|
async function saveWithLibTorrentResume(meta, savePath, dataDir) {
|
46
|
-
const rawMeta =
|
41
|
+
const rawMeta = bencode.decode(parseTorrent.toTorrentFile(meta));
|
47
42
|
rawMeta.libtorrent_resume = await createLibTorrentResumeTree(meta, dataDir);
|
48
|
-
await
|
43
|
+
await fs.writeFile(savePath, bencode.encode(rawMeta));
|
49
44
|
}
|
50
|
-
class RTorrent {
|
45
|
+
export default class RTorrent {
|
51
46
|
constructor() {
|
52
|
-
const { rtorrentRpcUrl } =
|
47
|
+
const { rtorrentRpcUrl } = getRuntimeConfig();
|
53
48
|
try {
|
54
49
|
const { origin, username, password, protocol, pathname } = new URL(rtorrentRpcUrl);
|
55
50
|
const clientCreator = protocol === "https:"
|
56
|
-
?
|
57
|
-
:
|
51
|
+
? xmlrpc.createSecureClient
|
52
|
+
: xmlrpc.createClient;
|
58
53
|
const shouldUseAuth = Boolean(username && password);
|
59
54
|
this.client = clientCreator({
|
60
55
|
url: origin + pathname,
|
@@ -67,13 +62,13 @@ class RTorrent {
|
|
67
62
|
});
|
68
63
|
}
|
69
64
|
catch (e) {
|
70
|
-
throw new
|
65
|
+
throw new CrossSeedError("rTorrent url must be percent-encoded");
|
71
66
|
}
|
72
67
|
}
|
73
68
|
async methodCallP(method, args) {
|
74
|
-
|
75
|
-
label:
|
76
|
-
message: `Calling method ${method} with params ${
|
69
|
+
logger.verbose({
|
70
|
+
label: Label.RTORRENT,
|
71
|
+
message: `Calling method ${method} with params ${inspect(args)}`,
|
77
72
|
});
|
78
73
|
return new Promise((resolve, reject) => {
|
79
74
|
this.client.methodCall(method, args, (err, data) => {
|
@@ -89,7 +84,7 @@ class RTorrent {
|
|
89
84
|
}
|
90
85
|
async getTorrentConfiguration(searchee) {
|
91
86
|
if (!searchee.infoHash) {
|
92
|
-
throw new
|
87
|
+
throw new CrossSeedError("rTorrent direct injection not implemented for data-based searchees");
|
93
88
|
}
|
94
89
|
const infoHash = searchee.infoHash.toUpperCase();
|
95
90
|
const result = await this.methodCallP("system.multicall", [
|
@@ -112,18 +107,18 @@ class RTorrent {
|
|
112
107
|
try {
|
113
108
|
const [[isMultiFileStr], [dir], [isCompleteStr]] = result;
|
114
109
|
return {
|
115
|
-
dataDir: Number(isMultiFileStr) ?
|
110
|
+
dataDir: Number(isMultiFileStr) ? dirname(dir) : dir,
|
116
111
|
isComplete: Boolean(Number(isCompleteStr)),
|
117
112
|
};
|
118
113
|
}
|
119
114
|
catch (e) {
|
120
|
-
|
121
|
-
|
122
|
-
|
115
|
+
logger.error(e);
|
116
|
+
logger.debug("Failure caused by server response below:");
|
117
|
+
logger.debug(inspect(result));
|
123
118
|
}
|
124
119
|
}
|
125
120
|
async validateConfig() {
|
126
|
-
const { rtorrentRpcUrl } =
|
121
|
+
const { rtorrentRpcUrl } = getRuntimeConfig();
|
127
122
|
// no validation to do
|
128
123
|
if (!rtorrentRpcUrl)
|
129
124
|
return;
|
@@ -131,19 +126,19 @@ class RTorrent {
|
|
131
126
|
await this.methodCallP("download_list", []);
|
132
127
|
}
|
133
128
|
catch (e) {
|
134
|
-
throw new
|
129
|
+
throw new CrossSeedError(`Failed to reach rTorrent at ${rtorrentRpcUrl}`);
|
135
130
|
}
|
136
131
|
}
|
137
132
|
async inject(meta, searchee, nonceOptions) {
|
138
|
-
const { outputDir: runtimeConfigOutputDir } =
|
133
|
+
const { outputDir: runtimeConfigOutputDir } = getRuntimeConfig();
|
139
134
|
const { outputDir = runtimeConfigOutputDir } = nonceOptions;
|
140
135
|
if (await this.checkForInfoHashInClient(meta.infoHash)) {
|
141
|
-
return
|
136
|
+
return InjectionResult.ALREADY_EXISTS;
|
142
137
|
}
|
143
138
|
const { dataDir, isComplete } = await this.getTorrentConfiguration(searchee);
|
144
139
|
if (!isComplete)
|
145
|
-
return
|
146
|
-
const torrentFilePath =
|
140
|
+
return InjectionResult.TORRENT_NOT_COMPLETE;
|
141
|
+
const torrentFilePath = resolve(outputDir, `${meta.name}.tmp.${Date.now()}.torrent`);
|
147
142
|
await saveWithLibTorrentResume(meta, torrentFilePath, dataDir);
|
148
143
|
for (let i = 0; i < 5; i++) {
|
149
144
|
try {
|
@@ -157,19 +152,18 @@ class RTorrent {
|
|
157
152
|
break;
|
158
153
|
}
|
159
154
|
catch (e) {
|
160
|
-
await
|
155
|
+
await wait(1000 * Math.pow(2, i));
|
161
156
|
}
|
162
157
|
}
|
163
158
|
for (let i = 0; i < 5; i++) {
|
164
159
|
if (await this.checkForInfoHashInClient(meta.infoHash)) {
|
165
|
-
setTimeout(() =>
|
166
|
-
return
|
160
|
+
setTimeout(() => fs.unlink(torrentFilePath), 1000);
|
161
|
+
return InjectionResult.SUCCESS;
|
167
162
|
}
|
168
|
-
await
|
163
|
+
await wait(100 * Math.pow(2, i));
|
169
164
|
}
|
170
|
-
setTimeout(() =>
|
171
|
-
return
|
165
|
+
setTimeout(() => fs.unlink(torrentFilePath), 1000);
|
166
|
+
return InjectionResult.FAILURE;
|
172
167
|
}
|
173
168
|
}
|
174
|
-
exports.default = RTorrent;
|
175
169
|
//# sourceMappingURL=RTorrent.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"RTorrent.js","sourceRoot":"","sources":["../../src/clients/RTorrent.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { getRuntimeConfig } from "../runtimeConfig.js";
|
2
|
+
import QBittorrent from "./QBittorrent.js";
|
3
|
+
import RTorrent from "./RTorrent.js";
|
4
|
+
let activeClient;
|
5
|
+
function instantiateDownloadClient() {
|
6
|
+
const { rtorrentRpcUrl, qbittorrentUrl } = getRuntimeConfig();
|
7
|
+
if (rtorrentRpcUrl) {
|
8
|
+
activeClient = new RTorrent();
|
9
|
+
}
|
10
|
+
else if (qbittorrentUrl) {
|
11
|
+
activeClient = new QBittorrent();
|
12
|
+
}
|
13
|
+
}
|
14
|
+
export function getClient() {
|
15
|
+
if (!activeClient) {
|
16
|
+
instantiateDownloadClient();
|
17
|
+
}
|
18
|
+
return activeClient;
|
19
|
+
}
|
20
|
+
//# sourceMappingURL=TorrentClient.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"TorrentClient.js","sourceRoot":"","sources":["../../src/clients/TorrentClient.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAgB,MAAM,qBAAqB,CAAC;AAErE,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,IAAI,YAA2B,CAAC;AAWhC,SAAS,yBAAyB;IACjC,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC9D,IAAI,cAAc,EAAE;QACnB,YAAY,GAAG,IAAI,QAAQ,EAAE,CAAC;KAC9B;SAAM,IAAI,cAAc,EAAE;QAC1B,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC;KACjC;AACF,CAAC;AAED,MAAM,UAAU,SAAS;IACxB,IAAI,CAAC,YAAY,EAAE;QAClB,yBAAyB,EAAE,CAAC;KAC5B;IACD,OAAO,YAAY,CAAC;AACrB,CAAC"}
|
@@ -1,24 +1,21 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
};
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
const
|
18
|
-
const
|
19
|
-
const util_1 = require("util");
|
20
|
-
require("./signalHandlers");
|
21
|
-
const startup_1 = require("./startup");
|
2
|
+
import chalk from "chalk";
|
3
|
+
import { Option, program } from "commander";
|
4
|
+
import { inspect } from "util";
|
5
|
+
import { generateConfig, getFileConfig } from "./configuration.js";
|
6
|
+
import { Action } from "./constants.js";
|
7
|
+
import { dropDatabase } from "./db.js";
|
8
|
+
import { CrossSeedError } from "./errors.js";
|
9
|
+
import { initializeLogger, Label, logger } from "./logger.js";
|
10
|
+
import { main } from "./pipeline.js";
|
11
|
+
import { initializePushNotifier, sendTestNotification, } from "./pushNotifier.js";
|
12
|
+
import { setRuntimeConfig } from "./runtimeConfig.js";
|
13
|
+
import { serve } from "./server.js";
|
14
|
+
import "./signalHandlers.js";
|
15
|
+
import { doStartupValidation } from "./startup.js";
|
16
|
+
import { createRequire } from "module";
|
17
|
+
const require = createRequire(import.meta.url);
|
18
|
+
const packageDotJson = require("../package.json");
|
22
19
|
function fallback(...args) {
|
23
20
|
for (const arg of args) {
|
24
21
|
if (arg !== undefined)
|
@@ -32,10 +29,10 @@ function processOptions(options) {
|
|
32
29
|
return options;
|
33
30
|
}
|
34
31
|
async function run() {
|
35
|
-
const fileConfig =
|
32
|
+
const fileConfig = await getFileConfig();
|
36
33
|
function createCommandWithSharedOptions(name, description) {
|
37
34
|
var _a;
|
38
|
-
return
|
35
|
+
return program
|
39
36
|
.command(name)
|
40
37
|
.description(description)
|
41
38
|
.requiredOption("-u, --jackett-server-url <url>", "Your Jackett server url", fileConfig.jackettServerUrl)
|
@@ -47,46 +44,46 @@ async function run() {
|
|
47
44
|
.option("-x, --exclude-older <cutoff>", "Exclude torrents first seen more than n minutes ago. Bypasses the -a flag.", (n) => parseInt(n), fileConfig.excludeOlder)
|
48
45
|
.option("-r, --exclude-recent-search <cutoff>", "Exclude torrents which have been searched more recently than n minutes ago. Bypasses the -a flag.", (n) => parseInt(n), fileConfig.excludeRecentSearch)
|
49
46
|
.requiredOption("-v, --verbose", "Log verbose output", false)
|
50
|
-
.addOption(new
|
51
|
-
.default(fallback(fileConfig.action,
|
52
|
-
.choices(Object.values(
|
47
|
+
.addOption(new Option("-A, --action <action>", "If set to 'inject', cross-seed will attempt to add the found torrents to your torrent client.")
|
48
|
+
.default(fallback(fileConfig.action, Action.SAVE))
|
49
|
+
.choices(Object.values(Action))
|
53
50
|
.makeOptionMandatory())
|
54
51
|
.option("--rtorrent-rpc-url <url>", "The url of your rtorrent XMLRPC interface. Requires '-A inject'. See the docs for more information.", fileConfig.rtorrentRpcUrl)
|
55
52
|
.option("--qbittorrent-url <url>", "The url of your qBittorrent webui. Requires '-A inject'. See the docs for more information.", fileConfig.qbittorrentUrl)
|
56
53
|
.option("--notification-webhook-url <url>", "cross-seed will send POST requests to this url with a JSON payload of { title, body }", fileConfig.notificationWebhookUrl);
|
57
54
|
}
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
program.name(packageDotJson.name);
|
56
|
+
program.description(chalk.yellow.bold("cross-seed"));
|
57
|
+
program.version(packageDotJson.version, "-V, --version", "output the current version");
|
58
|
+
program
|
62
59
|
.command("gen-config")
|
63
60
|
.description("Generate a config file")
|
64
61
|
.option("-d, --docker", "Generate the docker config instead of the normal one")
|
65
62
|
.action((options) => {
|
66
|
-
|
63
|
+
generateConfig(options);
|
67
64
|
});
|
68
|
-
|
65
|
+
program
|
69
66
|
.command("clear-cache")
|
70
67
|
.description("Clear the cache of downloaded-and-rejected torrents")
|
71
|
-
.action(
|
68
|
+
.action(dropDatabase);
|
72
69
|
createCommandWithSharedOptions("daemon", "Start the cross-seed daemon").action(async (options) => {
|
73
70
|
try {
|
74
71
|
const runtimeConfig = processOptions(options);
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
label:
|
80
|
-
message:
|
72
|
+
setRuntimeConfig(runtimeConfig);
|
73
|
+
initializeLogger();
|
74
|
+
initializePushNotifier();
|
75
|
+
logger.verbose({
|
76
|
+
label: Label.CONFIGDUMP,
|
77
|
+
message: inspect(runtimeConfig),
|
81
78
|
});
|
82
79
|
if (process.env.DOCKER_ENV === "true") {
|
83
|
-
|
80
|
+
generateConfig({ docker: true });
|
84
81
|
}
|
85
|
-
await
|
86
|
-
await
|
82
|
+
await doStartupValidation();
|
83
|
+
await serve();
|
87
84
|
}
|
88
85
|
catch (e) {
|
89
|
-
if (e instanceof
|
86
|
+
if (e instanceof CrossSeedError) {
|
90
87
|
e.print();
|
91
88
|
process.exitCode = 1;
|
92
89
|
return;
|
@@ -94,16 +91,16 @@ async function run() {
|
|
94
91
|
throw e;
|
95
92
|
}
|
96
93
|
});
|
97
|
-
|
94
|
+
program
|
98
95
|
.command("test-notification")
|
99
96
|
.description("Send a test notification")
|
100
97
|
.requiredOption("--notification-webhook-url <url>", "cross-seed will send POST requests to this url with a JSON payload of { title, body }", fileConfig.notificationWebhookUrl)
|
101
98
|
.action((options) => {
|
102
99
|
const runtimeConfig = processOptions(options);
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
100
|
+
setRuntimeConfig(runtimeConfig);
|
101
|
+
initializeLogger();
|
102
|
+
initializePushNotifier();
|
103
|
+
sendTestNotification();
|
107
104
|
});
|
108
105
|
createCommandWithSharedOptions("search", "Search for cross-seeds")
|
109
106
|
.requiredOption("-o, --offset <offset>", "Offset to start from", (n) => parseInt(n), 0)
|
@@ -112,18 +109,18 @@ async function run() {
|
|
112
109
|
.action(async (options) => {
|
113
110
|
try {
|
114
111
|
const runtimeConfig = processOptions(options);
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
label:
|
120
|
-
message:
|
112
|
+
setRuntimeConfig(runtimeConfig);
|
113
|
+
initializeLogger();
|
114
|
+
initializePushNotifier();
|
115
|
+
logger.verbose({
|
116
|
+
label: Label.CONFIGDUMP,
|
117
|
+
message: inspect(runtimeConfig),
|
121
118
|
});
|
122
|
-
await
|
123
|
-
await
|
119
|
+
await doStartupValidation();
|
120
|
+
await main();
|
124
121
|
}
|
125
122
|
catch (e) {
|
126
|
-
if (e instanceof
|
123
|
+
if (e instanceof CrossSeedError) {
|
127
124
|
e.print();
|
128
125
|
process.exitCode = 1;
|
129
126
|
return;
|
@@ -131,7 +128,7 @@ async function run() {
|
|
131
128
|
throw e;
|
132
129
|
}
|
133
130
|
});
|
134
|
-
await
|
131
|
+
await program.parseAsync();
|
135
132
|
}
|
136
133
|
run();
|
137
134
|
//# sourceMappingURL=cmd.js.map
|
package/dist/cmd.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"cmd.js","sourceRoot":"","sources":["../src/cmd.ts"],"names":[],"mappings":"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"}
|
@@ -1,7 +1,6 @@
|
|
1
1
|
// If you find yourself always using the same command-line flag, you can set
|
2
2
|
// it here as a default.
|
3
3
|
module.exports = {
|
4
|
-
configVersion: 1,
|
5
4
|
jackettServerUrl: "http://localhost:9117/jackett",
|
6
5
|
jackettApiKey: "YOUR_JACKETT_API_KEY_HERE",
|
7
6
|
// Pause at least this much in between each Jackett search. Higher is safer.
|
@@ -45,4 +44,4 @@ module.exports = {
|
|
45
44
|
// Conforms to the caronc/apprise REST API.
|
46
45
|
notificationWebhookUrl: undefined,
|
47
46
|
};
|
48
|
-
//# sourceMappingURL=config.template.
|
47
|
+
//# sourceMappingURL=config.template.cjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"config.template.cjs","sourceRoot":"","sources":["../src/config.template.cjs"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,wBAAwB;AAExB,MAAM,CAAC,OAAO,GAAG;IAChB,gBAAgB,EAAE,+BAA+B;IACjD,aAAa,EAAE,2BAA2B;IAE1C,4EAA4E;IAC5E,4DAA4D;IAC5D,KAAK,EAAE,EAAE;IAET,qBAAqB;IACrB,gDAAgD;IAChD,uDAAuD;IACvD,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;IAEnC,sCAAsC;IACtC,+CAA+C;IAC/C,2CAA2C;IAC3C,8CAA8C;IAC9C,UAAU,EAAE,2BAA2B;IAEvC,gEAAgE;IAChE,SAAS,EAAE,GAAG;IAEd,gDAAgD;IAChD,eAAe,EAAE,KAAK;IAEtB,wDAAwD;IACxD,yCAAyC;IACzC,SAAS,EAAE,KAAK;IAEhB,uDAAuD;IACvD,YAAY,EAAE,SAAS;IAEvB,4CAA4C;IAC5C,oCAAoC;IACpC,mBAAmB,EAAE,SAAS;IAE9B,oCAAoC;IACpC,6DAA6D;IAC7D,MAAM,EAAE,MAAM;IAEd,6CAA6C;IAC7C,uCAAuC;IACvC,wEAAwE;IACxE,cAAc,EAAE,SAAS;IAEzB,qCAAqC;IACrC,uCAAuC;IACvC,4DAA4D;IAC5D,4CAA4C;IAC5C,cAAc,EAAE,SAAS;IAEzB,iDAAiD;IACjD,0CAA0C;IAC1C,2CAA2C;IAC3C,sBAAsB,EAAE,SAAS;CACjC,CAAC"}
|
@@ -1,5 +1,3 @@
|
|
1
|
-
// All of the configuration can be overridden with command-line flags,
|
2
|
-
// and some are more useful as flags than permanent config (offset).
|
3
1
|
// If you find yourself always using the same command-line flag, you can set
|
4
2
|
// it here as a default.
|
5
3
|
module.exports = {
|
@@ -50,4 +48,4 @@ module.exports = {
|
|
50
48
|
// Conforms to the caronc/apprise REST API.
|
51
49
|
notificationWebhookUrl: undefined,
|
52
50
|
};
|
53
|
-
//# sourceMappingURL=config.template.docker.
|
51
|
+
//# sourceMappingURL=config.template.docker.cjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"config.template.docker.cjs","sourceRoot":"","sources":["../src/config.template.docker.cjs"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,wBAAwB;AAExB,MAAM,CAAC,OAAO,GAAG;IAChB,gBAAgB,EAAE,6BAA6B;IAC/C,aAAa,EAAE,2BAA2B;IAE1C,4EAA4E;IAC5E,4DAA4D;IAC5D,KAAK,EAAE,EAAE;IAET,qBAAqB;IACrB,gDAAgD;IAChD,uDAAuD;IACvD,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;IAEnC,sCAAsC;IACtC,+CAA+C;IAC/C,2CAA2C;IAC3C,8CAA8C;IAC9C,gCAAgC;IAChC,2DAA2D;IAC3D,UAAU,EAAE,WAAW;IAEvB,gEAAgE;IAChE,gCAAgC;IAChC,2DAA2D;IAC3D,SAAS,EAAE,cAAc;IAEzB,gDAAgD;IAChD,eAAe,EAAE,KAAK;IAEtB,wDAAwD;IACxD,yCAAyC;IACzC,SAAS,EAAE,KAAK;IAEhB,uDAAuD;IACvD,YAAY,EAAE,SAAS;IAEvB,4CAA4C;IAC5C,oCAAoC;IACpC,mBAAmB,EAAE,SAAS;IAE9B,oCAAoC;IACpC,6DAA6D;IAC7D,MAAM,EAAE,MAAM;IAEd,6CAA6C;IAC7C,uCAAuC;IACvC,wEAAwE;IACxE,cAAc,EAAE,SAAS;IAEzB,qCAAqC;IACrC,uCAAuC;IACvC,4DAA4D;IAC5D,4CAA4C;IAC5C,cAAc,EAAE,SAAS;IAEzB,iDAAiD;IACjD,0CAA0C;IAC1C,2CAA2C;IAC3C,sBAAsB,EAAE,SAAS;CACjC,CAAC"}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
import { copyFileSync, existsSync, mkdirSync } from "fs";
|
3
|
+
import { createRequire } from "module";
|
4
|
+
import path from "path";
|
5
|
+
const require = createRequire(import.meta.url);
|
6
|
+
const packageDotJson = require("../package.json");
|
7
|
+
export function appDir() {
|
8
|
+
return (process.env.CONFIG_DIR ||
|
9
|
+
(process.platform === "win32"
|
10
|
+
? path.resolve(process.env.LOCALAPPDATA, packageDotJson.name)
|
11
|
+
: path.resolve(process.env.HOME, `.${packageDotJson.name}`)));
|
12
|
+
}
|
13
|
+
export function createAppDir() {
|
14
|
+
mkdirSync(path.join(appDir(), "torrent_cache"), { recursive: true });
|
15
|
+
mkdirSync(path.join(appDir(), "logs"), { recursive: true });
|
16
|
+
}
|
17
|
+
export function generateConfig({ force = false, docker = false, }) {
|
18
|
+
createAppDir();
|
19
|
+
const dest = path.join(appDir(), "config.js");
|
20
|
+
const templatePath = path.join(`./config.template${docker ? ".docker" : ""}.cjs`);
|
21
|
+
if (!force && existsSync(dest)) {
|
22
|
+
console.log("Configuration file already exists.");
|
23
|
+
return;
|
24
|
+
}
|
25
|
+
copyFileSync(new URL(templatePath, import.meta.url), dest);
|
26
|
+
console.log("Configuration file created at", chalk.yellow.bold(dest));
|
27
|
+
}
|
28
|
+
export async function getFileConfig() {
|
29
|
+
const configPath = path.join(appDir(), "config.js");
|
30
|
+
try {
|
31
|
+
return (await import(configPath)).default;
|
32
|
+
}
|
33
|
+
catch (e) {
|
34
|
+
if (e.code !== "ERR_MODULE_NOT_FOUND")
|
35
|
+
throw e;
|
36
|
+
return {};
|
37
|
+
}
|
38
|
+
}
|
39
|
+
//# sourceMappingURL=configuration.js.map
|