@media-engine/providers 0.1.1 → 1.0.0

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 (204) hide show
  1. package/README.md +132 -3
  2. package/README.ru.md +134 -3
  3. package/dist/aniliberty-streaming/client.d.ts +33 -0
  4. package/dist/aniliberty-streaming/client.js +188 -0
  5. package/dist/aniliberty-streaming/client.js.map +1 -0
  6. package/dist/aniliberty-streaming/config.d.ts +24 -0
  7. package/dist/aniliberty-streaming/config.js +61 -0
  8. package/dist/aniliberty-streaming/config.js.map +1 -0
  9. package/dist/aniliberty-streaming/index.d.ts +4 -0
  10. package/dist/aniliberty-streaming/index.js +45 -0
  11. package/dist/aniliberty-streaming/index.js.map +1 -0
  12. package/dist/aniliberty-streaming/mapping.d.ts +3 -0
  13. package/dist/aniliberty-streaming/mapping.js +87 -0
  14. package/dist/aniliberty-streaming/mapping.js.map +1 -0
  15. package/dist/aniliberty-streaming/matching.d.ts +4 -0
  16. package/dist/aniliberty-streaming/matching.js +44 -0
  17. package/dist/aniliberty-streaming/matching.js.map +1 -0
  18. package/dist/anilist/graphql.d.ts +2 -0
  19. package/dist/anilist/graphql.js +135 -0
  20. package/dist/anilist/graphql.js.map +1 -0
  21. package/dist/anilist/index.js +8 -6
  22. package/dist/anilist/index.js.map +1 -1
  23. package/dist/bitsearch-torrent/client.d.ts +19 -0
  24. package/dist/bitsearch-torrent/client.js +181 -0
  25. package/dist/bitsearch-torrent/client.js.map +1 -0
  26. package/dist/bitsearch-torrent/config.d.ts +26 -0
  27. package/dist/bitsearch-torrent/config.js +74 -0
  28. package/dist/bitsearch-torrent/config.js.map +1 -0
  29. package/dist/bitsearch-torrent/index.d.ts +4 -0
  30. package/dist/bitsearch-torrent/index.js +35 -0
  31. package/dist/bitsearch-torrent/index.js.map +1 -0
  32. package/dist/bitsearch-torrent/mapping.d.ts +3 -0
  33. package/dist/bitsearch-torrent/mapping.js +53 -0
  34. package/dist/bitsearch-torrent/mapping.js.map +1 -0
  35. package/dist/bitsearch-torrent/matching.d.ts +3 -0
  36. package/dist/bitsearch-torrent/matching.js +13 -0
  37. package/dist/bitsearch-torrent/matching.js.map +1 -0
  38. package/dist/bitsearch-torrent/quota.d.ts +9 -0
  39. package/dist/bitsearch-torrent/quota.js +53 -0
  40. package/dist/bitsearch-torrent/quota.js.map +1 -0
  41. package/dist/cinemeta/index.js +37 -12
  42. package/dist/cinemeta/index.js.map +1 -1
  43. package/dist/ddbb-streaming/client.d.ts +24 -0
  44. package/dist/ddbb-streaming/client.js +98 -0
  45. package/dist/ddbb-streaming/client.js.map +1 -0
  46. package/dist/ddbb-streaming/config.d.ts +31 -0
  47. package/dist/ddbb-streaming/config.js +67 -0
  48. package/dist/ddbb-streaming/config.js.map +1 -0
  49. package/dist/ddbb-streaming/index.d.ts +4 -0
  50. package/dist/ddbb-streaming/index.js +53 -0
  51. package/dist/ddbb-streaming/index.js.map +1 -0
  52. package/dist/ddbb-streaming/mapping.d.ts +8 -0
  53. package/dist/ddbb-streaming/mapping.js +164 -0
  54. package/dist/ddbb-streaming/mapping.js.map +1 -0
  55. package/dist/ddbb-streaming/validation.d.ts +3 -0
  56. package/dist/ddbb-streaming/validation.js +84 -0
  57. package/dist/ddbb-streaming/validation.js.map +1 -0
  58. package/dist/experimental-streaming/index.js +55 -0
  59. package/dist/experimental-streaming/index.js.map +1 -1
  60. package/dist/flixhq-streaming/client.d.ts +12 -0
  61. package/dist/flixhq-streaming/client.js +103 -0
  62. package/dist/flixhq-streaming/client.js.map +1 -0
  63. package/dist/flixhq-streaming/index.d.ts +2 -2
  64. package/dist/flixhq-streaming/index.js +58 -104
  65. package/dist/flixhq-streaming/index.js.map +1 -1
  66. package/dist/imdb-dataset/index.d.ts +20 -5
  67. package/dist/imdb-dataset/index.js +82 -184
  68. package/dist/imdb-dataset/index.js.map +1 -1
  69. package/dist/imdb-dataset/memory-storage.d.ts +7 -0
  70. package/dist/imdb-dataset/memory-storage.js +168 -0
  71. package/dist/imdb-dataset/memory-storage.js.map +1 -0
  72. package/dist/imdb-dataset/sqlite-import.d.ts +24 -0
  73. package/dist/imdb-dataset/sqlite-import.js +298 -0
  74. package/dist/imdb-dataset/sqlite-import.js.map +1 -0
  75. package/dist/imdb-dataset/sqlite-runtime.d.ts +3 -0
  76. package/dist/imdb-dataset/sqlite-runtime.js +11 -0
  77. package/dist/imdb-dataset/sqlite-runtime.js.map +1 -0
  78. package/dist/imdb-dataset/sqlite-schema.d.ts +6 -0
  79. package/dist/imdb-dataset/sqlite-schema.js +88 -0
  80. package/dist/imdb-dataset/sqlite-schema.js.map +1 -0
  81. package/dist/imdb-dataset/sqlite-storage.d.ts +12 -0
  82. package/dist/imdb-dataset/sqlite-storage.js +208 -0
  83. package/dist/imdb-dataset/sqlite-storage.js.map +1 -0
  84. package/dist/imdb-dataset/storage.d.ts +33 -0
  85. package/dist/imdb-dataset/storage.js +2 -0
  86. package/dist/imdb-dataset/storage.js.map +1 -0
  87. package/dist/index.d.ts +7 -0
  88. package/dist/index.js +7 -0
  89. package/dist/index.js.map +1 -1
  90. package/dist/jacred-torrent/client.d.ts +24 -0
  91. package/dist/jacred-torrent/client.js +254 -0
  92. package/dist/jacred-torrent/client.js.map +1 -0
  93. package/dist/jacred-torrent/config.d.ts +24 -0
  94. package/dist/jacred-torrent/config.js +70 -0
  95. package/dist/jacred-torrent/config.js.map +1 -0
  96. package/dist/jacred-torrent/index.d.ts +4 -0
  97. package/dist/jacred-torrent/index.js +45 -0
  98. package/dist/jacred-torrent/index.js.map +1 -0
  99. package/dist/jacred-torrent/mapping.d.ts +3 -0
  100. package/dist/jacred-torrent/mapping.js +129 -0
  101. package/dist/jacred-torrent/mapping.js.map +1 -0
  102. package/dist/jacred-torrent/matching.d.ts +3 -0
  103. package/dist/jacred-torrent/matching.js +19 -0
  104. package/dist/jacred-torrent/matching.js.map +1 -0
  105. package/dist/kinobd/index.js +5 -6
  106. package/dist/kinobd/index.js.map +1 -1
  107. package/dist/kinobd-streaming/availability.js +52 -29
  108. package/dist/kinobd-streaming/availability.js.map +1 -1
  109. package/dist/kinobd-streaming/candidates.d.ts +3 -2
  110. package/dist/kinobd-streaming/candidates.js +89 -37
  111. package/dist/kinobd-streaming/candidates.js.map +1 -1
  112. package/dist/kinobd-streaming/config.d.ts +15 -0
  113. package/dist/kinobd-streaming/config.js +21 -17
  114. package/dist/kinobd-streaming/config.js.map +1 -1
  115. package/dist/kinobd-streaming/index.d.ts +1 -1
  116. package/dist/kinobd-streaming/index.js.map +1 -1
  117. package/dist/kinobd-streaming/players.d.ts +2 -1
  118. package/dist/kinobd-streaming/players.js +7 -7
  119. package/dist/kinobd-streaming/players.js.map +1 -1
  120. package/dist/kinobd-streaming/request-budget.d.ts +15 -0
  121. package/dist/kinobd-streaming/request-budget.js +61 -0
  122. package/dist/kinobd-streaming/request-budget.js.map +1 -0
  123. package/dist/kinobd-streaming/validation.d.ts +5 -3
  124. package/dist/kinobd-streaming/validation.js +78 -49
  125. package/dist/kinobd-streaming/validation.js.map +1 -1
  126. package/dist/magnetz-torrent/client.d.ts +16 -0
  127. package/dist/magnetz-torrent/client.js +235 -0
  128. package/dist/magnetz-torrent/client.js.map +1 -0
  129. package/dist/magnetz-torrent/config.d.ts +27 -0
  130. package/dist/magnetz-torrent/config.js +73 -0
  131. package/dist/magnetz-torrent/config.js.map +1 -0
  132. package/dist/magnetz-torrent/index.d.ts +4 -0
  133. package/dist/magnetz-torrent/index.js +35 -0
  134. package/dist/magnetz-torrent/index.js.map +1 -0
  135. package/dist/magnetz-torrent/mapping.d.ts +3 -0
  136. package/dist/magnetz-torrent/mapping.js +52 -0
  137. package/dist/magnetz-torrent/mapping.js.map +1 -0
  138. package/dist/magnetz-torrent/matching.d.ts +3 -0
  139. package/dist/magnetz-torrent/matching.js +5 -0
  140. package/dist/magnetz-torrent/matching.js.map +1 -0
  141. package/dist/magnetz-torrent/request-gate.d.ts +9 -0
  142. package/dist/magnetz-torrent/request-gate.js +48 -0
  143. package/dist/magnetz-torrent/request-gate.js.map +1 -0
  144. package/dist/package-version.d.ts +2 -0
  145. package/dist/package-version.js +5 -0
  146. package/dist/package-version.js.map +1 -0
  147. package/dist/shared/abort.d.ts +1 -0
  148. package/dist/shared/abort.js +22 -0
  149. package/dist/shared/abort.js.map +1 -1
  150. package/dist/shared/http.d.ts +8 -2
  151. package/dist/shared/http.js +37 -67
  152. package/dist/shared/http.js.map +1 -1
  153. package/dist/shared/index.d.ts +1 -0
  154. package/dist/shared/index.js +1 -0
  155. package/dist/shared/index.js.map +1 -1
  156. package/dist/shared/mapping.js +3 -1
  157. package/dist/shared/mapping.js.map +1 -1
  158. package/dist/shared/output-url.d.ts +2 -0
  159. package/dist/shared/output-url.js +50 -0
  160. package/dist/shared/output-url.js.map +1 -0
  161. package/dist/shared/rate-limit.js +2 -18
  162. package/dist/shared/rate-limit.js.map +1 -1
  163. package/dist/shared/response-body.d.ts +6 -0
  164. package/dist/shared/response-body.js +109 -0
  165. package/dist/shared/response-body.js.map +1 -0
  166. package/dist/shared/safe-fetch.d.ts +14 -0
  167. package/dist/shared/safe-fetch.js +274 -0
  168. package/dist/shared/safe-fetch.js.map +1 -0
  169. package/dist/shared/torrent-release-matching.d.ts +7 -0
  170. package/dist/shared/torrent-release-matching.js +143 -0
  171. package/dist/shared/torrent-release-matching.js.map +1 -0
  172. package/dist/shared/torrent-release-metadata.d.ts +4 -0
  173. package/dist/shared/torrent-release-metadata.js +95 -0
  174. package/dist/shared/torrent-release-metadata.js.map +1 -0
  175. package/dist/shikimori/index.js +4 -7
  176. package/dist/shikimori/index.js.map +1 -1
  177. package/dist/tvmaze/index.d.ts +11 -0
  178. package/dist/tvmaze/index.js +274 -0
  179. package/dist/tvmaze/index.js.map +1 -0
  180. package/dist/wikidata/cache.d.ts +11 -0
  181. package/dist/wikidata/cache.js +30 -0
  182. package/dist/wikidata/cache.js.map +1 -0
  183. package/dist/wikidata/candidates.d.ts +12 -0
  184. package/dist/wikidata/candidates.js +67 -0
  185. package/dist/wikidata/candidates.js.map +1 -0
  186. package/dist/wikidata/client.d.ts +40 -0
  187. package/dist/wikidata/client.js +224 -0
  188. package/dist/wikidata/client.js.map +1 -0
  189. package/dist/wikidata/index.d.ts +3 -0
  190. package/dist/wikidata/index.js +30 -104
  191. package/dist/wikidata/index.js.map +1 -1
  192. package/dist/yts-torrent/client.d.ts +25 -0
  193. package/dist/yts-torrent/client.js +163 -0
  194. package/dist/yts-torrent/client.js.map +1 -0
  195. package/dist/yts-torrent/config.d.ts +22 -0
  196. package/dist/yts-torrent/config.js +57 -0
  197. package/dist/yts-torrent/config.js.map +1 -0
  198. package/dist/yts-torrent/index.d.ts +4 -0
  199. package/dist/yts-torrent/index.js +42 -0
  200. package/dist/yts-torrent/index.js.map +1 -0
  201. package/dist/yts-torrent/mapping.d.ts +4 -0
  202. package/dist/yts-torrent/mapping.js +107 -0
  203. package/dist/yts-torrent/mapping.js.map +1 -0
  204. package/package.json +18 -5
