cross-seed 6.0.0-3 → 6.0.0-31

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 (69) hide show
  1. package/dist/Result.js +17 -11
  2. package/dist/Result.js.map +1 -1
  3. package/dist/action.js +188 -74
  4. package/dist/action.js.map +1 -1
  5. package/dist/arr.js +197 -0
  6. package/dist/arr.js.map +1 -0
  7. package/dist/clients/Deluge.js +153 -81
  8. package/dist/clients/Deluge.js.map +1 -1
  9. package/dist/clients/QBittorrent.js +95 -64
  10. package/dist/clients/QBittorrent.js.map +1 -1
  11. package/dist/clients/RTorrent.js +31 -10
  12. package/dist/clients/RTorrent.js.map +1 -1
  13. package/dist/clients/TorrentClient.js.map +1 -1
  14. package/dist/clients/Transmission.js +30 -10
  15. package/dist/clients/Transmission.js.map +1 -1
  16. package/dist/cmd.js +32 -16
  17. package/dist/cmd.js.map +1 -1
  18. package/dist/config.template.cjs +83 -46
  19. package/dist/config.template.cjs.map +1 -1
  20. package/dist/configSchema.js +98 -13
  21. package/dist/configSchema.js.map +1 -1
  22. package/dist/configuration.js +3 -0
  23. package/dist/configuration.js.map +1 -1
  24. package/dist/constants.js +113 -6
  25. package/dist/constants.js.map +1 -1
  26. package/dist/dataFiles.js +4 -5
  27. package/dist/dataFiles.js.map +1 -1
  28. package/dist/decide.js +276 -160
  29. package/dist/decide.js.map +1 -1
  30. package/dist/diff.js +12 -2
  31. package/dist/diff.js.map +1 -1
  32. package/dist/errors.js +5 -2
  33. package/dist/errors.js.map +1 -1
  34. package/dist/indexers.js +31 -4
  35. package/dist/indexers.js.map +1 -1
  36. package/dist/inject.js +409 -0
  37. package/dist/inject.js.map +1 -0
  38. package/dist/jobs.js +8 -1
  39. package/dist/jobs.js.map +1 -1
  40. package/dist/logger.js +20 -5
  41. package/dist/logger.js.map +1 -1
  42. package/dist/migrations/05-caps.js +16 -0
  43. package/dist/migrations/05-caps.js.map +1 -0
  44. package/dist/migrations/06-uniqueDecisions.js +29 -0
  45. package/dist/migrations/06-uniqueDecisions.js.map +1 -0
  46. package/dist/migrations/migrations.js +11 -1
  47. package/dist/migrations/migrations.js.map +1 -1
  48. package/dist/parseTorrent.js +6 -0
  49. package/dist/parseTorrent.js.map +1 -1
  50. package/dist/pipeline.js +202 -95
  51. package/dist/pipeline.js.map +1 -1
  52. package/dist/preFilter.js +130 -52
  53. package/dist/preFilter.js.map +1 -1
  54. package/dist/pushNotifier.js +6 -4
  55. package/dist/pushNotifier.js.map +1 -1
  56. package/dist/runtimeConfig.js.map +1 -1
  57. package/dist/searchee.js +190 -19
  58. package/dist/searchee.js.map +1 -1
  59. package/dist/server.js +70 -32
  60. package/dist/server.js.map +1 -1
  61. package/dist/startup.js +12 -1
  62. package/dist/startup.js.map +1 -1
  63. package/dist/torrent.js +103 -40
  64. package/dist/torrent.js.map +1 -1
  65. package/dist/torznab.js +304 -90
  66. package/dist/torznab.js.map +1 -1
  67. package/dist/utils.js +215 -33
  68. package/dist/utils.js.map +1 -1
  69. package/package.json +3 -1
package/dist/decide.js CHANGED
@@ -1,20 +1,17 @@
1
- import { existsSync, writeFileSync } from "fs";
1
+ import { existsSync, statSync, utimesSync, writeFileSync } from "fs";
2
2
  import path from "path";
3
3
  import { appDir } from "./configuration.js";
4
- import { Decision, MatchMode, RELEASE_GROUP_REGEX, REPACK_PROPER_REGEX, TORRENT_CACHE_FOLDER, } from "./constants.js";
4
+ import { Decision, isAnyMatchedDecision, isStaticDecision, MatchMode, RELEASE_GROUP_REGEX, REPACK_PROPER_REGEX, RES_STRICT_REGEX, parseSource, TORRENT_CACHE_FOLDER, ANIME_GROUP_REGEX, SEASON_REGEX, } from "./constants.js";
5
5
  import { db } from "./db.js";
