@vyla-entertainment/sdk 1.8.0 → 1.10.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.
@@ -1,114 +1,114 @@
1
- import { USER_AGENT } from '../utils/helpers.js';
2
-
3
- const BASE_URL = "https://vidvault.ru";
4
- const HEADERS = {
5
- "Referer": `${BASE_URL}/`,
6
- "Origin": BASE_URL,
7
- "User-Agent": USER_AGENT,
8
- };
9
-
10
- async function getToken() {
11
- const res = await fetch(`${BASE_URL}/api/get-token`, {
12
- method: "GET",
13
- headers: HEADERS
14
- });
15
- const data = await res.json();
16
- return data.t;
17
- }
18
-
19
- function getCaptionType(url) {
20
- return url.toLowerCase().includes(".vtt") ? "vtt" : "srt";
21
- }
22
-
23
- export async function getStream(args) {
24
- const { id, s, e } = args;
25
- const type = (s != null && e != null) ? "tv" : "movie";
26
-
27
- try {
28
- const token = await getToken();
29
-
30
- const payload = { type, tmdbId: String(id) };
31
- if (type === "tv") {
32
- payload.season = String(s);
33
- payload.episode = String(e);
34
- }
35
-
36
- const res = await fetch(`${BASE_URL}/api/download-proxy`, {
37
- method: "POST",
38
- headers: {
39
- ...HEADERS,
40
- "Content-Type": "application/json",
41
- "x-request-token": token
42
- },
43
- body: JSON.stringify(payload)
44
- });
45
- const data = await res.json();
46
-
47
- const allUrls = [];
48
- const subtitles = [];
49
-
50
- const mp4 = data?.mp4Data;
51
- if (mp4) {
52
- const country = mp4.country || "";
53
- const lanName = mp4.lanName || "";
54
- const detailPath = mp4.detailPath || "";
55
-
56
- const downloads = mp4.downloadInfo?.data?.downloads || [];
57
- for (const d of downloads) {
58
- if (!d?.url) continue;
59
- allUrls.push({
60
- quality: `${d.resolution}p ${detailPath} ${country} ${lanName}`.trim(),
61
- url: d.url,
62
- type: "mp4",
63
- headers: HEADERS
64
- });
65
- }
66
-
67
- const srtCaptions = mp4.downloadInfo?.data?.captions || [];
68
- for (const c of srtCaptions) {
69
- if (!c?.url) continue;
70
- subtitles.push({
71
- label: c.lanName || c.lan || "Unknown",
72
- type: getCaptionType(c.url),
73
- language: c.lan || "",
74
- url: c.url
75
- });
76
- }
77
- }
78
-
79
- const mkvFiles = data?.mkvData?.files || [];
80
- for (const f of mkvFiles) {
81
- if (!f?.url) continue;
82
- allUrls.push({
83
- quality: `MKV ${f.size || ""}`.trim(),
84
- url: f.url,
85
- type: "mp4",
86
- headers: HEADERS
87
- });
88
- }
89
-
90
- const mkvV2 = data?.mkvV2Data;
91
- if (mkvV2?.url) {
92
- allUrls.push({
93
- quality: `${mkvV2.quality || ""} ${mkvV2.language || ""} ${mkvV2.country || ""} (${mkvV2.size || ""})`.trim(),
94
- url: mkvV2.url,
95
- type: "mp4",
96
- headers: HEADERS
97
- });
98
- }
99
-
100
- const mkvV3 = data?.mkvV3Data;
101
- if (mkvV3?.url) {
102
- allUrls.push({
103
- quality: `${mkvV3.quality || ""} ${mkvV3.language || ""} ${mkvV3.country || ""} (${mkvV3.size || ""})`.trim(),
104
- url: mkvV3.url,
105
- type: "mp4",
106
- headers: HEADERS
107
- });
108
- }
109
-
110
- return allUrls.length ? { allUrls, subtitles } : null;
111
- } catch (err) {
112
- return null;
113
- }
1
+ import { USER_AGENT } from '../utils/helpers.js';
2
+
3
+ const BASE_URL = "https://vidvault.ru";
4
+ const HEADERS = {
5
+ "Referer": `${BASE_URL}/`,
6
+ "Origin": BASE_URL,
7
+ "User-Agent": USER_AGENT,
8
+ };
9
+
10
+ async function getToken() {
11
+ const res = await fetch(`${BASE_URL}/api/get-token`, {
12
+ method: "GET",
13
+ headers: HEADERS
14
+ });
15
+ const data = await res.json();
16
+ return data.t;
17
+ }
18
+
19
+ function getCaptionType(url) {
20
+ return url.toLowerCase().includes(".vtt") ? "vtt" : "srt";
21
+ }
22
+
23
+ export async function getStream(args) {
24
+ const { id, s, e } = args;
25
+ const type = (s != null && e != null) ? "tv" : "movie";
26
+
27
+ try {
28
+ const token = await getToken();
29
+
30
+ const payload = { type, tmdbId: String(id) };
31
+ if (type === "tv") {
32
+ payload.season = String(s);
33
+ payload.episode = String(e);
34
+ }
35
+
36
+ const res = await fetch(`${BASE_URL}/api/download-proxy`, {
37
+ method: "POST",
38
+ headers: {
39
+ ...HEADERS,
40
+ "Content-Type": "application/json",
41
+ "x-request-token": token
42
+ },
43
+ body: JSON.stringify(payload)
44
+ });
45
+ const data = await res.json();
46
+
47
+ const allUrls = [];
48
+ const subtitles = [];
49
+
50
+ const mp4 = data?.mp4Data;
51
+ if (mp4) {
52
+ const country = mp4.country || "";
53
+ const lanName = mp4.lanName || "";
54
+ const detailPath = mp4.detailPath || "";
55
+
56
+ const downloads = mp4.downloadInfo?.data?.downloads || [];
57
+ for (const d of downloads) {
58
+ if (!d?.url) continue;
59
+ allUrls.push({
60
+ quality: `${d.resolution}p ${detailPath} ${country} ${lanName}`.trim(),
61
+ url: d.url,
62
+ type: "mp4",
63
+ headers: HEADERS
64
+ });
65
+ }
66
+
67
+ const srtCaptions = mp4.downloadInfo?.data?.captions || [];
68
+ for (const c of srtCaptions) {
69
+ if (!c?.url) continue;
70
+ subtitles.push({
71
+ label: c.lanName || c.lan || "Unknown",
72
+ type: getCaptionType(c.url),
73
+ language: c.lan || "",
74
+ url: c.url
75
+ });
76
+ }
77
+ }
78
+
79
+ const mkvFiles = data?.mkvData?.files || [];
80
+ for (const f of mkvFiles) {
81
+ if (!f?.url) continue;
82
+ allUrls.push({
83
+ quality: `MKV ${f.size || ""}`.trim(),
84
+ url: f.url,
85
+ type: "mp4",
86
+ headers: HEADERS
87
+ });
88
+ }
89
+
90
+ const mkvV2 = data?.mkvV2Data;
91
+ if (mkvV2?.url) {
92
+ allUrls.push({
93
+ quality: `${mkvV2.quality || ""} ${mkvV2.language || ""} ${mkvV2.country || ""} (${mkvV2.size || ""})`.trim(),
94
+ url: mkvV2.url,
95
+ type: "mp4",
96
+ headers: HEADERS
97
+ });
98
+ }
99
+
100
+ const mkvV3 = data?.mkvV3Data;
101
+ if (mkvV3?.url) {
102
+ allUrls.push({
103
+ quality: `${mkvV3.quality || ""} ${mkvV3.language || ""} ${mkvV3.country || ""} (${mkvV3.size || ""})`.trim(),
104
+ url: mkvV3.url,
105
+ type: "mp4",
106
+ headers: HEADERS
107
+ });
108
+ }
109
+
110
+ return allUrls.length ? { allUrls, subtitles } : null;
111
+ } catch (err) {
112
+ return null;
113
+ }
114
114
  }
@@ -1,106 +1,184 @@
1
- // i can't fix this, i'll wait for someone else to fix this lol
1
+ import { USER_AGENT, fetchJson } from '../utils/helpers.js';
2
2
 
3
- import crypto from 'node:crypto';
4
- import { fetchJson, USER_AGENT } from '../utils/helpers.js';
5
-
6
- const CORE_URL = 'https://core.vidzee.wtf';
3
+ const BASE_URL = 'https://core.vidzee.wtf';
7
4
  const PLAYER_URL = 'https://player.vidzee.wtf';
8
- const KEY = 'c4a8f1d7e2b9a6c3d0f5e8a1b7c4d9e2';
5
+ const SERVICES = ['dcloud', 'ipcloud', 'tik', 'v6:Hindi', '3AHindi'];
6
+ const WASM_B64 = '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';
9
7
 
10
- function decryptAes(encryptedBase64) {
11
- const keyBuf = Buffer.from(KEY, 'utf8');
12
- const ciphertext = Buffer.from(encryptedBase64, 'base64');
8
+ let wasmInstanceCache = null;
13
9
 
10
+ async function getWasmInstance() {
11
+ if (wasmInstanceCache) return wasmInstanceCache;
14
12
  try {
15
- const decipher = crypto.createDecipheriv('aes-256-ecb', keyBuf, null);
16
- decipher.setAutoPadding(true);
17
- let dec = decipher.update(ciphertext);
18
- dec = Buffer.concat([dec, decipher.final()]);
19
- const text = dec.toString('utf8');
20
- if (text.startsWith('http') || text.includes('{')) return text;
21
- } catch { }
13
+ const wasmBuffer = Buffer.from(WASM_B64, 'base64');
14
+ const wasmModule = await WebAssembly.compile(wasmBuffer);
22
15
 
23
- try {
24
- const iv = Buffer.alloc(16, 0);
25
- const decipher = crypto.createDecipheriv('aes-256-cbc', keyBuf, iv);
26
- decipher.setAutoPadding(true);
27
- let dec = decipher.update(ciphertext);
28
- dec = Buffer.concat([dec, decipher.final()]);
29
- const text = dec.toString('utf8');
30
- if (text.startsWith('http') || text.includes('{')) return text;
31
- } catch { }
16
+ let memory;
17
+ let exports;
18
+
19
+ const env = {
20
+ abort() {
21
+ throw new Error('WASM abort');
22
+ }
23
+ };
24
+
25
+ const res = await WebAssembly.instantiate(wasmModule, { env });
26
+ exports = res.exports;
27
+ memory = exports.memory;
28
+
29
+ const refMap = new Map();
30
+ function pin(ptr) {
31
+ if (ptr) {
32
+ const count = refMap.get(ptr);
33
+ if (count) refMap.set(ptr, count + 1);
34
+ else refMap.set(exports.__pin(ptr), 1);
35
+ }
36
+ return ptr;
37
+ }
38
+ function unpin(ptr) {
39
+ if (ptr) {
40
+ const count = refMap.get(ptr);
41
+ if (count === 1) {
42
+ exports.__unpin(ptr);
43
+ refMap.delete(ptr);
44
+ } else if (count) {
45
+ refMap.set(ptr, count - 1);
46
+ }
47
+ }
48
+ }
49
+
50
+ wasmInstanceCache = {
51
+ decrypt(encryptedBytes, keyStr) {
52
+ let dataPtr = 0;
53
+ let keyPtr = 0;
54
+ try {
55
+ const len = encryptedBytes.length;
56
+ const pinPtr = exports.__pin(exports.__new(len, 1)) >>> 0;
57
+ dataPtr = exports.__new(12, 6) >>> 0;
58
+
59
+ const view = new DataView(memory.buffer);
60
+ view.setUint32(dataPtr, pinPtr, true);
61
+ view.setUint32(dataPtr + 4, pinPtr, true);
62
+ view.setUint32(dataPtr + 8, len, true);
63
+ new Uint8Array(memory.buffer, pinPtr, len).set(encryptedBytes);
64
+ exports.__unpin(pinPtr);
32
65
 
66
+ pin(dataPtr);
67
+
68
+ const kLen = keyStr.length;
69
+ keyPtr = exports.__new(kLen << 1, 2) >>> 0;
70
+ const u16View = new Uint16Array(memory.buffer);
71
+ for (let i = 0; i < kLen; i++) {
72
+ u16View[(keyPtr >>> 1) + i] = keyStr.charCodeAt(i);
73
+ }
74
+
75
+ const resPtr = exports.decrypt(dataPtr, keyPtr) >>> 0;
76
+ if (!resPtr) return new Uint8Array(0);
77
+
78
+ const resView = new DataView(memory.buffer);
79
+ const outPtr = resView.getUint32(resPtr + 4, true);
80
+ const outLen = resView.getUint32(resPtr + 8, true);
81
+ return new Uint8Array(memory.buffer, outPtr, outLen).slice();
82
+ } finally {
83
+ unpin(dataPtr);
84
+ }
85
+ }
86
+ };
87
+ return wasmInstanceCache;
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+
93
+ async function requestEndpoint(url, headers) {
33
94
  try {
34
- const iv = ciphertext.subarray(0, 16);
35
- const data = ciphertext.subarray(16);
36
- const decipher = crypto.createDecipheriv('aes-256-cbc', keyBuf, iv);
37
- decipher.setAutoPadding(true);
38
- let dec = decipher.update(data);
39
- dec = Buffer.concat([dec, decipher.final()]);
40
- const text = dec.toString('utf8');
41
- if (text.startsWith('http') || text.includes('{')) return text;
42
- } catch { }
95
+ return await fetchJson(url, {
96
+ headers,
97
+ signal: AbortSignal.timeout(6000)
98
+ });
99
+ } catch {
100
+ return null;
101
+ }
102
+ }
103
+
104
+ async function resolveServiceStream(service, isMovie, id, s, e, headers) {
105
+ const directEndpoint = isMovie
106
+ ? `${BASE_URL}/streams/movie/${id}?s=${service}`
107
+ : `${BASE_URL}/streams/tv/${id}/${s || 1}/${e || 1}?s=${service}`;
108
+
109
+ let res = await requestEndpoint(directEndpoint, headers);
43
110
 
111
+ if (!res || !res.url) {
112
+ const encEndpoint = `${directEndpoint}&e=1`;
113
+ const encRes = await requestEndpoint(encEndpoint, headers);
114
+
115
+ if (encRes && encRes.c) {
116
+ const instance = await getWasmInstance();
117
+ if (instance) {
118
+ const encryptedBytes = new Uint8Array(Buffer.from(encRes.c, 'base64'));
119
+ const decryptedBytes = instance.decrypt(encryptedBytes, 'player.vidzee.wtf');
120
+ if (decryptedBytes.length > 0) {
121
+ const str = new TextDecoder().decode(decryptedBytes);
122
+ try {
123
+ res = JSON.parse(str);
124
+ } catch { }
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ if (res && res.url) {
131
+ const format = res.url.includes('.m3u8') ? 'hls' : 'mp4';
132
+ return {
133
+ url: res.url,
134
+ server: `VidZee (${service})`,
135
+ quality: res.language || 'Auto',
136
+ type: format,
137
+ headers: {
138
+ 'User-Agent': USER_AGENT,
139
+ 'Referer': `${PLAYER_URL}/`,
140
+ 'Origin': PLAYER_URL,
141
+ ...(res.headers || {})
142
+ }
143
+ };
144
+ }
44
145
  return null;
45
146
  }
46
147
 
47
- export async function getStream({ id, s, e, clientIP }) {
148
+ export async function getStream(args) {
149
+ const { id, s, e, server, clientIP } = args;
150
+ const isTv = s != null && e != null;
151
+ const isMovie = !isTv;
152
+
48
153
  const headers = {
49
154
  'User-Agent': USER_AGENT,
50
- 'Accept': 'application/json',
51
- 'Referer': PLAYER_URL,
155
+ 'Accept': 'application/json, text/plain, */*',
156
+ 'Referer': `${PLAYER_URL}/`,
52
157
  'Origin': PLAYER_URL,
53
158
  ...(clientIP && { 'X-Forwarded-For': clientIP })
54
159
  };
55
160
 
56
- try {
57
- const isTv = s != null && e != null;
58
- const servers = ['tik', 'ipcloud', 'v6:Hindi'];
59
- const results = [];
60
-
61
- for (const sr of servers) {
62
- try {
63
- const url = isTv
64
- ? `${CORE_URL}/streams/tv/${id}/${s}/${e}?s=${encodeURIComponent(sr)}&e=${e}`
65
- : `${CORE_URL}/streams/movie/${id}?s=${encodeURIComponent(sr)}&e=1`;
66
-
67
- const data = await fetchJson(url, { headers, signal: AbortSignal.timeout(6000) });
68
-
69
- if (data && data.c) {
70
- const decryptedText = decryptAes(data.c);
71
- if (decryptedText) {
72
- let streamUrl = decryptedText;
73
- let extraHeaders = {};
74
-
75
- if (decryptedText.startsWith('{')) {
76
- try {
77
- const parsed = JSON.parse(decryptedText);
78
- streamUrl = parsed.url || parsed.link || parsed.file;
79
- if (parsed.headers) extraHeaders = parsed.headers;
80
- } catch { }
81
- }
82
-
83
- if (streamUrl && streamUrl.startsWith('http')) {
84
- results.push({
85
- url: streamUrl,
86
- server: `VidZee - ${sr}`,
87
- skipHlsCheck: true,
88
- headers: {
89
- 'User-Agent': USER_AGENT,
90
- 'Referer': PLAYER_URL,
91
- 'Origin': PLAYER_URL,
92
- ...extraHeaders
93
- }
94
- });
95
- }
96
- }
97
- }
98
- } catch (err) {
99
- }
100
- }
161
+ let targets = SERVICES;
162
+ if (server && server !== 'all') {
163
+ const clean = server.toLowerCase().replace('vidzee (', '').replace(')', '').replace('vidzee', '').trim();
164
+ targets = SERVICES.filter(srv => srv.toLowerCase().includes(clean));
165
+ if (!targets.length) targets = SERVICES;
166
+ }
101
167
 
102
- return results.length ? { allUrls: results } : null;
103
- } catch {
104
- return null;
168
+ const settled = await Promise.allSettled(
169
+ targets.map(service => resolveServiceStream(service, isMovie, id, s, e, headers))
170
+ );
171
+
172
+ const allUrls = [];
173
+ for (const r of settled) {
174
+ if (r.status === 'fulfilled' && r.value) {
175
+ allUrls.push(r.value);
176
+ }
105
177
  }
178
+
179
+ return allUrls.length ? { allUrls } : null;
180
+ }
181
+
182
+ export async function getSources() {
183
+ return SERVICES.map(s => `VidZee (${s})`);
106
184
  }
@@ -67,7 +67,7 @@ function cacheGet(cache, key) {
67
67
 
68
68
  function cacheSet(cache, key, val, ttl) { cache.set(key, { val, ts: Date.now(), ttl }); }
69
69
 
70
- export async function createStreamArgs(source, tmdbApiKey, id, s, e, clientIP = null) {
70
+ export async function createStreamArgs(source, sdk, id, s, e, clientIP = null) {
71
71
  const audio = /dub$/.test(source.key) ? 'dub' : 'sub';
72
72
  return {
73
73
  id: id,
@@ -76,7 +76,7 @@ export async function createStreamArgs(source, tmdbApiKey, id, s, e, clientIP =
76
76
  clientIP: clientIP,
77
77
  absoluteBase: '/',
78
78
  audio,
79
- tmdbApiKey,
79
+ sdk,
80
80
  config: source,
81
81
  }
82
82
  }
@@ -1,115 +0,0 @@
1
- import { USER_AGENT } from '../utils/helpers.js';
2
-
3
- const BASE_URL = "https://1embed.cc";
4
-
5
- const PROVIDERS = [
6
- { id: "BUKE", name: "1Embed - BUKE" },
7
- { id: "YOTA", name: "1Embed - YOTA" },
8
- { id: "NEPT", name: "1Embed - NEPT" },
9
- { id: "AZURE", name: "1Embed - AZURE" },
10
- { id: "YORU", name: "1Embed - YORU" }
11
- ];
12
-
13
- let cachedToken = null;
14
- let tokenExpiresAt = 0;
15
-
16
- async function getToken() {
17
- const now = Math.floor(Date.now() / 1000);
18
- if (cachedToken && tokenExpiresAt > now + 10) return cachedToken;
19
- try {
20
- const res = await fetch(`${BASE_URL}/api/token`, { headers: { "Referer": `${BASE_URL}/`, "User-Agent": USER_AGENT, "Accept": "application/json" }, signal: AbortSignal.timeout(10000) });
21
- if (!res.ok) return null;
22
- const data = await res.json();
23
- cachedToken = data.token;
24
- tokenExpiresAt = data.expiresAt;
25
- return cachedToken;
26
- } catch { return null; }
27
- }
28
-
29
- function decodeBsUrl(url) {
30
- if (!url) return url;
31
- let target = url;
32
- if (url.includes('d=')) {
33
- try {
34
- const parts = url.split(/[?&]/);
35
- for (const part of parts) {
36
- if (part.startsWith('d=')) {
37
- target = decodeURIComponent(part.substring(2));
38
- break;
39
- }
40
- }
41
- } catch { }
42
- }
43
- if (target.startsWith('bs_')) {
44
- try {
45
- const decoded = Buffer.from(target.slice(3), 'base64').toString('utf-8');
46
- const reversed = decoded.split('').reverse().join('');
47
- if (reversed.startsWith('http')) return reversed;
48
- } catch { }
49
- }
50
- return url;
51
- }
52
-
53
- async function fetchProviderStream(provider, type, id, s, e, token) {
54
- try {
55
- const referer = type === "movie" ? `${BASE_URL}/embed/movie/${id}` : `${BASE_URL}/embed/tv/${id}/${s}/${e}`;
56
- const payload = { type, id: String(id), provider: provider.id };
57
- if (type === "tv") { payload.season = Number(s); payload.episode = Number(e); }
58
- const res = await fetch(`${BASE_URL}/api/sources`, {
59
- method: "POST",
60
- headers: { "User-Agent": USER_AGENT, "Referer": referer, "Origin": BASE_URL, "Accept": "application/json", "Content-Type": "application/json", "x-bcine-key": token, "X-Requested-With": "XMLHttpRequest" },
61
- body: JSON.stringify(payload),
62
- signal: AbortSignal.timeout(15000)
63
- });
64
- if (!res.ok) return null;
65
- const data = await res.json();
66
-
67
- let rawSources = [];
68
- if (Array.isArray(data.servers)) rawSources.push(...data.servers);
69
- if (data.providerResults?.[provider.id]?.sources) rawSources.push(...data.providerResults[provider.id].sources);
70
- if (data.providerResults?.[provider.id] && Array.isArray(data.providerResults[provider.id])) rawSources.push(...data.providerResults[provider.id]);
71
-
72
- if (!rawSources.length) return null;
73
- const results = [];
74
- for (const src of rawSources) {
75
- if (typeof src !== 'object' || !src) continue;
76
- let rawUrl = src.url || src.file || src.link;
77
- if (typeof rawUrl !== 'string') continue;
78
- let streamUrl = decodeBsUrl(rawUrl);
79
- if (streamUrl.startsWith('/')) streamUrl = `${BASE_URL}${streamUrl}`;
80
- const isWorker = streamUrl.includes('omena-puu') || streamUrl.includes('nocach') || streamUrl.includes('?p=');
81
- const isHls = src.type === 'hls' || src.type === 'm3u8' || streamUrl.includes('m3u8') || isWorker;
82
- if (isHls && !streamUrl.includes('m3u8')) streamUrl += streamUrl.includes('?') ? '&format=.m3u8' : '?format=.m3u8';
83
- const srcHeaders = (src.headers && typeof src.headers === 'object') ? src.headers : {};
84
- results.push({
85
- url: streamUrl,
86
- server: provider.name,
87
- quality: src.quality || src.label || src.title || "Auto",
88
- type: isHls ? "hls" : "mp4",
89
- headers: { "User-Agent": USER_AGENT, "Referer": referer, "Origin": BASE_URL, ...srcHeaders },
90
- });
91
- }
92
- return results;
93
- } catch {
94
- return null;
95
- }
96
- }
97
-
98
- export async function getStream(args) {
99
- const { id, s, e, server } = args;
100
- const type = s != null && e != null ? "tv" : "movie";
101
- const token = await getToken();
102
- if (!token) return null;
103
- let targets = PROVIDERS;
104
- if (server && server !== 'all') {
105
- const cleanName = server.replace('1Embed - ', '').toLowerCase();
106
- targets = PROVIDERS.filter(p => p.id.toLowerCase() === cleanName || p.name.toLowerCase().includes(cleanName));
107
- if (!targets.length) targets = PROVIDERS;
108
- }
109
- const settled = await Promise.allSettled(targets.map(p => fetchProviderStream(p, type, id, s, e, token)));
110
- const allUrls = [];
111
- for (const r of settled) if (r.status === 'fulfilled' && r.value) allUrls.push(...r.value);
112
- return allUrls.length ? { allUrls } : null;
113
- }
114
-
115
- export async function getSources() { return PROVIDERS.map(p => p.name); }