@@ -1,3 +1,4 @@
1
+ import { waitForAbortableDelay } from "./abort.js";
1
2
  import { parseRetryAfterMs } from "./retry.js";
2
3
  const DEFAULT_MAX_COOLDOWN_MS = 30_000;
3
4
  const DEFAULT_RATE_LIMIT_FALLBACK_MS = 1_000;
@@ -32,7 +33,7 @@ export class ProviderRateLimitGate {
32
33
  if (remainingMs <= 0) {
33
34
  return;
34
35
  }
35
- await abortableDelay(remainingMs, signal);
36
+ await waitForAbortableDelay(remainingMs, signal);
36
37
  }
37
38
  }
38
39
  }
@@ -48,21 +49,4 @@ export function deferProviderRateLimitFromResponse(gate, response, fallbackDelay
48
49
  gate.defer(retryAfterMs);
49
50
  }
50
51
  }
51
- function abortableDelay(ms, signal) {
52
- return new Promise((resolve, reject) => {
53
- if (signal?.aborted) {
54
- reject(signal.reason);
55
- return;
56
- }
57
- const timeout = setTimeout(() => {
58
- signal?.removeEventListener("abort", onAbort);
59
- resolve();
60
- }, ms);
61
- const onAbort = () => {
62
- clearTimeout(timeout);
63
- reject(signal?.reason);
64
- };
65
- signal?.addEventListener("abort", onAbort, { once: true });
66
- });
67
- }
68
52
  //# sourceMappingURL=rate-limit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/shared/rate-limit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/shared/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,uBAAuB,GAAG,MAAM,CAAC;AACvC,MAAM,8BAA8B,GAAG,KAAK,CAAC;AAO7C,sFAAsF;AACtF,qFAAqF;AACrF,MAAM,OAAO,qBAAqB;IACvB,cAAc,CAAS;IACvB,IAAI,CAAe;IAC5B,aAAa,GAAG,CAAC,CAAC;IAElB,YAAY,UAAwC,EAAE;QACpD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;QAEvE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,UAAU,CAAC,kEAAkE,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACtC,CAAC;IAED,8EAA8E;IAC9E,mFAAmF;IACnF,KAAK,CAAC,OAAe;QACnB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;YAC3E,OAAO;QACT,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,cAAc,CAAC,CAAC;IAClF,CAAC;IAED,iFAAiF;IACjF,8EAA8E;IAC9E,KAAK,CAAC,IAAI,CAAC,MAAoB;QAC7B,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAErD,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,MAAM,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;CACF;AAED,mFAAmF;AACnF,qFAAqF;AACrF,MAAM,UAAU,kCAAkC,CAChD,IAA2B,EAC3B,QAAkB,EAClB,eAAe,GAAG,8BAA8B;IAEhD,MAAM,YAAY,GAAG,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAE5E,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,eAAe,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface ReadBoundedResponseBodyOptions {
