@vyla-entertainment/sdk 1.12.0 → 1.14.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vyla-entertainment/sdk",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "scripts": {
5
5
  "test": "node test/index.js"
6
6
  },
package/src/config.js CHANGED
@@ -6,18 +6,6 @@
6
6
  // Fshare/Fsonic Tested: 155 ( they don't have Michael )
7
7
 
8
8
  export const SOURCES = [
9
- {
10
- key: '4khdhub',
11
- label: '4KHDHub',
12
- sourceFile: '4khdhub',
13
- proxyParam: 'khd',
14
- timeout: 35000,
15
- jitter: 500,
16
- retries: 1,
17
- multiUrl: true,
18
- skipProxy: true,
19
- },
20
-
21
9
  {
22
10
  key: '123anime',
23
11
  label: '123Anime',
@@ -119,72 +107,20 @@ export const SOURCES = [
119
107
  },
120
108
 
121
109
  {
122
- key: 'cinejoy',
123
- label: 'Cinejoy',
124
- sourceFile: 'cinejoy',
125
- proxyParam: 'cj',
126
- timeout: 30000,
127
- jitter: 500,
128
- retries: 1,
129
- multiUrl: true,
130
- skipProxy: true,
131
- },
132
-
133
- {
134
- key: 'cinesrc',
135
- label: 'CineSrc',
136
- sourceFile: 'cinesrc',
137
- proxyParam: 'csr',
138
- timeout: 25000,
139
- jitter: 500,
140
- retries: 2,
141
- multiUrl: true,
142
- skipProxy: true,
143
- skipVerify: true,
144
- cdnHeaders: [{
145
- pattern: /glendale-plumbing\.com|1embed\.cc|bright\d+\.online/i,
146
- headers: {
147
- Referer: 'https://cinesrc.st/',
148
- Origin: 'https://cinesrc.st',
149
- },
150
- }],
151
- },
152
-
153
- {
154
- key: 'cinesu',
155
- label: 'CineSu',
156
- sourceFile: 'cinesu',
157
- proxyParam: 'cs',
110
+ key: 'dulo',
111
+ label: 'Dulo',
112
+ sourceFile: 'dulo',
113
+ proxyParam: 'dl',
158
114
  timeout: 25000,
159
115
  jitter: 500,
160
116
  retries: 2,
161
117
  multiUrl: true,
162
118
  skipProxy: true,
163
- skipVerify: true,
164
119
  cdnHeaders: [{
165
- pattern: /glendale-plumbing\.com/i,
120
+ pattern: /dulo\.mov/i,
166
121
  headers: {
167
- Referer: 'https://cine.su/',
168
- Origin: 'https://cine.su',
169
- },
170
- }],
171
- },
172
-
173
- {
174
- key: 'downloadeverything',
175
- label: 'DownloadEverything',
176
- sourceFile: 'downloadeverything',
177
- proxyParam: 'de',
178
- timeout: 35000,
179
- jitter: 500,
180
- retries: 1,
181
- multiUrl: true,
182
- skipProxy: true,
183
- cdnHeaders: [{
184
- pattern: /cloudflarestorage\.com|pixeldrain\.com|hakunaymatata\.com/i,
185
- headers: {
186
- Referer: 'https://downloadeverythingfromeverywhere.com/',
187
- Origin: 'https://downloadeverythingfromeverywhere.com',
122
+ Referer: 'https://dulo.mov/',
123
+ Origin: 'https://dulo.mov',
188
124
  },
189
125
  }],
190
126
  },
@@ -208,45 +144,6 @@ export const SOURCES = [
208
144
  },],
209
145
  },
210
146
 
