@media-engine/providers 1.12.0 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +20 -2
  2. package/README.ru.md +8 -2
  3. package/dist/anilist/index.js +1 -0
  4. package/dist/anilist/index.js.map +1 -1
  5. package/dist/cinemeta/index.js +1 -0
  6. package/dist/cinemeta/index.js.map +1 -1
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.js +3 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/kinobd/index.js +1 -0
  11. package/dist/kinobd/index.js.map +1 -1
  12. package/dist/kinobd-streaming/players.js +5 -0
  13. package/dist/kinobd-streaming/players.js.map +1 -1
  14. package/dist/kodik-streaming/client.d.ts +40 -0
  15. package/dist/kodik-streaming/client.js +209 -0
  16. package/dist/kodik-streaming/client.js.map +1 -0
  17. package/dist/kodik-streaming/config.d.ts +26 -0
  18. package/dist/kodik-streaming/config.js +58 -0
  19. package/dist/kodik-streaming/config.js.map +1 -0
  20. package/dist/kodik-streaming/index.d.ts +4 -0
  21. package/dist/kodik-streaming/index.js +58 -0
  22. package/dist/kodik-streaming/index.js.map +1 -0
  23. package/dist/kodik-streaming/mapping.d.ts +3 -0
  24. package/dist/kodik-streaming/mapping.js +192 -0
  25. package/dist/kodik-streaming/mapping.js.map +1 -0
  26. package/dist/package-version.d.ts +2 -2
  27. package/dist/package-version.js +1 -1
  28. package/dist/shikimori/index.js +1 -0
  29. package/dist/shikimori/index.js.map +1 -1
  30. package/dist/shikimori-graphql/index.d.ts +9 -0
  31. package/dist/shikimori-graphql/index.js +205 -0
  32. package/dist/shikimori-graphql/index.js.map +1 -0
  33. package/dist/tmdb/index.js +1 -0
  34. package/dist/tmdb/index.js.map +1 -1
  35. package/dist/tmdb-official/index.d.ts +9 -0
  36. package/dist/tmdb-official/index.js +246 -0
  37. package/dist/tmdb-official/index.js.map +1 -0
  38. package/dist/tvmaze/index.js +1 -0
  39. package/dist/tvmaze/index.js.map +1 -1
  40. package/dist/wikidata/index.js +1 -0
  41. package/dist/wikidata/index.js.map +1 -1
  42. package/package.json +3 -2
