cross-seed 7.0.0-1 → 7.0.0-2

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 (229) hide show
  1. package/dist/Result.d.ts +27 -0
  2. package/dist/Result.js +64 -0
  3. package/dist/Result.js.map +1 -0
  4. package/dist/action.d.ts +34 -0
  5. package/dist/action.js +694 -0
  6. package/dist/action.js.map +1 -0
  7. package/dist/arr.d.ts +31 -0
  8. package/dist/arr.js +267 -0
  9. package/dist/arr.js.map +1 -0
  10. package/dist/auth.d.ts +3 -0
  11. package/dist/auth.js +28 -0
  12. package/dist/auth.js.map +1 -0
  13. package/dist/clients/Deluge.d.ts +153 -0
  14. package/dist/clients/Deluge.js +698 -0
  15. package/dist/clients/Deluge.js.map +1 -0
  16. package/dist/clients/QBittorrent.d.ts +218 -0
  17. package/dist/clients/QBittorrent.js +785 -0
  18. package/dist/clients/QBittorrent.js.map +1 -0
  19. package/dist/clients/RTorrent.d.ts +43 -0
  20. package/dist/clients/RTorrent.js +657 -0
  21. package/dist/clients/RTorrent.js.map +1 -0
  22. package/dist/clients/TorrentClient.d.ts +108 -0
  23. package/dist/clients/TorrentClient.js +341 -0
  24. package/dist/clients/TorrentClient.js.map +1 -0
  25. package/dist/clients/Transmission.d.ts +43 -0
  26. package/dist/clients/Transmission.js +404 -0
  27. package/dist/clients/Transmission.js.map +1 -0
  28. package/dist/cmd.d.ts +2 -0
  29. package/dist/cmd.js +128 -0
  30. package/dist/cmd.js.map +1 -0
  31. package/dist/configSchema.d.ts +1 -0
  32. package/dist/configSchema.js +2 -0
  33. package/dist/configSchema.js.map +1 -0
  34. package/dist/configuration.d.ts +63 -0
  35. package/dist/configuration.js +321 -0
  36. package/dist/configuration.js.map +1 -0
  37. package/dist/constants.d.ts +108 -0
  38. package/dist/constants.js +251 -0
  39. package/dist/constants.js.map +1 -0
  40. package/dist/dataFiles.d.ts +8 -0
  41. package/dist/dataFiles.js +223 -0
  42. package/dist/dataFiles.js.map +1 -0
  43. package/dist/db.d.ts +3 -0
  44. package/dist/db.js +216 -0
  45. package/dist/db.js.map +1 -0
  46. package/dist/dbConfig.d.ts +4 -0
  47. package/dist/dbConfig.js +67 -0
  48. package/dist/dbConfig.js.map +1 -0
  49. package/dist/decide.d.ts +25 -0
  50. package/dist/decide.js +553 -0
  51. package/dist/decide.js.map +1 -0
  52. package/dist/diff.d.ts +1 -0
  53. package/dist/diff.js +24 -0
  54. package/dist/diff.js.map +1 -0
  55. package/dist/errors.d.ts +3 -0
  56. package/dist/errors.js +7 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/indexers.d.ts +105 -0
  59. package/dist/indexers.js +248 -0
  60. package/dist/indexers.js.map +1 -0
  61. package/dist/inject.d.ts +2 -0
  62. package/dist/inject.js +594 -0
  63. package/dist/inject.js.map +1 -0
  64. package/dist/jobs.d.ts +29 -0
  65. package/dist/jobs.js +151 -0
  66. package/dist/jobs.js.map +1 -0
  67. package/dist/logger.d.ts +29 -0
  68. package/dist/logger.js +157 -0
  69. package/dist/logger.js.map +1 -0
  70. package/dist/migrations/00-initialSchema.d.ts +9 -0
  71. package/dist/migrations/00-initialSchema.js +30 -0
  72. package/dist/migrations/00-initialSchema.js.map +1 -0
  73. package/dist/migrations/01-jobs.d.ts +9 -0
  74. package/dist/migrations/01-jobs.js +12 -0
  75. package/dist/migrations/01-jobs.js.map +1 -0
  76. package/dist/migrations/02-timestamps.d.ts +9 -0
  77. package/dist/migrations/02-timestamps.js +21 -0
  78. package/dist/migrations/02-timestamps.js.map +1 -0
  79. package/dist/migrations/03-rateLimits.d.ts +9 -0
  80. package/dist/migrations/03-rateLimits.js +14 -0
  81. package/dist/migrations/03-rateLimits.js.map +1 -0
  82. package/dist/migrations/04-auth.d.ts +9 -0
  83. package/dist/migrations/04-auth.js +13 -0
  84. package/dist/migrations/04-auth.js.map +1 -0
  85. package/dist/migrations/05-caps.d.ts +9 -0
  86. package/dist/migrations/05-caps.js +16 -0
  87. package/dist/migrations/05-caps.js.map +1 -0
  88. package/dist/migrations/06-uniqueDecisions.d.ts +9 -0
  89. package/dist/migrations/06-uniqueDecisions.js +29 -0
  90. package/dist/migrations/06-uniqueDecisions.js.map +1 -0
  91. package/dist/migrations/07-limits.d.ts +9 -0
  92. package/dist/migrations/07-limits.js +12 -0
  93. package/dist/migrations/07-limits.js.map +1 -0
  94. package/dist/migrations/08-rss.d.ts +9 -0
  95. package/dist/migrations/08-rss.js +15 -0
  96. package/dist/migrations/08-rss.js.map +1 -0
  97. package/dist/migrations/09-clientAndDataSearchees.d.ts +9 -0
  98. package/dist/migrations/09-clientAndDataSearchees.js +34 -0
  99. package/dist/migrations/09-clientAndDataSearchees.js.map +1 -0
  100. package/dist/migrations/10-indexerNameAudioBookCaps.d.ts +9 -0
  101. package/dist/migrations/10-indexerNameAudioBookCaps.js +18 -0
  102. package/dist/migrations/10-indexerNameAudioBookCaps.js.map +1 -0
  103. package/dist/migrations/11-trackers.d.ts +9 -0
  104. package/dist/migrations/11-trackers.js +38 -0
  105. package/dist/migrations/11-trackers.js.map +1 -0
  106. package/dist/migrations/12-user-auth.d.ts +9 -0
  107. package/dist/migrations/12-user-auth.js +22 -0
  108. package/dist/migrations/12-user-auth.js.map +1 -0
  109. package/dist/migrations/13-settings.d.ts +9 -0
  110. package/dist/migrations/13-settings.js +23 -0
  111. package/dist/migrations/13-settings.js.map +1 -0
  112. package/dist/migrations/14-indexer-enabled-flag.d.ts +9 -0
  113. package/dist/migrations/14-indexer-enabled-flag.js +12 -0
  114. package/dist/migrations/14-indexer-enabled-flag.js.map +1 -0
  115. package/dist/migrations/15-remove-url-unique-constraint.d.ts +9 -0
  116. package/dist/migrations/15-remove-url-unique-constraint.js +14 -0
  117. package/dist/migrations/15-remove-url-unique-constraint.js.map +1 -0
  118. package/dist/migrations/16-prune-inactive-indexers.d.ts +9 -0
  119. package/dist/migrations/16-prune-inactive-indexers.js +17 -0
  120. package/dist/migrations/16-prune-inactive-indexers.js.map +1 -0
  121. package/dist/migrations/migrations.d.ts +13 -0
  122. package/dist/migrations/migrations.js +41 -0
  123. package/dist/migrations/migrations.js.map +1 -0
  124. package/dist/parseTorrent.d.ts +53 -0
  125. package/dist/parseTorrent.js +128 -0
  126. package/dist/parseTorrent.js.map +1 -0
  127. package/dist/pipeline.d.ts +41 -0
  128. package/dist/pipeline.js +574 -0
  129. package/dist/pipeline.js.map +1 -0
  130. package/dist/preFilter.d.ts +25 -0
  131. package/dist/preFilter.js +250 -0
  132. package/dist/preFilter.js.map +1 -0
  133. package/dist/problems/linking.d.ts +2 -0
  134. package/dist/problems/linking.js +80 -0
  135. package/dist/problems/linking.js.map +1 -0
  136. package/dist/problems/path.d.ts +22 -0
  137. package/dist/problems/path.js +96 -0
  138. package/dist/problems/path.js.map +1 -0
  139. package/dist/problems.d.ts +13 -0
  140. package/dist/problems.js +48 -0
  141. package/dist/problems.js.map +1 -0
  142. package/dist/pushNotifier.d.ts +19 -0
  143. package/dist/pushNotifier.js +137 -0
  144. package/dist/pushNotifier.js.map +1 -0
  145. package/dist/routes/baseApi.d.ts +2 -0
  146. package/dist/routes/baseApi.js +354 -0
  147. package/dist/routes/baseApi.js.map +1 -0
  148. package/dist/routes/indexerApi.d.ts +6 -0
  149. package/dist/routes/indexerApi.js +165 -0
  150. package/dist/routes/indexerApi.js.map +1 -0
  151. package/dist/routes/staticFrontendPlugin.d.ts +4 -0
  152. package/dist/routes/staticFrontendPlugin.js +61 -0
  153. package/dist/routes/staticFrontendPlugin.js.map +1 -0
  154. package/dist/runtimeConfig.d.ts +6 -0
  155. package/dist/runtimeConfig.js +27 -0
  156. package/dist/runtimeConfig.js.map +1 -0
  157. package/dist/searchee.d.ts +108 -0
  158. package/dist/searchee.js +689 -0
  159. package/dist/searchee.js.map +1 -0
  160. package/dist/server.d.ts +4 -0
  161. package/dist/server.js +65 -0
  162. package/dist/server.js.map +1 -0
  163. package/dist/services/indexerService.d.ts +96 -0
  164. package/dist/services/indexerService.js +287 -0
  165. package/dist/services/indexerService.js.map +1 -0
  166. package/dist/sessionCookies.d.ts +5 -0
  167. package/dist/sessionCookies.js +27 -0
  168. package/dist/sessionCookies.js.map +1 -0
  169. package/dist/startup.d.ts +25 -0
  170. package/dist/startup.js +157 -0
  171. package/dist/startup.js.map +1 -0
  172. package/dist/torrent.d.ts +69 -0
  173. package/dist/torrent.js +641 -0
  174. package/dist/torrent.js.map +1 -0
  175. package/dist/torznab.d.ts +60 -0
  176. package/dist/torznab.js +711 -0
  177. package/dist/torznab.js.map +1 -0
  178. package/dist/trpc/fastifyAdapter.d.ts +2 -0
  179. package/dist/trpc/fastifyAdapter.js +9 -0
  180. package/dist/trpc/fastifyAdapter.js.map +1 -0
  181. package/dist/trpc/index.d.ts +49 -0
  182. package/dist/trpc/index.js +53 -0
  183. package/dist/trpc/index.js.map +1 -0
  184. package/dist/trpc/routers/auth.d.ts +43 -0
  185. package/dist/trpc/routers/auth.js +116 -0
  186. package/dist/trpc/routers/auth.js.map +1 -0
  187. package/dist/trpc/routers/clients.d.ts +21 -0
  188. package/dist/trpc/routers/clients.js +65 -0
  189. package/dist/trpc/routers/clients.js.map +1 -0
  190. package/dist/trpc/routers/health.d.ts +14 -0
  191. package/dist/trpc/routers/health.js +20 -0
  192. package/dist/trpc/routers/health.js.map +1 -0
  193. package/dist/trpc/routers/index.d.ts +391 -0
  194. package/dist/trpc/routers/index.js +23 -0
  195. package/dist/trpc/routers/index.js.map +1 -0
  196. package/dist/trpc/routers/indexers.d.ts +75 -0
  197. package/dist/trpc/routers/indexers.js +79 -0
  198. package/dist/trpc/routers/indexers.js.map +1 -0
  199. package/dist/trpc/routers/jobs.d.ts +33 -0
  200. package/dist/trpc/routers/jobs.js +84 -0
  201. package/dist/trpc/routers/jobs.js.map +1 -0
  202. package/dist/trpc/routers/logs.d.ts +27 -0
  203. package/dist/trpc/routers/logs.js +91 -0
  204. package/dist/trpc/routers/logs.js.map +1 -0
  205. package/dist/trpc/routers/searchees.d.ts +51 -0
  206. package/dist/trpc/routers/searchees.js +156 -0
  207. package/dist/trpc/routers/searchees.js.map +1 -0
  208. package/dist/trpc/routers/settings.d.ts +83 -0
  209. package/dist/trpc/routers/settings.js +92 -0
  210. package/dist/trpc/routers/settings.js.map +1 -0
  211. package/dist/trpc/routers/stats.d.ts +42 -0
  212. package/dist/trpc/routers/stats.js +102 -0
  213. package/dist/trpc/routers/stats.js.map +1 -0
  214. package/dist/userAuth.d.ts +21 -0
  215. package/dist/userAuth.js +86 -0
  216. package/dist/userAuth.js.map +1 -0
  217. package/dist/utils/authUtils.d.ts +10 -0
  218. package/dist/utils/authUtils.js +24 -0
  219. package/dist/utils/authUtils.js.map +1 -0
  220. package/dist/utils/logWatcher.d.ts +28 -0
  221. package/dist/utils/logWatcher.js +218 -0
  222. package/dist/utils/logWatcher.js.map +1 -0
  223. package/dist/utils/object.d.ts +1 -0
  224. package/dist/utils/object.js +4 -0
  225. package/dist/utils/object.js.map +1 -0
  226. package/dist/utils.d.ts +175 -0
  227. package/dist/utils.js +660 -0
  228. package/dist/utils.js.map +1 -0
  229. package/package.json +2 -2