211
- {
212
- key: 'frame',
213
- label: 'Frame',
214
- sourceFile: 'frame',
215
- proxyParam: 'fr',
216
- timeout: 25000,
217
- jitter: 500,
218
- retries: 2,
219
- multiUrl: true,
220
- skipProxy: true,
221
- },
222
-
223
- {
224
- key: 'fsharetv',
225
- label: 'FShareTV',
226
- sourceFile: 'fsharetv',
227
- proxyParam: 'fs',
228
- timeout: 25000,
229
- jitter: 600,
230
- retries: 2,
231
- multiUrl: false,
232
- verifyHeaders: {
233
- Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8',
234
- 'Accept-Language': 'en-US,en;q=0.9',
235
- Referer: 'https://fsharetv.cc',
236
- },
237
- },
238
-
239
- {
240
- key: 'fsonic',
241
- label: 'Fsonic',
242
- sourceFile: 'fsonic',
243
- proxyParam: 'fn',
244
- timeout: 35000,
245
- jitter: 600,
246
- retries: 1,
247
- multiUrl: true,
248
- },
249
-
250
147
  {
251
148
  key: 'fsonline',
252
149
  label: 'FSOnline',
@@ -259,16 +156,6 @@ export const SOURCES = [
259
156
  skipProxy: true,
260
157
  },
261
158
 
262
- {
263
- key: 'hexa',
264
- label: 'Hexa',
265
- sourceFile: 'hexa',
266
- proxyParam: 'hx',
267
- timeout: 20000,
268
- jitter: 500,
269
- retries: 2,
270
- },
271
-
272
159
  {
273
160
  key: 'kisskh',
274
161
  label: 'KissKH',
@@ -304,44 +191,6 @@ export const SOURCES = [
304
191
  },
305
192
  },
306
193
 
307
- {
308
- key: 'luna-sub',
309
- label: 'Luna (Sub)',
310
- sourceFile: 'luna',
311
- proxyParam: 'lusub',
312
- subtype: 'sub',
313
- timeout: 25000,
314
- jitter: 500,
315
- retries: 2,
316
- multiUrl: true,
317
- skipProxy: true,
318
- },
319
-
320
- {
321
- key: 'luna-dub',
322
- label: 'Luna (Dub)',
323
- sourceFile: 'luna',
324
- proxyParam: 'ludub',
325
- subtype: 'dub',
326
- timeout: 25000,
327
- jitter: 500,
328
- retries: 2,
329
- multiUrl: true,
330
- skipProxy: true,
331
- },
332
-
333
- {
334
- key: 'meowtv',
335
- label: 'MeowTV',
336
- sourceFile: 'meowtv',
337
- proxyParam: 'mt',
338
- timeout: 20000,
339
- jitter: 500,
340
- retries: 2,
341
- multiUrl: true,
342
- skipProxy: true
343
- },
344
-
345
194
  {
346
195
  key: 'movienight',
347
196
  label: 'MovieNight',
@@ -380,18 +229,6 @@ export const SOURCES = [
380
229
  }],
381
230
  },
382
231
 
383
- {
384
- key: 'peestream',
385
- label: 'PeeStream',
386
- sourceFile: 'peestream',
387
- proxyParam: 'pee',
388
- timeout: 25000,
389
- jitter: 500,
390
- retries: 2,
391
- multiUrl: true,
392
- skipProxy: true,
393
- },
394
-
395
232
  {
396
233
  key: 'pengu',
397
234
  label: 'Pengu',
@@ -456,26 +293,6 @@ export const SOURCES = [
456
293
  },
457
294
  }],
458
295
  },
