cross-seed 2.9.3 → 3.0.3

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.
Files changed (91) hide show
  1. package/README.md +2 -1
  2. package/dist/{src/clients → clients}/QBittorrent.js +31 -37
  3. package/dist/clients/QBittorrent.js.map +1 -0
  4. package/dist/{src/clients → clients}/RTorrent.js +45 -48
  5. package/dist/clients/RTorrent.js.map +1 -0
  6. package/dist/clients/TorrentClient.js +20 -0
  7. package/dist/clients/TorrentClient.js.map +1 -0
  8. package/dist/cmd.js +148 -0
  9. package/dist/cmd.js.map +1 -0
  10. package/dist/{src/config.template.js → config.template.cjs} +4 -2
  11. package/dist/config.template.cjs.map +1 -0
  12. package/dist/{src/config.template.docker.js → config.template.docker.cjs} +4 -3
  13. package/dist/config.template.docker.cjs.map +1 -0
  14. package/dist/configuration.js +39 -0
  15. package/dist/configuration.js.map +1 -0
  16. package/dist/constants.js +33 -0
  17. package/dist/constants.js.map +1 -0
  18. package/dist/db.js +29 -0
  19. package/dist/db.js.map +1 -0
  20. package/dist/decide.js +142 -0
  21. package/dist/decide.js.map +1 -0
  22. package/dist/diff.js +23 -0
  23. package/dist/diff.js.map +1 -0
  24. package/dist/errors.js +11 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/jackett.js +68 -0
  27. package/dist/jackett.js.map +1 -0
  28. package/dist/logger.js +88 -0
  29. package/dist/logger.js.map +1 -0
  30. package/dist/pipeline.js +134 -0
  31. package/dist/pipeline.js.map +1 -0
  32. package/dist/preFilter.js +66 -0
  33. package/dist/preFilter.js.map +1 -0
  34. package/dist/pushNotifier.js +27 -0
  35. package/dist/pushNotifier.js.map +1 -0
  36. package/dist/runtimeConfig.js +12 -0
  37. package/dist/runtimeConfig.js.map +1 -0
  38. package/dist/searchee.js +52 -0
  39. package/dist/searchee.js.map +1 -0
  40. package/dist/{src/server.js → server.js} +23 -30
  41. package/dist/server.js.map +1 -0
  42. package/dist/{src/signalHandlers.js → signalHandlers.js} +0 -0
  43. package/dist/signalHandlers.js.map +1 -0
  44. package/dist/startup.js +24 -0
  45. package/dist/startup.js.map +1 -0
  46. package/dist/torrent.js +128 -0
  47. package/dist/torrent.js.map +1 -0
  48. package/dist/utils.js +28 -0
  49. package/dist/utils.js.map +1 -0
  50. package/package.json +22 -25
  51. package/dist/package.json +0 -68
  52. package/dist/src/clients/QBittorrent.js.map +0 -1
  53. package/dist/src/clients/RTorrent.js.map +0 -1
  54. package/dist/src/clients/TorrentClient.js +0 -27
  55. package/dist/src/clients/TorrentClient.js.map +0 -1
  56. package/dist/src/cmd.js +0 -137
  57. package/dist/src/cmd.js.map +0 -1
  58. package/dist/src/config.template.docker.js.map +0 -1
  59. package/dist/src/config.template.js.map +0 -1
  60. package/dist/src/configuration.js +0 -66
  61. package/dist/src/configuration.js.map +0 -1
  62. package/dist/src/constants.js +0 -39
  63. package/dist/src/constants.js.map +0 -1
  64. package/dist/src/db.js +0 -34
  65. package/dist/src/db.js.map +0 -1
  66. package/dist/src/decide.js +0 -143
  67. package/dist/src/decide.js.map +0 -1
  68. package/dist/src/errors.js +0 -15
  69. package/dist/src/errors.js.map +0 -1
  70. package/dist/src/jackett.js +0 -76
  71. package/dist/src/jackett.js.map +0 -1
  72. package/dist/src/logger.js +0 -78
  73. package/dist/src/logger.js.map +0 -1
  74. package/dist/src/pipeline.js +0 -140
  75. package/dist/src/pipeline.js.map +0 -1
  76. package/dist/src/preFilter.js +0 -77
  77. package/dist/src/preFilter.js.map +0 -1
  78. package/dist/src/pushNotifier.js +0 -35
  79. package/dist/src/pushNotifier.js.map +0 -1
  80. package/dist/src/runtimeConfig.js +0 -17
  81. package/dist/src/runtimeConfig.js.map +0 -1
  82. package/dist/src/searchee.js +0 -72
  83. package/dist/src/searchee.js.map +0 -1
  84. package/dist/src/server.js.map +0 -1
  85. package/dist/src/signalHandlers.js.map +0 -1
  86. package/dist/src/startup.js +0 -28
  87. package/dist/src/startup.js.map +0 -1
  88. package/dist/src/torrent.js +0 -169
  89. package/dist/src/torrent.js.map +0 -1
  90. package/dist/src/utils.js +0 -39
  91. package/dist/src/utils.js.map +0 -1