2
+ signal?: AbortSignal;
3
+ overflow?: "throw" | "truncate";
4
+ }
5
+ export declare function readBoundedResponseBytes(provider: string, response: Response, maxBytes: number, options?: ReadBoundedResponseBodyOptions): Promise<Uint8Array>;
6
+ export declare function readBoundedResponseText(provider: string, response: Response, maxBytes: number, options?: ReadBoundedResponseBodyOptions): Promise<string>;
@@ -0,0 +1,109 @@
1
+ import { ProviderError } from "@media-engine/core";
2
+ // Reads at most the configured response bytes and cancels the stream as soon as it overflows.
3
+ // Читает не больше заданного объема ответа и отменяет stream сразу при переполнении.
4
+ export async function readBoundedResponseBytes(provider, response, maxBytes, options = {}) {
5
+ assertPositiveByteLimit(maxBytes);
6
+ const overflow = options.overflow ?? "throw";
7
+ const declaredLength = parseContentLength(response.headers.get("content-length"));
8
+ if (overflow === "throw" && declaredLength !== undefined && declaredLength > maxBytes) {
9
+ await cancelBody(response.body);
10
+ throw createOversizedResponseError(provider, maxBytes);
11
+ }
12
+ if (options.signal?.aborted) {
13
+ await cancelBody(response.body, options.signal.reason);
14
+ throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
15
+ }
16
+ if (!response.body) {
17
+ return new Uint8Array();
18
+ }
19
+ const reader = response.body.getReader();
20
+ const chunks = [];
21
+ let totalBytes = 0;
22
+ const onAbort = () => {
23
+ void reader.cancel(options.signal?.reason).catch(() => undefined);
24
+ };
25
+ options.signal?.addEventListener("abort", onAbort, { once: true });
26
+ try {
27
+ while (true) {
28
+ const { done, value } = await reader.read();
29
+ if (options.signal?.aborted) {
30
+ throw options.signal.reason ?? new DOMException("Aborted", "AbortError");
31
+ }
32
+ if (done) {
33
+ break;
34
+ }
35
+ if (totalBytes + value.byteLength > maxBytes) {
36
+ await cancelReader(reader);
37
+ if (overflow === "truncate") {
38
+ break;
39
+ }
40
+ throw createOversizedResponseError(provider, maxBytes);
41
+ }
42
+ chunks.push(value);
43
+ totalBytes += value.byteLength;
44
+ }
45
+ }
46
+ catch (error) {
47
+ if (options.signal?.aborted) {
48
+ throw options.signal.reason ?? error;
49
+ }
50
+ throw error;
51
+ }
52
+ finally {
53
+ options.signal?.removeEventListener("abort", onAbort);
54
+ reader.releaseLock();
55
+ }
56
+ const body = new Uint8Array(totalBytes);
57
+ let offset = 0;
58
+ for (const chunk of chunks) {
59
+ body.set(chunk, offset);
60
+ offset += chunk.byteLength;
61
+ }
62
+ return body;
63
+ }
64
+ // Reads a bounded UTF-8 response body.
65
+ // Читает ограниченное UTF-8 тело ответа.
66
+ export async function readBoundedResponseText(provider, response, maxBytes, options = {}) {
67
+ const body = await readBoundedResponseBytes(provider, response, maxBytes, options);
68
+ return new TextDecoder().decode(body);
69
+ }
70
+ function createOversizedResponseError(provider, maxBytes) {
71
+ return new ProviderError({
72
+ provider,
73
+ code: "PROVIDER_RESPONSE_TOO_LARGE",
74
+ message: `Provider "${provider}" response exceeded the ${maxBytes}-byte limit.`,
75
+ retryable: false,
76
+ });
77
+ }
78
+ function parseContentLength(value) {
79
+ if (value === null || !/^\d+$/.test(value.trim())) {
80
+ return undefined;
81
+ }
82
+ const length = Number(value);
83
+ return Number.isSafeInteger(length) ? length : undefined;
84
+ }
85
+ function assertPositiveByteLimit(maxBytes) {
86
+ if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) {
87
+ throw new TypeError("Response body maxBytes must be a positive safe integer.");
88
+ }
89
+ }
90
+ async function cancelBody(body, reason) {
91
+ if (!body) {
92
+ return;
93
+ }
94
+ try {
95
+ await body.cancel(reason);
96
+ }
97
+ catch {
98
+ // Cancellation cleanup must not hide the original response error.
99
+ }
100
+ }
101
+ async function cancelReader(reader, reason) {
102
+ try {
103
+ await reader.cancel(reason);
104
+ }
105
+ catch {
106
+ // Cancellation cleanup must not hide the original response error.
107
+ }
108
+ }
109
+ //# sourceMappingURL=response-body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-body.js","sourceRoot":"","sources":["../../src/shared/response-body.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface ResolvedAddress {
2
+ address: string;
3
+ family: 4 | 6;
4
+ }
5
+ export type HostnameResolver = (hostname: string) => Promise<ReadonlyArray<ResolvedAddress>>;
6
+ export type PinnedHttpTransport = (url: URL, init: RequestInit, address: ResolvedAddress) => Promise<Response>;
7
+ export interface HardenedProviderFetchOptions {
8
+ provider: string;
9
+ maxRedirects?: number;
10
+ resolver?: HostnameResolver;
11
+ transport?: PinnedHttpTransport;
12
+ }
13
+ export declare function createHardenedProviderFetch(options: HardenedProviderFetchOptions): (input: string | URL, init?: RequestInit) => Promise<Response>;
14
+ export declare function isPublicIpAddress(address: string): boolean;
@@ -0,0 +1,274 @@
1
+ import { lookup } from "node:dns/promises";
2
+ import { request as requestHttp } from "node:http";
3
+ import { request as requestHttps } from "node:https";
4
+ import { isIP } from "node:net";
5
+ import { Readable } from "node:stream";
6
+ import { ProviderError } from "@media-engine/core";
7
+ const DEFAULT_MAX_REDIRECTS = 3;
8
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
9
+ // Creates a GET/HEAD fetch that validates every DNS answer and redirect, then pins the connection.
10
+ // Создает GET/HEAD fetch с проверкой каждого DNS-ответа/redirect и закреплением соединения.
11
+ export function createHardenedProviderFetch(options) {
12
+ const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
13
+ const resolver = options.resolver ?? resolveHostname;
14
+ const transport = options.transport ?? requestPinned;
15
+ if (!Number.isSafeInteger(maxRedirects) || maxRedirects < 0) {
16
+ throw new TypeError("Hardened provider fetch maxRedirects must be a non-negative safe integer.");
17
+ }
18
+ return async (input, init = {}) => {
19
+ assertSupportedRequest(init);
20
+ let url = normalizeExternalUrl(options.provider, input);
21
+ const visited = new Set();
22
+ for (let redirects = 0;; redirects += 1) {
23
+ if (visited.has(url.href)) {
24
+ throw createUnsafeTargetError(options.provider, "redirect loop");
25
+ }
26
+ visited.add(url.href);
27
+ const addresses = await resolveAndValidate(options.provider, url, resolver);
28
+ const response = await requestResolvedAddresses(url, { ...init, redirect: "manual" }, preferIpv4(addresses), transport);
29
+ const location = REDIRECT_STATUSES.has(response.status)
30
+ ? response.headers.get("location")
31
+ : null;
32
+ if (!location) {
33
+ return response;
34
+ }
35
+ await cancelResponse(response);
36
+ if (redirects >= maxRedirects) {
37
+ throw createUnsafeTargetError(options.provider, "redirect limit exceeded");
38
+ }
39
+ url = normalizeExternalUrl(options.provider, new URL(location, url));
40
+ }
41
+ };
42
+ }
43
+ // Returns true only for globally routable IPv4/IPv6 unicast addresses.
44
+ // Возвращает true только для глобально маршрутизируемых unicast IPv4/IPv6 адресов.
45
+ export function isPublicIpAddress(address) {
46
+ const normalized = address.replace(/^\[|\]$/g, "").split("%")[0] ?? "";
47
+ const family = isIP(normalized);
48
+ if (family === 4) {
49
+ return isPublicIpv4(normalized);
50
+ }
51
+ if (family !== 6) {
52
+ return false;
53
+ }
54
+ const words = parseIpv6Words(normalized);
55
+ if (!words) {
56
+ return false;
57
+ }
58
+ const embeddedIpv4 = getEmbeddedIpv4(words);
59
+ if (embeddedIpv4) {
60
+ return isPublicIpv4(embeddedIpv4);
61
+ }
62
+ const [first = 0, second = 0] = words;
63
+ if (first < 0x2000 ||
64
+ first > 0x3fff ||
65
+ first === 0x2002 ||
66
+ (first === 0x2001 && second <= 0x01ff) ||
67
+ (first === 0x2001 && second === 0x0db8) ||
68
+ (first & 0xfff0) === 0x3ff0) {
69
+ return false;
70
+ }
71
+ return true;
72
+ }
73
+ async function resolveHostname(hostname) {
74
+ const addresses = await lookup(hostname, { all: true, verbatim: true });
75
+ return addresses.flatMap(({ address, family }) => family === 4 || family === 6 ? [{ address, family }] : []);
76
+ }
77
+ async function resolveAndValidate(provider, url, resolver) {
78
+ const hostname = stripIpv6Brackets(url.hostname);
79
+ const literalFamily = isIP(hostname);
80
+ const addresses = literalFamily
81
+ ? [{ address: hostname, family: literalFamily }]
82
+ : await resolver(hostname);
83
+ if (addresses.length === 0 ||
84
+ addresses.some(({ address, family }) => isIP(address) !== family || !isPublicIpAddress(address))) {
85
+ throw createUnsafeTargetError(provider, "non-public DNS address");
86
+ }
87
+ return addresses;
88
+ }
89
+ function normalizeExternalUrl(provider, input) {
90
+ let url;
91
+ try {
92
+ url = new URL(input);
93
+ }
94
+ catch (error) {
95
+ throw createUnsafeTargetError(provider, "invalid URL", error);
96
+ }
97
+ if ((url.protocol !== "http:" && url.protocol !== "https:") ||
98
+ url.username !== "" ||
99
+ url.password !== "" ||
100
+ url.hostname === "localhost" ||
101
+ url.hostname.endsWith(".localhost")) {
102
+ throw createUnsafeTargetError(provider, "unsupported URL target");
103
+ }
104
+ return url;
105
+ }
106
+ function assertSupportedRequest(init) {
107
+ const method = (init.method ?? "GET").toUpperCase();
108
+ if ((method !== "GET" && method !== "HEAD") || init.body != null) {
109
+ throw new TypeError("Hardened provider fetch supports only GET and HEAD requests without a body.");
110
+ }
111
+ }
112
+ function requestPinned(url, init, address) {
113
+ return new Promise((resolve, reject) => {
114
+ let settled = false;
115
+ const resolveOnce = (response) => {
116
+ if (settled)
117
+ return;
118
+ settled = true;
119
+ resolve(response);
120
+ };
121
+ const rejectOnce = (error) => {
122
+ if (settled)
123
+ return;
124
+ settled = true;
125
+ reject(error);
126
+ };
127
+ const lookupPinned = (_hostname, lookupOptions, callback) => {
128
+ if (lookupOptions.all) {
129
+ callback(null, [address]);
130
+ return;
131
+ }
132
+ callback(null, address.address, address.family);
133
+ };
134
+ const request = (url.protocol === "https:" ? requestHttps : requestHttp)(url, {
135
+ method: init.method ?? "GET",
136
+ headers: Object.fromEntries(new Headers(init.headers).entries()),
137
+ signal: init.signal ?? undefined,
138
+ lookup: lookupPinned,
139
+ agent: false,
140
+ }, (incoming) => {
141
+ const headers = new Headers();
142
+ for (const [name, value] of Object.entries(incoming.headers)) {
143
+ for (const item of Array.isArray(value) ? value : value === undefined ? [] : [value]) {
144
+ headers.append(name, item);
145
+ }
146
+ }
147
+ const status = incoming.statusCode ?? 500;
148
+ const hasBody = init.method?.toUpperCase() !== "HEAD" &&
149
+ status !== 204 &&
150
+ status !== 205 &&
151
+ status !== 304;
152
+ const body = hasBody ? Readable.toWeb(incoming) : null;
153
+ resolveOnce(new Response(body, {
154
+ status,
155
+ statusText: incoming.statusMessage,
156
+ headers,
157
+ }));
158
+ });
159
+ request.once("socket", (socket) => {
160
+ socket.once("error", rejectOnce);
161
+ });
162
+ request.once("error", rejectOnce);
163
+ request.end();
164
+ });
165
+ }
166
+ async function requestResolvedAddresses(url, init, addresses, transport) {
167
+ let lastError;
168
+ for (const address of addresses) {
169
+ try {
170
+ return await transport(url, init, address);
171
+ }
172
+ catch (error) {
173
+ if (init.signal?.aborted)
174
+ throw error;
175
+ lastError = error;
176
+ }
177
+ }
178
+ throw lastError ?? new Error("No validated provider address was available.");
179
+ }
180
+ function preferIpv4(addresses) {
181
+ return [...addresses].sort((left, right) => left.family - right.family);
182
+ }
183
+ function isPublicIpv4(address) {
184
+ const octets = address.split(".").map(Number);
185
+ if (octets.length !== 4 || octets.some((octet) => octet < 0 || octet > 255)) {
186
+ return false;
187
+ }
188
+ const [first = 0, second = 0, third = 0] = octets;
189
+ return !(first === 0 ||
190
+ first === 10 ||
191
+ first === 127 ||
192
+ (first === 100 && second >= 64 && second <= 127) ||
193
+ (first === 169 && second === 254) ||
194
+ (first === 172 && second >= 16 && second <= 31) ||
195
+ (first === 192 && second === 0 && third === 0) ||
196
+ (first === 192 && second === 0 && third === 2) ||
197
+ (first === 192 && second === 88 && third === 99) ||
198
+ (first === 192 && second === 168) ||
199
+ (first === 198 && (second === 18 || second === 19)) ||
200
+ (first === 198 && second === 51 && third === 100) ||
201
+ (first === 203 && second === 0 && third === 113) ||
202
+ first >= 224);
203
+ }
204
+ function parseIpv6Words(address) {
205
+ const doubleColon = address.indexOf("::");
206
+ if (doubleColon !== -1 && doubleColon !== address.lastIndexOf("::")) {
207
+ return undefined;
208
+ }
209
+ const [leftValue, rightValue = ""] = doubleColon === -1
210
+ ? [address, ""]
211
+ : [address.slice(0, doubleColon), address.slice(doubleColon + 2)];
212
+ const left = expandIpv4Segment(leftValue ? leftValue.split(":") : []);
213
+ const right = expandIpv4Segment(rightValue ? rightValue.split(":") : []);
214
+ if (!left || !right) {
215
+ return undefined;
216
+ }
217
+ const missing = 8 - left.length - right.length;
218
+ if ((doubleColon === -1 && missing !== 0) || (doubleColon !== -1 && missing < 1)) {
219
+ return undefined;
220
+ }
221
+ const words = [...left, ...Array.from({ length: missing }, () => 0), ...right];
222
+ return words.length === 8 ? words : undefined;
223
+ }
224
+ function expandIpv4Segment(parts) {
225
+ const last = parts.at(-1);
226
+ if (!last?.includes(".")) {
227
+ return parseHexWords(parts);
228
+ }
229
+ const ipv4 = last.split(".").map(Number);
230
+ if (ipv4.length !== 4 ||
231
+ ipv4.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) {
232
+ return undefined;
233
+ }
234
+ return parseHexWords([
235
+ ...parts.slice(0, -1),
236
+ ((ipv4[0] << 8) | ipv4[1]).toString(16),
237
+ ((ipv4[2] << 8) | ipv4[3]).toString(16),
238
+ ]);
239
+ }
240
+ function parseHexWords(parts) {
241
+ const words = parts.map((part) => /^[\da-f]{1,4}$/i.test(part) ? Number.parseInt(part, 16) : NaN);
242
+ return words.every(Number.isInteger) ? words : undefined;
243
+ }
244
+ function getEmbeddedIpv4(words) {
245
+ const prefixIsZero = words.slice(0, 5).every((word) => word === 0);
246
+ const isMapped = prefixIsZero && words[5] === 0xffff;
247
+ const isCompatible = words.slice(0, 6).every((word) => word === 0) && (words[6] !== 0 || words[7] > 1);
248
+ const isNat64 = words[0] === 0x0064 && words[1] === 0xff9b && words.slice(2, 6).every((word) => word === 0);
249
+ if (!isMapped && !isCompatible && !isNat64) {
250
+ return undefined;
251
+ }
252
+ return `${words[6] >> 8}.${words[6] & 0xff}.${words[7] >> 8}.${words[7] & 0xff}`;
253
+ }
254
+ function stripIpv6Brackets(hostname) {
255
+ return hostname.replace(/^\[|\]$/g, "");
256
+ }
257
+ async function cancelResponse(response) {
258
+ try {
259
+ await response.body?.cancel();
260
+ }
261
+ catch {
262
+ // Redirect cleanup must not hide the policy error or next request.
263
+ }
264
+ }
265
+ function createUnsafeTargetError(provider, reason, cause) {
266
+ return new ProviderError({
267
+ provider,
268
+ code: "PROVIDER_INVALID_RESPONSE",
269
+ message: `Provider "${provider}" returned an unsafe external URL (${reason}).`,
270
+ retryable: false,
271
+ cause,
272
+ });
273
+ }
274
+ //# sourceMappingURL=safe-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-fetch.js","sourceRoot":"","sources":["../../src/shared/safe-fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { TorrentDiscoveryQuery } from "@media-engine/core";
2
+ export interface NamedTorrentRelease {
3
+ title: string;
4
+ }
5
+ export declare function canResolveStrictTorrentQuery(query: TorrentDiscoveryQuery): boolean;
6
+ export declare function createTorrentReleaseSearchTerm(query: TorrentDiscoveryQuery): string;
7
+ export declare function selectStrictTorrentReleases<T extends NamedTorrentRelease>(releases: T[], query: TorrentDiscoveryQuery): T[];
@@ -0,0 +1,143 @@
1
+ import { normalizeProviderSearchText } from "./mapping.js";
2
+ const LEADING_GROUPS = /^(?:\s*[[(][^\])]{1,80}[\])]\s*)+/u;
3
+ const SEASON_TOKEN = /(?:^|[\s._([{])(?:s(?:eason)?[ ._-]*\d{1,3}|\d{1,3}[ ._-]*x[ ._-]*\d{1,4})(?=$|[\s._)\]}-])/iu;
4
+ const ABSOLUTE_EPISODE_TOKEN = /(?:^|[\s._([{])(?:ep(?:isode)?[ ._-]*\d{1,4}|e[ ._-]*\d{1,4}|-[ ]*\d{1,4})(?=$|[\s._)\]}-])/iu;
5
+ export function canResolveStrictTorrentQuery(query) {
6
+ const title = query.title?.trim();
7
+ const numericFields = [query.seasonNumber, query.episodeNumber, query.absoluteEpisodeNumber];
8
+ if (!title ||
9
+ title.length < 2 ||
10
+ !Number.isInteger(query.year) ||
11
+ query.year < 1_800 ||
12
+ query.year > 3_000 ||
13
+ numericFields.some((value) => value !== undefined && (!Number.isInteger(value) || value < 0 || value > 9_999))) {
14
+ return false;
15
+ }
16
+ if (query.type === "movie") {
17
+ return numericFields.every((value) => value === undefined);
18
+ }
19
+ if (query.absoluteEpisodeNumber !== undefined) {
20
+ return query.seasonNumber === undefined && query.episodeNumber === undefined;
21
+ }
22
+ return query.episodeNumber === undefined || query.seasonNumber !== undefined;
23
+ }
24
+ export function createTorrentReleaseSearchTerm(query) {
25
+ const parts = [query.title.trim(), String(query.year)];
26
+ if (query.absoluteEpisodeNumber !== undefined) {
27
+ parts.push(`E${formatEpisodeNumber(query.absoluteEpisodeNumber)}`);
28
+ }
29
+ else if (query.seasonNumber !== undefined && query.episodeNumber !== undefined) {
30
+ parts.push(`S${formatEpisodeNumber(query.seasonNumber)}E${formatEpisodeNumber(query.episodeNumber)}`);
31
+ }
32
+ else if (query.seasonNumber !== undefined) {
33
+ parts.push(`S${formatEpisodeNumber(query.seasonNumber)}`);
34
+ }
35
+ return parts.join(" ");
36
+ }
37
+ export function selectStrictTorrentReleases(releases, query) {
38
+ return releases.filter((release) => hasExactYear(release.title, query.year) &&
39
+ hasExactTitle(release.title, query.title, query) &&
40
+ matchesEpisodeQuery(release.title, query));
41
+ }
42
+ function hasExactYear(title, year) {
43
+ return new RegExp(`(?<!\\d)${year}(?!\\d)`, "u").test(title);
44
+ }
45
+ function hasExactTitle(releaseTitle, queryTitle, query) {
46
+ const title = releaseTitle.replace(LEADING_GROUPS, "");
47
+ const markerIndexes = [findYearIndex(title, query.year)];
48
+ if (query.type !== "movie") {
49
+ markerIndexes.push(findMatchIndex(title, SEASON_TOKEN));
50
+ markerIndexes.push(findMatchIndex(title, ABSOLUTE_EPISODE_TOKEN));
51
+ }
52
+ const markerIndex = markerIndexes
53
+ .filter((index) => index !== undefined)
54
+ .reduce((earliest, index) => {
55
+ return earliest === undefined || index < earliest ? index : earliest;
56
+ }, undefined);
57
+ if (markerIndex === undefined)
58
+ return false;
59
+ const expected = normalizeProviderSearchText(queryTitle);
60
+ const candidates = title
61
+ .slice(0, markerIndex)
62
+ .split(/\s+(?:\/|\||aka)\s+/iu)
63
+ .map((candidate) => normalizeProviderSearchText(candidate))
64
+ .filter(Boolean);
65
+ return candidates.includes(expected);
66
+ }
67
+ function matchesEpisodeQuery(title, query) {
68
+ if (query.seasonNumber === undefined &&
69
+ query.episodeNumber === undefined &&
70
+ query.absoluteEpisodeNumber === undefined) {
71
+ return true;
72
+ }
73
+ const scope = parseEpisodeScope(title);
74
+ if (query.absoluteEpisodeNumber !== undefined) {
75
+ return includesNumber(query.absoluteEpisodeNumber, scope.absoluteStart, scope.absoluteEnd);
76
+ }
77
+ if (query.seasonNumber === undefined ||
78
+ !includesNumber(query.seasonNumber, scope.seasonStart, scope.seasonEnd)) {
79
+ return false;
80
+ }
81
+ return query.episodeNumber === undefined
82
+ ? true
83
+ : includesNumber(query.episodeNumber, scope.episodeStart, scope.episodeEnd);
84
+ }
85
+ function parseEpisodeScope(title) {
86
+ const compact = title.replace(/[._]/gu, " ");
87
+ const seasonEpisode = /\bs\s*(\d{1,3})(?:\s*-\s*s?\s*(\d{1,3}))?(?:\s*e\s*(\d{1,4})(?:\s*-\s*e?\s*(\d{1,4}))?)?\b/iu.exec(compact);
88
+ if (seasonEpisode?.[1]) {
89
+ return {
90
+ seasonStart: Number(seasonEpisode[1]),
91
+ seasonEnd: Number(seasonEpisode[2] ?? seasonEpisode[1]),
92
+ ...(seasonEpisode[3]
93
+ ? {
94
+ episodeStart: Number(seasonEpisode[3]),
95
+ episodeEnd: Number(seasonEpisode[4] ?? seasonEpisode[3]),
96
+ }
97
+ : {}),
98
+ };
99
+ }
100
+ const namedSeason = /\bseason\s*(\d{1,3})(?:\s*-\s*(\d{1,3}))?(?:\s*episode\s*(\d{1,4})(?:\s*-\s*(\d{1,4}))?)?\b/iu.exec(compact);
101
+ if (namedSeason?.[1]) {
102
+ return {
103
+ seasonStart: Number(namedSeason[1]),
104
+ seasonEnd: Number(namedSeason[2] ?? namedSeason[1]),
105
+ ...(namedSeason[3]
106
+ ? {
107
+ episodeStart: Number(namedSeason[3]),
108
+ episodeEnd: Number(namedSeason[4] ?? namedSeason[3]),
109
+ }
110
+ : {}),
111
+ };
112
+ }
113
+ const xEpisode = /\b(\d{1,3})\s*x\s*(\d{1,4})(?:\s*-\s*(\d{1,4}))?\b/iu.exec(compact);
114
+ if (xEpisode?.[1] && xEpisode[2]) {
115
+ return {
116
+ seasonStart: Number(xEpisode[1]),
117
+ seasonEnd: Number(xEpisode[1]),
118
+ episodeStart: Number(xEpisode[2]),
119
+ episodeEnd: Number(xEpisode[3] ?? xEpisode[2]),
120
+ };
121
+ }
122
+ const absoluteEpisode = /\b(?:ep(?:isode)?|e)\s*(\d{1,4})(?:\s*-\s*(?:ep(?:isode)?|e)?\s*(\d{1,4}))?\b/iu.exec(compact) ?? /(?:^|\s)-\s*(\d{1,4})(?:\s*-\s*(\d{1,4}))?(?=$|\s|\[)/u.exec(compact);
123
+ return absoluteEpisode?.[1]
124
+ ? {
125
+ absoluteStart: Number(absoluteEpisode[1]),
126
+ absoluteEnd: Number(absoluteEpisode[2] ?? absoluteEpisode[1]),
127
+ }
128
+ : {};
129
+ }
130
+ function formatEpisodeNumber(value) {
131
+ return String(value).padStart(2, "0");
132
+ }
133
+ function includesNumber(value, start, end) {
134
+ return start !== undefined && value >= start && value <= (end ?? start);
135
+ }
136
+ function findYearIndex(title, year) {
137
+ return findMatchIndex(title, new RegExp(`(?<!\\d)${year}(?!\\d)`, "u"));
138
+ }
139
+ function findMatchIndex(title, pattern) {
140
+ const index = pattern.exec(title)?.index;
141
+ return index === undefined ? undefined : index;
142
+ }
143
+ //# sourceMappingURL=torrent-release-matching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"torrent-release-matching.js","sourceRoot":"","sources":["../../src/shared/torrent-release-matching.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { TorrentDiscoveryQuery, TorrentEpisodeRef, TorrentReleaseInfo } from "@media-engine/core";
2
+ export declare function mapTorrentReleaseTitle(title: string): TorrentReleaseInfo;
3
+ export declare function createTorrentEpisodeRef(query: TorrentDiscoveryQuery): TorrentEpisodeRef | undefined;
4
+ export declare function createCanonicalMagnetUri(hash: string, title: string): string;