459
-
460
- {
461
- key: 'vadapav',
462
- label: 'Vadapav',
463
- sourceFile: 'vadapav',
464
- proxyParam: 'vp',
465
- timeout: 25000,
466
- jitter: 500,
467
- retries: 2,
468
- multiUrl: true,
469
- skipProxy: true,
470
- cdnHeaders: [{
471
- pattern: /vadapav\.mov/i,
472
- headers: {
473
- Referer: 'https://stremio.vadapav.mov/',
474
- Origin: 'https://stremio.vadapav.mov',
475
- },
476
- }],
477
- },
478
-
479
296
  {
480
297
  key: 'vidapi',
481
298
  label: 'VidAPI',
@@ -489,23 +306,23 @@ export const SOURCES = [
489
306
 
490
307
  {
491
308
  key: 'vidcore',
309
+ label: 'VidCore',
492
310
  sourceFile: 'vidcore',
493
- label: 'Vidcore',
494
311
  proxyParam: 'vc',
495
- timeout: 30000,
312
+ timeout: 35000,
496
313
  jitter: 500,
497
- retries: 2,
498
- sourcesTimeout: 10000,
314
+ retries: 1,
315
+ multiUrl: true,
499
316
  },
500
-
501
317
  {
502
318
  key: 'vidfast',
503
- label: 'Vidfast',
319
+ label: 'VidFast',
504
320
  sourceFile: 'vidfast',
505
321
  proxyParam: 'vf',
506
322
  timeout: 35000,
507
323
  jitter: 500,
508
324
  retries: 1,
325
+ multiUrl: true,
509
326
  },
510
327
 
511
328
  {
@@ -644,25 +461,6 @@ export const SOURCES = [
644
461
  },
645
462
  },
646
463
 
647
- {
648
- key: 'vuflix',
649
- label: 'Vuflix',
650
- sourceFile: 'vuflix',
651
- proxyParam: 'vfx',
652
- timeout: 25000,
653
- jitter: 500,
654
- retries: 2,
655
- multiUrl: true,
656
- skipProxy: true,
657
- cdnHeaders: [{
658
- pattern: /vuflix\.co/i,
659
- headers: {
660
- Referer: 'https://vuflix.co/',
661
- Origin: 'https://vuflix.co',
662
- },
663
- }],
664
- },
665
-
666
464
  {
667
465
  key: 'xdownloader',
668
466
  label: 'XDownloader',
@@ -0,0 +1,150 @@
1
+ import { getUA } from '../utils/helpers.js';
2
+
3
+ const BASE_URL = 'https://dulo.mov';
4
+
5
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
+
7
+ async function resolveDetails(sdk, id, isTv) {
8
+ const apiKey = sdk?.tmdbApiKey || process.env.TMDB_API_KEY;
9
+ if (!apiKey) return null;
10
+ const type = isTv ? 'tv' : 'movie';
11
+ try {
12
+ const res = await fetch(`https://api.themoviedb.org/3/${type}/${id}?api_key=${apiKey}`, {
13
+ signal: AbortSignal.timeout(6000),
14
+ });
15
+ if (!res.ok) return null;
16
+ const data = await res.json();
17
+ const title = isTv ? data.name : data.title;
18
+ const releaseDate = isTv ? data.first_air_date : data.release_date;
19
+ const year = releaseDate ? releaseDate.split('-')[0] : '';
20
+ const runtime = isTv ? (data.episode_run_time?.[0] || 24) : (data.runtime || 90);
21
+ return { title, year, runtime };
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+
27
+ async function fetchSource(url, headers) {
28
+ try {
29
+ const res = await fetch(url, {
30
+ headers,
31
+ signal: AbortSignal.timeout(8000),
32
+ });
33
+ if (!res.ok) return null;
34
+ return await res.json();
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+
40
+ export async function getStream({ id, s, e, sdk }) {
41
+ const isTv = Boolean(s && e);
42
+ const mediaType = isTv ? 'tv' : 'movie';
43
+ const ua = getUA();
44
+
45
+ const details = await resolveDetails(sdk, id, isTv);
46
+ const title = details?.title || '';
47
+ const year = details?.year || '';
48
+ const runtime = details?.runtime || '';
49
+
50
+ const referer = isTv
51
+ ? `${BASE_URL}/watch/tv/${id}/${s}/${e}`
52
+ : `${BASE_URL}/watch/movie/${id}`;
53
+
54
+ const defaultHeaders = {
55
+ 'User-Agent': ua,
56
+ Referer: referer,
57
+ Origin: BASE_URL,
58
+ Accept: '*/*',
59
+ 'Sec-Fetch-Dest': 'empty',
60
+ 'Sec-Fetch-Mode': 'cors',
61
+ 'Sec-Fetch-Site': 'same-origin',
62
+ };
63
+
64
+ const baseParams = new URLSearchParams({
65
+ tmdbId: String(id),
66
+ type: mediaType,
67
+ });
68
+
69
+ const additionalParams = new URLSearchParams({
70
+ tmdbId: String(id),
71
+ type: mediaType,
72
+ progressive: 'true',
73
+ });
74
+
75
+ if (title) additionalParams.set('title', title);
76
+ if (year) additionalParams.set('year', String(year));
77
+ if (runtime) additionalParams.set('runtime', String(runtime));
78
+
79
+ if (isTv) {
80
+ baseParams.set('season', String(s));
81
+ baseParams.set('episode', String(e));
82
+ additionalParams.set('season', String(s));
83
+ additionalParams.set('episode', String(e));
84
+ }
85
+
86
+ const endpoints = [
87
+ `${BASE_URL}/api/sources?${baseParams.toString()}`,
88
+ `${BASE_URL}/api/sources/willow?${baseParams.toString()}`,
89
+ `${BASE_URL}/api/sources/additional?${additionalParams.toString()}`,
90
+ ];
91
+
92
+ const seenUrls = new Set();
93
+ const allUrls = [];
94
+
95
+ let pendingUrls = [...endpoints];
96
+ const maxPollTime = Date.now() + 16000;
97
+
98
+ while (pendingUrls.length > 0 && Date.now() < maxPollTime) {
99
+ const results = await Promise.all(
100
+ pendingUrls.map((url) => fetchSource(url, defaultHeaders))
101
+ );
102
+
103
+ const nextPending = [];
104
+
105
+ results.forEach((data, index) => {
106
+ if (!data) return;
107
+
108
+ if (Array.isArray(data.sources) && data.sources.length > 0) {
109
+ for (const src of data.sources) {
110
+ let streamUrl = String(src?.url || '').trim();
111
+ if (!streamUrl) continue;
112
+
113
+ if (streamUrl.startsWith('/')) {
114
+ streamUrl = `${BASE_URL}${streamUrl}`;
115
+ }
116
+
117
+ if (!streamUrl.startsWith('http') || seenUrls.has(streamUrl)) continue;
118
+ seenUrls.add(streamUrl);
119
+
120
+ allUrls.push({
121
+ url: streamUrl,
122
+ label: src.label || 'Dulo',
123
+ headers: {
124
+ 'User-Agent': ua,
125
+ Referer: referer,
126
+ },
127
+ captions: Array.isArray(src.captions) ? src.captions : [],
128
+ });
129
+ }
130
+ }
131
+
132
+ if (data.pending) {
133
+ nextPending.push(pendingUrls[index]);
134
+ }
135
+ });
136
+
137
+ pendingUrls = nextPending;
138
+ if (pendingUrls.length > 0) {
139
+ await sleep(1500);
140
+ }
141
+ }
142
+
143
+ if (allUrls.length === 0) return null;
144
+
145
+ return {
146
+ url: allUrls[0].url,
147
+ allUrls,
148
+ headers: allUrls[0].headers,
149
+ };
150
+ }
@@ -49,9 +49,9 @@ export async function getStream({ id, s, e, sdk }) {
49
49
  'User-Agent': ua,
50
50
  Referer: `${BASE_URL}/`,
51
51
  Origin: BASE_URL,
52
- Accept: 'application/x-ndjson, text/plain, */*',
52
+ Accept: 'text/event-stream, application/x-ndjson, text/plain, */*',
53
53
  },
54
- signal: AbortSignal.timeout(18000),
54
+ signal: AbortSignal.timeout(90000),
55
55
  });
56
56
 
57
57
  if (!res.ok) return null;
@@ -89,7 +89,9 @@ export async function getStream({ id, s, e, sdk }) {
89
89
 
90
90
  for (const line of lines) {
91
91
  try {
92
- const item = JSON.parse(line);
92
+ const raw = line.startsWith('data:') ? line.slice(5).trim() : line;
93
+ if (!raw || raw === '[DONE]') continue;
94
+ const item = JSON.parse(raw);
93
95
  const streamUrl = String(item?.url || '').trim();
94
96
  if (!streamUrl || !streamUrl.startsWith('http') || seenUrls.has(streamUrl)) continue;
95
97
 
@@ -1,43 +1,123 @@
1
- import { fetchJson, fetchText, USER_AGENT } from '../utils/helpers.js';
1
+ import { getUA } from '../utils/helpers.js';
2
2
 
3
- const API_BASE = 'https://enc-dec.app/api';
4
- const HEADERS = { 'User-Agent': USER_AGENT, 'Referer': 'https://vidcore.net/', 'X-Requested-With': 'XMLHttpRequest' };
3
+ const BASE_URL = 'https://vidcore.io';
4
+ const API = 'https://enc-dec.app/api';
5
+
6
+ export async function getStream({ id, s, e }) {
7
+ const isTv = Boolean(s && e);
8
+ const targetUrl = isTv
9
+ ? `${BASE_URL}/tv/${id}/${s}/${e}/`
10
+ : `${BASE_URL}/movie/${id}`;
11
+
12
+ const ua = getUA();
13
+ const baseHeaders = {
14
+ 'User-Agent': ua,
15
+ 'Referer': `${BASE_URL}/`,
16
+ 'X-Requested-With': 'XMLHttpRequest',
17
+ };
5
18
 
6
- async function getDynamicServers(id, s, e) {
7
19
  try {
8
- const html = await fetchText(s != null && e != null ? `https://vidcore.net/tv/${id}/${s}/${e}/` : `https://vidcore.net/movie/${id}/`, { headers: HEADERS });
20
+ const pageRes = await fetch(targetUrl, {
21
+ headers: { 'User-Agent': ua },
22
+ signal: AbortSignal.timeout(10000),
23
+ });
24
+ if (!pageRes.ok) return null;
25
+ const html = await pageRes.text();
9
26
 
10
- const match = html.match(/\\"(?:en|token)\\":\\"(.*?)\\"/) || html.match(/"(?:en|token)":"(.*?)"/);
11
- if (!match?.[1]) return null;
27
+ const match = html.match(/\\"(?:en|token)\\":\\"(.*?)\\"/);
28
+ if (!match || !match[1]) return null;
29
+ const enToken = match[1];
12
30
 
13
- const encData = await fetchJson(`${API_BASE}/enc-vidcore?text=${encodeURIComponent(match[1])}`);
14
- if (!encData?.result) return null;
15
- const { servers: serversUrl, stream: streamUrl, token } = encData.result;
16
- const reqHeaders = { ...HEADERS, 'X-CSRF-Token': token };
17
- const serversEncrypted = await fetchText(serversUrl, { method: 'POST', headers: reqHeaders });
18
- const decData = await fetchJson(`${API_BASE}/dec-vidcore`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: serversEncrypted }) });
19
- return decData?.result ? { servers: decData.result, streamUrl, reqHeaders } : null;
20
- } catch { return null; }
21
- }
31
+ const s1Res = await fetch(`${API}/enc-vidcore?text=${encodeURIComponent(enToken)}&stage=1`, {
32
+ signal: AbortSignal.timeout(8000),
33
+ });
34
+ const s1Data = await s1Res.json();
35
+ if (s1Data?.status !== 200 || !s1Data?.result?.stage1) return null;
22
36
 
23
- export async function getStream({ id, s, e }) {
24
- const data = await getDynamicServers(id, s, e);
25
- if (!data?.servers?.length) return null;
26
- for (const srv of data.servers) {
27
- try {
28
- const streamEncrypted = await fetchText(`${data.streamUrl}/${srv.data}`, { method: 'POST', headers: data.reqHeaders });
29
- const decData = await fetchJson(`${API_BASE}/dec-vidcore`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: streamEncrypted }) });
30
- const url = decData?.result?.url;
31
- if (url) {
32
- const r = await fetch(url, { headers: { ...HEADERS, 'Range': 'bytes=0-511' }, signal: AbortSignal.timeout(5000) });
33
- if (r.ok || r.status === 206) return { url, subtitles: (decData.result.captions || []).map(c => ({ url: c.file, lang: c.label || 'Unknown' })), headers: { ...HEADERS, 'Origin': 'https://vidcore.net' }, server: srv.name };
34
- }
35
- } catch { }
36
- }
37
- return null;
38
- }
37
+ const token1 = s1Data.result.token;
38
+ const stage1Url = s1Data.result.stage1;
39
+
40
+ const post1Res = await fetch(stage1Url, {
41
+ method: 'POST',
42
+ headers: { ...baseHeaders, 'X-CSRF-Token': token1 },
43
+ signal: AbortSignal.timeout(10000),
44
+ });
45
+ if (!post1Res.ok) return null;
46
+ const stage1Text = await post1Res.text();
47
+
48
+ const s2Res = await fetch(`${API}/enc-vidcore?text=${encodeURIComponent(stage1Text)}&stage=2`, {
49
+ signal: AbortSignal.timeout(8000),
50
+ });
51
+ const s2Data = await s2Res.json();
52
+ if (s2Data?.status !== 200 || !s2Data?.result?.servers) return null;
53
+
54
+ const { servers: serversUrl, stream: streamBaseUrl, token: token2 } = s2Data.result;
55
+ const currentHeaders = { ...baseHeaders, 'X-CSRF-Token': token2 };
56
+
57
+ const serversRes = await fetch(serversUrl, {
58
+ method: 'POST',
59
+ headers: currentHeaders,
60
+ signal: AbortSignal.timeout(10000),
61
+ });
62
+ if (!serversRes.ok) return null;
63
+ const serversEncrypted = await serversRes.text();
39
64
 
40
- export async function getSources(args) {
41
- const data = await getDynamicServers(args.id, args.s, args.e);
42
- return data?.servers ? data.servers.map(s => s.name) : [];
65
+ const decServersRes = await fetch(`${API}/dec-vidcore`, {
66
+ method: 'POST',
67
+ headers: { 'Content-Type': 'application/json' },
68
+ body: JSON.stringify({ text: serversEncrypted }),
69
+ signal: AbortSignal.timeout(8000),
70
+ });
71
+ const decServersData = await decServersRes.json();
72
+ if (decServersData?.status !== 200 || !Array.isArray(decServersData.result)) return null;
73
+
74
+ const allUrls = [];
75
+
76
+ for (const server of decServersData.result) {
77
+ if (!server?.data) continue;
78
+ try {
79
+ const streamUrl = `${streamBaseUrl}/${server.data}`;
80
+ const streamEncRes = await fetch(streamUrl, {
81
+ method: 'POST',
82
+ headers: currentHeaders,
83
+ signal: AbortSignal.timeout(8000),
84
+ });
85
+ if (!streamEncRes.ok) continue;
86
+ const streamEncText = await streamEncRes.text();
87
+
88
+ const decStreamRes = await fetch(`${API}/dec-vidcore`, {
89
+ method: 'POST',
90
+ headers: { 'Content-Type': 'application/json' },
91
+ body: JSON.stringify({ text: streamEncText }),
92
+ signal: AbortSignal.timeout(8000),
93
+ });
94
+ const decStreamData = await decStreamRes.json();
95
+ if (decStreamData?.status !== 200 || !decStreamData.result) continue;
96
+
97
+ const streamResult = decStreamData.result;
98
+ const resultUrl = typeof streamResult === 'string' ? streamResult : streamResult?.url || streamResult?.file;
99
+
100
+ if (typeof resultUrl === 'string' && resultUrl.startsWith('http')) {
101
+ allUrls.push({
102
+ url: resultUrl,
103
+ label: server.name || server.title || 'VidCore',
104
+ headers: {
105
+ 'User-Agent': ua,
106
+ 'Referer': `${BASE_URL}/`,
107
+ },
108
+ });
109
+ }
110
+ } catch { }
111
+ }
112
+
113
+ if (allUrls.length === 0) return null;
114
+
115
+ return {
116
+ url: allUrls[0].url,
117
+ allUrls,
118
+ headers: allUrls[0].headers,
119
+ };
120
+ } catch {
121
+ return null;
122
+ }
43
123
  }