package/README.md CHANGED
@@ -19,7 +19,7 @@ delivery into your client.
19
19
 
20
20
  ## Requirements
21
21
 
22
- - [Node 12+](https://nodejs.org/en/download)
22
+ - [Node 14+](https://nodejs.org/en/download)
23
23
  - [Jackett](https://github.com/Jackett/Jackett)
24
24
 
25
25
  It will work on Mac and on Linux; I haven't tested it on Windows but it should
@@ -59,6 +59,7 @@ Options:
59
59
  -i, --torrent-dir <dir> Directory with torrent files
60
60
  -s, --output-dir <dir> Directory to save results in
61
61
  -a, --search-all Search for all torrents regardless of their contents (default: false)
62
+ --fuzzy-size-threshold <decimal> The size difference allowed to be considered a match. (default: 0.02)
62
63
  -v, --verbose Log verbose output (default: false)
63
64
  -A, --action <action> If set to 'inject', cross-seed will attempt to add the found torrents to your torrent client. (choices: "save", "inject", default: "save")
64
65
  --rtorrent-rpc-url <url> The url of your rtorrent XMLRPC interface. Requires '-A inject'. See the docs for more information.
@@ -1,57 +1,52 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const form_data_1 = __importDefault(require("form-data"));
7
- const node_fetch_1 = __importDefault(require("node-fetch"));
8
- const parse_torrent_1 = __importDefault(require("parse-torrent"));
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 } = runtimeConfig_1.getRuntimeConfig();
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 errors_1.CrossSeedError("qBittorrent url must be percent-encoded");
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 = querystring_1.default.encode({
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 errors_1.CrossSeedError("qBittorrent url must be percent-encoded");
32
+ throw new CrossSeedError("qBittorrent url must be percent-encoded");
38
33
  }
39
34
  let response;
40
35
  try {
41
- response = await node_fetch_1.default(`${origin}${pathname}/auth/login?${qs}`);
36
+ response = await fetch(`${origin}${pathname}/auth/login?${qs}`);
42
37
  }
43
38
  catch (e) {
44
- throw new errors_1.CrossSeedError(`qBittorrent login failed: ${e.message}`);
39
+ throw new CrossSeedError(`qBittorrent login failed: ${e.message}`);
45
40
  }
46
41
  if (response.status !== 200) {
47
- throw new errors_1.CrossSeedError(`qBittorrent login failed with code ${response.status}`);
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 errors_1.CrossSeedError(`qBittorrent login failed: Invalid username or password`);
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
- logger_1.logger.verbose({
63
- label: logger_1.Label.QBITTORRENT,
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 node_fetch_1.default(`${origin}${pathname}${path}`, {
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
- logger_1.logger.verbose({
74
- label: logger_1.Label.QBITTORRENT,
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 constants_1.InjectionResult.ALREADY_EXISTS;
101
+ return InjectionResult.ALREADY_EXISTS;
107
102
  }
108
- const buf = parse_torrent_1.default.toTorrentFile(newTorrent);
103
+ const buf = parseTorrent.toTorrentFile(newTorrent);
109
104
  try {
110
- const { save_path, category, isComplete, } = await this.getTorrentConfiguration(searchee);
105
+ const { save_path, category, isComplete } = await this.getTorrentConfiguration(searchee);
111
106
  if (!isComplete)
112
- return constants_1.InjectionResult.TORRENT_NOT_COMPLETE;
113
- const formData = new form_data_1.default();
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 constants_1.InjectionResult.SUCCESS;
118
+ return InjectionResult.SUCCESS;
124
119
  }
125
120
  catch (e) {
126
- logger_1.logger.debug({
127
- label: logger_1.Label.QBITTORRENT,
121
+ logger.debug({
122
+ label: Label.QBITTORRENT,
128
123
  message: `injection failed: ${e.message}`,
129
124
  });
130
- return constants_1.InjectionResult.FAILURE;
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
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const bencode_1 = __importDefault(require("bencode"));
7
- const fs_1 = require("fs");
8
- const parse_torrent_1 = __importDefault(require("parse-torrent"));
9
- const path_1 = require("path");
10
- const util_1 = require("util");
11
- const xmlrpc_1 = __importDefault(require("xmlrpc"));
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 = path_1.resolve(dataDir, file.path);
20
- const fileStat = await fs_1.promises
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
- logger_1.logger.debug({
25
- label: logger_1.Label.RTORRENT,
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 = bencode_1.default.decode(parse_torrent_1.default.toTorrentFile(meta));
41
+ const rawMeta = bencode.decode(parseTorrent.toTorrentFile(meta));
47
42
  rawMeta.libtorrent_resume = await createLibTorrentResumeTree(meta, dataDir);
48
- await fs_1.promises.writeFile(savePath, bencode_1.default.encode(rawMeta));
43
+ await fs.writeFile(savePath, bencode.encode(rawMeta));
49
44
  }
50
- class RTorrent {
45
+ export default class RTorrent {
51
46
  constructor() {
52
- const { rtorrentRpcUrl } = runtimeConfig_1.getRuntimeConfig();
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
- ? xmlrpc_1.default.createSecureClient
57
- : xmlrpc_1.default.createClient;
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,16 @@ class RTorrent {
67
62
  });
68
63
  }
69
64
  catch (e) {
70
- throw new errors_1.CrossSeedError("rTorrent url must be percent-encoded");
65
+ throw new CrossSeedError("rTorrent url must be percent-encoded");
71
66
  }
72
67
  }
73
68
  async methodCallP(method, args) {
74
- logger_1.logger.verbose({
75
- label: logger_1.Label.RTORRENT,
76
- message: `Calling method ${method} with params ${util_1.inspect(args)}`,
69
+ logger.verbose({
70
+ label: Label.RTORRENT,
71
+ message: `Calling method ${method} with params ${inspect(args, {
72
+ depth: null,
73
+ compact: true,
74
+ })}`,
77
75
  });
78
76
  return new Promise((resolve, reject) => {
79
77
  this.client.methodCall(method, args, (err, data) => {
@@ -89,7 +87,7 @@ class RTorrent {
89
87
  }
90
88
  async getTorrentConfiguration(searchee) {
91
89
  if (!searchee.infoHash) {
92
- throw new errors_1.CrossSeedError("rTorrent direct injection not implemented for data-based searchees");
90
+ throw new CrossSeedError("rTorrent direct injection not implemented for data-based searchees");
93
91
  }
94
92
  const infoHash = searchee.infoHash.toUpperCase();
95
93
  const result = await this.methodCallP("system.multicall", [
@@ -112,18 +110,18 @@ class RTorrent {
112
110
  try {
113
111
  const [[isMultiFileStr], [dir], [isCompleteStr]] = result;
114
112
  return {
115
- dataDir: Number(isMultiFileStr) ? path_1.dirname(dir) : dir,
113
+ dataDir: Number(isMultiFileStr) ? dirname(dir) : dir,
116
114
  isComplete: Boolean(Number(isCompleteStr)),
117
115
  };
118
116
  }
119
117
  catch (e) {
120
- logger_1.logger.error(e);
121
- logger_1.logger.debug("Failure caused by server response below:");
122
- logger_1.logger.debug(util_1.inspect(result));
118
+ logger.error(e);
119
+ logger.debug("Failure caused by server response below:");
120
+ logger.debug(inspect(result));
123
121
  }
124
122
  }
125
123
  async validateConfig() {
126
- const { rtorrentRpcUrl } = runtimeConfig_1.getRuntimeConfig();
124
+ const { rtorrentRpcUrl } = getRuntimeConfig();
127
125
  // no validation to do
128
126
  if (!rtorrentRpcUrl)
129
127
  return;
@@ -131,19 +129,19 @@ class RTorrent {
131
129
  await this.methodCallP("download_list", []);
132
130
  }
133
131
  catch (e) {
134
- throw new errors_1.CrossSeedError(`Failed to reach rTorrent at ${rtorrentRpcUrl}`);
132
+ throw new CrossSeedError(`Failed to reach rTorrent at ${rtorrentRpcUrl}`);
135
133
  }
136
134
  }
137
135
  async inject(meta, searchee, nonceOptions) {
138
- const { outputDir: runtimeConfigOutputDir } = runtimeConfig_1.getRuntimeConfig();
136
+ const { outputDir: runtimeConfigOutputDir } = getRuntimeConfig();
139
137
  const { outputDir = runtimeConfigOutputDir } = nonceOptions;
140
138
  if (await this.checkForInfoHashInClient(meta.infoHash)) {
141
- return constants_1.InjectionResult.ALREADY_EXISTS;
139
+ return InjectionResult.ALREADY_EXISTS;
142
140
  }
143
141
  const { dataDir, isComplete } = await this.getTorrentConfiguration(searchee);
144
142
  if (!isComplete)
145
- return constants_1.InjectionResult.TORRENT_NOT_COMPLETE;
146
- const torrentFilePath = path_1.resolve(outputDir, `${meta.name}.tmp.${Date.now()}.torrent`);
143
+ return InjectionResult.TORRENT_NOT_COMPLETE;
144
+ const torrentFilePath = resolve(outputDir, `${meta.name}.tmp.${Date.now()}.torrent`);
147
145
  await saveWithLibTorrentResume(meta, torrentFilePath, dataDir);
148
146
  for (let i = 0; i < 5; i++) {
149
147
  try {
@@ -157,19 +155,18 @@ class RTorrent {
157
155
  break;
158
156
  }
159
157
  catch (e) {
160
- await utils_1.wait(1000 * Math.pow(2, i));
158
+ await wait(1000 * Math.pow(2, i));
161
159
  }
162
160
  }
163
161
  for (let i = 0; i < 5; i++) {
164
162
  if (await this.checkForInfoHashInClient(meta.infoHash)) {
165
- setTimeout(() => fs_1.promises.unlink(torrentFilePath), 1000);
166
- return constants_1.InjectionResult.SUCCESS;
163
+ setTimeout(() => fs.unlink(torrentFilePath), 1000);
164
+ return InjectionResult.SUCCESS;
167
165
  }
168
- await utils_1.wait(100 * Math.pow(2, i));
166
+ await wait(100 * Math.pow(2, i));
169
167
  }
170
- setTimeout(() => fs_1.promises.unlink(torrentFilePath), 1000);
171
- return constants_1.InjectionResult.FAILURE;
168
+ setTimeout(() => fs.unlink(torrentFilePath), 1000);
169
+ return InjectionResult.FAILURE;
172
170
  }
173
171
  }
174
- exports.default = RTorrent;
175
172
  //# 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"}
package/dist/cmd.js ADDED
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ import chalk from "chalk";
3
+ import { Option, program } from "commander";
4
+ import { createRequire } from "module";
5
+ import { inspect } from "util";
6
+ import { generateConfig, getFileConfig } from "./configuration.js";
7
+ import { Action } from "./constants.js";
8
+ import { dropDatabase } from "./db.js";
9
+ import { diffCmd } from "./diff.js";
10
+ import { CrossSeedError } from "./errors.js";
11
+ import { initializeLogger, Label, logger } from "./logger.js";
12
+ import { main } from "./pipeline.js";
13
+ import { initializePushNotifier, sendTestNotification, } from "./pushNotifier.js";
14
+ import { setRuntimeConfig } from "./runtimeConfig.js";
15
+ import { createSearcheeFromMetafile } from "./searchee.js";
16
+ import { serve } from "./server.js";
17
+ import "./signalHandlers.js";
18
+ import { doStartupValidation } from "./startup.js";
19
+ import { parseTorrentFromFilename } from "./torrent.js";
20
+ const require = createRequire(import.meta.url);
21
+ const packageDotJson = require("../package.json");
22
+ function fallback(...args) {
23
+ for (const arg of args) {
24
+ if (arg !== undefined)
25
+ return arg;
26
+ }
27
+ return undefined;
28
+ }
29
+ function processOptions(options) {
30
+ var _a;
31
+ options.trackers = (_a = options.trackers) === null || _a === void 0 ? void 0 : _a.split(",").filter((e) => e !== "");
32
+ return options;
33
+ }
34
+ const fileConfig = await getFileConfig();
35
+ function createCommandWithSharedOptions(name, description) {
36
+ var _a;
37
+ return program
38
+ .command(name)
39
+ .description(description)
40
+ .requiredOption("-u, --jackett-server-url <url>", "Your Jackett server url", fileConfig.jackettServerUrl)
41
+ .requiredOption("-k, --jackett-api-key <key>", "Your Jackett API key", fileConfig.jackettApiKey)
42
+ .requiredOption("-t, --trackers <tracker1>,<tracker2>", "Comma-separated list of Jackett tracker ids to search (Tracker ids can be found in their Torznab feed paths)", fallback((_a = fileConfig.trackers) === null || _a === void 0 ? void 0 : _a.join(","), ""))
43
+ .requiredOption("-i, --torrent-dir <dir>", "Directory with torrent files", fileConfig.torrentDir)
44
+ .requiredOption("-s, --output-dir <dir>", "Directory to save results in", fileConfig.outputDir)
45
+ .requiredOption("-a, --search-all", "Search for all torrents regardless of their contents", fallback(fileConfig.searchAll, false))
46
+ .requiredOption("--fuzzy-size-threshold <decimal>", "The size difference allowed to be considered a match.", fallback(fileConfig.fuzzySizeThreshold, 0.02))
47
+ .option("-x, --exclude-older <cutoff>", "Exclude torrents first seen more than n minutes ago. Bypasses the -a flag.", (n) => parseInt(n), fileConfig.excludeOlder)
48
+ .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
+ .requiredOption("-v, --verbose", "Log verbose output", false)
50
+ .addOption(new Option("-A, --action <action>", "If set to 'inject', cross-seed will attempt to add the found torrents to your torrent client.")
51
+ .default(fallback(fileConfig.action, Action.SAVE))
52
+ .choices(Object.values(Action))
53
+ .makeOptionMandatory())
54
+ .option("--rtorrent-rpc-url <url>", "The url of your rtorrent XMLRPC interface. Requires '-A inject'. See the docs for more information.", fileConfig.rtorrentRpcUrl)
55
+ .option("--qbittorrent-url <url>", "The url of your qBittorrent webui. Requires '-A inject'. See the docs for more information.", fileConfig.qbittorrentUrl)
56
+ .option("--notification-webhook-url <url>", "cross-seed will send POST requests to this url with a JSON payload of { title, body }", fileConfig.notificationWebhookUrl);
57
+ }
58
+ program.name(packageDotJson.name);
59
+ program.description(chalk.yellow.bold("cross-seed"));
60
+ program.version(packageDotJson.version, "-V, --version", "output the current version");
61
+ program
62
+ .command("gen-config")
63
+ .description("Generate a config file")
64
+ .option("-d, --docker", "Generate the docker config instead of the normal one")
65
+ .action((options) => {
66
+ generateConfig(options);
67
+ });
68
+ program
69
+ .command("clear-cache")
70
+ .description("Clear the cache of downloaded-and-rejected torrents")
71
+ .action(dropDatabase);
72
+ program
73
+ .command("test-notification")
74
+ .description("Send a test notification")
75
+ .requiredOption("--notification-webhook-url <url>", "cross-seed will send POST requests to this url with a JSON payload of { title, body }", fileConfig.notificationWebhookUrl)
76
+ .action((options) => {
77
+ const runtimeConfig = processOptions(options);
78
+ setRuntimeConfig(runtimeConfig);
79
+ initializeLogger();
80
+ initializePushNotifier();
81
+ sendTestNotification();
82
+ });
83
+ program
84
+ .command("diff")
85
+ .description("Analyze two torrent files for cross-seed compatibility")
86
+ .argument("searchee")
87
+ .argument("candidate")
88
+ .action(diffCmd);
89
+ program
90
+ .command("tree")
91
+ .description("Print a torrent's file tree")
92
+ .argument("torrent")
93
+ .action(async (fn) => {
94
+ console.log(createSearcheeFromMetafile(await parseTorrentFromFilename(fn)));
95
+ });
96
+ createCommandWithSharedOptions("daemon", "Start the cross-seed daemon").action(async (options) => {
97
+ try {
98
+ const runtimeConfig = processOptions(options);
99
+ setRuntimeConfig(runtimeConfig);
100
+ initializeLogger();
101
+ initializePushNotifier();
102
+ logger.verbose({
103
+ label: Label.CONFIGDUMP,
104
+ message: inspect(runtimeConfig),
105
+ });
106
+ if (process.env.DOCKER_ENV === "true") {
107
+ generateConfig({ docker: true });
108
+ }
109
+ await doStartupValidation();
110
+ await serve();
111
+ }
112
+ catch (e) {
113
+ if (e instanceof CrossSeedError) {
114
+ e.print();
115
+ process.exitCode = 1;
116
+ return;
117
+ }
118
+ throw e;
119
+ }
120
+ });
121
+ createCommandWithSharedOptions("search", "Search for cross-seeds")
122
+ .requiredOption("-o, --offset <offset>", "Offset to start from", (n) => parseInt(n), 0)
123
+ .requiredOption("-d, --delay <delay>", "Pause duration (seconds) between searches", parseFloat, fallback(fileConfig.delay, 10))
124
+ .option("-e, --include-episodes", "Include single-episode torrents in the search", fallback(fileConfig.includeEpisodes, false))
125
+ .action(async (options) => {
126
+ try {
127
+ const runtimeConfig = processOptions(options);
128
+ setRuntimeConfig(runtimeConfig);
129
+ initializeLogger();
130
+ initializePushNotifier();
131
+ logger.verbose({
132
+ label: Label.CONFIGDUMP,
133
+ message: inspect(runtimeConfig),
134
+ });
135
+ await doStartupValidation();
136
+ await main();
137
+ }
138
+ catch (e) {
139
+ if (e instanceof CrossSeedError) {
140
+ e.print();
141
+ process.exitCode = 1;
142
+ return;
143
+ }
144
+ throw e;
145
+ }
146
+ });
147
+ await program.parseAsync();
148
+ //# sourceMappingURL=cmd.js.map
@@ -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.
@@ -23,6 +22,9 @@ module.exports = {
23
22
  // search for all torrents, regardless of their contents
24
23
  // this option overrides includeEpisodes.
25
24
  searchAll: false,
25
+ // fuzzy size match threshold
26
+ // decimal value (0.02 = 2%)
27
+ fuzzySizeThreshold: 0.02,
26
28
  // Exclude torrents first seen more than n minutes ago.
27
29
  excludeOlder: undefined,
28
30
  // Exclude torrents which have been searched
@@ -45,4 +47,4 @@ module.exports = {
45
47
  // Conforms to the caronc/apprise REST API.
46
48
  notificationWebhookUrl: undefined,
47
49
  };
48
- //# sourceMappingURL=config.template.js.map
50
+ //# 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,6BAA6B;IAC7B,4BAA4B;IAC5B,kBAAkB,EAAE,IAAI;IAExB,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 = {
@@ -28,6 +26,9 @@ module.exports = {
28
26
  // search for all torrents, regardless of their contents
29
27
  // this option overrides includeEpisodes.
30
28
  searchAll: false,
29
+ // fuzzy size match threshold
30
+ // decimal value (0.02 = 2%)
31
+ fuzzySizeThreshold: 0.02,
31
32
  // Exclude torrents first seen more than n minutes ago.
32
33
  excludeOlder: undefined,
33
34
  // Exclude torrents which have been searched
@@ -50,4 +51,4 @@ module.exports = {
50
51
  // Conforms to the caronc/apprise REST API.
51
52
  notificationWebhookUrl: undefined,
52
53
  };
53
- //# sourceMappingURL=config.template.docker.js.map
54
+ //# 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,6BAA6B;IAC7B,4BAA4B;IAC5B,kBAAkB,EAAE,IAAI;IAExB,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