@@ -0,0 +1,209 @@
1
+ import { ProviderError } from "@media-engine/core";
2
+ import { fetchJson } from "../shared/index.js";
3
+ const MAX_TITLE_LENGTH = 500;
4
+ const MAX_URL_LENGTH = 8_192;
5
+ export async function searchKodik(config, query, context) {
6
+ for (const lookup of resolveLookups(query)) {
7
+ const requestUrl = createSearchUrl(config, lookup);
8
+ let payload;
9
+ try {
10
+ payload = await fetchJson({
11
+ provider: config.name,
12
+ url: requestUrl,
13
+ context,
14
+ fetch: config.fetch,
15
+ rateLimitGate: config.rateLimitGate,
16
+ maxRetries: 0,
17
+ maxResponseBytes: config.maxResponseBytes,
18
+ init: { headers: { Accept: "application/json", "User-Agent": config.userAgent } },
19
+ });
20
+ }
21
+ catch (error) {
22
+ throw redactRequestError(config.name, error);
23
+ }
24
+ const results = parseKodikResponse(config.name, payload, config.resultLimit);
25
+ if (results.length > 0) {
26
+ return { results, sourceUrl: new URL("/search", `${config.baseUrl}/`).href };
27
+ }
28
+ }
29
+ return null;
30
+ }
31
+ function redactRequestError(provider, error) {
32
+ const code = error instanceof ProviderError ? error.code : "PROVIDER_UNAVAILABLE";
33
+ return new ProviderError({
34
+ provider,
35
+ code,
36
+ retryable: error instanceof ProviderError ? error.retryable : true,
37
+ message: `Provider "${provider}" Kodik request failed (${code}).`,
38
+ });
39
+ }
40
+ export function createSearchUrl(config, lookup) {
41
+ const url = new URL("/search", `${config.baseUrl}/`);
42
+ url.searchParams.set("token", config.apiKey);
43
+ url.searchParams.set(lookup.key, lookup.value);
44
+ url.searchParams.set("with_episodes", "true");
45
+ url.searchParams.set("limit", String(config.resultLimit));
46
+ return url;
47
+ }
48
+ export function parseKodikResponse(provider, value, limit) {
49
+ if (!isRecord(value) || !Array.isArray(value.results))
50
+ throw invalidResponse(provider);
51
+ const results = value.results.slice(0, limit).flatMap((entry) => {
52
+ const result = parseResult(entry);
53
+ return result ? [result] : [];
54
+ });
55
+ if (value.results.length > 0 && results.length === 0)
56
+ throw invalidResponse(provider);
57
+ return results;
58
+ }
59
+ function resolveLookups(query) {
60
+ const ids = {
61
+ kinopoisk: query.ids?.kinopoisk ?? query.kinopoisk,
62
+ imdb: query.ids?.imdb ?? query.imdb,
63
+ shikimori: query.ids?.shikimori ?? query.shikimori,
64
+ };
65
+ const ordered = query.type === "anime"
66
+ ? [
67
+ ["shikimori_id", ids.shikimori],
68
+ ["kinopoisk_id", ids.kinopoisk],
69
+ ["imdb_id", ids.imdb],
70
+ ]
71
+ : [
72
+ ["kinopoisk_id", ids.kinopoisk],
73
+ ["imdb_id", ids.imdb],
74
+ ];
75
+ return ordered.flatMap(([key, value]) => {
76
+ const normalized = normalizeLookup(key, value);
77
+ return normalized ? [{ key, value: normalized }] : [];
78
+ });
79
+ }
80
+ function normalizeLookup(key, value) {
81
+ const normalized = value?.trim();
82
+ if (!normalized)
83
+ return undefined;
84
+ if (key === "imdb_id")
85
+ return /^tt\d{5,12}$/u.test(normalized) ? normalized : undefined;
86
+ return /^\d{1,12}$/u.test(normalized) ? normalized : undefined;
87
+ }
88
+ function parseResult(value) {
89
+ if (!isRecord(value) || !isRecord(value.translation))
90
+ return undefined;
91
+ const id = readString(value.id, 100);
92
+ const type = readString(value.type, 100);
93
+ const link = readString(value.link, MAX_URL_LENGTH);
94
+ const title = readString(value.title, MAX_TITLE_LENGTH);
95
+ const translationTitle = readString(value.translation.title, MAX_TITLE_LENGTH);
96
+ if (!id || !type || !link || !title || !translationTitle)
97
+ return undefined;
98
+ const originalTitle = readString(value.title_orig, MAX_TITLE_LENGTH);
99
+ const year = readInteger(value.year, 1_800, 3_000);
100
+ const translationId = readIdentifier(value.translation.id);
101
+ const translationType = readString(value.translation.type, 100);
102
+ const quality = readString(value.quality, 200);
103
+ return {
104
+ id,
105
+ type,
106
+ link,
107
+ title,
108
+ ...(originalTitle ? { originalTitle } : {}),
109
+ ...(year !== undefined ? { year } : {}),
110
+ ...readExternalIds(value),
111
+ translation: {
112
+ ...(translationId ? { id: translationId } : {}),
113
+ title: translationTitle,
114
+ ...(translationType ? { type: translationType } : {}),
115
+ },
116
+ ...(quality ? { quality } : {}),
117
+ blockedCountries: readStringArray(value.blocked_countries, 100, 100),
118
+ blockedSeasons: readBlockedSeasons(value.blocked_seasons),
119
+ seasons: readSeasons(value.seasons),
120
+ };
121
+ }
122
+ function readExternalIds(value) {
123
+ const kinopoiskId = readNumericIdentifier(value.kinopoisk_id);
124
+ const imdbId = readString(value.imdb_id, 32);
125
+ const shikimoriId = readNumericIdentifier(value.shikimori_id);
126
+ return {
127
+ ...(kinopoiskId ? { kinopoiskId } : {}),
128
+ ...(imdbId && /^tt\d{5,12}$/u.test(imdbId) ? { imdbId } : {}),
129
+ ...(shikimoriId ? { shikimoriId } : {}),
130
+ };
131
+ }
132
+ function readSeasons(value) {
133
+ if (!isRecord(value))
134
+ return {};
135
+ const seasons = {};
136
+ for (const [seasonKey, rawSeason] of Object.entries(value).slice(0, 100)) {
137
+ const seasonNumber = parsePositiveInteger(seasonKey);
138
+ if (seasonNumber === undefined || !isRecord(rawSeason) || !isRecord(rawSeason.episodes))
139
+ continue;
140
+ const episodes = {};
141
+ for (const [episodeKey, rawLink] of Object.entries(rawSeason.episodes).slice(0, 2_000)) {
142
+ const episodeNumber = parsePositiveInteger(episodeKey);
143
+ const link = readString(rawLink, MAX_URL_LENGTH);
144
+ if (episodeNumber !== undefined && link)
145
+ episodes[episodeNumber] = link;
146
+ }
147
+ const link = readString(rawSeason.link, MAX_URL_LENGTH);
148
+ seasons[seasonNumber] = { ...(link ? { link } : {}), episodes };
149
+ }
150
+ return seasons;
151
+ }
152
+ function readBlockedSeasons(value) {
153
+ const values = Array.isArray(value)
154
+ ? value
155
+ : isRecord(value)
156
+ ? Object.entries(value)
157
+ .filter(([, blocked]) => Boolean(blocked))
158
+ .map(([key]) => key)
159
+ : [];
160
+ return new Set(values.flatMap((entry) => {
161
+ const parsed = parsePositiveInteger(String(entry));
162
+ return parsed === undefined ? [] : [parsed];
163
+ }));
164
+ }
165
+ function readStringArray(value, limit, maxLength) {
166
+ return Array.isArray(value)
167
+ ? value
168
+ .slice(0, limit)
169
+ .flatMap((entry) => (readString(entry, maxLength) ? [readString(entry, maxLength)] : []))
170
+ : [];
171
+ }
172
+ function readString(value, maxLength) {
173
+ if (typeof value !== "string")
174
+ return undefined;
175
+ const normalized = value.trim();
176
+ return normalized && normalized.length <= maxLength ? normalized : undefined;
177
+ }
178
+ function readIdentifier(value) {
179
+ if (typeof value === "number" && Number.isSafeInteger(value) && value > 0)
180
+ return String(value);
181
+ return readString(value, 100);
182
+ }
183
+ function readNumericIdentifier(value) {
184
+ const normalized = readIdentifier(value);
185
+ return normalized && /^\d{1,12}$/u.test(normalized) ? normalized : undefined;
186
+ }
187
+ function readInteger(value, min, max) {
188
+ return Number.isSafeInteger(value) && Number(value) >= min && Number(value) <= max
189
+ ? Number(value)
190
+ : undefined;
191
+ }
192
+ function parsePositiveInteger(value) {
193
+ if (!/^[1-9]\d{0,5}$/u.test(value))
194
+ return undefined;
195
+ const parsed = Number(value);
196
+ return Number.isSafeInteger(parsed) ? parsed : undefined;
197
+ }
198
+ function isRecord(value) {
199
+ return typeof value === "object" && value !== null && !Array.isArray(value);
200
+ }
201
+ function invalidResponse(provider) {
202
+ return new ProviderError({
203
+ provider,
204
+ code: "PROVIDER_INVALID_RESPONSE",
205
+ message: `Provider "${provider}" returned an invalid Kodik response.`,
206
+ retryable: false,
207
+ });
208
+ }
209
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/kodik-streaming/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { StreamingProviderCapabilities } from "@media-engine/core";
2
+ import { ProviderRateLimitGate, type ProviderFetch } from "../shared/index.js";
3
+ export interface KodikStreamingProviderOptions {
4
+ apiKey: string;
5
+ name?: string;
6
+ version?: string;
7
+ baseUrl?: string;
8
+ fetch?: ProviderFetch;
9
+ maxResponseBytes?: number;
10
+ resultLimit?: number;
11
+ userAgent?: string;
12
+ now?: () => number;
13
+ }
14
+ export interface KodikStreamingConfig {
15
+ name: string;
16
+ apiKey: string;
17
+ baseUrl: string;
18
+ fetch: ProviderFetch;
19
+ rateLimitGate: ProviderRateLimitGate;
20
+ maxResponseBytes: number;
21
+ resultLimit: number;
22
+ userAgent: string;
23
+ now: () => number;
24
+ }
25
+ export declare function createKodikConfig(options: KodikStreamingProviderOptions): KodikStreamingConfig;
26
+ export declare function createKodikCapabilities(): StreamingProviderCapabilities;
@@ -0,0 +1,58 @@
1
+ import { MEDIA_ENGINE_DEFAULT_USER_AGENT } from "../package-version.js";
2
+ import { ProviderRateLimitGate } from "../shared/index.js";
3
+ import { resolveBoundedIntegerOption } from "../shared/options.js";
4
+ import { createHardenedProviderFetch } from "../shared/safe-fetch.js";
5
+ const DEFAULT_PROVIDER_NAME = "kodik-streaming";
6
+ const DEFAULT_BASE_URL = "https://kodik-api.com";
7
+ const DEFAULT_MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
8
+ const DEFAULT_RESULT_LIMIT = 100;
9
+ export function createKodikConfig(options) {
10
+ const name = normalizeRequiredValue(options.name ?? DEFAULT_PROVIDER_NAME, "provider name", 100);
11
+ return {
12
+ name,
13
+ apiKey: normalizeRequiredValue(options.apiKey, "apiKey", 4_096),
14
+ baseUrl: normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL),
15
+ fetch: options.fetch ?? createHardenedProviderFetch({ provider: name, maxRedirects: 2 }),
16
+ rateLimitGate: new ProviderRateLimitGate(),
17
+ maxResponseBytes: resolveBoundedIntegerOption(options.maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES, "Kodik streaming maxResponseBytes", 1_024, 16 * 1024 * 1024),
18
+ resultLimit: resolveBoundedIntegerOption(options.resultLimit, DEFAULT_RESULT_LIMIT, "Kodik streaming resultLimit", 1, 100),
19
+ userAgent: options.userAgent?.trim() || MEDIA_ENGINE_DEFAULT_USER_AGENT,
20
+ now: options.now ?? Date.now,
21
+ };
22
+ }
23
+ export function createKodikCapabilities() {
24
+ return {
25
+ mediaTypes: ["movie", "series", "anime"],
26
+ animeKinds: ["movie", "tv"],
27
+ lookup: {
28
+ byTitle: false,
29
+ byExternalIds: ["kinopoisk", "imdb", "shikimori"],
30
+ byEpisode: true,
31
+ },
32
+ features: ["embed", "translations", "qualities", "episode_mapping"],
33
+ };
34
+ }
35
+ function normalizeRequiredValue(value, label, maxLength) {
36
+ const normalized = value.trim();
37
+ if (!normalized || normalized.length > maxLength || /[\u0000-\u001f\u007f]/u.test(normalized)) {
38
+ throw new TypeError(`Kodik streaming ${label} is invalid.`);
39
+ }
40
+ return normalized;
41
+ }
42
+ function normalizeBaseUrl(value) {
43
+ let url;
44
+ try {
45
+ url = new URL(value.trim());
46
+ }
47
+ catch (error) {
48
+ throw new TypeError("Kodik streaming baseUrl must be a valid HTTPS URL.", { cause: error });
49
+ }
50
+ if (url.protocol !== "https:" || url.username || url.password) {
51
+ throw new TypeError("Kodik streaming baseUrl must be a credential-free HTTPS URL.");
52
+ }
53
+ url.pathname = "/";
54
+ url.search = "";
55
+ url.hash = "";
56
+ return url.href.replace(/\/$/u, "");
57
+ }
58
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/kodik-streaming/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { StreamingProvider } from "@media-engine/core";
2
+ import { type KodikStreamingProviderOptions } from "./config.js";
3
+ export type { KodikStreamingProviderOptions } from "./config.js";
4
+ export declare function kodikStreamingProvider(options: KodikStreamingProviderOptions): StreamingProvider;
@@ -0,0 +1,58 @@
1
+ import { rethrowIfProviderAborted } from "../shared/abort.js";
2
+ import { searchKodik } from "./client.js";
3
+ import { createKodikCapabilities, createKodikConfig, } from "./config.js";
4
+ import { mapKodikAvailability } from "./mapping.js";
5
+ export function kodikStreamingProvider(options) {
6
+ const config = createKodikConfig(options);
7
+ return {
8
+ name: config.name,
9
+ version: options.version,
10
+ kind: "streaming",
11
+ capabilities: createKodikCapabilities(),
12
+ async getAvailability(query, context) {
13
+ if (query.providers && !query.providers.includes(config.name))
14
+ return null;
15
+ if (!canResolveQuery(query))
16
+ return null;
17
+ try {
18
+ const search = await searchKodik(config, query, context);
19
+ return search
20
+ ? mapKodikAvailability(config.name, search.results, query, search.sourceUrl, config.now())
21
+ : null;
22
+ }
23
+ catch (error) {
24
+ rethrowIfProviderAborted(context, error);
25
+ throw error;
26
+ }
27
+ },
28
+ };
29
+ }
30
+ function canResolveQuery(query) {
31
+ const hasKodikId = Boolean(query.ids?.kinopoisk ??
32
+ query.kinopoisk ??
33
+ query.ids?.imdb ??
34
+ query.imdb ??
35
+ (query.type === "anime" ? (query.ids?.shikimori ?? query.shikimori) : undefined));
36
+ if (!hasKodikId)
37
+ return false;
38
+ const isFilm = query.type === "movie" || (query.type === "anime" && query.animeKind === "movie");
39
+ if (isFilm) {
40
+ return (query.seasonNumber === undefined &&
41
+ query.episodeNumber === undefined &&
42
+ query.absoluteEpisodeNumber === undefined);
43
+ }
44
+ if (query.type === "anime") {
45
+ const hasAnyEpisodeCoordinate = query.seasonNumber !== undefined ||
46
+ query.episodeNumber !== undefined ||
47
+ query.absoluteEpisodeNumber !== undefined;
48
+ return (query.animeKind === "tv" &&
49
+ (!hasAnyEpisodeCoordinate ||
50
+ (query.seasonNumber !== undefined &&
51
+ query.episodeNumber !== undefined &&
52
+ query.absoluteEpisodeNumber !== undefined)));
53
+ }
54
+ return (query.absoluteEpisodeNumber === undefined &&
55
+ ((query.seasonNumber === undefined && query.episodeNumber === undefined) ||
56
+ (query.seasonNumber !== undefined && query.episodeNumber !== undefined)));
57
+ }
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/kodik-streaming/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { MediaAvailability } from "@media-engine/core";
2
+ import type { KodikResult } from "./client.js";
3
+ export declare function mapKodikAvailability(provider: string, results: KodikResult[], query: MediaAvailability["query"], sourceUrl: string, now: number): MediaAvailability | null;
@@ -0,0 +1,192 @@
1
+ import { resolveAnimeEpisodeSelection, verifyAnimeEpisodeSelection, } from "../shared/anime-episode.js";
2
+ import { normalizeProviderOutputUrl } from "../shared/index.js";
3
+ const MOVIE_TYPES = new Set([
4
+ "foreign-movie",
5
+ "russian-movie",
6
+ "soviet-cartoon",
7
+ "foreign-cartoon",
8
+ ]);
9
+ const SERIES_TYPES = new Set([
10
+ "foreign-serial",
11
+ "russian-serial",
12
+ "cartoon-serial",
13
+ "documentary-serial",
14
+ ]);
15
+ export function mapKodikAvailability(provider, results, query, sourceUrl, now) {
16
+ const matching = results.filter((result) => matchesQuery(result, query));
17
+ const options = uniqueOptions(matching.flatMap((result) => {
18
+ const selected = selectAccess(result, query);
19
+ return selected ? [createOption(provider, result, selected, query)] : [];
20
+ }));
21
+ if (options.length === 0)
22
+ return null;
23
+ const first = matching[0];
24
+ const ids = collectIds(first);
25
+ const episode = options[0]?.episode;
26
+ return {
27
+ query,
28
+ item: {
29
+ type: query.type,
30
+ title: first.title,
31
+ ...(first.originalTitle ? { originalTitle: first.originalTitle } : {}),
32
+ ...(first.year !== undefined ? { year: first.year } : {}),
33
+ ids,
34
+ },
35
+ ...(episode ? { episodes: [{ ...episode, options }] } : {}),
36
+ options,
37
+ sourceProviders: [{ provider, url: sourceUrl, ids }],
38
+ checkedAt: new Date(now).toISOString(),
39
+ };
40
+ }
41
+ function matchesQuery(result, query) {
42
+ if (!matchesType(result.type, query))
43
+ return false;
44
+ const expected = {
45
+ kinopoisk: query.ids?.kinopoisk ?? query.kinopoisk,
46
+ imdb: query.ids?.imdb ?? query.imdb,
47
+ shikimori: query.ids?.shikimori ?? query.shikimori,
48
+ };
49
+ const actual = {
50
+ kinopoisk: result.kinopoiskId,
51
+ imdb: result.imdbId,
52
+ shikimori: result.shikimoriId,
53
+ };
54
+ const comparable = Object.entries(expected).filter(([, value]) => value !== undefined);
55
+ const observed = comparable.filter(([key]) => actual[key] !== undefined);
56
+ return (observed.length > 0 &&
57
+ observed.every(([key, value]) => actual[key] === value));
58
+ }
59
+ function matchesType(type, query) {
60
+ if (query.type === "movie")
61
+ return MOVIE_TYPES.has(type);
62
+ if (query.type === "series")
63
+ return SERIES_TYPES.has(type);
64
+ if (query.animeKind === "movie")
65
+ return type === "anime";
66
+ return query.animeKind === "tv" && type === "anime-serial";
67
+ }
68
+ function selectAccess(result, query) {
69
+ const isFilm = query.type === "movie" || (query.type === "anime" && query.animeKind === "movie");
70
+ if (isFilm)
71
+ return normalizeLink(result.link);
72
+ const hasSeason = query.seasonNumber !== undefined;
73
+ const hasEpisode = query.episodeNumber !== undefined;
74
+ if (query.type === "series") {
75
+ if (!hasSeason && !hasEpisode && query.absoluteEpisodeNumber === undefined) {
76
+ return normalizeLink(result.link);
77
+ }
78
+ if (!hasSeason || !hasEpisode || query.absoluteEpisodeNumber !== undefined)
79
+ return undefined;
80
+ return selectEpisode(result, query.seasonNumber, query.episodeNumber);
81
+ }
82
+ if (!hasSeason && !hasEpisode && query.absoluteEpisodeNumber === undefined) {
83
+ return normalizeLink(result.link);
84
+ }
85
+ const catalog = Object.entries(result.seasons).flatMap(([seasonNumber, season]) => Object.keys(season.episodes).map((episodeNumber) => ({
86
+ seasonNumber: Number(seasonNumber),
87
+ episodeNumber: Number(episodeNumber),
88
+ })));
89
+ const selection = verifyAnimeEpisodeSelection(query, catalog) ?? resolveReleaseLocalEpisode(result, query);
90
+ return selection
91
+ ? selectEpisode(result, selection.seasonNumber, selection.episodeNumber)
92
+ : undefined;
93
+ }
94
+ function resolveReleaseLocalEpisode(result, query) {
95
+ const selection = resolveAnimeEpisodeSelection(query);
96
+ const release = query.animeReleaseEpisode;
97
+ if (!selection?.releaseEpisodeNumber || !release)
98
+ return undefined;
99
+ const expectedCount = release.releaseEpisodeCounts[release.releaseIndex];
100
+ const candidates = Object.entries(result.seasons).filter(([, season]) => {
101
+ const episodes = Object.keys(season.episodes).map(Number);
102
+ return (episodes.length === expectedCount &&
103
+ episodes.every((episodeNumber, index) => episodeNumber === index + 1) &&
104
+ season.episodes[selection.releaseEpisodeNumber] !== undefined);
105
+ });
106
+ return candidates.length === 1
107
+ ? {
108
+ seasonNumber: Number(candidates[0][0]),
109
+ episodeNumber: selection.releaseEpisodeNumber,
110
+ }
111
+ : undefined;
112
+ }
113
+ function selectEpisode(result, seasonNumber, episodeNumber) {
114
+ const link = result.seasons[seasonNumber]?.episodes[episodeNumber];
115
+ const normalized = normalizeLink(link);
116
+ return normalized ? { ...normalized, providerSeason: seasonNumber } : undefined;
117
+ }
118
+ function normalizeLink(value) {
119
+ const normalized = normalizeProviderOutputUrl(value?.startsWith("//") ? `https:${value}` : value);
120
+ return normalized ? { url: normalized } : undefined;
121
+ }
122
+ function createOption(provider, result, selected, query) {
123
+ const episode = createEpisodeRef(query);
124
+ const quality = result.quality?.trim();
125
+ const heightMatch = quality?.match(/(?:^|\D)(\d{3,4})p(?:\D|$)/iu);
126
+ const availability = result.blockedCountries.length > 0
127
+ ? "region_locked"
128
+ : selected.providerSeason !== undefined && result.blockedSeasons.has(selected.providerSeason)
129
+ ? "temporarily_unavailable"
130
+ : "available";
131
+ const episodeKey = episode
132
+ ? `:s${episode.seasonNumber ?? ""}:e${episode.episodeNumber ?? ""}:a${episode.absoluteEpisodeNumber ?? ""}`
133
+ : "";
134
+ return {
135
+ id: `${provider}:${result.id}${episodeKey}`,
136
+ provider,
137
+ discovery: "direct",
138
+ player: { kind: "embed", label: "Kodik", provider: "kodik", providerPlayerId: result.id },
139
+ translation: mapTranslation(result.translation),
140
+ ...(quality
141
+ ? {
142
+ quality: {
143
+ label: quality,
144
+ ...(heightMatch ? { height: Number(heightMatch[1]) } : {}),
145
+ },
146
+ }
147
+ : {}),
148
+ ...(episode ? { episode } : {}),
149
+ access: { url: selected.url },
150
+ availability,
151
+ sourceUrl: selected.url,
152
+ };
153
+ }
154
+ function createEpisodeRef(query) {
155
+ if (query.episodeNumber === undefined)
156
+ return undefined;
157
+ return {
158
+ ...(query.seasonNumber !== undefined ? { seasonNumber: query.seasonNumber } : {}),
159
+ episodeNumber: query.episodeNumber,
160
+ ...(query.type === "anime" && query.absoluteEpisodeNumber !== undefined
161
+ ? { absoluteEpisodeNumber: query.absoluteEpisodeNumber }
162
+ : {}),
163
+ };
164
+ }
165
+ function mapTranslation(translation) {
166
+ const normalized = translation.type?.toLowerCase();
167
+ return {
168
+ ...(translation.id ? { id: translation.id } : {}),
169
+ title: translation.title,
170
+ type: normalized === "subtitles" ? "subtitles" : normalized === "voice" ? "voiceover" : "unknown",
171
+ language: "ru",
172
+ team: translation.title,
173
+ };
174
+ }
175
+ function collectIds(result) {
176
+ return {
177
+ ...(result.kinopoiskId ? { kinopoisk: result.kinopoiskId } : {}),
178
+ ...(result.imdbId ? { imdb: result.imdbId } : {}),
179
+ ...(result.shikimoriId ? { shikimori: result.shikimoriId } : {}),
180
+ };
181
+ }
182
+ function uniqueOptions(options) {
183
+ const seen = new Set();
184
+ return options.filter((option) => {
185
+ const key = `${option.access.url}\u0000${option.translation?.id ?? option.translation?.title ?? ""}`;
186
+ if (seen.has(key))
187
+ return false;
188
+ seen.add(key);
189
+ return true;
190
+ });
191
+ }
192
+ //# sourceMappingURL=mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/kodik-streaming/mapping.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare const MEDIA_ENGINE_PROVIDERS_VERSION = "1.12.0";
2
- export declare const MEDIA_ENGINE_DEFAULT_USER_AGENT = "MediaEngine/1.12.0 (https://github.com/Yaneart/media-engine)";
1
+ export declare const MEDIA_ENGINE_PROVIDERS_VERSION = "1.13.1";
2
+ export declare const MEDIA_ENGINE_DEFAULT_USER_AGENT = "MediaEngine/1.13.1 (https://github.com/Yaneart/media-engine)";
@@ -1,5 +1,5 @@
1
1
  // Keep this runtime value aligned with packages/providers/package.json.
2
2
  // scripts/check-release-consistency.mjs enforces the manifest/runtime contract.
3
- export const MEDIA_ENGINE_PROVIDERS_VERSION = "1.12.0";
3
+ export const MEDIA_ENGINE_PROVIDERS_VERSION = "1.13.1";
4
4
  export const MEDIA_ENGINE_DEFAULT_USER_AGENT = `MediaEngine/${MEDIA_ENGINE_PROVIDERS_VERSION} (https://github.com/Yaneart/media-engine)`;
5
5
  //# sourceMappingURL=package-version.js.map
@@ -20,6 +20,7 @@ export function shikimoriProvider(options = {}) {
20
20
  searchPosterMatchesDetails: true,
21
21
  capabilities: {
22
22
  mediaTypes: ["anime"],
23
+ metadataRoute: "fallback",
23
24
  search: {
24
25
  byTitle: true,
25
26
  byExternalIds: ["shikimori", "myAnimeList"],