@@ -0,0 +1,574 @@
1
+ import chalk from "chalk";
2
+ import { stat } from "fs/promises";
3
+ // Utility function to replace lodash zip
4
+ function zip(arr1, arr2, arr3) {
5
+ return arr1.map((item, index) => [item, arr2[index], arr3[index]]);
6
+ }
7
+ import ms from "ms";
8
+ import { basename } from "path";
9
+ import { performAction, performActions } from "./action.js";
10
+ import { byClientHostPriority, getClients } from "./clients/TorrentClient.js";
11
+ import { Decision, InjectionResult, isAnyMatchedDecision, SaveResult, } from "./constants.js";
12
+ import { findPotentialNestedRoots, findSearcheesFromAllDataDirs, } from "./dataFiles.js";
13
+ import { db } from "./db.js";
14
+ import { assessCandidateCaching, getGuidInfoHashMap, } from "./decide.js";
15
+ import { getAllIndexers, IndexerStatus, updateIndexerStatus, updateSearchTimestamps, } from "./indexers.js";
16
+ import { getJobLastRun, JobName } from "./jobs.js";
17
+ import { Label, logger } from "./logger.js";
18
+ import { filterByContent, filterDupesFromSimilar, filterTimestamps, } from "./preFilter.js";
19
+ import { sendResultsNotification } from "./pushNotifier.js";
20
+ import { isOk } from "./Result.js";
21
+ import { getRuntimeConfig } from "./runtimeConfig.js";
22
+ import { createEnsembleSearchees, createSearcheeFromPath, createSearcheeFromTorrentFile, getNewestFileAge, getSeasonKeys, } from "./searchee.js";
23
+ import { getInfoHashesToExclude, getSimilarByName, getTorrentByCriteria, indexTorrentsAndDataDirs, loadTorrentDirLight, } from "./torrent.js";
24
+ import { getSearchString, queryRssFeeds, searchTorznab, } from "./torznab.js";
25
+ import { getEnabledIndexers } from "./indexers.js";
26
+ import { AsyncSemaphore, comparing, filterAsync, flatMapAsync, formatAsList, getLogString, humanReadableDate, humanReadableSize, inBatches, isTruthy, mapAsync, Mutex, notExists, reduceAsync, stripExtension, withMutex, } from "./utils.js";
27
+ async function assessCandidates(candidates, searchee, infoHashesToExclude, options) {
28
+ const guidInfoHashMap = await getGuidInfoHashMap();
29
+ const candidatesByIndexer = candidates.reduce((acc, cur) => {
30
+ if (!acc.has(cur.indexerId))
31
+ acc.set(cur.indexerId, []);
32
+ acc.get(cur.indexerId).push(cur);
33
+ return acc;
34
+ }, new Map());
35
+ return flatMapAsync(Array.from(candidatesByIndexer.values()), async (candidates) => {
36
+ const assessments = [];
37
+ for (const candidate of candidates) {
38
+ assessments.push({
39
+ assessment: await assessCandidateCaching(candidate, searchee, infoHashesToExclude, guidInfoHashMap, options),
40
+ tracker: candidate.tracker,
41
+ });
42
+ }
43
+ return assessments;
44
+ });
45
+ }
46
+ async function findOnOtherSites(searchee, infoHashesToExclude, indexerSearchCount, cachedSearch, progress, options) {
47
+ // make sure searchee is in database
48
+ await db("searchee")
49
+ .insert({ name: searchee.title })
50
+ .onConflict("name")
51
+ .ignore();
52
+ const response = await searchTorznab(searchee, indexerSearchCount, cachedSearch, progress, options);
53
+ const cachedIndexers = cachedSearch.indexerCandidates.length;
54
+ const searchedIndexers = response.length - cachedIndexers;
55
+ cachedSearch.indexerCandidates = response;
56
+ const candidates = response.flatMap((e) => e.candidates);
57
+ if (response.length) {
58
+ logger.verbose({
59
+ label: `${searchee.label}/${Label.DECIDE}`,
60
+ message: `Assessing ${candidates.length} candidates for ${searchee.title} from ${searchedIndexers}|${cachedIndexers} indexers by search|cache`,
61
+ });
62
+ }
63
+ const assessments = await assessCandidates(candidates, searchee, infoHashesToExclude, options);
64
+ const allIndexers = await getAllIndexers();
65
+ const rateLimitedNames = new Set();
66
+ const { rateLimited, notRateLimited } = assessments.reduce((acc, cur, idx) => {
67
+ const candidate = candidates[idx];
68
+ if (cur.assessment.decision === Decision.RATE_LIMITED) {
69
+ const indexer = allIndexers.find((i) => i.id === candidate.indexerId);
70
+ rateLimitedNames.add(indexer.name ?? indexer.url);
71
+ acc.rateLimited.add(candidate.indexerId);
72
+ acc.notRateLimited.delete(candidate.indexerId);
73
+ }
74
+ return acc;
75
+ }, {
76
+ rateLimited: new Set(),
77
+ notRateLimited: new Set(response.map((r) => r.indexerId)),
78
+ });
79
+ const matches = assessments.filter((e) => isAnyMatchedDecision(e.assessment.decision));
80
+ const actionResults = await performActions(searchee, matches);
81
+ await updateSearchTimestamps(searchee.title, Array.from(notRateLimited));
82
+ await updateIndexerStatus(IndexerStatus.RATE_LIMITED, Date.now() + ms("1 hour"), Array.from(rateLimited), rateLimitedNames);
83
+ const zipped = zip(matches.map((m) => m.assessment), matches.map((m) => m.tracker), actionResults);
84
+ sendResultsNotification(searchee, zipped);
85
+ return { searchedIndexers, matches: matches.length };
86
+ }
87
+ async function findMatchesBatch(searchees, infoHashesToExclude, options) {
88
+ const { searchLimit } = getRuntimeConfig(options?.configOverride);
89
+ const indexerSearchCount = new Map();
90
+ let totalFound = 0;
91
+ const cachedSearch = {
92
+ q: null,
93
+ indexerCandidates: [],
94
+ lastSearch: 0,
95
+ };
96
+ for (const [i, searchee] of searchees.entries()) {
97
+ const progress = chalk.blue(`(${i + 1}/${searchees.length}) `);
98
+ const prevSearch = cachedSearch.lastSearch;
99
+ try {
100
+ const { searchedIndexers, matches } = await findOnOtherSites(searchee, infoHashesToExclude, indexerSearchCount, cachedSearch, progress, options);
101
+ totalFound += matches;
102
+ if (searchLimit &&
103
+ indexerSearchCount.size &&
104
+ Array.from(indexerSearchCount.values()).every((n) => n >= searchLimit)) {
105
+ logger.info({
106
+ label: searchee.label,
107
+ message: `Reached searchLimit of ${searchLimit} on all indexers`,
108
+ });
109
+ break;
110
+ }
111
+ // if all indexers were rate limited or cached, don't sleep
112
+ if (searchedIndexers === 0)
113
+ cachedSearch.lastSearch = prevSearch;
114
+ }
115
+ catch (e) {
116
+ const searcheeLog = getLogString(searchee, chalk.bold.white);
117
+ logger.error({
118
+ label: searchee.label,
119
+ message: `${progress}Error searching for ${searcheeLog}: ${e.message}`,
120
+ });
121
+ logger.debug(e);
122
+ }
123
+ }
124
+ return totalFound;
125
+ }
126
+ export async function searchForLocalTorrentByCriteria(criteria, options) {
127
+ const { maxDataDepth, searchLimit } = getRuntimeConfig();
128
+ const rawSearchees = [];
129
+ if (!criteria.path) {
130
+ rawSearchees.push(...(await getTorrentByCriteria(criteria)));
131
+ }
132
+ else {
133
+ const memoizedPaths = new Map();
134
+ const memoizedLengths = new Map();
135
+ rawSearchees.push(...(await mapAsync(await findPotentialNestedRoots(criteria.path, maxDataDepth), (path) => createSearcheeFromPath(path, memoizedPaths, memoizedLengths)))
136
+ .filter(isOk)
137
+ .map((r) => r.unwrap()));
138
+ }
139
+ const searchees = rawSearchees
140
+ .sort(comparing((searchee) => byClientHostPriority(searchee.clientHost), (searchee) => -searchee.files.length, // Assume searchees are complete
141
+ (searchee) => !searchee.infoHash))
142
+ .map((searchee) => ({
143
+ ...searchee,
144
+ label: Label.WEBHOOK,
145
+ }));
146
+ const allowSeasonPackEpisodes = Array.from(searchees
147
+ .reduce((acc, cur) => {
148
+ acc.set(cur.clientHost, (acc.get(cur.clientHost) ?? 0) + 1);
149
+ return acc;
150
+ }, new Map())
151
+ .values()).some((v) => v === 1);
152
+ const infoHashesToExclude = await getInfoHashesToExclude();
153
+ const indexerSearchCount = new Map();
154
+ let totalFound = 0;
155
+ let filtered = 0;
156
+ const cachedSearch = {
157
+ q: null,
158
+ indexerCandidates: [],
159
+ lastSearch: 0,
160
+ };
161
+ for (const [i, searchee] of searchees.entries()) {
162
+ const progress = chalk.blue(`(${i + 1}/${searchees.length}) `);
163
+ const prevSearch = cachedSearch.lastSearch;
164
+ try {
165
+ if (!(await filterByContent(searchee, {
166
+ configOverride: options.configOverride,
167
+ allowSeasonPackEpisodes,
168
+ ignoreCrossSeeds: options.ignoreCrossSeeds,
169
+ }))) {
170
+ filtered++;
171
+ continue;
172
+ }
173
+ const { matches, searchedIndexers } = await findOnOtherSites(searchee, infoHashesToExclude, indexerSearchCount, cachedSearch, progress, options);
174
+ totalFound += matches;
175
+ if (searchLimit &&
176
+ indexerSearchCount.size &&
177
+ Array.from(indexerSearchCount.values()).every((n) => n >= searchLimit)) {
178
+ logger.info({
179
+ label: searchee.label,
180
+ message: `Reached searchLimit of ${searchLimit} on all indexers`,
181
+ });
182
+ break;
183
+ }
184
+ // if all indexers were rate limited, don't sleep
185
+ if (searchedIndexers === 0)
186
+ cachedSearch.lastSearch = prevSearch;
187
+ }
188
+ catch (e) {
189
+ const searcheeLog = getLogString(searchee, chalk.bold.white);
190
+ logger.error({
191
+ label: searchee.label,
192
+ message: `${progress}Error searching for ${searcheeLog}: ${e.message}`,
193
+ });
194
+ logger.debug(e);
195
+ }
196
+ }
197
+ if (filtered === searchees.length)
198
+ return null;
199
+ return totalFound;
200
+ }
201
+ async function getSearcheesForCandidate(candidate, searcheeLabel) {
202
+ const candidateLog = `${chalk.bold.white(candidate.name)} from ${candidate.tracker}`;
203
+ const { keys, clientSearchees, dataSearchees } = await getSimilarByName(candidate.name);
204
+ const method = keys.length ? `[${keys}]` : "fuzzy fallback";
205
+ if (!clientSearchees.length && !dataSearchees.length) {
206
+ logger.verbose({
207
+ label: searcheeLabel,
208
+ message: `Did not find an existing entry using ${method} for ${candidateLog}`,
209
+ });
210
+ return null;
211
+ }
212
+ const searchees = filterDupesFromSimilar(await filterAsync([...clientSearchees, ...dataSearchees].map((searchee) => ({
213
+ ...searchee,
214
+ label: searcheeLabel,
215
+ })), filterByContent));
216
+ if (!searchees.length) {
217
+ logger.verbose({
218
+ label: searcheeLabel,
219
+ message: `No valid entries found using ${method} for ${candidateLog}`,
220
+ });
221
+ return null;
222
+ }
223
+ return { searchees, method };
224
+ }
225
+ async function getEnsembleForCandidate(candidate, searcheeLabel) {
226
+ const { seasonFromEpisodes } = getRuntimeConfig();
227
+ if (!seasonFromEpisodes)
228
+ return null;
229
+ const seasonKeys = getSeasonKeys(stripExtension(candidate.name));
230
+ if (!seasonKeys)
231
+ return null;
232
+ const method = "ensemble";
233
+ const candidateLog = `${chalk.bold.white(candidate.name)} from ${candidate.tracker}`;
234
+ const { ensembleTitles, keyTitles, season } = seasonKeys;
235
+ const keys = keyTitles.map((keyTitle) => `${keyTitle}.${season}`);
236
+ const ensemble = await db("ensemble").whereIn("ensemble", keys);
237
+ if (ensemble.length === 0) {
238
+ logger.verbose({
239
+ label: searcheeLabel,
240
+ message: `Did not find an ${method} [${ensembleTitles}] for ${candidateLog}`,
241
+ });
242
+ return null;
243
+ }
244
+ const duplicateFiles = new Set();
245
+ const entriesToDelete = new Set();
246
+ const hosts = new Map();
247
+ const filesWithElement = await reduceAsync(ensemble, async (acc, entry) => {
248
+ const path = entry.path;
249
+ if (await notExists(path)) {
250
+ entriesToDelete.add(path);
251
+ return acc;
252
+ }
253
+ const length = (await stat(path)).size;
254
+ const name = basename(path);
255
+ const element = entry.element;
256
+ const clientHost = entry.client_host;
257
+ const uniqueKey = `${clientHost}-${element}-${length}`;
258
+ if (duplicateFiles.has(uniqueKey))
259
+ return acc; // cross seeded file
260
+ duplicateFiles.add(uniqueKey);
261
+ if (clientHost) {
262
+ hosts.set(clientHost, (hosts.get(clientHost) ?? 0) + 1);
263
+ }
264
+ acc.push({ length, name, path, element });
265
+ return acc;
266
+ }, []);
267
+ await inBatches(Array.from(entriesToDelete), async (batch) => {
268
+ await db("data").whereIn("path", batch).del();
269
+ await db("ensemble").whereIn("path", batch).del();
270
+ });
271
+ if (filesWithElement.length === 0) {
272
+ logger.verbose({
273
+ label: searcheeLabel,
274
+ message: `Did not find any files for ${method} [${ensembleTitles}] for ${candidateLog}: sources may be incomplete or missing`,
275
+ });
276
+ return null;
277
+ }
278
+ // Get searchee.length by total size of each episode (average if multiple files for episode)
279
+ const uniqueElements = new Set(filesWithElement.map((f) => f.element));
280
+ const totalLength = Math.round([...uniqueElements].reduce((acc, cur) => {
281
+ const lengths = filesWithElement.reduce((lengths, f) => {
282
+ if (f.element === cur)
283
+ lengths.push(f.length);
284
+ return lengths;
285
+ }, []);
286
+ return acc + lengths.reduce((a, b) => a + b) / lengths.length;
287
+ }, 0));
288
+ const files = filesWithElement.map(({ element, ...f }) => f); // eslint-disable-line @typescript-eslint/no-unused-vars
289
+ const mtimeMs = await getNewestFileAge(files.map((f) => f.path));
290
+ const searchees = ensembleTitles.map((title) => ({
291
+ name: title,
292
+ title,
293
+ files,
294
+ length: totalLength,
295
+ mtimeMs,
296
+ clientHost: [...hosts].sort(comparing((host) => -host[1], (host) => byClientHostPriority(host[0])))[0]?.[0],
297
+ label: searcheeLabel,
298
+ }));
299
+ logger.verbose({
300
+ label: searcheeLabel,
301
+ message: `Using (${searchees.length}) ${method} [${ensembleTitles}] for ${candidateLog}: ${humanReadableSize(totalLength)} - ${files.length} files`,
302
+ });
303
+ return { searchees, method };
304
+ }
305
+ const checkNewCandidateMatchSemaphore = new AsyncSemaphore({
306
+ permits: 1,
307
+ lifetimeMs: ms(`1 minute`),
308
+ }); // Limit concurrent candidate processing to avoid bogarting the event loop
309
+ export async function checkNewCandidateMatch(candidate, searcheeLabel) {
310
+ const searchees = [];
311
+ const methods = [];
312
+ const semaphoreId = await checkNewCandidateMatchSemaphore.acquire();
313
+ try {
314
+ const lookup = await getSearcheesForCandidate(candidate, searcheeLabel);
315
+ if (lookup) {
316
+ searchees.push(...lookup.searchees);
317
+ methods.push(lookup.method);
318
+ }
319
+ const ensemble = await getEnsembleForCandidate(candidate, searcheeLabel);
320
+ if (ensemble) {
321
+ searchees.push(...ensemble.searchees);
322
+ methods.push(ensemble.method);
323
+ }
324
+ if (!searchees.length)
325
+ return { decision: null, actionResult: null };
326
+ }
327
+ finally {
328
+ checkNewCandidateMatchSemaphore.release(semaphoreId);
329
+ }
330
+ logger.verbose({
331
+ label: searcheeLabel,
332
+ message: `Unique entries (${searchees.length}) [${searchees.map((m) => m.title)}] using ${formatAsList(methods, { sort: true })} for ${chalk.bold.white(candidate.name)} from ${candidate.tracker}`,
333
+ });
334
+ searchees.sort(comparing((searchee) => byClientHostPriority(searchee.clientHost), (searchee) => !searchee.infoHash, // Prefer packs over ensemble
335
+ (searchee) => -searchee.files.length));
336
+ const infoHashesToExclude = await getInfoHashesToExclude();
337
+ const guidInfoHashMap = await getGuidInfoHashMap();
338
+ let decision = null;
339
+ let actionResult = null;
340
+ let matchedSearchee = null;
341
+ let matchedAssessment = null;
342
+ for (const searchee of searchees) {
343
+ await db("searchee")
344
+ .insert({ name: searchee.title })
345
+ .onConflict("name")
346
+ .ignore();
347
+ const assessment = await assessCandidateCaching(candidate, searchee, infoHashesToExclude, guidInfoHashMap);
348
+ if (assessment.decision === Decision.INFO_HASH_ALREADY_EXISTS) {
349
+ decision = assessment.decision;
350
+ break; // In client before rss/announce
351
+ }
352
+ if (!isAnyMatchedDecision(assessment.decision))
353
+ continue;
354
+ const actionReturn = await performAction(assessment.metafile, assessment.decision, searchee, candidate.tracker);
355
+ if (actionReturn.actionResult === SaveResult.SAVED) {
356
+ decision = assessment.decision;
357
+ actionResult = actionReturn.actionResult;
358
+ matchedSearchee = searchee;
359
+ matchedAssessment = assessment;
360
+ break;
361
+ }
362
+ if (assessment.decision !== Decision.MATCH_PARTIAL &&
363
+ (actionReturn.actionResult === InjectionResult.SUCCESS ||
364
+ actionReturn.actionResult === InjectionResult.ALREADY_EXISTS)) {
365
+ decision = assessment.decision;
366
+ actionResult = InjectionResult.SUCCESS;
367
+ matchedSearchee = searchee;
368
+ matchedAssessment = assessment;
369
+ break;
370
+ }
371
+ if (actionResult === InjectionResult.SUCCESS)
372
+ continue;
373
+ if (actionResult &&
374
+ actionReturn.actionResult === InjectionResult.FAILURE) {
375
+ continue;
376
+ }
377
+ if (actionResult === InjectionResult.ALREADY_EXISTS &&
378
+ actionReturn.actionResult === InjectionResult.TORRENT_NOT_COMPLETE) {
379
+ continue;
380
+ }
381
+ decision = assessment.decision;
382
+ actionResult = actionReturn.actionResult;
383
+ matchedSearchee = searchee;
384
+ matchedAssessment = assessment;
385
+ }
386
+ if (matchedSearchee) {
387
+ sendResultsNotification(matchedSearchee, [
388
+ [matchedAssessment, candidate.tracker, actionResult],
389
+ ]);
390
+ }
391
+ if (actionResult === InjectionResult.SUCCESS) {
392
+ void indexTorrentsAndDataDirs();
393
+ }
394
+ return { decision, actionResult };
395
+ }
396
+ export async function findAllSearchees(searcheeLabel) {
397
+ const { dataDirs, torrentDir, torrents, useClientTorrents } = getRuntimeConfig();
398
+ const clients = getClients();
399
+ let rawSearchees = [];
400
+ await withMutex(Mutex.CREATE_ALL_SEARCHEES, { useQueue: true }, async () => {
401
+ if (Array.isArray(torrents)) {
402
+ const torrentInfos = await flatMapAsync(clients, (client) => client.getAllTorrents());
403
+ rawSearchees.push(...(await mapAsync(torrents, (torrent) => createSearcheeFromTorrentFile(torrent, torrentInfos)))
404
+ .filter(isOk)
405
+ .map((r) => r.unwrap()));
406
+ }
407
+ else {
408
+ if (useClientTorrents) {
409
+ rawSearchees = rawSearchees.concat(await flatMapAsync(clients, async (client) => (await client.getClientSearchees({
410
+ includeFiles: true,
411
+ includeTrackers: true,
412
+ })).searchees));
413
+ }
414
+ else if (torrentDir) {
415
+ rawSearchees = rawSearchees.concat(await loadTorrentDirLight(torrentDir));
416
+ }
417
+ if (dataDirs.length) {
418
+ const memoizedPaths = new Map();
419
+ const memoizedLengths = new Map();
420
+ rawSearchees = rawSearchees.concat((await mapAsync(await findSearcheesFromAllDataDirs(), (path) => createSearcheeFromPath(path, memoizedPaths, memoizedLengths)))
421
+ .filter(isOk)
422
+ .map((r) => r.unwrap()));
423
+ }
424
+ }
425
+ });
426
+ return rawSearchees.map((searchee) => ({
427
+ ...searchee,
428
+ label: searcheeLabel,
429
+ }));
430
+ }
431
+ async function findSearchableTorrents(options) {
432
+ const { excludeOlder, excludeRecentSearch, searchLimit } = getRuntimeConfig(options?.configOverride);
433
+ logger.info({
434
+ label: Label.SEARCH,
435
+ message: "Gathering searchees...",
436
+ });
437
+ const realSearchees = await findAllSearchees(Label.SEARCH);
438
+ const ensembleSearchees = await createEnsembleSearchees(realSearchees, {
439
+ useFilters: true,
440
+ });
441
+ const ignoring = [
442
+ (!excludeOlder || excludeOlder === Number.MAX_SAFE_INTEGER) &&
443
+ "excludeOlder",
444
+ (!excludeRecentSearch || excludeRecentSearch === 1) &&
445
+ "excludeRecentSearch",
446
+ ].filter(isTruthy);
447
+ logger.info({
448
+ label: Label.SEARCH,
449
+ message: `Filtering searchees based on config${ignoring.length ? ` (ignoring ${formatAsList(ignoring, { sort: true })})` : ""}...`,
450
+ });
451
+ const infoHashesToExclude = new Set(realSearchees.map((t) => t.infoHash).filter(isTruthy));
452
+ // Group the exact same search queries together for easy cache use later
453
+ const grouping = new Map();
454
+ const validSearchees = [
455
+ ...(await filterAsync(ensembleSearchees, (searchee) => filterByContent(searchee, {
456
+ configOverride: {},
457
+ allowSeasonPackEpisodes: false,
458
+ ignoreCrossSeeds: false,
459
+ blockListOnly: true, // Only option that matters
460
+ }))),
461
+ ...(await filterAsync(realSearchees, filterByContent)),
462
+ ];
463
+ for (const searchee of validSearchees) {
464
+ const key = await getSearchString(searchee);
465
+ if (!grouping.has(key)) {
466
+ grouping.set(key, []);
467
+ }
468
+ grouping.get(key).push(searchee);
469
+ }
470
+ for (const [key, groupedSearchees] of grouping) {
471
+ // If one searchee needs to be searched, use the candidates for all
472
+ const filteredSearchees = filterDupesFromSimilar(groupedSearchees);
473
+ const results = await mapAsync(filteredSearchees, (searchee) => filterTimestamps(searchee, options));
474
+ if (!results.some(isTruthy)) {
475
+ grouping.delete(key);
476
+ continue;
477
+ }
478
+ filteredSearchees.sort(comparing((searchee) => byClientHostPriority(searchee.clientHost), (searchee) => -searchee.files.length, // Assume searchees are complete
479
+ (searchee) => !searchee.infoHash));
480
+ grouping.set(key, filteredSearchees);
481
+ }
482
+ const finalSearchees = Array.from(grouping.values()).flat();
483
+ logger.info({
484
+ label: Label.SEARCH,
485
+ message: `Found ${realSearchees.length + ensembleSearchees.length} torrents, ${finalSearchees.length} suitable to search for matches using ${grouping.size} unique queries`,
486
+ });
487
+ if (searchLimit && grouping.size > searchLimit) {
488
+ logger.info({
489
+ label: Label.SEARCH,
490
+ message: `Limited to ${searchLimit} searches (unique queries) per indexer`,
491
+ });
492
+ }
493
+ return { searchees: finalSearchees, infoHashesToExclude };
494
+ }
495
+ export async function bulkSearch(options) {
496
+ const searchOptions = options?.configOverride
497
+ ? { configOverride: options.configOverride }
498
+ : undefined;
499
+ const { searchees, infoHashesToExclude } = await findSearchableTorrents(searchOptions);
500
+ const totalFound = await findMatchesBatch(searchees, infoHashesToExclude, options);
501
+ logger.info({
502
+ label: Label.SEARCH,
503
+ message: chalk.cyan(`Found ${chalk.bold.white(totalFound)} cross seeds from ${chalk.bold.white(searchees.length)} original torrents`),
504
+ });
505
+ }
506
+ export async function bulkSearchByNames(names, options) {
507
+ const normalizedNames = Array.from(new Set(names
508
+ .map((name) => name.trim())
509
+ .filter((name) => name.length > 0 && name.length <= 500)));
510
+ if (!normalizedNames.length) {
511
+ return { attempted: 0, totalFound: 0, requested: 0 };
512
+ }
513
+ const nameSet = new Set(normalizedNames);
514
+ const searchOptions = options?.configOverride
515
+ ? { configOverride: options.configOverride }
516
+ : undefined;
517
+ const { searchees, infoHashesToExclude } = await findSearchableTorrents(searchOptions);
518
+ const selectedSearchees = searchees.filter((searchee) => {
519
+ const titleOrName = searchee.title ?? searchee.name;
520
+ return titleOrName ? nameSet.has(titleOrName) : false;
521
+ });
522
+ if (!selectedSearchees.length) {
523
+ logger.warn({
524
+ label: Label.SEARCH,
525
+ message: `Manual bulk search requested for ${normalizedNames.length} items, but none were eligible after filtering`,
526
+ });
527
+ return {
528
+ attempted: 0,
529
+ totalFound: 0,
530
+ requested: normalizedNames.length,
531
+ };
532
+ }
533
+ logger.info({
534
+ label: Label.SEARCH,
535
+ message: `Starting manual bulk search for ${selectedSearchees.length}/${normalizedNames.length} selected items`,
536
+ });
537
+ const totalFound = await findMatchesBatch(selectedSearchees, infoHashesToExclude, searchOptions);
538
+ return {
539
+ attempted: selectedSearchees.length,
540
+ totalFound,
541
+ requested: normalizedNames.length,
542
+ };
543
+ }
544
+ export async function scanRssFeeds() {
545
+ const { dataDirs, torrentDir, useClientTorrents } = getRuntimeConfig();
546
+ await indexTorrentsAndDataDirs();
547
+ const enabledIndexers = await getEnabledIndexers();
548
+ if (!enabledIndexers.length ||
549
+ (!useClientTorrents && !torrentDir && !dataDirs.length)) {
550
+ logger.warn({
551
+ label: Label.RSS,
552
+ message: "RSS requires enabled indexers and at least one of useClientTorrents, torrentDir, or dataDirs to be set",
553
+ });
554
+ return;
555
+ }
556
+ logger.verbose({
557
+ label: Label.RSS,
558
+ message: "Querying RSS feeds...",
559
+ });
560
+ const lastRun = (await getJobLastRun(JobName.RSS)) ?? 0;
561
+ await indexTorrentsAndDataDirs();
562
+ let numCandidates = 0;
563
+ await mapAsync(await queryRssFeeds(lastRun, enabledIndexers), async (candidates) => {
564
+ for await (const candidate of candidates) {
565
+ await checkNewCandidateMatch(candidate, Label.RSS);
566
+ numCandidates++;
567
+ }
568
+ });
569
+ logger.info({
570
+ label: Label.RSS,
571
+ message: `RSS scan complete - checked ${numCandidates} new candidates since ${humanReadableDate(lastRun)}`,
572
+ });
573
+ }
574
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { MediaType } from "./constants.js";
2
+ import { RuntimeConfig } from "./runtimeConfig.js";
3
+ import { Searchee, SearcheeWithLabel } from "./searchee.js";
4
+ export declare function logFilterReason(reason: string, searchee: SearcheeWithLabel, mediaType: MediaType, options?: {
5
+ logWithoutSearcheeLabel?: boolean;
6
+ }): void;
7
+ export declare function isSingleEpisode(searchee: Searchee, mediaType: MediaType): boolean;
8
+ export declare function filterByContent(searchee: SearcheeWithLabel, options?: {
9
+ configOverride: Partial<RuntimeConfig>;
10
+ allowSeasonPackEpisodes: boolean;
11
+ ignoreCrossSeeds: boolean;
12
+ blockListOnly?: boolean;
13
+ logWithoutSearcheeLabel?: boolean;
14
+ }): Promise<boolean>;
15
+ export declare function findBlockedStringInReleaseMaybe(searchee: Searchee, blockList: string[]): string | undefined;
16
+ /**
17
+ * Filters duplicates from searchees that are for the same candidates,
18
+ * e.g. searchees for the same media but different resolutions.
19
+ * @param searchees - An array of searchees for a specific media.
20
+ * @returns An array of searchees that are unique from a matching perspective.
21
+ */
22
+ export declare function filterDupesFromSimilar<T extends Searchee>(searchees: T[]): T[];
23
+ export declare function filterTimestamps(searchee: SearcheeWithLabel, options?: {
24
+ configOverride: Partial<RuntimeConfig>;
25
+ }): Promise<boolean>;