6
6
  import { Label, logger } from "./logger.js";
7
- import { findBlockedStringInReleaseMaybe } from "./preFilter.js";
7
+ import { Metafile } from "./parseTorrent.js";
8
+ import { findBlockedStringInReleaseMaybe, isSingleEpisode, } from "./preFilter.js";
8
9
  import { getRuntimeConfig } from "./runtimeConfig.js";
9
- import { parseTorrentFromFilename, parseTorrentFromURL, SnatchError, } from "./torrent.js";
10
- import { humanReadableSize } from "./utils.js";
11
- const createReasonLogger = (Title, tracker, name) => (decision, cached, searchee, candidate) => {
12
- function logReason(reason) {
13
- logger.verbose({
14
- label: Label.DECIDE,
15
- message: `${name} - no match for ${tracker} torrent ${Title} - ${reason}`,
16
- });
17
- }
10
+ import { parseTorrentFromFilename, snatch, SnatchError } from "./torrent.js";
11
+ import { extractInt, getFuzzySizeFactor, getLogString, getMediaType, getMinSizeRatio, sanitizeInfoHash, stripExtension, wait, } from "./utils.js";
12
+ import ms from "ms";
13
+ function logDecision(searchee, candidate, decision, metafile, tracker) {
14
+ const { matchMode } = getRuntimeConfig();
18
15
  let reason;
19
16
  switch (decision) {
20
17
  case Decision.MATCH_PARTIAL:
@@ -23,8 +20,17 @@ const createReasonLogger = (Title, tracker, name) => (decision, cached, searchee
23
20
  return;
24
21
  case Decision.MATCH:
25
22
  return;
23
+ case Decision.FUZZY_SIZE_MISMATCH:
24
+ reason = `the total sizes are outside of the fuzzySizeThreshold range: ${Math.abs((candidate.size - searchee.length) / searchee.length).toFixed(3)} > ${getFuzzySizeFactor()}`;
25
+ break;
26
26
  case Decision.SIZE_MISMATCH:
27
- reason = `its size does not match - (${humanReadableSize(searchee.length)} -> ${humanReadableSize(candidate.size)})`;
27
+ reason = `some files are missing or have different sizes${compareFileTreesPartial(metafile, searchee) ? ` (will match in partial match mode)` : ""}`;
28
+ break;
29
+ case Decision.PARTIAL_SIZE_MISMATCH:
30
+ reason = `too many files are missing or have different sizes: torrent progress would be ${(getPartialSizeRatio(metafile, searchee) * 100).toFixed(3)}%`;
31
+ break;
32
+ case Decision.RESOLUTION_MISMATCH:
33
+ reason = `its resolution does not match: ${searchee.title.match(RES_STRICT_REGEX)?.groups?.res} -> ${candidate.name.match(RES_STRICT_REGEX)?.groups?.res}`;
28
34
  break;
29
35
  case Decision.NO_DOWNLOAD_LINK:
30
36
  reason = "it doesn't have a download link";
@@ -35,34 +41,44 @@ const createReasonLogger = (Title, tracker, name) => (decision, cached, searchee
35
41
  case Decision.DOWNLOAD_FAILED:
36
42
  reason = "the torrent file failed to download";
37
43
  break;
44
+ case Decision.MAGNET_LINK:
45
+ reason = "the torrent is a magnet link";
46
+ break;
47
+ case Decision.SAME_INFO_HASH:
48
+ reason = "the info hash is the same";
49
+ break;
38
50
  case Decision.INFO_HASH_ALREADY_EXISTS:
39
51
  reason = "the info hash matches a torrent you already have";
40
52
  break;
41
53
  case Decision.FILE_TREE_MISMATCH:
42
- reason = "it has a different file tree";
54
+ reason = `it has a different file tree${matchMode === MatchMode.SAFE ? " (will match in risky or partial match mode)" : ""}`;
43
55
  break;
44
56
  case Decision.RELEASE_GROUP_MISMATCH:
45
- reason = `it has a different release group - (${searchee.name
46
- .match(RELEASE_GROUP_REGEX)?.[0]
47
- ?.trim()} -> ${candidate.name
48
- .match(RELEASE_GROUP_REGEX)?.[0]
49
- ?.trim()})`;
57
+ reason = `it has a different release group: ${stripExtension(searchee.title)
58
+ .match(RELEASE_GROUP_REGEX)
59
+ ?.groups?.group?.trim()} -> ${stripExtension(candidate.name)
60
+ .match(RELEASE_GROUP_REGEX)
61
+ ?.groups?.group?.trim()}`;
50
62
  break;
51
63
  case Decision.PROPER_REPACK_MISMATCH:
52
- reason = `one is a different subsequent release - (${searchee.name.match(REPACK_PROPER_REGEX)?.groups?.type ??
53
- "INITIAL"} -> ${candidate.name.match(REPACK_PROPER_REGEX)?.groups?.type ?? "INITIAL"})`;
64
+ reason = `one is a different subsequent release: ${searchee.title.match(REPACK_PROPER_REGEX)?.groups?.type ??
65
+ "INITIAL"} -> ${candidate.name.match(REPACK_PROPER_REGEX)?.groups?.type ?? "INITIAL"}`;
66
+ break;
67
+ case Decision.SOURCE_MISMATCH:
68
+ reason = `it has a different source: ${parseSource(searchee.title)} -> ${parseSource(candidate.name)}`;
54
69
  break;
55
70
  case Decision.BLOCKED_RELEASE:
56
- reason = `it matches the blocklist - ("${findBlockedStringInReleaseMaybe(searchee, getRuntimeConfig().blockList)}")`;
71
+ reason = `it matches the blocklist: "${findBlockedStringInReleaseMaybe(searchee, getRuntimeConfig().blockList)}"`;
57
72
  break;
58
73
  default:
59
74
  reason = decision;
60
75
  break;
61
76
  }
62
- if (!cached) {
63
- logReason(reason);
64
- }
65
- };
77
+ logger.verbose({
78
+ label: Label.DECIDE,
79
+ message: `${getLogString(searchee)} - no match for ${tracker} torrent ${candidate.name}${metafile ? ` [${sanitizeInfoHash(metafile.infoHash)}]` : ""} - ${reason}`,
80
+ });
81
+ }
66
82
  export function compareFileTrees(candidate, searchee) {
67
83
  const cmp = (elOfA, elOfB) => {
68
84
  const lengthsAreEqual = elOfB.length === elOfA.length;
@@ -72,13 +88,21 @@ export function compareFileTrees(candidate, searchee) {
72
88
  return candidate.files.every((elOfA) => searchee.files.some((elOfB) => cmp(elOfA, elOfB)));
73
89
  }
74
90
  export function compareFileTreesIgnoringNames(candidate, searchee) {
75
- const cmp = (candidate, searchee) => {
76
- return searchee.length === candidate.length;
77
- };
78
- return candidate.files.every((elOfA) => searchee.files.some((elOfB) => cmp(elOfA, elOfB)));
91
+ const availableFiles = searchee.files.slice();
92
+ for (const candidateFile of candidate.files) {
93
+ let matchedSearcheeFiles = availableFiles.filter((searcheeFile) => searcheeFile.length === candidateFile.length);
94
+ if (matchedSearcheeFiles.length > 1) {
95
+ matchedSearcheeFiles = matchedSearcheeFiles.filter((searcheeFile) => searcheeFile.name === candidateFile.name);
96
+ }
97
+ if (matchedSearcheeFiles.length === 0) {
98
+ return false;
99
+ }
100
+ const index = availableFiles.indexOf(matchedSearcheeFiles[0]);
101
+ availableFiles.splice(index, 1);
102
+ }
103
+ return true;
79
104
  }
80
- export function compareFileTreesPartialIgnoringNames(candidate, searchee) {
81
- const { fuzzySizeThreshold } = getRuntimeConfig();
105
+ export function getPartialSizeRatio(candidate, searchee) {
82
106
  let matchedSizes = 0;
83
107
  for (const candidateFile of candidate.files) {
84
108
  const searcheeHasFileSize = searchee.files.some((searcheeFile) => searcheeFile.length === candidateFile.length);
@@ -86,211 +110,303 @@ export function compareFileTreesPartialIgnoringNames(candidate, searchee) {
86
110
  matchedSizes += candidateFile.length;
87
111
  }
88
112
  }
89
- return matchedSizes / candidate.length >= 1 - fuzzySizeThreshold;
113
+ return matchedSizes / candidate.length;
90
114
  }
91
115
  export function compareFileTreesPartial(candidate, searchee) {
92
- const { fuzzySizeThreshold } = getRuntimeConfig();
93
116
  let matchedSizes = 0;
117
+ const availableFiles = searchee.files.slice();
94
118
  for (const candidateFile of candidate.files) {
95
- let matchedSearcheeFiles = searchee.files.filter((searcheeFile) => searcheeFile.length === candidateFile.length);
119
+ let matchedSearcheeFiles = availableFiles.filter((searcheeFile) => searcheeFile.length === candidateFile.length);
96
120
  if (matchedSearcheeFiles.length > 1) {
97
121
  matchedSearcheeFiles = matchedSearcheeFiles.filter((searcheeFile) => searcheeFile.name === candidateFile.name);
98
122
  }
99
123
  if (matchedSearcheeFiles.length) {
100
124
  matchedSizes += candidateFile.length;
125
+ const index = availableFiles.indexOf(matchedSearcheeFiles[0]);
126
+ availableFiles.splice(index, 1);
101
127
  }
102
128
  }
103
129
  const totalPieces = Math.ceil(candidate.length / candidate.pieceLength);
104
130
  const availablePieces = Math.floor(matchedSizes / candidate.pieceLength);
105
- return availablePieces / totalPieces >= 1 - fuzzySizeThreshold;
131
+ return availablePieces / totalPieces >= getMinSizeRatio();
106
132
  }
107
- function sizeDoesMatch(resultSize, searchee) {
108
- const { fuzzySizeThreshold } = getRuntimeConfig();
133
+ function fuzzySizeDoesMatch(resultSize, searchee) {
134
+ const fuzzySizeFactor = getFuzzySizeFactor();
109
135
  const { length } = searchee;
110
- const lowerBound = length - fuzzySizeThreshold * length;
111
- const upperBound = length + fuzzySizeThreshold * length;
136
+ const lowerBound = length - fuzzySizeFactor * length;
137
+ const upperBound = length + fuzzySizeFactor * length;
112
138
  return resultSize >= lowerBound && resultSize <= upperBound;
113
139
  }
114
- function releaseVersionDoesMatch(searcheeName, candidateName, matchMode) {
115
- const searcheeVersionType = searcheeName.match(REPACK_PROPER_REGEX);
116
- const candidateVersionType = candidateName.match(REPACK_PROPER_REGEX);
117
- //sets either match arrtype or type to corresponding VersionType
118
- if (searcheeVersionType?.[0].toLowerCase() !==
119
- candidateVersionType?.[0].toLowerCase() ||
120
- (searcheeVersionType?.groups?.arrtype && candidateVersionType)) {
121
- return matchMode !== MatchMode.SAFE;
122
- }
123
- return searcheeVersionType === candidateVersionType;
140
+ function resolutionDoesMatch(searcheeTitle, candidateName) {
141
+ const searcheeRes = searcheeTitle
142
+ .match(RES_STRICT_REGEX)
143
+ ?.groups?.res?.trim()
144
+ ?.toLowerCase();
145
+ const candidateRes = candidateName
146
+ .match(RES_STRICT_REGEX)
147
+ ?.groups?.res?.trim()
148
+ ?.toLowerCase();
149
+ if (!searcheeRes || !candidateRes)
150
+ return true;
151
+ return extractInt(searcheeRes) === extractInt(candidateRes);
124
152
  }
125
- function releaseGroupDoesMatch(searcheeName, candidateName, matchMode) {
126
- const searcheeReleaseGroup = searcheeName
127
- .match(RELEASE_GROUP_REGEX)?.[0]
128
- ?.trim()
153
+ function releaseGroupDoesMatch(searcheeTitle, candidateName) {
154
+ const searcheeReleaseGroup = stripExtension(searcheeTitle)
155
+ .match(RELEASE_GROUP_REGEX)
156
+ ?.groups?.group?.trim()
157
+ ?.toLowerCase();
158
+ const candidateReleaseGroup = stripExtension(candidateName)
159
+ .match(RELEASE_GROUP_REGEX)
160
+ ?.groups?.group?.trim()
161
+ ?.toLowerCase();
162
+ if (!searcheeReleaseGroup || !candidateReleaseGroup) {
163
+ return true; // Pass if missing -GRP
164
+ }
165
+ if (searcheeReleaseGroup.startsWith(candidateReleaseGroup) ||
166
+ candidateReleaseGroup.startsWith(searcheeReleaseGroup)) {
167
+ return true; // -GRP matches
168
+ }
169
+ // Anime naming can cause weird things to match as release groups
170
+ const searcheeAnimeGroup = searcheeTitle
171
+ .match(ANIME_GROUP_REGEX)
172
+ ?.groups?.group?.trim()
129
173
  ?.toLowerCase();
130
- const candidateReleaseGroup = candidateName
131
- .match(RELEASE_GROUP_REGEX)?.[0]
132
- ?.trim()
174
+ const candidateAnimeGroup = candidateName
175
+ .match(ANIME_GROUP_REGEX)
176
+ ?.groups?.group?.trim()
133
177
  ?.toLowerCase();
134
- if (searcheeReleaseGroup === candidateReleaseGroup) {
178
+ if (!searcheeAnimeGroup && !candidateAnimeGroup) {
179
+ return false;
180
+ }
181
+ // Most checks will never get here, below are rare edge cases
182
+ if (searcheeAnimeGroup === candidateAnimeGroup) {
135
183
  return true;
136
184
  }
137
- // if we are unsure, pass in risky or partial mode but fail in safe mode
138
- if (!searcheeReleaseGroup || !candidateReleaseGroup) {
139
- return matchMode !== MatchMode.SAFE;
185
+ if (searcheeAnimeGroup && searcheeAnimeGroup === candidateReleaseGroup) {
186
+ return true;
187
+ }
188
+ if (candidateAnimeGroup && searcheeReleaseGroup === candidateAnimeGroup) {
189
+ return true;
140
190
  }
141
- return searcheeReleaseGroup.startsWith(candidateReleaseGroup);
191
+ return false;
192
+ }
193
+ function sourceDoesMatch(searcheeTitle, candidateName) {
194
+ const searcheeSource = parseSource(searcheeTitle);
195
+ const candidateSource = parseSource(candidateName);
196
+ if (!searcheeSource || !candidateSource)
197
+ return true;
198
+ return searcheeSource === candidateSource;
142
199
  }
143
- async function assessCandidateHelper({ link, size, name }, searchee, hashesToExclude) {
144
- const { matchMode, blockList } = getRuntimeConfig();
200
+ export async function assessCandidate(metaOrCandidate, searchee, hashesToExclude) {
201
+ const { blockList, includeSingleEpisodes, matchMode } = getRuntimeConfig();
202
+ // When metaOrCandidate is a Metafile, skip straight to the
203
+ // main matching algorithms as we don't need pre-download filtering.
204
+ const isCandidate = !(metaOrCandidate instanceof Metafile);
205
+ const name = metaOrCandidate.name;
206
+ const size = isCandidate ? metaOrCandidate.size : metaOrCandidate.length;
207
+ if (isCandidate) {
208
+ if (!releaseGroupDoesMatch(searchee.title, name)) {
209
+ return { decision: Decision.RELEASE_GROUP_MISMATCH };
210
+ }
211
+ if (!resolutionDoesMatch(searchee.title, name)) {
212
+ return { decision: Decision.RESOLUTION_MISMATCH };
213
+ }
214
+ if (!sourceDoesMatch(searchee.title, name)) {
215
+ return { decision: Decision.SOURCE_MISMATCH };
216
+ }
217
+ if (size && !fuzzySizeDoesMatch(size, searchee)) {
218
+ return { decision: Decision.FUZZY_SIZE_MISMATCH };
219
+ }
220
+ if (!metaOrCandidate.link) {
221
+ return { decision: Decision.NO_DOWNLOAD_LINK };
222
+ }
223
+ }
145
224
  if (findBlockedStringInReleaseMaybe(searchee, blockList)) {
146
225
  return { decision: Decision.BLOCKED_RELEASE };
147
226
  }
148
- if (size && !sizeDoesMatch(size, searchee)) {
149
- return { decision: Decision.SIZE_MISMATCH };
227
+ let metafile;
228
+ if (isCandidate) {
229
+ let res = await snatch(metaOrCandidate);
230
+ if (res.isErr()) {
231
+ const e = res.unwrapErr();
232
+ if ([Label.ANNOUNCE, Label.RSS].includes(searchee.label) &&
233
+ ![SnatchError.RATE_LIMITED, SnatchError.MAGNET_LINK].includes(e)) {
234
+ await wait(ms("30 seconds"));
235
+ res = await snatch(metaOrCandidate);
236
+ }
237
+ if (res.isErr()) {
238
+ const err = res.unwrapErr();
239
+ return err === SnatchError.MAGNET_LINK
240
+ ? { decision: Decision.MAGNET_LINK }
241
+ : err === SnatchError.RATE_LIMITED
242
+ ? { decision: Decision.RATE_LIMITED }
243
+ : { decision: Decision.DOWNLOAD_FAILED };
244
+ }
245
+ }
246
+ metafile = res.unwrap();
247
+ cacheTorrentFile(metafile);
248
+ metaOrCandidate.size = metafile.length; // Trackers can be wrong
150
249
  }
151
- if (!link)
152
- return { decision: Decision.NO_DOWNLOAD_LINK };
153
- if (!releaseGroupDoesMatch(searchee.name, name, matchMode)) {
154
- return { decision: Decision.RELEASE_GROUP_MISMATCH };
250
+ else {
251
+ metafile = metaOrCandidate;
155
252
  }
156
- if (!releaseVersionDoesMatch(searchee.name, name, matchMode)) {
157
- return { decision: Decision.PROPER_REPACK_MISMATCH };
253
+ if (searchee.infoHash === metafile.infoHash) {
254
+ return { decision: Decision.SAME_INFO_HASH, metafile };
158
255
  }
159
- const result = await parseTorrentFromURL(link);
160
- if (result.isErr()) {
161
- return result.unwrapErrOrThrow() === SnatchError.RATE_LIMITED
162
- ? { decision: Decision.RATE_LIMITED }
163
- : { decision: Decision.DOWNLOAD_FAILED };
256
+ if (hashesToExclude.includes(metafile.infoHash)) {
257
+ return { decision: Decision.INFO_HASH_ALREADY_EXISTS, metafile };
164
258
  }
165
- const candidateMeta = result.unwrapOrThrow();
166
- if (hashesToExclude.includes(candidateMeta.infoHash)) {
167
- return { decision: Decision.INFO_HASH_ALREADY_EXISTS };
259
+ // Prevent candidate episodes from matching searchee season packs
260
+ if (!includeSingleEpisodes &&
261
+ SEASON_REGEX.test(searchee.title) &&
262
+ isSingleEpisode(metafile, getMediaType(metafile))) {
263
+ return { decision: Decision.FILE_TREE_MISMATCH, metafile };
168
264
  }
169
- const sizeMatch = compareFileTreesIgnoringNames(candidateMeta, searchee);
170
- const perfectMatch = compareFileTrees(candidateMeta, searchee);
265
+ const perfectMatch = compareFileTrees(metafile, searchee);
171
266
  if (perfectMatch) {
172
- return { decision: Decision.MATCH, metafile: candidateMeta };
267
+ return { decision: Decision.MATCH, metafile };
173
268
  }
174
- if (sizeMatch &&
175
- matchMode !== MatchMode.SAFE &&
176
- searchee.files.length === 1) {
177
- return {
178
- decision: Decision.MATCH_SIZE_ONLY,
179
- metafile: candidateMeta,
180
- };
269
+ const sizeMatch = compareFileTreesIgnoringNames(metafile, searchee);
270
+ if (sizeMatch && matchMode !== MatchMode.SAFE) {
271
+ return { decision: Decision.MATCH_SIZE_ONLY, metafile };
181
272
  }
182
273
  if (matchMode === MatchMode.PARTIAL) {
183
- const partialSizeMatch = compareFileTreesPartialIgnoringNames(candidateMeta, searchee);
274
+ const partialSizeMatch = getPartialSizeRatio(metafile, searchee) >= getMinSizeRatio();
184
275
  if (!partialSizeMatch) {
185
- return { decision: Decision.SIZE_MISMATCH };
276
+ return { decision: Decision.PARTIAL_SIZE_MISMATCH, metafile };
186
277
  }
187
- const partialMatch = compareFileTreesPartial(candidateMeta, searchee);
278
+ const partialMatch = compareFileTreesPartial(metafile, searchee);
188
279
  if (partialMatch) {
189
- return {
190
- decision: Decision.MATCH_PARTIAL,
191
- metafile: candidateMeta,
192
- };
280
+ return { decision: Decision.MATCH_PARTIAL, metafile };
193
281
  }
194
282
  }
195
283
  else if (!sizeMatch) {
196
- return { decision: Decision.SIZE_MISMATCH };
284
+ return { decision: Decision.SIZE_MISMATCH, metafile };
197
285
  }
198
- return { decision: Decision.FILE_TREE_MISMATCH };
286
+ return { decision: Decision.FILE_TREE_MISMATCH, metafile };
199
287
  }
200
288
  function existsInTorrentCache(infoHash) {
201
- return existsSync(path.join(appDir(), TORRENT_CACHE_FOLDER, `${infoHash}.cached.torrent`));
289
+ const torrentPath = path.join(appDir(), TORRENT_CACHE_FOLDER, `${infoHash}.cached.torrent`);
290
+ if (!existsSync(torrentPath))
291
+ return false;
292
+ utimesSync(torrentPath, new Date(), statSync(torrentPath).mtime);
293
+ return true;
202
294
  }
203
295
  async function getCachedTorrentFile(infoHash) {
204
296
  return parseTorrentFromFilename(path.join(appDir(), TORRENT_CACHE_FOLDER, `${infoHash}.cached.torrent`));
205
297
  }
206
298
  function cacheTorrentFile(meta) {
207
- writeFileSync(path.join(appDir(), TORRENT_CACHE_FOLDER, `${meta.infoHash}.cached.torrent`), meta.encode());
299
+ const torrentPath = path.join(appDir(), TORRENT_CACHE_FOLDER, `${meta.infoHash}.cached.torrent`);
300
+ if (existsInTorrentCache(meta.infoHash))
301
+ return;
302
+ writeFileSync(torrentPath, meta.encode());
208
303
  }
209
- async function assessAndSaveResults(result, searchee, guid, infoHashesToExclude) {
210
- const assessment = await assessCandidateHelper(result, searchee, infoHashesToExclude);
211
- if (assessment.decision === Decision.MATCH ||
212
- assessment.decision === Decision.MATCH_SIZE_ONLY ||
213
- assessment.decision === Decision.MATCH_PARTIAL) {
214
- cacheTorrentFile(assessment.metafile);
215
- }
304
+ async function assessAndSaveResults(metaOrCandidate, searchee, guid, infoHashesToExclude, firstSeen) {
305
+ const assessment = await assessCandidate(metaOrCandidate, searchee, infoHashesToExclude);
216
306
  await db.transaction(async (trx) => {
217
- const now = Date.now();
218
307
  const { id } = await trx("searchee")
219
308
  .select("id")
220
- .where({ name: searchee.name })
309
+ .where({ name: searchee.title })
221
310
  .first();
222
- await trx("decision").insert({
311
+ await trx("decision")
312
+ .insert({
223
313
  searchee_id: id,
224
314
  guid: guid,
315
+ info_hash: assessment.metafile?.infoHash ?? null,
225
316
  decision: assessment.decision,
226
- info_hash: assessment.decision === Decision.MATCH ||
227
- assessment.decision === Decision.MATCH_SIZE_ONLY ||
228
- assessment.decision === Decision.MATCH_PARTIAL
229
- ? assessment.metafile.infoHash
230
- : null,
231
- last_seen: now,
232
- first_seen: now,
233
- });
317
+ first_seen: firstSeen,
318
+ last_seen: Date.now(),
319
+ fuzzy_size_factor: getFuzzySizeFactor(),
320
+ })
321
+ .onConflict(["searchee_id", "guid"])
322
+ .merge();
234
323
  });
235
324
  return assessment;
236
325
  }
237
- async function assessCandidateCaching(candidate, searchee, infoHashesToExclude) {
326
+ /**
327
+ * Some trackers have alt titles which get their own guid but resolve to same torrent
328
+ * @param guid The guid of the candidate
329
+ * @returns The info hash of the torrent if found
330
+ */
331
+ async function fuzzyGuidLookup(guid) {
332
+ if (!guid.includes(".tv/torrent/"))
333
+ return;
334
+ const torrentIdStr = guid.match(/\.tv\/torrent\/(\d+)\/group/)?.[1];
335
+ if (!torrentIdStr)
336
+ return;
337
+ return (await db("decision")
338
+ .select({ infoHash: "info_hash" })
339
+ .where("guid", "like", `%.tv/torrent/${torrentIdStr}/group%`)
340
+ .whereNotNull("info_hash")
341
+ .first())?.infoHash;
342
+ }
343
+ export async function assessCandidateCaching(candidate, searchee, infoHashesToExclude) {
238
344
  const { guid, name, tracker } = candidate;
239
- const logReason = createReasonLogger(name, tracker, searchee.name);
240
345
  const cacheEntry = await db("decision")
241
346
  .select({
242
- decision: "decision.decision",
243
- infoHash: "decision.info_hash",
244
347
  id: "decision.id",
348
+ infoHash: "decision.info_hash",
349
+ decision: "decision.decision",
350
+ firstSeen: "decision.first_seen",
351
+ fuzzySizeFactor: "decision.fuzzy_size_factor",
245
352
  })
246
353
  .join("searchee", "decision.searchee_id", "searchee.id")
247
- .where({ name: searchee.name, guid })
354
+ .where({ name: searchee.title, guid })
248
355
  .first();
356
+ const metaInfoHash = (await db("decision")
357
+ .select({ infoHash: "info_hash" })
358
+ .where({ guid })
359
+ .whereNotNull("info_hash")
360
+ .first())?.infoHash ?? (await fuzzyGuidLookup(guid));
361
+ const metaOrCandidate = metaInfoHash
362
+ ? existsInTorrentCache(metaInfoHash)
363
+ ? await getCachedTorrentFile(metaInfoHash)
364
+ : candidate
365
+ : candidate;
366
+ if (metaOrCandidate instanceof Metafile) {
367
+ logger.verbose({
368
+ label: Label.DECIDE,
369
+ message: `Using cached torrent ${sanitizeInfoHash(metaInfoHash)} for ${tracker} assessment ${name}`,
370
+ });
371
+ candidate.size = metaOrCandidate.length; // Trackers can be wrong
372
+ }
249
373
  let assessment;
250
- if (!cacheEntry?.decision ||
251
- cacheEntry.decision === Decision.DOWNLOAD_FAILED ||
252
- cacheEntry.decision === Decision.RATE_LIMITED) {
253
- assessment = await assessAndSaveResults(candidate, searchee, guid, infoHashesToExclude);
254
- logReason(assessment.decision, false, searchee, candidate);
374
+ if (!cacheEntry?.decision) {
375
+ // New candiate, could be metafile from cache
376
+ assessment = await assessAndSaveResults(metaOrCandidate, searchee, guid, infoHashesToExclude, Date.now());
255
377
  }
256
- else if ((cacheEntry.decision === Decision.MATCH ||
257
- cacheEntry.decision === Decision.MATCH_SIZE_ONLY ||
258
- cacheEntry.decision === Decision.MATCH_PARTIAL) &&
378
+ else if (isAnyMatchedDecision(cacheEntry.decision) &&
259
379
  infoHashesToExclude.includes(cacheEntry.infoHash)) {
260
- // has been added since the last run
380
+ // Already injected fast path, preserve match decision
261
381
  assessment = { decision: Decision.INFO_HASH_ALREADY_EXISTS };
262
- await db("decision")
263
- .where({ id: cacheEntry.id })
264
- .update({ decision: Decision.INFO_HASH_ALREADY_EXISTS });
265
- }
266
- else if ((cacheEntry.decision === Decision.MATCH ||
267
- cacheEntry.decision === Decision.MATCH_SIZE_ONLY ||
268
- cacheEntry.decision === Decision.MATCH_PARTIAL) &&
269
- existsInTorrentCache(cacheEntry.infoHash)) {
270
- // cached match
271
- assessment = {
272
- decision: cacheEntry.decision,
273
- metafile: await getCachedTorrentFile(cacheEntry.infoHash),
274
- };
382
+ await db("decision").where({ id: cacheEntry.id }).update({
383
+ last_seen: Date.now(),
384
+ });
275
385
  }
276
- else if (cacheEntry.decision === Decision.MATCH ||
277
- cacheEntry.decision === Decision.MATCH_SIZE_ONLY ||
278
- cacheEntry.decision === Decision.MATCH_PARTIAL) {
279
- assessment = await assessAndSaveResults(candidate, searchee, guid, infoHashesToExclude);
280
- logReason(assessment.decision, false, searchee, candidate);
386
+ else if (isStaticDecision(cacheEntry.decision)) {
387
+ // These decisions will never change unless we update their logic
388
+ assessment = { decision: cacheEntry.decision };
389
+ await db("decision").where({ id: cacheEntry.id }).update({
390
+ last_seen: Date.now(),
391
+ });
281
392
  }
282
393
  else {
283
- // cached rejection
284
- assessment = { decision: cacheEntry.decision };
285
- logReason(cacheEntry.decision, true, searchee, candidate);
394
+ // Re-assess decisions using Metafile if cached
395
+ if (cacheEntry.decision !== Decision.FUZZY_SIZE_MISMATCH ||
396
+ cacheEntry.fuzzySizeFactor < getFuzzySizeFactor()) {
397
+ assessment = await assessAndSaveResults(metaOrCandidate, searchee, guid, infoHashesToExclude, cacheEntry.firstSeen);
398
+ }
399
+ else {
400
+ assessment = { decision: Decision.FUZZY_SIZE_MISMATCH };
401
+ await db("decision").where({ id: cacheEntry.id }).update({
402
+ last_seen: Date.now(),
403
+ });
404
+ }
286
405
  }
287
- // if previously known
288
- if (cacheEntry) {
289
- await db("decision")
290
- .where({ id: cacheEntry.id })
291
- .update({ last_seen: Date.now() });
406
+ const wasCached = cacheEntry?.decision === assessment.decision;
407
+ if (!wasCached) {
408
+ logDecision(searchee, candidate, assessment.decision, assessment.metafile, tracker);
292
409
  }
293
410
  return assessment;
294
411
  }
295
- export { assessCandidateCaching as assessCandidate };
296
412
  //# sourceMappingURL=decide.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"decide.js","sourceRoot":"","sources":["../src/decide.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decide.js","sourceRoot":"","sources":["../src/decide.ts"],"names":[],"mappings":"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"}