@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.
- package/README.md +132 -3
- package/README.ru.md +134 -3
- package/dist/aniliberty-streaming/client.d.ts +33 -0
- package/dist/aniliberty-streaming/client.js +188 -0
- package/dist/aniliberty-streaming/client.js.map +1 -0
- package/dist/aniliberty-streaming/config.d.ts +24 -0
- package/dist/aniliberty-streaming/config.js +61 -0
- package/dist/aniliberty-streaming/config.js.map +1 -0
- package/dist/aniliberty-streaming/index.d.ts +4 -0
- package/dist/aniliberty-streaming/index.js +45 -0
- package/dist/aniliberty-streaming/index.js.map +1 -0
- package/dist/aniliberty-streaming/mapping.d.ts +3 -0
- package/dist/aniliberty-streaming/mapping.js +87 -0
- package/dist/aniliberty-streaming/mapping.js.map +1 -0
- package/dist/aniliberty-streaming/matching.d.ts +4 -0
- package/dist/aniliberty-streaming/matching.js +44 -0
- package/dist/aniliberty-streaming/matching.js.map +1 -0
- package/dist/anilist/graphql.d.ts +2 -0
- package/dist/anilist/graphql.js +135 -0
- package/dist/anilist/graphql.js.map +1 -0
- package/dist/anilist/index.js +8 -6
- package/dist/anilist/index.js.map +1 -1
- package/dist/bitsearch-torrent/client.d.ts +19 -0
- package/dist/bitsearch-torrent/client.js +181 -0
- package/dist/bitsearch-torrent/client.js.map +1 -0
- package/dist/bitsearch-torrent/config.d.ts +26 -0
- package/dist/bitsearch-torrent/config.js +74 -0
- package/dist/bitsearch-torrent/config.js.map +1 -0
- package/dist/bitsearch-torrent/index.d.ts +4 -0
- package/dist/bitsearch-torrent/index.js +35 -0
- package/dist/bitsearch-torrent/index.js.map +1 -0
- package/dist/bitsearch-torrent/mapping.d.ts +3 -0
- package/dist/bitsearch-torrent/mapping.js +53 -0
- package/dist/bitsearch-torrent/mapping.js.map +1 -0
- package/dist/bitsearch-torrent/matching.d.ts +3 -0
- package/dist/bitsearch-torrent/matching.js +13 -0
- package/dist/bitsearch-torrent/matching.js.map +1 -0
- package/dist/bitsearch-torrent/quota.d.ts +9 -0
- package/dist/bitsearch-torrent/quota.js +53 -0
- package/dist/bitsearch-torrent/quota.js.map +1 -0
- package/dist/cinemeta/index.js +37 -12
- package/dist/cinemeta/index.js.map +1 -1
- package/dist/ddbb-streaming/client.d.ts +24 -0
- package/dist/ddbb-streaming/client.js +98 -0
- package/dist/ddbb-streaming/client.js.map +1 -0
- package/dist/ddbb-streaming/config.d.ts +31 -0
- package/dist/ddbb-streaming/config.js +67 -0
- package/dist/ddbb-streaming/config.js.map +1 -0
- package/dist/ddbb-streaming/index.d.ts +4 -0
- package/dist/ddbb-streaming/index.js +53 -0
- package/dist/ddbb-streaming/index.js.map +1 -0
- package/dist/ddbb-streaming/mapping.d.ts +8 -0
- package/dist/ddbb-streaming/mapping.js +164 -0
- package/dist/ddbb-streaming/mapping.js.map +1 -0
- package/dist/ddbb-streaming/validation.d.ts +3 -0
- package/dist/ddbb-streaming/validation.js +84 -0
- package/dist/ddbb-streaming/validation.js.map +1 -0
- package/dist/experimental-streaming/index.js +55 -0
- package/dist/experimental-streaming/index.js.map +1 -1
- package/dist/flixhq-streaming/client.d.ts +12 -0
- package/dist/flixhq-streaming/client.js +103 -0
- package/dist/flixhq-streaming/client.js.map +1 -0
- package/dist/flixhq-streaming/index.d.ts +2 -2
- package/dist/flixhq-streaming/index.js +58 -104
- package/dist/flixhq-streaming/index.js.map +1 -1
- package/dist/imdb-dataset/index.d.ts +20 -5
- package/dist/imdb-dataset/index.js +82 -184
- package/dist/imdb-dataset/index.js.map +1 -1
- package/dist/imdb-dataset/memory-storage.d.ts +7 -0
- package/dist/imdb-dataset/memory-storage.js +168 -0
- package/dist/imdb-dataset/memory-storage.js.map +1 -0
- package/dist/imdb-dataset/sqlite-import.d.ts +24 -0
- package/dist/imdb-dataset/sqlite-import.js +298 -0
- package/dist/imdb-dataset/sqlite-import.js.map +1 -0
- package/dist/imdb-dataset/sqlite-runtime.d.ts +3 -0
- package/dist/imdb-dataset/sqlite-runtime.js +11 -0
- package/dist/imdb-dataset/sqlite-runtime.js.map +1 -0
- package/dist/imdb-dataset/sqlite-schema.d.ts +6 -0
- package/dist/imdb-dataset/sqlite-schema.js +88 -0
- package/dist/imdb-dataset/sqlite-schema.js.map +1 -0
- package/dist/imdb-dataset/sqlite-storage.d.ts +12 -0
- package/dist/imdb-dataset/sqlite-storage.js +208 -0
- package/dist/imdb-dataset/sqlite-storage.js.map +1 -0
- package/dist/imdb-dataset/storage.d.ts +33 -0
- package/dist/imdb-dataset/storage.js +2 -0
- package/dist/imdb-dataset/storage.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/jacred-torrent/client.d.ts +24 -0
- package/dist/jacred-torrent/client.js +254 -0
- package/dist/jacred-torrent/client.js.map +1 -0
- package/dist/jacred-torrent/config.d.ts +24 -0
- package/dist/jacred-torrent/config.js +70 -0
- package/dist/jacred-torrent/config.js.map +1 -0
- package/dist/jacred-torrent/index.d.ts +4 -0
- package/dist/jacred-torrent/index.js +45 -0
- package/dist/jacred-torrent/index.js.map +1 -0
- package/dist/jacred-torrent/mapping.d.ts +3 -0
- package/dist/jacred-torrent/mapping.js +129 -0
- package/dist/jacred-torrent/mapping.js.map +1 -0
- package/dist/jacred-torrent/matching.d.ts +3 -0
- package/dist/jacred-torrent/matching.js +19 -0
- package/dist/jacred-torrent/matching.js.map +1 -0
- package/dist/kinobd/index.js +5 -6
- package/dist/kinobd/index.js.map +1 -1
- package/dist/kinobd-streaming/availability.js +52 -29
- package/dist/kinobd-streaming/availability.js.map +1 -1
- package/dist/kinobd-streaming/candidates.d.ts +3 -2
- package/dist/kinobd-streaming/candidates.js +89 -37
- package/dist/kinobd-streaming/candidates.js.map +1 -1
- package/dist/kinobd-streaming/config.d.ts +15 -0
- package/dist/kinobd-streaming/config.js +21 -17
- package/dist/kinobd-streaming/config.js.map +1 -1
- package/dist/kinobd-streaming/index.d.ts +1 -1
- package/dist/kinobd-streaming/index.js.map +1 -1
- package/dist/kinobd-streaming/players.d.ts +2 -1
- package/dist/kinobd-streaming/players.js +7 -7
- package/dist/kinobd-streaming/players.js.map +1 -1
- package/dist/kinobd-streaming/request-budget.d.ts +15 -0
- package/dist/kinobd-streaming/request-budget.js +61 -0
- package/dist/kinobd-streaming/request-budget.js.map +1 -0
- package/dist/kinobd-streaming/validation.d.ts +5 -3
- package/dist/kinobd-streaming/validation.js +78 -49
- package/dist/kinobd-streaming/validation.js.map +1 -1
- package/dist/magnetz-torrent/client.d.ts +16 -0
- package/dist/magnetz-torrent/client.js +235 -0
- package/dist/magnetz-torrent/client.js.map +1 -0
- package/dist/magnetz-torrent/config.d.ts +27 -0
- package/dist/magnetz-torrent/config.js +73 -0
- package/dist/magnetz-torrent/config.js.map +1 -0
- package/dist/magnetz-torrent/index.d.ts +4 -0
- package/dist/magnetz-torrent/index.js +35 -0
- package/dist/magnetz-torrent/index.js.map +1 -0
- package/dist/magnetz-torrent/mapping.d.ts +3 -0
- package/dist/magnetz-torrent/mapping.js +52 -0
- package/dist/magnetz-torrent/mapping.js.map +1 -0
- package/dist/magnetz-torrent/matching.d.ts +3 -0
- package/dist/magnetz-torrent/matching.js +5 -0
- package/dist/magnetz-torrent/matching.js.map +1 -0
- package/dist/magnetz-torrent/request-gate.d.ts +9 -0
- package/dist/magnetz-torrent/request-gate.js +48 -0
- package/dist/magnetz-torrent/request-gate.js.map +1 -0
- package/dist/package-version.d.ts +2 -0
- package/dist/package-version.js +5 -0
- package/dist/package-version.js.map +1 -0
- package/dist/shared/abort.d.ts +1 -0
- package/dist/shared/abort.js +22 -0
- package/dist/shared/abort.js.map +1 -1
- package/dist/shared/http.d.ts +8 -2
- package/dist/shared/http.js +37 -67
- package/dist/shared/http.js.map +1 -1
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/mapping.js +3 -1
- package/dist/shared/mapping.js.map +1 -1
- package/dist/shared/output-url.d.ts +2 -0
- package/dist/shared/output-url.js +50 -0
- package/dist/shared/output-url.js.map +1 -0
- package/dist/shared/rate-limit.js +2 -18
- package/dist/shared/rate-limit.js.map +1 -1
- package/dist/shared/response-body.d.ts +6 -0
- package/dist/shared/response-body.js +109 -0
- package/dist/shared/response-body.js.map +1 -0
- package/dist/shared/safe-fetch.d.ts +14 -0
- package/dist/shared/safe-fetch.js +274 -0
- package/dist/shared/safe-fetch.js.map +1 -0
- package/dist/shared/torrent-release-matching.d.ts +7 -0
- package/dist/shared/torrent-release-matching.js +143 -0
- package/dist/shared/torrent-release-matching.js.map +1 -0
- package/dist/shared/torrent-release-metadata.d.ts +4 -0
- package/dist/shared/torrent-release-metadata.js +95 -0
- package/dist/shared/torrent-release-metadata.js.map +1 -0
- package/dist/shikimori/index.js +4 -7
- package/dist/shikimori/index.js.map +1 -1
- package/dist/tvmaze/index.d.ts +11 -0
- package/dist/tvmaze/index.js +274 -0
- package/dist/tvmaze/index.js.map +1 -0
- package/dist/wikidata/cache.d.ts +11 -0
- package/dist/wikidata/cache.js +30 -0
- package/dist/wikidata/cache.js.map +1 -0
- package/dist/wikidata/candidates.d.ts +12 -0
- package/dist/wikidata/candidates.js +67 -0
- package/dist/wikidata/candidates.js.map +1 -0
- package/dist/wikidata/client.d.ts +40 -0
- package/dist/wikidata/client.js +224 -0
- package/dist/wikidata/client.js.map +1 -0
- package/dist/wikidata/index.d.ts +3 -0
- package/dist/wikidata/index.js +30 -104
- package/dist/wikidata/index.js.map +1 -1
- package/dist/yts-torrent/client.d.ts +25 -0
- package/dist/yts-torrent/client.js +163 -0
- package/dist/yts-torrent/client.js.map +1 -0
- package/dist/yts-torrent/config.d.ts +22 -0
- package/dist/yts-torrent/config.js +57 -0
- package/dist/yts-torrent/config.js.map +1 -0
- package/dist/yts-torrent/index.d.ts +4 -0
- package/dist/yts-torrent/index.js +42 -0
- package/dist/yts-torrent/index.js.map +1 -0
- package/dist/yts-torrent/mapping.d.ts +4 -0
- package/dist/yts-torrent/mapping.js +107 -0
- package/dist/yts-torrent/mapping.js.map +1 -0
- package/package.json +18 -5
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { rethrowIfProviderAborted } from "../shared/abort.js";
|
|
2
|
+
import { canResolveStrictTorrentQuery } from "../shared/torrent-release-matching.js";
|
|
3
|
+
import { searchMagnetzTorrents } from "./client.js";
|
|
4
|
+
import { createMagnetzTorrentCapabilities, createMagnetzTorrentConfig, } from "./config.js";
|
|
5
|
+
import { mapMagnetzTorrentResponse } from "./mapping.js";
|
|
6
|
+
import { selectMagnetzTorrentReleases } from "./matching.js";
|
|
7
|
+
export function magnetzTorrentProvider(options = {}) {
|
|
8
|
+
const config = createMagnetzTorrentConfig(options);
|
|
9
|
+
return {
|
|
10
|
+
name: config.name,
|
|
11
|
+
version: options.version,
|
|
12
|
+
kind: "torrent",
|
|
13
|
+
catalog: {
|
|
14
|
+
displayName: "Magnetz",
|
|
15
|
+
scope: "international",
|
|
16
|
+
},
|
|
17
|
+
capabilities: createMagnetzTorrentCapabilities(),
|
|
18
|
+
async discoverTorrents(query, context) {
|
|
19
|
+
if (query.providers && !query.providers.includes(config.name))
|
|
20
|
+
return null;
|
|
21
|
+
if (!canResolveStrictTorrentQuery(query))
|
|
22
|
+
return null;
|
|
23
|
+
try {
|
|
24
|
+
const releases = await searchMagnetzTorrents(config, query, context);
|
|
25
|
+
const matches = selectMagnetzTorrentReleases(releases, query);
|
|
26
|
+
return mapMagnetzTorrentResponse(config.name, config.baseUrl, matches, query);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
rethrowIfProviderAborted(context, error);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/magnetz-torrent/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,gCAAgC,EAChC,0BAA0B,GAE3B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAI7D,MAAM,UAAU,sBAAsB,CACpC,UAAyC,EAAE;IAE3C,MAAM,MAAM,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;IAEnD,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,SAAS;QACf,OAAO,EAAE;YACP,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,eAAe;SACvB;QACD,YAAY,EAAE,gCAAgC,EAAE;QAChD,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO;YACnC,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC3E,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAEtD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;gBACrE,MAAM,OAAO,GAAG,4BAA4B,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC9D,OAAO,yBAAyB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YAChF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,wBAAwB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACzC,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { TorrentDiscoveryQuery, TorrentDiscoveryResponse } from "@media-engine/core";
|
|
2
|
+
import type { MagnetzTorrentRelease } from "./client.js";
|
|
3
|
+
export declare function mapMagnetzTorrentResponse(provider: string, providerUrl: string, releases: MagnetzTorrentRelease[], query: TorrentDiscoveryQuery): TorrentDiscoveryResponse | null;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createCanonicalMagnetUri, createTorrentEpisodeRef, mapTorrentReleaseTitle, } from "../shared/torrent-release-metadata.js";
|
|
2
|
+
export function mapMagnetzTorrentResponse(provider, providerUrl, releases, query) {
|
|
3
|
+
const checkedAt = new Date().toISOString();
|
|
4
|
+
const candidates = deduplicateReleases(releases).map((release) => mapCandidate(provider, release, query, checkedAt));
|
|
5
|
+
if (candidates.length === 0)
|
|
6
|
+
return null;
|
|
7
|
+
return {
|
|
8
|
+
query,
|
|
9
|
+
item: {
|
|
10
|
+
type: query.type,
|
|
11
|
+
title: query.title,
|
|
12
|
+
year: query.year,
|
|
13
|
+
},
|
|
14
|
+
candidates,
|
|
15
|
+
sourceProviders: [{ provider, url: providerUrl }],
|
|
16
|
+
checkedAt,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function mapCandidate(provider, release, query, checkedAt) {
|
|
20
|
+
const episode = createTorrentEpisodeRef(query);
|
|
21
|
+
return {
|
|
22
|
+
id: `${provider}:${release.infoHash.toLowerCase()}`,
|
|
23
|
+
provider,
|
|
24
|
+
title: release.title,
|
|
25
|
+
infoHash: release.infoHash,
|
|
26
|
+
sizeBytes: release.sizeBytes,
|
|
27
|
+
publishedAt: release.createdAt,
|
|
28
|
+
...(episode ? { episode } : {}),
|
|
29
|
+
release: mapTorrentReleaseTitle(release.title),
|
|
30
|
+
peers: {
|
|
31
|
+
seeders: release.seeders,
|
|
32
|
+
leechers: release.leechers,
|
|
33
|
+
checkedAt,
|
|
34
|
+
},
|
|
35
|
+
handoff: {
|
|
36
|
+
kind: "magnet",
|
|
37
|
+
uri: createCanonicalMagnetUri(release.infoHash, release.title),
|
|
38
|
+
},
|
|
39
|
+
availability: release.seeders > 0 ? "available" : "unseeded",
|
|
40
|
+
sourceUrl: release.sourceUrl,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function deduplicateReleases(releases) {
|
|
44
|
+
const seen = new Set();
|
|
45
|
+
return releases.filter((release) => {
|
|
46
|
+
if (seen.has(release.infoHash))
|
|
47
|
+
return false;
|
|
48
|
+
seen.add(release.infoHash);
|
|
49
|
+
return true;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/magnetz-torrent/mapping.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,uCAAuC,CAAC;AAG/C,MAAM,UAAU,yBAAyB,CACvC,QAAgB,EAChB,WAAmB,EACnB,QAAiC,EACjC,KAA4B;IAE5B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAC/D,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,CAClD,CAAC;IAEF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,OAAO;QACL,KAAK;QACL,IAAI,EAAE;YACJ,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB;QACD,UAAU;QACV,eAAe,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;QACjD,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CACnB,QAAgB,EAChB,OAA8B,EAC9B,KAA4B,EAC5B,SAAiB;IAEjB,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO;QACL,EAAE,EAAE,GAAG,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE;QACnD,QAAQ;QACR,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,WAAW,EAAE,OAAO,CAAC,SAAS;QAC9B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC,KAAK,CAAC;QAC9C,KAAK,EAAE;YACL,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS;SACV;QACD,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,GAAG,EAAE,wBAAwB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC;SAC/D;QACD,YAAY,EAAE,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU;QAC5D,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAiC;IAC5D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matching.js","sourceRoot":"","sources":["../../src/magnetz-torrent/matching.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,uCAAuC,CAAC;AAGpF,MAAM,UAAU,4BAA4B,CAC1C,QAAiC,EACjC,KAA4B;IAE5B,OAAO,2BAA2B,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { waitForAbortableDelay } from "../shared/abort.js";
|
|
2
|
+
const DEFAULT_NOW = Date.now;
|
|
3
|
+
// Serializes starts from one provider instance and leaves a small gap between them. The live API
|
|
4
|
+
// advertises a 30-request header but has also returned short burst 429 responses below that count.
|
|
5
|
+
export class MagnetzRequestGate {
|
|
6
|
+
#intervalMs;
|
|
7
|
+
#now;
|
|
8
|
+
#tail = Promise.resolve();
|
|
9
|
+
#nextStartAt = 0;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.#intervalMs = options.intervalMs;
|
|
12
|
+
this.#now = options.now ?? DEFAULT_NOW;
|
|
13
|
+
}
|
|
14
|
+
async wait(signal) {
|
|
15
|
+
const previous = this.#tail;
|
|
16
|
+
let release = () => { };
|
|
17
|
+
const turn = new Promise((resolve) => {
|
|
18
|
+
release = resolve;
|
|
19
|
+
});
|
|
20
|
+
this.#tail = previous.then(() => turn);
|
|
21
|
+
try {
|
|
22
|
+
await waitForPromise(previous, signal);
|
|
23
|
+
await waitForAbortableDelay(Math.max(0, this.#nextStartAt - this.#now()), signal);
|
|
24
|
+
this.#nextStartAt = this.#now() + this.#intervalMs;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
release();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function waitForPromise(promise, signal) {
|
|
32
|
+
if (!signal)
|
|
33
|
+
return promise;
|
|
34
|
+
if (signal.aborted)
|
|
35
|
+
return Promise.reject(signal.reason);
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const onAbort = () => reject(signal.reason);
|
|
38
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
39
|
+
void promise.then(() => {
|
|
40
|
+
signal.removeEventListener("abort", onAbort);
|
|
41
|
+
resolve();
|
|
42
|
+
}, (error) => {
|
|
43
|
+
signal.removeEventListener("abort", onAbort);
|
|
44
|
+
reject(error);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=request-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-gate.js","sourceRoot":"","sources":["../../src/magnetz-torrent/request-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC;AAO7B,iGAAiG;AACjG,mGAAmG;AACnG,MAAM,OAAO,kBAAkB;IACpB,WAAW,CAAS;IACpB,IAAI,CAAe;IAC5B,KAAK,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IACzC,YAAY,GAAG,CAAC,CAAC;IAEjB,YAAY,OAAkC;QAC5C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAoB;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;QAC5B,IAAI,OAAO,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACzC,OAAO,GAAG,OAAO,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvC,MAAM,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YAClF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;QACrD,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAED,SAAS,cAAc,CAAC,OAAsB,EAAE,MAA+B;IAC7E,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEzD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,KAAK,OAAO,CAAC,IAAI,CACf,GAAG,EAAE;YACH,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,EAAE,CAAC;QACZ,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACR,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Keep this runtime value aligned with packages/providers/package.json.
|
|
2
|
+
// scripts/check-release-consistency.mjs enforces the manifest/runtime contract.
|
|
3
|
+
export const MEDIA_ENGINE_PROVIDERS_VERSION = "1.0.0";
|
|
4
|
+
export const MEDIA_ENGINE_DEFAULT_USER_AGENT = `MediaEngine/${MEDIA_ENGINE_PROVIDERS_VERSION} (https://github.com/Yaneart/media-engine)`;
|
|
5
|
+
//# sourceMappingURL=package-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.js","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,gFAAgF;AAChF,MAAM,CAAC,MAAM,8BAA8B,GAAG,OAAO,CAAC;AAEtD,MAAM,CAAC,MAAM,+BAA+B,GAAG,eAAe,8BAA8B,4CAA4C,CAAC"}
|
package/dist/shared/abort.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { ProviderContext } from "@media-engine/core";
|
|
2
2
|
export declare function rethrowIfProviderAborted(context: Pick<ProviderContext, "signal">, error: unknown): void;
|
|
3
|
+
export declare function waitForAbortableDelay(milliseconds: number, signal: AbortSignal | undefined): Promise<void>;
|
package/dist/shared/abort.js
CHANGED
|
@@ -5,4 +5,26 @@ export function rethrowIfProviderAborted(context, error) {
|
|
|
5
5
|
throw context.signal.reason ?? error;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
+
// Waits without losing caller cancellation and removes the listener on normal completion.
|
|
9
|
+
// Ждёт с поддержкой отмены caller и удаляет listener после обычного завершения.
|
|
10
|
+
export function waitForAbortableDelay(milliseconds, signal) {
|
|
11
|
+
if (milliseconds <= 0) {
|
|
12
|
+
return signal?.aborted ? Promise.reject(signal.reason) : Promise.resolve();
|
|
13
|
+
}
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
if (signal?.aborted) {
|
|
16
|
+
reject(signal.reason);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const timeout = setTimeout(() => {
|
|
20
|
+
signal?.removeEventListener("abort", onAbort);
|
|
21
|
+
resolve();
|
|
22
|
+
}, milliseconds);
|
|
23
|
+
const onAbort = () => {
|
|
24
|
+
clearTimeout(timeout);
|
|
25
|
+
reject(signal?.reason);
|
|
26
|
+
};
|
|
27
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
28
|
+
});
|
|
29
|
+
}
|
|
8
30
|
//# sourceMappingURL=abort.js.map
|
package/dist/shared/abort.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abort.js","sourceRoot":"","sources":["../../src/shared/abort.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,oGAAoG;AACpG,MAAM,UAAU,wBAAwB,CACtC,OAAwC,EACxC,KAAc;IAEd,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"abort.js","sourceRoot":"","sources":["../../src/shared/abort.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,oGAAoG;AACpG,MAAM,UAAU,wBAAwB,CACtC,OAAwC,EACxC,KAAc;IAEd,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,gFAAgF;AAChF,MAAM,UAAU,qBAAqB,CACnC,YAAoB,EACpB,MAA+B;IAE/B,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7E,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,YAAY,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC;QACF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/shared/http.d.ts
CHANGED
|
@@ -2,7 +2,10 @@ import { ProviderError, type ProviderErrorCode } from "@media-engine/core";
|
|
|
2
2
|
import type { ProviderContext } from "@media-engine/core";
|
|
3
3
|
import type { ProviderRateLimitGate } from "./rate-limit.js";
|
|
4
4
|
export type ProviderFetch = (input: string | URL, init?: RequestInit) => Promise<Response>;
|
|
5
|
-
export
|
|
5
|
+
export interface ProviderHttpScheduler {
|
|
6
|
+
setTimeout(callback: () => void, delayMs: number): unknown;
|
|
7
|
+
clearTimeout(handle: unknown): void;
|
|
8
|
+
}
|
|
6
9
|
export interface FetchJsonOptions {
|
|
7
10
|
provider: string;
|
|
8
11
|
url: string | URL;
|
|
@@ -13,10 +16,13 @@ export interface FetchJsonOptions {
|
|
|
13
16
|
retryDelayMs?: number;
|
|
14
17
|
maxRetryDelayMs?: number;
|
|
15
18
|
retryJitterRatio?: number;
|
|
19
|
+
maxResponseBytes?: number;
|
|
16
20
|
rateLimitGate?: ProviderRateLimitGate;
|
|
21
|
+
scheduler?: ProviderHttpScheduler;
|
|
17
22
|
}
|
|
18
23
|
export declare function fetchJson<T>(options: FetchJsonOptions): Promise<T>;
|
|
19
|
-
export declare function parseJsonResponse<T>(provider: string, response: Response): Promise<T>;
|
|
24
|
+
export declare function parseJsonResponse<T>(provider: string, response: Response, maxResponseBytes?: number, signal?: AbortSignal): Promise<T>;
|
|
20
25
|
export declare function mapProviderHttpError(provider: string, error: unknown): ProviderError;
|
|
21
26
|
export declare function mapHttpStatusToProviderErrorCode(status: number): ProviderErrorCode;
|
|
22
27
|
export declare function mapHttpResponseToProviderError(provider: string, response: Response): ProviderError;
|
|
28
|
+
export declare function getProviderHttpStatus(error: unknown): number | undefined;
|
package/dist/shared/http.js
CHANGED
|
@@ -1,60 +1,15 @@
|
|
|
1
1
|
import { ProviderError } from "@media-engine/core";
|
|
2
|
+
import { readBoundedResponseText } from "./response-body.js";
|
|
2
3
|
import { calculateRetryDelayMs, parseRetryAfterMs } from "./retry.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
url.username !== "" ||
|
|
13
|
-
url.password !== "" ||
|
|
14
|
-
isPrivateHostname(url.hostname)) {
|
|
15
|
-
return undefined;
|
|
16
|
-
}
|
|
17
|
-
return url.href;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function isPrivateHostname(value) {
|
|
24
|
-
const hostname = value
|
|
25
|
-
.toLowerCase()
|
|
26
|
-
.replace(/^\[|\]$/g, "")
|
|
27
|
-
.replace(/\.$/, "");
|
|
28
|
-
if (hostname === "localhost" ||
|
|
29
|
-
hostname.endsWith(".localhost") ||
|
|
30
|
-
hostname === "0.0.0.0" ||
|
|
31
|
-
hostname === "::" ||
|
|
32
|
-
hostname === "::1") {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
if (hostname.includes(":")) {
|
|
36
|
-
const first = Number.parseInt(hostname.split(":")[0] ?? "", 16);
|
|
37
|
-
return (hostname.startsWith("::ffff:") ||
|
|
38
|
-
(first >= 0xfc00 && first <= 0xfdff) ||
|
|
39
|
-
(first >= 0xfe80 && first <= 0xfebf));
|
|
40
|
-
}
|
|
41
|
-
const octets = hostname.split(".").map(Number);
|
|
42
|
-
if (octets.length !== 4 ||
|
|
43
|
-
octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
const [first, second] = octets;
|
|
47
|
-
return (first === 0 ||
|
|
48
|
-
first === 10 ||
|
|
49
|
-
first === 127 ||
|
|
50
|
-
(first === 100 && second >= 64 && second <= 127) ||
|
|
51
|
-
(first === 169 && second === 254) ||
|
|
52
|
-
(first === 172 && second >= 16 && second <= 31) ||
|
|
53
|
-
(first === 192 && second === 0) ||
|
|
54
|
-
(first === 192 && second === 168) ||
|
|
55
|
-
(first === 198 && (second === 18 || second === 19)) ||
|
|
56
|
-
first >= 224);
|
|
57
|
-
}
|
|
4
|
+
const DEFAULT_MAX_JSON_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
5
|
+
const defaultScheduler = {
|
|
6
|
+
setTimeout(callback, delayMs) {
|
|
7
|
+
return setTimeout(callback, delayMs);
|
|
8
|
+
},
|
|
9
|
+
clearTimeout(handle) {
|
|
10
|
+
clearTimeout(handle);
|
|
11
|
+
},
|
|
12
|
+
};
|
|
58
13
|
// Reads JSON through fetch and maps failures to ProviderError.
|
|
59
14
|
// Читает JSON через fetch и преобразует сбои в ProviderError.
|
|
60
15
|
export async function fetchJson(options) {
|
|
@@ -62,10 +17,16 @@ export async function fetchJson(options) {
|
|
|
62
17
|
const retryDelayMs = options.retryDelayMs ?? 150;
|
|
63
18
|
const maxRetryDelayMs = options.maxRetryDelayMs ?? 2_000;
|
|
64
19
|
const retryJitterRatio = options.retryJitterRatio ?? 0.2;
|
|
65
|
-
const
|
|
20
|
+
const maxResponseBytes = options.maxResponseBytes ?? DEFAULT_MAX_JSON_RESPONSE_BYTES;
|
|
21
|
+
if (!Number.isSafeInteger(maxResponseBytes) || maxResponseBytes <= 0) {
|
|
22
|
+
throw new TypeError("fetchJson maxResponseBytes must be a positive safe integer.");
|
|
23
|
+
}
|
|
24
|
+
const scheduler = options.scheduler ?? defaultScheduler;
|
|
25
|
+
const timeout = createProviderTimeout(options.provider, options.context, scheduler);
|
|
66
26
|
const signal = mergeAbortSignals(options.context?.signal, timeout.controller.signal);
|
|
67
27
|
const boundedOptions = {
|
|
68
28
|
...options,
|
|
29
|
+
maxResponseBytes,
|
|
69
30
|
context: {
|
|
70
31
|
...options.context,
|
|
71
32
|
signal,
|
|
@@ -95,7 +56,7 @@ export async function fetchJson(options) {
|
|
|
95
56
|
if (!providerError.retryable || attempt >= maxRetries) {
|
|
96
57
|
throw providerError;
|
|
97
58
|
}
|
|
98
|
-
await delay(retryDelay, signal);
|
|
59
|
+
await delay(retryDelay, signal, scheduler);
|
|
99
60
|
attempt += 1;
|
|
100
61
|
}
|
|
101
62
|
}
|
|
@@ -109,7 +70,7 @@ export async function fetchJson(options) {
|
|
|
109
70
|
// Выполняет одну попытку JSON HTTP с новым timeout signal.
|
|
110
71
|
async function fetchJsonAttempt(options) {
|
|
111
72
|
const fetchImpl = options.fetch ?? fetch;
|
|
112
|
-
const timeout = createProviderTimeout(options.provider, options.context);
|
|
73
|
+
const timeout = createProviderTimeout(options.provider, options.context, options.scheduler ?? defaultScheduler);
|
|
113
74
|
const signal = mergeAbortSignals(options.context?.signal, timeout.controller.signal);
|
|
114
75
|
try {
|
|
115
76
|
const response = await fetchImpl(options.url, {
|
|
@@ -119,7 +80,7 @@ async function fetchJsonAttempt(options) {
|
|
|
119
80
|
if (!response.ok) {
|
|
120
81
|
throw mapHttpResponseToProviderError(options.provider, response);
|
|
121
82
|
}
|
|
122
|
-
return await parseJsonResponse(options.provider, response);
|
|
83
|
+
return await parseJsonResponse(options.provider, response, options.maxResponseBytes ?? DEFAULT_MAX_JSON_RESPONSE_BYTES, signal);
|
|
123
84
|
}
|
|
124
85
|
finally {
|
|
125
86
|
timeout.clear();
|
|
@@ -127,9 +88,10 @@ async function fetchJsonAttempt(options) {
|
|
|
127
88
|
}
|
|
128
89
|
// Parses response JSON and maps invalid bodies to ProviderError.
|
|
129
90
|
// Парсит JSON ответа и преобразует невалидное тело в ProviderError.
|
|
130
|
-
export async function parseJsonResponse(provider, response) {
|
|
91
|
+
export async function parseJsonResponse(provider, response, maxResponseBytes = DEFAULT_MAX_JSON_RESPONSE_BYTES, signal) {
|
|
92
|
+
const text = await readBoundedResponseText(provider, response, maxResponseBytes, { signal });
|
|
131
93
|
try {
|
|
132
|
-
return
|
|
94
|
+
return JSON.parse(text);
|
|
133
95
|
}
|
|
134
96
|
catch (error) {
|
|
135
97
|
throw new ProviderError({
|
|
@@ -197,13 +159,21 @@ export function mapHttpResponseToProviderError(provider, response) {
|
|
|
197
159
|
code,
|
|
198
160
|
message: `Provider "${provider}" returned HTTP ${status}.`,
|
|
199
161
|
retryable: code === "PROVIDER_RATE_LIMITED" || code === "PROVIDER_UNAVAILABLE",
|
|
162
|
+
status,
|
|
200
163
|
retryAfterMs: parseRetryAfterMs(response.headers.get("retry-after")),
|
|
201
164
|
});
|
|
202
165
|
}
|
|
166
|
+
// Returns the HTTP status retained by errors created from provider responses.
|
|
167
|
+
// Возвращает HTTP status, сохраненный в ошибках из provider response.
|
|
168
|
+
export function getProviderHttpStatus(error) {
|
|
169
|
+
return error instanceof HttpProviderError ? error.status : undefined;
|
|
170
|
+
}
|
|
203
171
|
class HttpProviderError extends ProviderError {
|
|
172
|
+
status;
|
|
204
173
|
retryAfterMs;
|
|
205
174
|
constructor(options) {
|
|
206
175
|
super(options);
|
|
176
|
+
this.status = options.status;
|
|
207
177
|
this.retryAfterMs = options.retryAfterMs;
|
|
208
178
|
}
|
|
209
179
|
}
|
|
@@ -224,7 +194,7 @@ function deferSharedRateLimit(gate, error, fallbackDelayMs) {
|
|
|
224
194
|
}
|
|
225
195
|
// Creates a timeout controller for provider HTTP calls.
|
|
226
196
|
// Создает timeout controller для HTTP-вызовов провайдера.
|
|
227
|
-
function createProviderTimeout(provider, context) {
|
|
197
|
+
function createProviderTimeout(provider, context, scheduler) {
|
|
228
198
|
const controller = new AbortController();
|
|
229
199
|
const timeoutMs = context?.timeoutMs;
|
|
230
200
|
if (timeoutMs === undefined) {
|
|
@@ -250,13 +220,13 @@ function createProviderTimeout(provider, context) {
|
|
|
250
220
|
},
|
|
251
221
|
};
|
|
252
222
|
}
|
|
253
|
-
const timeout = setTimeout(() => {
|
|
223
|
+
const timeout = scheduler.setTimeout(() => {
|
|
254
224
|
controller.abort(timeoutError);
|
|
255
225
|
}, timeoutMs);
|
|
256
226
|
return {
|
|
257
227
|
controller,
|
|
258
228
|
clear() {
|
|
259
|
-
clearTimeout(timeout);
|
|
229
|
+
scheduler.clearTimeout(timeout);
|
|
260
230
|
},
|
|
261
231
|
};
|
|
262
232
|
}
|
|
@@ -273,7 +243,7 @@ function isAbortError(error) {
|
|
|
273
243
|
}
|
|
274
244
|
// Waits before the next provider retry.
|
|
275
245
|
// Ждет перед следующей provider retry.
|
|
276
|
-
function delay(ms, signal) {
|
|
246
|
+
function delay(ms, signal, scheduler) {
|
|
277
247
|
if (ms <= 0) {
|
|
278
248
|
return Promise.resolve();
|
|
279
249
|
}
|
|
@@ -282,12 +252,12 @@ function delay(ms, signal) {
|
|
|
282
252
|
reject(signal.reason);
|
|
283
253
|
return;
|
|
284
254
|
}
|
|
285
|
-
const timeout = setTimeout(() => {
|
|
255
|
+
const timeout = scheduler.setTimeout(() => {
|
|
286
256
|
signal?.removeEventListener("abort", onAbort);
|
|
287
257
|
resolve();
|
|
288
258
|
}, ms);
|
|
289
259
|
const onAbort = () => {
|
|
290
|
-
clearTimeout(timeout);
|
|
260
|
+
scheduler.clearTimeout(timeout);
|
|
291
261
|
reject(signal?.reason);
|
|
292
262
|
};
|
|
293
263
|
signal?.addEventListener("abort", onAbort, { once: true });
|
package/dist/shared/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/shared/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA0B,MAAM,oBAAoB,CAAC;AAG3E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/shared/http.ts"],"names":[],"mappings":"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"}
|
package/dist/shared/index.d.ts
CHANGED
package/dist/shared/index.js
CHANGED
package/dist/shared/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
|
package/dist/shared/mapping.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeProviderOutputUrl } from "./output-url.js";
|
|
1
2
|
// Maps simple genre labels into normalized provider-attributed values.
|
|
2
3
|
// Преобразует простые названия жанров в нормализованные значения с источником.
|
|
3
4
|
export function mapGenreNames(genres, source) {
|
|
@@ -6,7 +7,8 @@ export function mapGenreNames(genres, source) {
|
|
|
6
7
|
// Creates one normalized provider-attributed image from a direct URL.
|
|
7
8
|
// Создает одно нормализованное изображение с источником из прямого URL.
|
|
8
9
|
export function createProviderImage(url, type, source) {
|
|
9
|
-
|
|
10
|
+
const normalizedUrl = normalizeProviderOutputUrl(url);
|
|
11
|
+
return normalizedUrl ? { url: normalizedUrl, type, source } : undefined;
|
|
10
12
|
}
|
|
11
13
|
// Normalizes text for conservative provider-local title comparisons.
|
|
12
14
|
// Нормализует текст для консервативного сравнения названий внутри провайдеров.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/shared/mapping.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/shared/mapping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAE7D,uEAAuE;AACvE,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,MAA4B,EAAE,MAAc;IACxE,OAAO,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,sEAAsE;AACtE,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CACjC,GAA8B,EAC9B,IAAmB,EACnB,MAAc;IAEd,MAAM,aAAa,GAAG,0BAA0B,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1E,CAAC;AAED,qEAAqE;AACrE,+EAA+E;AAC/E,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACvD,OAAO,KAAK;SACT,iBAAiB,EAAE;SACnB,UAAU,CAAC,kBAAkB,EAAE,GAAG,CAAC;SACnC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,yEAAyE;AACzE,qEAAqE;AACrE,MAAM,UAAU,kBAAkB,CAAC,IAA+B;IAChE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isPublicIpAddress } from "./safe-fetch.js";
|
|
2
|
+
const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/u;
|
|
3
|
+
// Normalizes a provider URL before it is exposed through metadata or streaming output.
|
|
4
|
+
// Нормализует URL провайдера перед публикацией в metadata или streaming output.
|
|
5
|
+
export function normalizeProviderOutputUrl(value) {
|
|
6
|
+
if (!value || CONTROL_CHARACTERS.test(value)) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
const url = new URL(value);
|
|
11
|
+
if ((url.protocol !== "http:" && url.protocol !== "https:") ||
|
|
12
|
+
url.username !== "" ||
|
|
13
|
+
url.password !== "" ||
|
|
14
|
+
isLiteralLocalTarget(url.hostname)) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
return url.href;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Backwards-compatible name for the provider output URL policy.
|
|
24
|
+
// Обратно совместимое имя политики provider output URL.
|
|
25
|
+
export function normalizePublicHttpUrl(value) {
|
|
26
|
+
return normalizeProviderOutputUrl(value);
|
|
27
|
+
}
|
|
28
|
+
function isLiteralLocalTarget(value) {
|
|
29
|
+
const hostname = value
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.replace(/^\[|\]$/g, "")
|
|
32
|
+
.replace(/\.$/, "");
|
|
33
|
+
if (hostname === "localhost" ||
|
|
34
|
+
hostname.endsWith(".localhost") ||
|
|
35
|
+
hostname === "0.0.0.0" ||
|
|
36
|
+
hostname === "::" ||
|
|
37
|
+
hostname === "::1") {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (hostname.includes(":")) {
|
|
41
|
+
return !isPublicIpAddress(hostname);
|
|
42
|
+
}
|
|
43
|
+
const octets = hostname.split(".").map(Number);
|
|
44
|
+
if (octets.length !== 4 ||
|
|
45
|
+
octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return !isPublicIpAddress(hostname);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=output-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-url.js","sourceRoot":"","sources":["../../src/shared/output-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AAEpD,uFAAuF;AACvF,gFAAgF;AAChF,MAAM,UAAU,0BAA0B,CAAC,KAAgC;IACzE,IAAI,CAAC,KAAK,IAAI,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAE3B,IACE,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;YACvD,GAAG,CAAC,QAAQ,KAAK,EAAE;YACnB,GAAG,CAAC,QAAQ,KAAK,EAAE;YACnB,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAClC,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,wDAAwD;AACxD,MAAM,UAAU,sBAAsB,CAAC,KAAgC;IACrE,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IACzC,MAAM,QAAQ,GAAG,KAAK;SACnB,WAAW,EAAE;SACb,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtB,IACE,QAAQ,KAAK,WAAW;QACxB,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC/B,QAAQ,KAAK,SAAS;QACtB,QAAQ,KAAK,IAAI;QACjB,QAAQ,KAAK,KAAK,EAClB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE/C,IACE,MAAM,CAAC,MAAM,KAAK,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC,EAC5E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC"}
|