cross-seed 2.9.1 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +52 -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 +134 -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 -136
  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 -140
  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
@@ -0,0 +1,66 @@
1
+ import { uniqBy } from "lodash-es";
2
+ import path from "path";
3
+ import { EP_REGEX, EXTENSIONS } from "./constants.js";
4
+ import db from "./db.js";
5
+ import { Label, logger } from "./logger.js";
6
+ import { getRuntimeConfig } from "./runtimeConfig.js";
7
+ import { nMinutesAgo } from "./utils.js";
8
+ const extensionsWithDots = EXTENSIONS.map((e) => `.${e}`);
9
+ export function filterByContent(searchee) {
10
+ const { includeEpisodes, searchAll } = getRuntimeConfig();
11
+ if (searchAll)
12
+ return true;
13
+ function logReason(reason) {
14
+ logger.verbose({
15
+ label: Label.PREFILTER,
16
+ message: `Torrent ${searchee.name} was not selected for searching because ${reason}`,
17
+ });
18
+ }
19
+ if (!includeEpisodes &&
20
+ searchee.files.length === 1 &&
21
+ EP_REGEX.test(searchee.files[0].name)) {
22
+ logReason("it is a single episode");
23
+ return false;
24
+ }
25
+ const allVideos = searchee.files.every((file) => extensionsWithDots.includes(path.extname(file.name)));
26
+ if (!allVideos) {
27
+ logReason("not all files are videos");
28
+ return false;
29
+ }
30
+ return true;
31
+ }
32
+ export function filterDupes(searchees) {
33
+ const filtered = uniqBy(searchees, "name");
34
+ const numDupes = searchees.length - filtered.length;
35
+ if (numDupes > 0) {
36
+ logger.verbose({
37
+ label: Label.PREFILTER,
38
+ message: `${numDupes} duplicates not selected for searching`,
39
+ });
40
+ }
41
+ return filtered;
42
+ }
43
+ export function filterTimestamps(searchee) {
44
+ const { excludeOlder, excludeRecentSearch } = getRuntimeConfig();
45
+ const timestampData = db.data.searchees[searchee.name];
46
+ if (!timestampData)
47
+ return true;
48
+ const { firstSearched, lastSearched } = timestampData;
49
+ function logReason(reason) {
50
+ logger.verbose({
51
+ label: Label.PREFILTER,
52
+ message: `Torrent ${searchee.name} was not selected for searching because ${reason}`,
53
+ });
54
+ }
55
+ if (excludeOlder && firstSearched < nMinutesAgo(excludeOlder)) {
56
+ logReason(`its first search timestamp ${firstSearched} is older than ${excludeOlder} minutes ago`);
57
+ return false;
58
+ }
59
+ if (excludeRecentSearch &&
60
+ lastSearched > nMinutesAgo(excludeRecentSearch)) {
61
+ logReason(`its last search timestamp ${lastSearched} is newer than ${excludeRecentSearch} minutes ago`);
62
+ return false;
63
+ }
64
+ return true;
65
+ }
66
+ //# sourceMappingURL=preFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preFilter.js","sourceRoot":"","sources":["../src/preFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,kBAAkB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAE1D,MAAM,UAAU,eAAe,CAAC,QAAkB;IACjD,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAE1D,IAAI,SAAS;QAAE,OAAO,IAAI,CAAC;IAE3B,SAAS,SAAS,CAAC,MAAM;QACxB,MAAM,CAAC,OAAO,CAAC;YACd,KAAK,EAAE,KAAK,CAAC,SAAS;YACtB,OAAO,EAAE,WAAW,QAAQ,CAAC,IAAI,2CAA2C,MAAM,EAAE;SACpF,CAAC,CAAC;IACJ,CAAC;IAED,IACC,CAAC,eAAe;QAChB,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAC3B,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EACpC;QACD,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;KACb;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAC/C,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CACpD,CAAC;IAEF,IAAI,CAAC,SAAS,EAAE;QACf,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACtC,OAAO,KAAK,CAAC;KACb;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAqB;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAW,SAAS,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IACpD,IAAI,QAAQ,GAAG,CAAC,EAAE;QACjB,MAAM,CAAC,OAAO,CAAC;YACd,KAAK,EAAE,KAAK,CAAC,SAAS;YACtB,OAAO,EAAE,GAAG,QAAQ,wCAAwC;SAC5D,CAAC,CAAC;KACH;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IAClD,MAAM,EAAE,YAAY,EAAE,mBAAmB,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACjE,MAAM,aAAa,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,aAAa,CAAC;IACtD,SAAS,SAAS,CAAC,MAAM;QACxB,MAAM,CAAC,OAAO,CAAC;YACd,KAAK,EAAE,KAAK,CAAC,SAAS;YACtB,OAAO,EAAE,WAAW,QAAQ,CAAC,IAAI,2CAA2C,MAAM,EAAE;SACpF,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,IAAI,aAAa,GAAG,WAAW,CAAC,YAAY,CAAC,EAAE;QAC9D,SAAS,CACR,8BAA8B,aAAa,kBAAkB,YAAY,cAAc,CACvF,CAAC;QACF,OAAO,KAAK,CAAC;KACb;IAED,IACC,mBAAmB;QACnB,YAAY,GAAG,WAAW,CAAC,mBAAmB,CAAC,EAC9C;QACD,SAAS,CACR,6BAA6B,YAAY,kBAAkB,mBAAmB,cAAc,CAC5F,CAAC;QACF,OAAO,KAAK,CAAC;KACb;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -0,0 +1,27 @@
1
+ import fetch from "node-fetch";
2
+ import { logger } from "./logger.js";
3
+ import { getRuntimeConfig } from "./runtimeConfig.js";
4
+ export let pushNotifier;
5
+ export class PushNotifier {
6
+ constructor(url) {
7
+ this.url = url;
8
+ }
9
+ notify({ title = "cross-seed", body, ...rest }) {
10
+ if (this.url) {
11
+ fetch(this.url, {
12
+ method: "POST",
13
+ headers: { "Content-Type": "application/json" },
14
+ body: JSON.stringify({ title, body, ...rest }),
15
+ });
16
+ }
17
+ }
18
+ }
19
+ export function initializePushNotifier() {
20
+ const { notificationWebhookUrl } = getRuntimeConfig();
21
+ pushNotifier = new PushNotifier(notificationWebhookUrl);
22
+ }
23
+ export function sendTestNotification() {
24
+ pushNotifier.notify({ body: "Test" });
25
+ logger.info("Sent test notification");
26
+ }
27
+ //# sourceMappingURL=pushNotifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pushNotifier.js","sourceRoot":"","sources":["../src/pushNotifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,CAAC,IAAI,YAA0B,CAAC;AAQtC,MAAM,OAAO,YAAY;IAExB,YAAY,GAAW;QACtB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,EAAE,KAAK,GAAG,YAAY,EAAE,IAAI,EAAE,GAAG,IAAI,EAAoB;QAC/D,IAAI,IAAI,CAAC,GAAG,EAAE;YACb,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACf,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;aAC9C,CAAC,CAAC;SACH;IACF,CAAC;CACD;AAED,MAAM,UAAU,sBAAsB;IACrC,MAAM,EAAE,sBAAsB,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACtD,YAAY,GAAG,IAAI,YAAY,CAAC,sBAAsB,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,oBAAoB;IACnC,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export const EmptyNonceOptions = {
2
+ trackers: undefined,
3
+ outputDir: undefined,
4
+ };
5
+ let runtimeConfig;
6
+ export function setRuntimeConfig(configObj) {
7
+ runtimeConfig = configObj;
8
+ }
9
+ export function getRuntimeConfig() {
10
+ return runtimeConfig;
11
+ }
12
+ //# sourceMappingURL=runtimeConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeConfig.js","sourceRoot":"","sources":["../src/runtimeConfig.ts"],"names":[],"mappings":"AA0BA,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,SAAS;CACpB,CAAC;AAEF,IAAI,aAA4B,CAAC;AAEjC,MAAM,UAAU,gBAAgB,CAAC,SAAwB;IACxD,aAAa,GAAG,SAAS,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC/B,OAAO,aAAa,CAAC;AACtB,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { sortBy } from "lodash-es";
2
+ import path, { join } from "path";
3
+ import { getRuntimeConfig } from "./runtimeConfig.js";
4
+ import { parseTorrentFromFilename } from "./torrent.js";
5
+ import { logger } from "./logger.js";
6
+ function getFilesFromTorrent(meta) {
7
+ if (!meta.info.files) {
8
+ return [
9
+ {
10
+ name: meta.name,
11
+ path: meta.name,
12
+ length: meta.length,
13
+ },
14
+ ];
15
+ }
16
+ const unsortedFiles = meta.info.files.map((file) => {
17
+ const rawPathSegments = file["path.utf-8"] || file.path;
18
+ const pathSegments = rawPathSegments.map((s) => s.toString());
19
+ return {
20
+ name: pathSegments[pathSegments.length - 1],
21
+ length: file.length,
22
+ // Note that we don't use path.join here because of
23
+ // https://github.com/mmgoodnow/cross-seed/issues/46.
24
+ // path.join ignores zero-length path segments,
25
+ // which we do not want.
26
+ path: [meta.name, ...pathSegments].join(path.sep),
27
+ };
28
+ });
29
+ return sortBy(unsortedFiles, "path");
30
+ }
31
+ export function createSearcheeFromMetafile(meta) {
32
+ return {
33
+ files: getFilesFromTorrent(meta),
34
+ infoHash: meta.infoHash,
35
+ name: meta.name,
36
+ length: meta.length,
37
+ };
38
+ }
39
+ export async function createSearcheeFromTorrentFile(filename) {
40
+ const { torrentDir } = getRuntimeConfig();
41
+ const fullPath = join(torrentDir, filename);
42
+ try {
43
+ const meta = await parseTorrentFromFilename(fullPath);
44
+ return createSearcheeFromMetafile(meta);
45
+ }
46
+ catch (e) {
47
+ logger.error(`Failed to parse ${filename}`);
48
+ logger.debug(e);
49
+ return e;
50
+ }
51
+ }
52
+ //# sourceMappingURL=searchee.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"searchee.js","sourceRoot":"","sources":["../src/searchee.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAerC,SAAS,mBAAmB,CAAC,IAAc;IAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;QACrB,OAAO;YACN;gBACC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;aACnB;SACD,CAAC;KACF;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAClD,MAAM,eAAe,GAAa,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;QAClE,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9D,OAAO;YACN,IAAI,EAAE,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;YAC3C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,mDAAmD;YACnD,qDAAqD;YACrD,+CAA+C;YAC/C,wBAAwB;YACxB,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;SACjD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,IAAc;IACxD,OAAO;QACN,KAAK,EAAE,mBAAmB,CAAC,IAAI,CAAC;QAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;KACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAClD,QAAgB;IAEhB,MAAM,EAAE,UAAU,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI;QACH,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAO,0BAA0B,CAAC,IAAI,CAAC,CAAC;KACxC;IAAC,OAAO,CAAC,EAAE;QACX,MAAM,CAAC,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO,CAAC,CAAC;KACT;AACF,CAAC"}
@@ -1,15 +1,9 @@
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
- exports.serve = void 0;
7
- const http_1 = __importDefault(require("http"));
8
- const lodash_1 = require("lodash");
9
- const querystring_1 = require("querystring");
10
- const util_1 = require("util");
11
- const logger_1 = require("./logger");
12
- const pipeline_1 = require("./pipeline");
1
+ import http from "http";
2
+ import { pick } from "lodash-es";
3
+ import { parse as qsParse } from "querystring";
4
+ import { inspect } from "util";
5
+ import { Label, logger } from "./logger.js";
6
+ import { searchForLocalTorrentByCriteria } from "./pipeline.js";
13
7
  function getData(req) {
14
8
  return new Promise((resolve) => {
15
9
  const chunks = [];
@@ -27,7 +21,7 @@ function parseData(data) {
27
21
  parsed = JSON.parse(data);
28
22
  }
29
23
  catch (_) {
30
- parsed = querystring_1.parse(data);
24
+ parsed = qsParse(data);
31
25
  }
32
26
  // transformations
33
27
  {
@@ -56,49 +50,48 @@ async function handleRequest(req, res) {
56
50
  }
57
51
  const dataStr = await getData(req);
58
52
  const data = parseData(dataStr);
59
- const criteria = lodash_1.pick(data, ["infoHash", "name"]);
60
- const nonceOptions = lodash_1.pick(data, ["trackers", "outputDir"]);
53
+ const criteria = pick(data, ["infoHash", "name"]);
54
+ const nonceOptions = pick(data, ["trackers", "outputDir"]);
61
55
  if (!criteria) {
62
- logger_1.logger.error({
63
- label: logger_1.Label.SERVER,
56
+ logger.error({
57
+ label: Label.SERVER,
64
58
  message: "A name or info hash must be provided",
65
59
  });
66
60
  res.writeHead(400);
67
61
  res.end();
68
62
  }
69
- const criteriaStr = util_1.inspect(criteria);
63
+ const criteriaStr = inspect(criteria);
70
64
  res.writeHead(204);
71
65
  res.end();
72
- logger_1.logger.info({ label: logger_1.Label.SERVER, message: `Received ${criteriaStr}` });
66
+ logger.info({ label: Label.SERVER, message: `Received ${criteriaStr}` });
73
67
  try {
74
68
  let numFound = null;
75
69
  if (criteria) {
76
- numFound = await pipeline_1.searchForLocalTorrentByCriteria(criteria, nonceOptions);
70
+ numFound = await searchForLocalTorrentByCriteria(criteria, nonceOptions);
77
71
  }
78
72
  if (numFound === null) {
79
- logger_1.logger.info({
80
- label: logger_1.Label.SERVER,
73
+ logger.info({
74
+ label: Label.SERVER,
81
75
  message: `Did not search for ${criteriaStr}`,
82
76
  });
83
77
  }
84
78
  else {
85
- logger_1.logger.info({
86
- label: logger_1.Label.SERVER,
79
+ logger.info({
80
+ label: Label.SERVER,
87
81
  message: `Found ${numFound} torrents for ${criteriaStr}`,
88
82
  });
89
83
  }
90
84
  }
91
85
  catch (e) {
92
- logger_1.logger.error(e);
86
+ logger.error(e);
93
87
  }
94
88
  }
95
- async function serve() {
96
- const server = http_1.default.createServer(handleRequest);
89
+ export async function serve() {
90
+ const server = http.createServer(handleRequest);
97
91
  server.listen(2468);
98
- logger_1.logger.info({
99
- label: logger_1.Label.SERVER,
92
+ logger.info({
93
+ label: Label.SERVER,
100
94
  message: "Server is running on port 2468, ^C to stop.",
101
95
  });
102
96
  }
103
- exports.serve = serve;
104
97
  //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signalHandlers.js","sourceRoot":"","sources":["../src/signalHandlers.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AACnC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { getClient } from "./clients/TorrentClient.js";
2
+ import { CrossSeedError } from "./errors.js";
3
+ import { validateJackettApi } from "./jackett.js";
4
+ import { logger } from "./logger.js";
5
+ import { getRuntimeConfig } from "./runtimeConfig.js";
6
+ import { validateTorrentDir } from "./torrent.js";
7
+ function validateOptions() {
8
+ const { action, rtorrentRpcUrl, qbittorrentUrl } = getRuntimeConfig();
9
+ if (action === "inject" && !(rtorrentRpcUrl || qbittorrentUrl)) {
10
+ throw new CrossSeedError("You need to specify --rtorrent-rpc-url or --qbittorrent-url when using '-A inject'.");
11
+ }
12
+ }
13
+ export async function doStartupValidation() {
14
+ logger.info("Validating your configuration...");
15
+ validateOptions();
16
+ const downloadClient = getClient();
17
+ await Promise.all([
18
+ validateJackettApi(),
19
+ downloadClient === null || downloadClient === void 0 ? void 0 : downloadClient.validateConfig(),
20
+ validateTorrentDir(),
21
+ ].filter(Boolean));
22
+ logger.info("Your configuration is valid!");
23
+ }
24
+ //# sourceMappingURL=startup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,SAAS,eAAe;IACvB,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACtE,IAAI,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,cAAc,IAAI,cAAc,CAAC,EAAE;QAC/D,MAAM,IAAI,cAAc,CACvB,qFAAqF,CACrF,CAAC;KACF;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACxC,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAChD,eAAe,EAAE,CAAC;IAClB,MAAM,cAAc,GAAG,SAAS,EAAE,CAAC;IACnC,MAAM,OAAO,CAAC,GAAG,CAChB;QACC,kBAAkB,EAAE;QACpB,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,cAAc,EAAE;QAChC,kBAAkB,EAAE;KACpB,CAAC,MAAM,CAAC,OAAO,CAAC,CACjB,CAAC;IACF,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,128 @@
1
+ import fs, { promises as fsPromises } from "fs";
2
+ import parseTorrent from "parse-torrent";
3
+ import path from "path";
4
+ import simpleGet from "simple-get";
5
+ import { inspect } from "util";
6
+ import db from "./db.js";
7
+ import { CrossSeedError } from "./errors.js";
8
+ import { logger } from "./logger.js";
9
+ import { getRuntimeConfig } from "./runtimeConfig.js";
10
+ import { createSearcheeFromTorrentFile } from "./searchee.js";
11
+ import { ok, stripExtension } from "./utils.js";
12
+ export async function parseTorrentFromFilename(filename) {
13
+ const data = await fsPromises.readFile(filename);
14
+ return parseTorrent(data);
15
+ }
16
+ export async function parseTorrentFromURL(url) {
17
+ var _a;
18
+ let response;
19
+ try {
20
+ response = await new Promise((resolve, reject) => {
21
+ simpleGet.concat({ url, followRedirects: false }, (err, res, data) => {
22
+ if (err)
23
+ return reject(err);
24
+ res.data = data;
25
+ return resolve(res);
26
+ });
27
+ });
28
+ }
29
+ catch (e) {
30
+ logger.error(`failed to access ${url}`);
31
+ logger.debug(e);
32
+ return null;
33
+ }
34
+ if (response.statusCode < 200 || response.statusCode >= 300) {
35
+ if (response.statusCode >= 300 &&
36
+ response.statusCode < 400 &&
37
+ ((_a = response.headers.location) === null || _a === void 0 ? void 0 : _a.startsWith("magnet:"))) {
38
+ logger.error(`Unsupported: magnet link detected at ${url}`);
39
+ return null;
40
+ }
41
+ else {
42
+ logger.error(`error downloading torrent at ${url}: ${response.statusCode} ${response.statusMessage}`);
43
+ logger.debug("response: %s", response.data);
44
+ logger.debug("headers: %s", response.headers);
45
+ return null;
46
+ }
47
+ }
48
+ try {
49
+ return parseTorrent(response.data);
50
+ }
51
+ catch (e) {
52
+ logger.error(`invalid torrent contents at ${url}`);
53
+ logger.debug(e);
54
+ return null;
55
+ }
56
+ }
57
+ export function saveTorrentFile(tracker, tag = "", info, nonceOptions) {
58
+ const { outputDir: runtimeConfigOutputDir } = getRuntimeConfig();
59
+ const { outputDir = runtimeConfigOutputDir } = nonceOptions;
60
+ const buf = parseTorrent.toTorrentFile(info);
61
+ const name = stripExtension(info.name);
62
+ const filename = `[${tag}][${tracker}]${name}.torrent`;
63
+ fs.writeFileSync(path.join(outputDir, filename), buf, { mode: 0o644 });
64
+ }
65
+ export async function findAllTorrentFilesInDir(torrentDir) {
66
+ return (await fsPromises.readdir(torrentDir))
67
+ .filter((fn) => path.extname(fn) === ".torrent")
68
+ .sort()
69
+ .map((fn) => path.resolve(path.join(torrentDir, fn)));
70
+ }
71
+ export async function indexNewTorrents() {
72
+ const { torrentDir } = getRuntimeConfig();
73
+ const dirContents = await findAllTorrentFilesInDir(torrentDir);
74
+ // index new torrents in the torrentDir
75
+ for (const filepath of dirContents) {
76
+ const doesAlreadyExist = db.data.indexedTorrents.find((e) => e.filepath === filepath);
77
+ if (!doesAlreadyExist) {
78
+ let meta;
79
+ try {
80
+ meta = await parseTorrentFromFilename(filepath);
81
+ }
82
+ catch (e) {
83
+ logger.error(`Failed to parse ${filepath}`);
84
+ logger.debug(e);
85
+ continue;
86
+ }
87
+ db.data.indexedTorrents.push({
88
+ filepath,
89
+ infoHash: meta.infoHash,
90
+ name: meta.name,
91
+ });
92
+ }
93
+ }
94
+ // clean up torrents that no longer exist in the torrentDir
95
+ db.data.indexedTorrents = db.data.indexedTorrents.filter((e) => dirContents.includes(e.filepath));
96
+ db.write();
97
+ }
98
+ export function getInfoHashesToExclude() {
99
+ return db.data.indexedTorrents.map((t) => t.infoHash);
100
+ }
101
+ export async function validateTorrentDir() {
102
+ const { torrentDir } = getRuntimeConfig();
103
+ try {
104
+ await fsPromises.readdir(torrentDir);
105
+ }
106
+ catch (e) {
107
+ throw new CrossSeedError(`Torrent dir ${torrentDir} is invalid`);
108
+ }
109
+ }
110
+ export async function loadTorrentDirLight() {
111
+ const { torrentDir } = getRuntimeConfig();
112
+ return Promise.all(fs
113
+ .readdirSync(torrentDir)
114
+ .filter((fn) => path.extname(fn) === ".torrent")
115
+ .sort()
116
+ .map(createSearcheeFromTorrentFile)).then((searcheeResults) => searcheeResults.filter(ok));
117
+ }
118
+ export async function getTorrentByCriteria(criteria) {
119
+ await indexNewTorrents();
120
+ const findResult = db.data.indexedTorrents.find((e) => (!criteria.infoHash || criteria.infoHash === e.infoHash) &&
121
+ (!criteria.name || criteria.name === e.name));
122
+ if (findResult === undefined) {
123
+ const message = `could not find a torrent with the criteria ${inspect(criteria)}`;
124
+ throw new Error(message);
125
+ }
126
+ return parseTorrentFromFilename(findResult.filepath);
127
+ }
128
+ //# sourceMappingURL=torrent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"torrent.js","sourceRoot":"","sources":["../src/torrent.ts"],"names":[],"mappings":"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"}
package/dist/utils.js ADDED
@@ -0,0 +1,28 @@
1
+ import { EP_REGEX, EXTENSIONS, MOVIE_REGEX, SEASON_REGEX, } from "./constants.js";
2
+ export function stripExtension(filename) {
3
+ for (const ext of EXTENSIONS) {
4
+ const re = new RegExp(`\\.${ext}$`);
5
+ if (re.test(filename))
6
+ return filename.replace(re, "");
7
+ }
8
+ return filename;
9
+ }
10
+ export function nMinutesAgo(n) {
11
+ const date = new Date();
12
+ date.setMinutes(date.getMinutes() - n);
13
+ return date.getTime();
14
+ }
15
+ export function wait(n) {
16
+ return new Promise((resolve) => setTimeout(resolve, n));
17
+ }
18
+ export function getTag(name) {
19
+ return EP_REGEX.test(name)
20
+ ? "episode"
21
+ : SEASON_REGEX.test(name)
22
+ ? "pack"
23
+ : MOVIE_REGEX.test(name)
24
+ ? "movie"
25
+ : "unknown";
26
+ }
27
+ export const ok = (r) => !(r instanceof Error);
28
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,QAAQ,EACR,UAAU,EACV,WAAW,EACX,YAAY,GACZ,MAAM,gBAAgB,CAAC;AAExB,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC9C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;QAC7B,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QACpC,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;KACvD;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,CAAS;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IACvC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,CAAS;IAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAY;IAClC,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACzB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;YACzB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,SAAS,CAAC;AACd,CAAC;AAID,MAAM,CAAC,MAAM,EAAE,GAAG,CAAI,CAAY,EAAU,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,19 +1,22 @@
1
1
  {
2
2
  "name": "cross-seed",
3
- "version": "2.9.1",
3
+ "version": "3.0.1",
4
4
  "description": "Query Jackett for cross-seedable torrents",
5
5
  "scripts": {
6
6
  "test": "true",
7
7
  "build": "tsc",
8
- "release": "np",
9
- "prepare": "rimraf dist && npm run build"
8
+ "prepare": "rimraf dist && npm run build && husky install"
10
9
  },
11
10
  "bin": {
12
- "cross-seed": "dist/src/cmd.js"
11
+ "cross-seed": "dist/cmd.js"
12
+ },
13
+ "engines": {
14
+ "node": ">=14"
13
15
  },
14
16
  "files": [
15
17
  "dist/"
16
18
  ],
19
+ "type": "module",
17
20
  "repository": {
18
21
  "type": "git",
19
22
  "url": "git://github.com/mmgoodnow/cross-seed.git"
@@ -22,42 +25,36 @@
22
25
  "license": "Apache-2.0",
23
26
  "dependencies": {
24
27
  "bencode": "^2.0.1",
25
- "chalk": "^4.1.0",
26
- "commander": "^7.0.0",
27
- "form-data": "^3.0.1",
28
- "lodash": "^4.17.21",
29
- "lowdb": "^1.0.0",
30
- "node-fetch": "^2.6.1",
28
+ "chalk": "^5.0.0",
29
+ "commander": "^8.3.0",
30
+ "form-data": "^4.0.0",
31
+ "lodash-es": "^4.17.21",
32
+ "lowdb": "^3.0.0",
33
+ "node-fetch": "^3.1.0",
31
34
  "parse-torrent": "^9.1.3",
32
- "rimraf": "^2.6.3",
35
+ "rimraf": "^3.0.2",
33
36
  "simple-get": "^4.0.0",
34
37
  "winston": "^3.3.3",
38
+ "winston-daily-rotate-file": "^4.5.5",
35
39
  "xmlrpc": "^1.3.2"
36
40
  },
37
41
  "devDependencies": {
38
- "@types/bencode": "^2.0.0",
42
+ "@types/bencode": "^2.0.1",
39
43
  "@types/lowdb": "^1.0.9",
40
- "@types/node-fetch": "^2.5.8",
41
44
  "@types/xmlrpc": "^1.3.6",
42
- "@typescript-eslint/eslint-plugin": "^4.16.1",
43
- "@typescript-eslint/parser": "^4.16.1",
44
- "eslint": "^7.11.0",
45
- "husky": "^4.3.0",
46
- "lint-staged": "^10.4.0",
47
- "np": "*",
45
+ "@typescript-eslint/eslint-plugin": "^5.8.1",
46
+ "@typescript-eslint/parser": "^5.8.1",
47
+ "eslint": "^8.5.0",
48
+ "husky": "^7.0.0",
49
+ "lint-staged": "^12.1.4",
48
50
  "prettier": "^2.0.5",
49
- "typescript": "^4.2.3"
51
+ "typescript": "^4.6.0-dev.20211227"
50
52
  },
51
53
  "prettier": {
52
54
  "tabWidth": 4,
53
55
  "useTabs": true,
54
56
  "proseWrap": "always"
55
57
  },
56
- "husky": {
57
- "hooks": {
58
- "pre-commit": "npm run build && lint-staged"
59
- }
60
- },
61
58
  "lint-staged": {
62
59
  "*.{js,ts}": "eslint --cache",
63
60
  "*.{js,json,ts,css,md}": "prettier --write"
package/dist/package.json DELETED
@@ -1,68 +0,0 @@
1
- {
2
- "name": "cross-seed",
3
- "version": "2.9.1",
4
- "description": "Query Jackett for cross-seedable torrents",
5
- "scripts": {
6
- "test": "true",
7
- "build": "tsc",
8
- "release": "np",
9
- "prepare": "rimraf dist && npm run build"
10
- },
11
- "bin": {
12
- "cross-seed": "dist/src/cmd.js"
13
- },
14
- "files": [
15
- "dist/"
16
- ],
17
- "repository": {
18
- "type": "git",
19
- "url": "git://github.com/mmgoodnow/cross-seed.git"
20
- },
21
- "author": "Michael Goodnow",
22
- "license": "Apache-2.0",
23
- "dependencies": {
24
- "bencode": "^2.0.1",
25
- "chalk": "^4.1.0",
26
- "commander": "^7.0.0",
27
- "form-data": "^3.0.1",
28
- "lodash": "^4.17.21",
29
- "lowdb": "^1.0.0",
30
- "node-fetch": "^2.6.1",
31
- "parse-torrent": "^9.1.3",
32
- "rimraf": "^2.6.3",
33
- "simple-get": "^4.0.0",
34
- "winston": "^3.3.3",
35
- "xmlrpc": "^1.3.2"
36
- },
37
- "devDependencies": {
38
- "@types/bencode": "^2.0.0",
39
- "@types/lowdb": "^1.0.9",
40
- "@types/node-fetch": "^2.5.8",
41
- "@types/xmlrpc": "^1.3.6",
42
- "@typescript-eslint/eslint-plugin": "^4.16.1",
43
- "@typescript-eslint/parser": "^4.16.1",
44
- "eslint": "^7.11.0",
45
- "husky": "^4.3.0",
46
- "lint-staged": "^10.4.0",
47
- "np": "*",
48
- "prettier": "^2.0.5",
49
- "typescript": "^4.2.3"
50
- },
51
- "prettier": {
52
- "tabWidth": 4,
53
- "useTabs": true,
54
- "proseWrap": "always"
55
- },
56
- "husky": {
57
- "hooks": {
58
- "pre-commit": "npm run build && lint-staged"
59
- }
60
- },
61
- "lint-staged": {
62
- "*.{js,ts}": "eslint --cache",
63
- "*.{js,json,ts,css,md}": "prettier --write"
64
- },
65
- "np": {
66
- "yarn": false
67
- }
68
- }