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.
- package/README.md +2 -1
- package/dist/{src/clients → clients}/QBittorrent.js +31 -37
- package/dist/clients/QBittorrent.js.map +1 -0
- package/dist/{src/clients → clients}/RTorrent.js +45 -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/cmd.js +148 -0
- package/dist/cmd.js.map +1 -0
- package/dist/{src/config.template.js → config.template.cjs} +4 -2
- package/dist/config.template.cjs.map +1 -0
- package/dist/{src/config.template.docker.js → config.template.docker.cjs} +4 -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 +29 -0
- package/dist/db.js.map +1 -0
- package/dist/decide.js +142 -0
- package/dist/decide.js.map +1 -0
- package/dist/diff.js +23 -0
- package/dist/diff.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/logger.js +88 -0
- 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 +52 -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 +22 -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 +0 -137
- 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 +0 -78
- 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
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"configuration.js","sourceRoot":"","sources":["../src/configuration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AA0BlD,MAAM,UAAU,MAAM;IACrB,OAAO,CACN,OAAO,CAAC,GAAG,CAAC,UAAU;QACtB,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC5B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC;YAC7D,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAC7D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC3B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAC9B,KAAK,GAAG,KAAK,EACb,MAAM,GAAG,KAAK,GACQ;IACtB,YAAY,EAAE,CAAC;IACf,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAC7B,oBAAoB,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,CACjD,CAAC;IACF,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE;QAC/B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,OAAO;KACP;IACD,YAAY,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC;IAEpD,IAAI;QACH,OAAO,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;KAC1C;IAAC,OAAO,CAAC,EAAE;QACX,IAAI,CAAC,CAAC,IAAI,KAAK,sBAAsB;YAAE,MAAM,CAAC,CAAC;QAC/C,OAAO,EAAE,CAAC;KACV;AACF,CAAC"}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
export const EP_REGEX = /^(?<title>.+)[. ](?<season>S\d+)(?<episode>E\d+)/i;
|
2
|
+
export const SEASON_REGEX = /^(?<title>.+)[. ](?<season>S\d+)(?:\s?-\s?(?<seasonmax>S?\d+))?(?!E\d+)/i;
|
3
|
+
export const MOVIE_REGEX = /^(?<title>.+)[. ][[(]?(?<year>\d{4})[)\]]?(?![pi])/i;
|
4
|
+
export const EXTENSIONS = ["mkv", "mp4", "avi"];
|
5
|
+
export const CONFIG_TEMPLATE_URL = "https://github.com/mmgoodnow/cross-seed/blob/master/src/config.template.js";
|
6
|
+
export const TORRENT_CACHE_FOLDER = "torrent_cache";
|
7
|
+
export var Action;
|
8
|
+
(function (Action) {
|
9
|
+
Action["SAVE"] = "save";
|
10
|
+
Action["INJECT"] = "inject";
|
11
|
+
})(Action = Action || (Action = {}));
|
12
|
+
export var InjectionResult;
|
13
|
+
(function (InjectionResult) {
|
14
|
+
InjectionResult[InjectionResult["SUCCESS"] = 0] = "SUCCESS";
|
15
|
+
InjectionResult[InjectionResult["FAILURE"] = 1] = "FAILURE";
|
16
|
+
InjectionResult[InjectionResult["ALREADY_EXISTS"] = 2] = "ALREADY_EXISTS";
|
17
|
+
InjectionResult[InjectionResult["TORRENT_NOT_COMPLETE"] = 3] = "TORRENT_NOT_COMPLETE";
|
18
|
+
})(InjectionResult = InjectionResult || (InjectionResult = {}));
|
19
|
+
export var Decision;
|
20
|
+
(function (Decision) {
|
21
|
+
Decision["MATCH"] = "MATCH";
|
22
|
+
Decision["SIZE_MISMATCH"] = "SIZE_MISMATCH";
|
23
|
+
Decision["NO_DOWNLOAD_LINK"] = "NO_DOWNLOAD_LINK";
|
24
|
+
Decision["DOWNLOAD_FAILED"] = "DOWNLOAD_FAILED";
|
25
|
+
Decision["INFO_HASH_ALREADY_EXISTS"] = "INFO_HASH_ALREADY_EXISTS";
|
26
|
+
Decision["FILE_TREE_MISMATCH"] = "FILE_TREE_MISMATCH";
|
27
|
+
})(Decision = Decision || (Decision = {}));
|
28
|
+
export const PermanentDecisions = [
|
29
|
+
Decision.SIZE_MISMATCH,
|
30
|
+
Decision.NO_DOWNLOAD_LINK,
|
31
|
+
Decision.FILE_TREE_MISMATCH,
|
32
|
+
];
|
33
|
+
//# sourceMappingURL=constants.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,mDAAmD,CAAC;AAC5E,MAAM,CAAC,MAAM,YAAY,GACxB,0EAA0E,CAAC;AAC5E,MAAM,CAAC,MAAM,WAAW,GACvB,qDAAqD,CAAC;AAEvD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAEhD,MAAM,CAAC,MAAM,mBAAmB,GAC/B,4EAA4E,CAAC;AAE9E,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD,MAAM,CAAN,IAAY,MAGX;AAHD,WAAY,MAAM;IACjB,uBAAa,CAAA;IACb,2BAAiB,CAAA;AAClB,CAAC,EAHW,MAAM,GAAN,MAAM,KAAN,MAAM,QAGjB;AAED,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IAC1B,2DAAO,CAAA;IACP,2DAAO,CAAA;IACP,yEAAc,CAAA;IACd,qFAAoB,CAAA;AACrB,CAAC,EALW,eAAe,GAAf,eAAe,KAAf,eAAe,QAK1B;AAED,MAAM,CAAN,IAAY,QAOX;AAPD,WAAY,QAAQ;IACnB,2BAAe,CAAA;IACf,2CAA+B,CAAA;IAC/B,iDAAqC,CAAA;IACrC,+CAAmC,CAAA;IACnC,iEAAqD,CAAA;IACrD,qDAAyC,CAAA;AAC1C,CAAC,EAPW,QAAQ,GAAR,QAAQ,KAAR,QAAQ,QAOnB;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC7C,QAAQ,CAAC,aAAa;IACtB,QAAQ,CAAC,gBAAgB;IACzB,QAAQ,CAAC,kBAAkB;CAC3B,CAAC"}
|
package/dist/db.js
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
var _a;
|
2
|
+
import { unlinkSync } from "fs";
|
3
|
+
import { JSONFileSync, LowSync } from "lowdb";
|
4
|
+
import path from "path";
|
5
|
+
import rimraf from "rimraf";
|
6
|
+
import { appDir, createAppDir } from "./configuration.js";
|
7
|
+
createAppDir();
|
8
|
+
const emptyDatabase = {
|
9
|
+
searchees: {},
|
10
|
+
decisions: {},
|
11
|
+
indexedTorrents: [],
|
12
|
+
dbVersion: 3,
|
13
|
+
};
|
14
|
+
const db = new LowSync(new JSONFileSync(path.join(appDir(), "cache.json")));
|
15
|
+
db.read();
|
16
|
+
(_a = db.data) !== null && _a !== void 0 ? _a : (db.data = emptyDatabase);
|
17
|
+
const dbVersion = db.data.dbVersion;
|
18
|
+
if (!dbVersion || dbVersion < emptyDatabase.dbVersion) {
|
19
|
+
db.data = emptyDatabase;
|
20
|
+
}
|
21
|
+
db.write();
|
22
|
+
export function dropDatabase() {
|
23
|
+
db.data = emptyDatabase;
|
24
|
+
db.write();
|
25
|
+
unlinkSync(path.join(appDir(), "cache.json"));
|
26
|
+
rimraf.sync(path.join(appDir(), "torrent_cache"));
|
27
|
+
}
|
28
|
+
export default db;
|
29
|
+
//# sourceMappingURL=db.js.map
|
package/dist/db.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG1D,YAAY,EAAE,CAAC;AA4Bf,MAAM,aAAa,GAAG;IACrB,SAAS,EAAE,EAAE;IACb,SAAS,EAAE,EAAE;IACb,eAAe,EAAE,EAAE;IACnB,SAAS,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,EAAE,GAAG,IAAI,OAAO,CACrB,IAAI,YAAY,CAAS,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAC3D,CAAC;AAEF,EAAE,CAAC,IAAI,EAAE,CAAC;AAEV,MAAA,EAAE,CAAC,IAAI,oCAAP,EAAE,CAAC,IAAI,GAAK,aAAa,EAAC;AAE1B,MAAM,SAAS,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;AAEpC,IAAI,CAAC,SAAS,IAAI,SAAS,GAAG,aAAa,CAAC,SAAS,EAAE;IACtD,EAAE,CAAC,IAAI,GAAG,aAAa,CAAC;CACxB;AAED,EAAE,CAAC,KAAK,EAAE,CAAC;AAEX,MAAM,UAAU,YAAY;IAC3B,EAAE,CAAC,IAAI,GAAG,aAAa,CAAC;IACxB,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,eAAe,EAAE,CAAC"}
|
package/dist/decide.js
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
import { existsSync, writeFileSync } from "fs";
|
2
|
+
import parseTorrent from "parse-torrent";
|
3
|
+
import path from "path";
|
4
|
+
import { appDir } from "./configuration.js";
|
5
|
+
import { Decision, TORRENT_CACHE_FOLDER } from "./constants.js";
|
6
|
+
import db from "./db.js";
|
7
|
+
import { Label, logger } from "./logger.js";
|
8
|
+
import { getRuntimeConfig } from "./runtimeConfig.js";
|
9
|
+
import { parseTorrentFromFilename, parseTorrentFromURL } from "./torrent.js";
|
10
|
+
const createReasonLogger = (Title, tracker, name) => (decision, cached) => {
|
11
|
+
function logReason(reason) {
|
12
|
+
logger.verbose({
|
13
|
+
label: Label.DECIDE,
|
14
|
+
message: `${name} - no match for ${tracker} torrent ${Title} - ${reason}`,
|
15
|
+
});
|
16
|
+
}
|
17
|
+
let reason;
|
18
|
+
switch (decision) {
|
19
|
+
case Decision.MATCH:
|
20
|
+
return;
|
21
|
+
case Decision.SIZE_MISMATCH:
|
22
|
+
reason = "its size does not match";
|
23
|
+
break;
|
24
|
+
case Decision.NO_DOWNLOAD_LINK:
|
25
|
+
reason = "it doesn't have a download link";
|
26
|
+
break;
|
27
|
+
case Decision.DOWNLOAD_FAILED:
|
28
|
+
reason = "the torrent file failed to download";
|
29
|
+
break;
|
30
|
+
case Decision.INFO_HASH_ALREADY_EXISTS:
|
31
|
+
reason = "the info hash matches a torrent you already have";
|
32
|
+
break;
|
33
|
+
case Decision.FILE_TREE_MISMATCH:
|
34
|
+
reason = "it has a different file tree";
|
35
|
+
break;
|
36
|
+
default:
|
37
|
+
reason = decision;
|
38
|
+
break;
|
39
|
+
}
|
40
|
+
if (cached)
|
41
|
+
logReason(`${reason} (cached)`);
|
42
|
+
else
|
43
|
+
logReason(reason);
|
44
|
+
};
|
45
|
+
export function compareFileTrees(candidate, searchee) {
|
46
|
+
const cmp = (elOfA, elOfB) => {
|
47
|
+
const lengthsAreEqual = elOfB.length === elOfA.length;
|
48
|
+
const pathsAreEqual = elOfB.path === elOfA.path;
|
49
|
+
return lengthsAreEqual && pathsAreEqual;
|
50
|
+
};
|
51
|
+
return candidate.files.every((elOfA) => searchee.files.some((elOfB) => cmp(elOfA, elOfB)));
|
52
|
+
}
|
53
|
+
function sizeDoesMatch(resultSize, searchee) {
|
54
|
+
const { fuzzySizeThreshold } = getRuntimeConfig();
|
55
|
+
const { length } = searchee;
|
56
|
+
const lowerBound = length - fuzzySizeThreshold * length;
|
57
|
+
const upperBound = length + fuzzySizeThreshold * length;
|
58
|
+
return resultSize >= lowerBound && resultSize <= upperBound;
|
59
|
+
}
|
60
|
+
async function assessResultHelper({ Link, Size }, searchee, hashesToExclude) {
|
61
|
+
if (!sizeDoesMatch(Size, searchee)) {
|
62
|
+
return { decision: Decision.SIZE_MISMATCH };
|
63
|
+
}
|
64
|
+
if (!Link)
|
65
|
+
return { decision: Decision.NO_DOWNLOAD_LINK };
|
66
|
+
const info = await parseTorrentFromURL(Link);
|
67
|
+
if (!info)
|
68
|
+
return { decision: Decision.DOWNLOAD_FAILED };
|
69
|
+
if (hashesToExclude.includes(info.infoHash)) {
|
70
|
+
return { decision: Decision.INFO_HASH_ALREADY_EXISTS };
|
71
|
+
}
|
72
|
+
if (!compareFileTrees(info, searchee)) {
|
73
|
+
return { decision: Decision.FILE_TREE_MISMATCH };
|
74
|
+
}
|
75
|
+
return { decision: Decision.MATCH, info };
|
76
|
+
}
|
77
|
+
function existsInTorrentCache(infoHash) {
|
78
|
+
return existsSync(path.join(appDir(), TORRENT_CACHE_FOLDER, `${infoHash}.cached.torrent`));
|
79
|
+
}
|
80
|
+
async function getCachedTorrentFile(infoHash) {
|
81
|
+
return parseTorrentFromFilename(path.join(appDir(), TORRENT_CACHE_FOLDER, `${infoHash}.cached.torrent`));
|
82
|
+
}
|
83
|
+
function cacheTorrentFile(meta) {
|
84
|
+
writeFileSync(path.join(appDir(), TORRENT_CACHE_FOLDER, `${meta.infoHash}.cached.torrent`), parseTorrent.toTorrentFile(meta));
|
85
|
+
}
|
86
|
+
async function assessAndSaveResults(result, searchee, Guid, infoHashesToExclude) {
|
87
|
+
const assessment = await assessResultHelper(result, searchee, infoHashesToExclude);
|
88
|
+
db.data.decisions[searchee.name][Guid] = {
|
89
|
+
decision: assessment.decision,
|
90
|
+
lastSeen: Date.now(),
|
91
|
+
firstSeen: Date.now(),
|
92
|
+
};
|
93
|
+
if (assessment.decision === Decision.MATCH) {
|
94
|
+
db.data.decisions[searchee.name][Guid].infoHash =
|
95
|
+
assessment.info.infoHash;
|
96
|
+
cacheTorrentFile(assessment.info);
|
97
|
+
}
|
98
|
+
return assessment;
|
99
|
+
}
|
100
|
+
async function assessResultCaching(result, searchee, infoHashesToExclude) {
|
101
|
+
var _a;
|
102
|
+
var _b, _c;
|
103
|
+
const { Guid, Title, TrackerId: tracker } = result;
|
104
|
+
const logReason = createReasonLogger(Title, tracker, searchee.name);
|
105
|
+
(_a = (_b = db.data.decisions)[_c = searchee.name]) !== null && _a !== void 0 ? _a : (_b[_c] = {});
|
106
|
+
const cacheEntry = db.data.decisions[searchee.name][Guid];
|
107
|
+
let assessment;
|
108
|
+
if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.decision) ||
|
109
|
+
cacheEntry.decision === Decision.DOWNLOAD_FAILED) {
|
110
|
+
assessment = await assessAndSaveResults(result, searchee, Guid, infoHashesToExclude);
|
111
|
+
logReason(assessment.decision, false);
|
112
|
+
}
|
113
|
+
else if (cacheEntry.decision === Decision.MATCH &&
|
114
|
+
infoHashesToExclude.includes(cacheEntry.infoHash)) {
|
115
|
+
// has been added since the last run
|
116
|
+
assessment = { decision: Decision.INFO_HASH_ALREADY_EXISTS };
|
117
|
+
db.data.decisions[searchee.name][Guid].decision =
|
118
|
+
Decision.INFO_HASH_ALREADY_EXISTS;
|
119
|
+
}
|
120
|
+
else if (cacheEntry.decision === Decision.MATCH &&
|
121
|
+
existsInTorrentCache(cacheEntry.infoHash)) {
|
122
|
+
// cached match
|
123
|
+
assessment = {
|
124
|
+
decision: cacheEntry.decision,
|
125
|
+
info: await getCachedTorrentFile(cacheEntry.infoHash),
|
126
|
+
};
|
127
|
+
}
|
128
|
+
else if (cacheEntry.decision === Decision.MATCH) {
|
129
|
+
assessment = await assessAndSaveResults(result, searchee, Guid, infoHashesToExclude);
|
130
|
+
logReason(assessment.decision, false);
|
131
|
+
}
|
132
|
+
else {
|
133
|
+
// cached rejection
|
134
|
+
assessment = { decision: cacheEntry.decision };
|
135
|
+
logReason(cacheEntry.decision, true);
|
136
|
+
}
|
137
|
+
db.data.decisions[searchee.name][Guid].lastSeen = Date.now();
|
138
|
+
db.write();
|
139
|
+
return assessment;
|
140
|
+
}
|
141
|
+
export { assessResultCaching as assessResult };
|
142
|
+
//# sourceMappingURL=decide.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"decide.js","sourceRoot":"","sources":["../src/decide.ts"],"names":[],"mappings":"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"}
|
package/dist/diff.js
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
import { createSearcheeFromMetafile } from "./searchee.js";
|
2
|
+
import { parseTorrentFromFilename } from "./torrent.js";
|
3
|
+
import { deepStrictEqual } from "assert";
|
4
|
+
function diff(thing1, thing2) {
|
5
|
+
try {
|
6
|
+
deepStrictEqual(thing1, thing2);
|
7
|
+
console.log(thing1);
|
8
|
+
console.log("Torrents are equal");
|
9
|
+
}
|
10
|
+
catch (e) {
|
11
|
+
console.log(e);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
export async function diffCmd(first, second) {
|
15
|
+
const firstMeta = await parseTorrentFromFilename(first);
|
16
|
+
const secondMeta = await parseTorrentFromFilename(second);
|
17
|
+
const firstSearchee = createSearcheeFromMetafile(firstMeta);
|
18
|
+
const secondSearchee = createSearcheeFromMetafile(secondMeta);
|
19
|
+
delete firstSearchee.infoHash;
|
20
|
+
delete secondSearchee.infoHash;
|
21
|
+
diff(firstSearchee, secondSearchee);
|
22
|
+
}
|
23
|
+
//# sourceMappingURL=diff.js.map
|
package/dist/diff.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAEzC,SAAS,IAAI,CAAC,MAAM,EAAE,MAAM;IAC3B,IAAI;QACH,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;KAClC;IAAC,OAAO,CAAC,EAAE;QACX,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KACf;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAAa,EAAE,MAAc;IAC1D,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC;IAC5D,MAAM,cAAc,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAC9D,OAAO,aAAa,CAAC,QAAQ,CAAC;IAC9B,OAAO,cAAc,CAAC,QAAQ,CAAC;IAC/B,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/errors.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,OAAO,cAAe,SAAQ,KAAK;IACxC,YAAY,OAAe;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAED,KAAK;QACJ,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;CACD"}
|
package/dist/jackett.js
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
import querystring from "querystring";
|
2
|
+
import get from "simple-get";
|
3
|
+
import { EP_REGEX, MOVIE_REGEX, SEASON_REGEX } from "./constants.js";
|
4
|
+
import { CrossSeedError } from "./errors.js";
|
5
|
+
import { Label, logger } from "./logger.js";
|
6
|
+
import { EmptyNonceOptions, getRuntimeConfig, } from "./runtimeConfig.js";
|
7
|
+
function reformatTitleForSearching(name) {
|
8
|
+
const seasonMatch = name.match(SEASON_REGEX);
|
9
|
+
const movieMatch = name.match(MOVIE_REGEX);
|
10
|
+
const episodeMatch = name.match(EP_REGEX);
|
11
|
+
const fullMatch = episodeMatch
|
12
|
+
? episodeMatch[0]
|
13
|
+
: seasonMatch
|
14
|
+
? seasonMatch[0]
|
15
|
+
: movieMatch
|
16
|
+
? movieMatch[0]
|
17
|
+
: name;
|
18
|
+
return fullMatch
|
19
|
+
.replace(/[.()[\]]/g, " ")
|
20
|
+
.replace(/\s+/g, " ")
|
21
|
+
.trim();
|
22
|
+
}
|
23
|
+
function fullJackettUrl(jackettServerUrl, params) {
|
24
|
+
const jackettPath = `/api/v2.0/indexers/all/results`;
|
25
|
+
return `${jackettServerUrl}${jackettPath}?${querystring.encode(params)}`;
|
26
|
+
}
|
27
|
+
export async function validateJackettApi() {
|
28
|
+
const { jackettServerUrl, jackettApiKey: apikey } = getRuntimeConfig();
|
29
|
+
if (/\/$/.test(jackettServerUrl)) {
|
30
|
+
logger.warn("Warning: Jackett server url should not end with '/'");
|
31
|
+
}
|
32
|
+
// search for gibberish so the results will be empty
|
33
|
+
const gibberish = "bscdjpstabgdspjdasmomdsenqciadsnocdpsikncaodsnimcdqsanc";
|
34
|
+
try {
|
35
|
+
await makeJackettRequest(gibberish);
|
36
|
+
}
|
37
|
+
catch (e) {
|
38
|
+
const dummyUrl = fullJackettUrl(jackettServerUrl, { apikey });
|
39
|
+
throw new CrossSeedError(`Could not reach Jackett at ${dummyUrl}`);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
export function makeJackettRequest(name, nonceOptions = EmptyNonceOptions) {
|
43
|
+
const { jackettApiKey, trackers: runtimeConfigTrackers, jackettServerUrl, } = getRuntimeConfig();
|
44
|
+
const { trackers = runtimeConfigTrackers } = nonceOptions;
|
45
|
+
const params = {
|
46
|
+
apikey: jackettApiKey,
|
47
|
+
Query: reformatTitleForSearching(name),
|
48
|
+
"Tracker[]": trackers,
|
49
|
+
};
|
50
|
+
const opts = {
|
51
|
+
method: "GET",
|
52
|
+
url: fullJackettUrl(jackettServerUrl, params),
|
53
|
+
json: true,
|
54
|
+
};
|
55
|
+
logger.verbose({
|
56
|
+
label: Label.JACKETT,
|
57
|
+
message: `making search with query "${params.Query}"`,
|
58
|
+
});
|
59
|
+
return new Promise((resolve, reject) => {
|
60
|
+
get.concat(opts, (err, res, data) => {
|
61
|
+
if (err)
|
62
|
+
reject(err);
|
63
|
+
else
|
64
|
+
resolve(data);
|
65
|
+
});
|
66
|
+
});
|
67
|
+
}
|
68
|
+
//# sourceMappingURL=jackett.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"jackett.js","sourceRoot":"","sources":["../src/jackett.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.js
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
import { join } from "path";
|
2
|
+
import winston from "winston";
|
3
|
+
import { appDir, createAppDir } from "./configuration.js";
|
4
|
+
import { getRuntimeConfig } from "./runtimeConfig.js";
|
5
|
+
import DailyRotateFile from "winston-daily-rotate-file";
|
6
|
+
export var Label;
|
7
|
+
(function (Label) {
|
8
|
+
Label["QBITTORRENT"] = "qbittorrent";
|
9
|
+
Label["RTORRENT"] = "rtorrent";
|
10
|
+
Label["DECIDE"] = "decide";
|
11
|
+
Label["PREFILTER"] = "prefilter";
|
12
|
+
Label["CONFIGDUMP"] = "configdump";
|
13
|
+
Label["JACKETT"] = "jackett";
|
14
|
+
Label["SERVER"] = "server";
|
15
|
+
Label["STARTUP"] = "startup";
|
16
|
+
})(Label = Label || (Label = {}));
|
17
|
+
export let logger;
|
18
|
+
const redactionMsg = "[REDACTED]";
|
19
|
+
function redactUrlPassword(message, urlStr) {
|
20
|
+
let url;
|
21
|
+
try {
|
22
|
+
url = new URL(urlStr);
|
23
|
+
if (url.password) {
|
24
|
+
const urlDecodedPassword = decodeURIComponent(url.password);
|
25
|
+
const urlEncodedPassword = encodeURIComponent(url.password);
|
26
|
+
message = message.split(url.password).join(redactionMsg);
|
27
|
+
message = message.split(urlDecodedPassword).join(redactionMsg);
|
28
|
+
message = message.split(urlEncodedPassword).join(redactionMsg);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
catch (e) {
|
32
|
+
// do nothing
|
33
|
+
}
|
34
|
+
return message;
|
35
|
+
}
|
36
|
+
function redactMessage(message) {
|
37
|
+
const runtimeConfig = getRuntimeConfig();
|
38
|
+
message = message.split(runtimeConfig.jackettApiKey).join(redactionMsg);
|
39
|
+
for (const [key, urlStr] of Object.entries(runtimeConfig)) {
|
40
|
+
if (key.endsWith("Url") && urlStr) {
|
41
|
+
message = redactUrlPassword(message, urlStr);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
return message;
|
45
|
+
}
|
46
|
+
export function initializeLogger() {
|
47
|
+
createAppDir();
|
48
|
+
logger = winston.createLogger({
|
49
|
+
level: "info",
|
50
|
+
format: winston.format.combine(winston.format.timestamp({
|
51
|
+
format: "YYYY-MM-DD HH:mm:ss",
|
52
|
+
}), winston.format.errors({ stack: true }), winston.format.splat(), winston.format.colorize(), winston.format.printf(({ level, message, label, timestamp }) => {
|
53
|
+
return `${timestamp} ${level}: ${label ? `[${label}] ` : ""}${redactMessage(message)}`;
|
54
|
+
})),
|
55
|
+
transports: [
|
56
|
+
new DailyRotateFile({
|
57
|
+
filename: "error.%DATE%.log",
|
58
|
+
createSymlink: true,
|
59
|
+
symlinkName: "error.current.log",
|
60
|
+
dirname: join(appDir(), "logs"),
|
61
|
+
maxFiles: "14d",
|
62
|
+
level: "error",
|
63
|
+
}),
|
64
|
+
new DailyRotateFile({
|
65
|
+
filename: "info.%DATE%.log",
|
66
|
+
createSymlink: true,
|
67
|
+
symlinkName: "info.current.log",
|
68
|
+
dirname: join(appDir(), "logs"),
|
69
|
+
maxFiles: "14d",
|
70
|
+
}),
|
71
|
+
new DailyRotateFile({
|
72
|
+
filename: "verbose.%DATE%.log",
|
73
|
+
createSymlink: true,
|
74
|
+
symlinkName: "verbose.current.log",
|
75
|
+
dirname: join(appDir(), "logs"),
|
76
|
+
maxFiles: "14d",
|
77
|
+
level: "silly",
|
78
|
+
}),
|
79
|
+
new winston.transports.Console({
|
80
|
+
level: getRuntimeConfig().verbose ? "silly" : "info",
|
81
|
+
format: winston.format.combine(winston.format.errors({ stack: true }), winston.format.splat(), winston.format.colorize(), winston.format.printf(({ level, message, label }) => {
|
82
|
+
return `${level}: ${label ? `[${label}] ` : ""}${redactMessage(message)}`;
|
83
|
+
})),
|
84
|
+
}),
|
85
|
+
],
|
86
|
+
});
|
87
|
+
}
|
88
|
+
//# sourceMappingURL=logger.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
package/dist/pipeline.js
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
import chalk from "chalk";
|
2
|
+
import fs from "fs";
|
3
|
+
import { getClient } from "./clients/TorrentClient.js";
|
4
|
+
import { Action, Decision, InjectionResult } from "./constants.js";
|
5
|
+
import db from "./db.js";
|
6
|
+
import { assessResult } from "./decide.js";
|
7
|
+
import { makeJackettRequest, } from "./jackett.js";
|
8
|
+
import { logger } from "./logger.js";
|
9
|
+
import { filterByContent, filterDupes, filterTimestamps } from "./preFilter.js";
|
10
|
+
import { pushNotifier } from "./pushNotifier.js";
|
11
|
+
import { EmptyNonceOptions, getRuntimeConfig, } from "./runtimeConfig.js";
|
12
|
+
import { getInfoHashesToExclude, getTorrentByCriteria, loadTorrentDirLight, saveTorrentFile, } from "./torrent.js";
|
13
|
+
import { getTag, stripExtension } from "./utils.js";
|
14
|
+
async function findOnOtherSites(searchee, hashesToExclude, nonceOptions = EmptyNonceOptions) {
|
15
|
+
const { action } = getRuntimeConfig();
|
16
|
+
const assessEach = async (result) => ({
|
17
|
+
assessment: await assessResult(result, searchee, hashesToExclude),
|
18
|
+
tracker: result.TrackerId,
|
19
|
+
});
|
20
|
+
const tag = getTag(searchee.name);
|
21
|
+
const query = stripExtension(searchee.name);
|
22
|
+
let response;
|
23
|
+
try {
|
24
|
+
response = await makeJackettRequest(query, nonceOptions);
|
25
|
+
}
|
26
|
+
catch (e) {
|
27
|
+
logger.error(`error querying Jackett for ${query}`);
|
28
|
+
return 0;
|
29
|
+
}
|
30
|
+
const results = response.Results;
|
31
|
+
const loaded = await Promise.all(results.map(assessEach));
|
32
|
+
const successful = loaded.filter((e) => e.assessment.decision === Decision.MATCH);
|
33
|
+
pushNotifier.notify({
|
34
|
+
body: `Found ${searchee.name} on ${successful.length} trackers${successful.length &&
|
35
|
+
// @ts-expect-error ListFormat totally exists in node 12
|
36
|
+
`: ${new Intl.ListFormat("en", {
|
37
|
+
style: "long",
|
38
|
+
type: "conjunction",
|
39
|
+
}).format(successful.map((s) => s.tracker))}`}`,
|
40
|
+
extra: {
|
41
|
+
infoHashes: successful.map((s) => s.assessment.info.infoHash),
|
42
|
+
trackers: successful.map((s) => s.tracker),
|
43
|
+
},
|
44
|
+
});
|
45
|
+
let isTorrentIncomplete;
|
46
|
+
for (const { tracker, assessment: { info: newInfo }, } of successful) {
|
47
|
+
const styledName = chalk.green.bold(newInfo.name);
|
48
|
+
const styledTracker = chalk.bold(tracker);
|
49
|
+
if (action === Action.INJECT) {
|
50
|
+
const result = await getClient().inject(newInfo, searchee, nonceOptions);
|
51
|
+
switch (result) {
|
52
|
+
case InjectionResult.SUCCESS:
|
53
|
+
logger.info(`Found ${styledName} on ${styledTracker} - injected`);
|
54
|
+
break;
|
55
|
+
case InjectionResult.ALREADY_EXISTS:
|
56
|
+
logger.info(`Found ${styledName} on ${styledTracker} - exists`);
|
57
|
+
break;
|
58
|
+
case InjectionResult.TORRENT_NOT_COMPLETE:
|
59
|
+
logger.warn(`Found ${styledName} on ${styledTracker} - skipping incomplete torrent`);
|
60
|
+
isTorrentIncomplete = true;
|
61
|
+
break;
|
62
|
+
case InjectionResult.FAILURE:
|
63
|
+
default:
|
64
|
+
logger.error(`Found ${styledName} on ${styledTracker} - failed to inject, saving instead`);
|
65
|
+
saveTorrentFile(tracker, tag, newInfo, nonceOptions);
|
66
|
+
break;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
saveTorrentFile(tracker, tag, newInfo, nonceOptions);
|
71
|
+
logger.info(`Found ${styledName} on ${styledTracker}`);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
if (!isTorrentIncomplete) {
|
75
|
+
updateSearchTimestamps(searchee.name);
|
76
|
+
}
|
77
|
+
return successful.length;
|
78
|
+
}
|
79
|
+
function updateSearchTimestamps(name) {
|
80
|
+
if (db.data.searchees[name]) {
|
81
|
+
db.data.searchees[name].lastSearched = Date.now();
|
82
|
+
}
|
83
|
+
else {
|
84
|
+
db.data.searchees[name] = {
|
85
|
+
firstSearched: Date.now(),
|
86
|
+
lastSearched: Date.now(),
|
87
|
+
};
|
88
|
+
}
|
89
|
+
db.write();
|
90
|
+
}
|
91
|
+
async function findMatchesBatch(samples, hashesToExclude) {
|
92
|
+
const { delay, offset } = getRuntimeConfig();
|
93
|
+
let totalFound = 0;
|
94
|
+
for (const [i, sample] of samples.entries()) {
|
95
|
+
const sleep = new Promise((r) => setTimeout(r, delay * 1000));
|
96
|
+
const progress = chalk.blue(`[${i + 1 + offset}/${samples.length + offset}]`);
|
97
|
+
const name = stripExtension(sample.name);
|
98
|
+
logger.info("%s %s %s", progress, chalk.dim("Searching for"), name);
|
99
|
+
const numFoundPromise = findOnOtherSites(sample, hashesToExclude);
|
100
|
+
const [numFound] = await Promise.all([numFoundPromise, sleep]);
|
101
|
+
totalFound += numFound;
|
102
|
+
}
|
103
|
+
return totalFound;
|
104
|
+
}
|
105
|
+
export async function searchForLocalTorrentByCriteria(criteria, nonceOptions) {
|
106
|
+
const meta = await getTorrentByCriteria(criteria);
|
107
|
+
const hashesToExclude = getInfoHashesToExclude();
|
108
|
+
if (!filterByContent(meta))
|
109
|
+
return null;
|
110
|
+
return findOnOtherSites(meta, hashesToExclude, nonceOptions);
|
111
|
+
}
|
112
|
+
async function findSearchableTorrents() {
|
113
|
+
const { offset } = getRuntimeConfig();
|
114
|
+
const parsedTorrents = await loadTorrentDirLight();
|
115
|
+
const hashesToExclude = parsedTorrents
|
116
|
+
.map((t) => t.infoHash)
|
117
|
+
.filter(Boolean);
|
118
|
+
const filteredTorrents = filterDupes(parsedTorrents)
|
119
|
+
.filter(filterByContent)
|
120
|
+
.filter(filterTimestamps);
|
121
|
+
const samples = filteredTorrents.slice(offset);
|
122
|
+
logger.info("Found %d torrents, %d suitable to search for matches", parsedTorrents.length, filteredTorrents.length);
|
123
|
+
return { samples, hashesToExclude };
|
124
|
+
}
|
125
|
+
export async function main() {
|
126
|
+
const { offset, outputDir } = getRuntimeConfig();
|
127
|
+
const { samples, hashesToExclude } = await findSearchableTorrents();
|
128
|
+
if (offset > 0)
|
129
|
+
logger.info(`Starting at offset ${offset}`);
|
130
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
131
|
+
const totalFound = await findMatchesBatch(samples, hashesToExclude);
|
132
|
+
logger.info(chalk.cyan("Done! Found %s cross seeds from %s original torrents"), chalk.bold.white(totalFound), chalk.bold.white(samples.length));
|
133
|
+
}
|
134
|
+
//# sourceMappingURL=pipeline.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
|