@vyla-entertainment/sdk 1.11.0 → 1.12.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.11.0",
3
+ "version": "1.12.0",
4
4
  "scripts": {
5
5
  "test": "node test/index.js"
6
6
  },
@@ -30,4 +30,4 @@
30
30
  "publishConfig": {
31
31
  "access": "public"
32
32
  }
33
- }
33
+ }
package/src/config.js CHANGED
@@ -1,4 +1,4 @@
1
- // Currently active sources reported on 9:22:41 PM PST 7/30/2026
1
+ // Currently active sources reported on 6:18:22 PM PST 9/13/2026
2
2
 
3
3
  // None Anime Tested: 936075
4
4
  // Anime Tested: 37854
@@ -6,6 +6,18 @@
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
+
9
21
  {
10
22
  key: '123anime',
11
23
  label: '123Anime',
@@ -25,6 +37,25 @@ export const SOURCES = [
25
37
  },],
26
38
  },
27
39
 
40
+ {
41
+ key: '111477',
42
+ label: '111477',
43
+ sourceFile: '111477',
44
+ proxyParam: 'a11',
45
+ timeout: 25000,
46
+ jitter: 500,
47
+ retries: 2,
48
+ multiUrl: true,
49
+ skipProxy: true,
50
+ cdnHeaders: [{
51
+ pattern: /111477\.xyz/i,
52
+ headers: {
53
+ Referer: 'https://st.111477.xyz/',
54
+ Origin: 'https://st.111477.xyz',
55
+ },
56
+ }],
57
+ },
58
+
28
59
  {
29
60
  key: 'anihq-sub',
30
61
  label: 'AniHQ (Sub)',
@@ -69,40 +100,6 @@ export const SOURCES = [
69
100
  retries: 2
70
101
  },
71
102
 
72
- {
73
- key: 'anipm-sub',
74
- sourceFile: 'anipm',
75
- label: 'AniPM (Sub)',
76
- proxyParam: 'apsub',
77
- timeout: 25000,
78
- jitter: 500,
79
- retries: 2,
80
- skipProxy: true,
81
- skipVerify: true,
82
- multiUrl: true,
83
- verifyHeaders: {
84
- Referer: 'https://ani.pm/',
85
- Origin: 'https://ani.pm',
86
- },
87
- },
88
-
89
- {
90
- key: 'anipm-dub',
91
- sourceFile: 'anipm',
92
- label: 'AniPM (Dub)',
93
- proxyParam: 'apdub',
94
- timeout: 25000,
95
- jitter: 500,
96
- retries: 2,
97
- skipProxy: true,
98
- skipVerify: true,
99
- multiUrl: true,
100
- verifyHeaders: {
101
- Referer: 'https://ani.pm/',
102
- Origin: 'https://ani.pm',
103
- },
104
- },
105
-
106
103
  {
107
104
  key: 'bcine',
108
105
  label: 'Bcine',
@@ -173,6 +170,25 @@ export const SOURCES = [
173
170
  }],
174
171
  },
175
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',
188
+ },
189
+ }],
190
+ },
191
+
176
192
  {
177
193
  key: 'flaxmovies',
178
194
  label: 'FlaxMovies',
@@ -314,16 +330,6 @@ export const SOURCES = [
314
330
  skipProxy: true,
315
331
  },
316
332
 
317
- {
318
- key: 'mapple',
319
- label: 'Mapple',
320
- sourceFile: 'mapple',
321
- proxyParam: 'mp',
322
- timeout: 15000,
323
- retries: 1,
324
- jitter: 0
325
- },
326
-
327
333
  {
328
334
  key: 'meowtv',
329
335
  label: 'MeowTV',
@@ -336,6 +342,44 @@ export const SOURCES = [
336
342
  skipProxy: true
337
343
  },
338
344
 
345
+ {
346
+ key: 'movienight',
347
+ label: 'MovieNight',
348
+ sourceFile: 'movienight',
349
+ proxyParam: 'mn',
350
+ timeout: 20000,
351
+ jitter: 500,
352
+ retries: 2,
353
+ multiUrl: true,
354
+ skipProxy: true,
355
+ cdnHeaders: [{
356
+ pattern: /movienig\.ht/i,
357
+ headers: {
358
+ Referer: 'https://movienig.ht/',
359
+ Origin: 'https://movienig.ht',
360
+ },
361
+ }],
362
+ },
363
+
364
+ {
365
+ key: 'movy',
366
+ label: 'Movy',
367
+ sourceFile: 'movy',
368
+ proxyParam: 'mv',
369
+ timeout: 25000,
370
+ jitter: 500,
371
+ retries: 2,
372
+ multiUrl: true,
373
+ skipProxy: true,
374
+ cdnHeaders: [{
375
+ pattern: /wecollege\.net|movy\.bz/i,
376
+ headers: {
377
+ Referer: 'https://www.movy.bz/',
378
+ Origin: 'https://www.movy.bz',
379
+ },
380
+ }],
381
+ },
382
+
339
383
  {
340
384
  key: 'peestream',
341
385
  label: 'PeeStream',
@@ -372,28 +416,6 @@ export const SOURCES = [
372
416
  multiUrl: true,
373
417
  },
374
418
 
375
- {
376
- key: 'nova',
377
- label: 'Nova',
378
- sourceFile: 'nova',
379
- proxyParam: 'nv',
380
- timeout: 25000,
381
- jitter: 500,
382
- retries: 1,
383
- multiUrl: true,
384
- },
385
-
386
- {
387
- key: 'megasource',
388
- label: 'MegaSource',
389
- sourceFile: 'megasource',
390
- proxyParam: 'mg',
391
- timeout: 25000,
392
- jitter: 500,
393
- retries: 1,
394
- multiUrl: true,
395
- },
396
-
397
419
  {
398
420
  key: 'purstream',
399
421
  sourceFile: 'purstream',
@@ -416,6 +438,44 @@ export const SOURCES = [
416
438
  multiUrl: true,
417
439
  },
418
440
 
441
+ {
442
+ key: 'streamaggregator',
443
+ label: 'StreamAggregator',
444
+ sourceFile: 'streamaggregator',
445
+ proxyParam: 'sa',
446
+ timeout: 25000,
447
+ jitter: 500,
448
+ retries: 2,
449
+ multiUrl: true,
450
+ skipProxy: true,
451
+ cdnHeaders: [{
452
+ pattern: /streamaggregator\.in/i,
453
+ headers: {
454
+ Referer: 'https://streamaggregator.in/',
455
+ Origin: 'https://streamaggregator.in',
456
+ },
457
+ }],
458
+ },
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
+
419
479
  {
420
480
  key: 'vidapi',
421
481
  label: 'VidAPI',
@@ -438,23 +498,6 @@ export const SOURCES = [
438
498
  sourcesTimeout: 10000,
439
499
  },
440
500
 
441
- {
442
- key: 'videasy',
443
- label: 'Videasy',
444
- sourceFile: 'videasy',
445
- proxyParam: 'vy',
446
- timeout: 40000,
447
- sourcesTimeout: 10000,
448
- jitter: 900,
449
- retries: 3,
450
- multiUrl: true,
451
- verifyHeaders: {
452
- Accept: 'application/json, /; q=0.01',
453
- Referer: 'https://player.videasy.net/',
454
- Origin: 'https://player.videasy.net',
455
- },
456
- },
457
-
458
501
  {
459
502
  key: 'vidfast',
460
503
  label: 'Vidfast',
@@ -487,7 +530,6 @@ export const SOURCES = [
487
530
  retries: 2,
488
531
  skipProxy: true,
489
532
  multiUrl: true,
490
- disabled: true, // Temporarily disabled because their site is down, all streams are returning 403's
491
533
  },
492
534
 
493
535
  {
@@ -603,25 +645,41 @@ export const SOURCES = [
603
645
  },
604
646
 
605
647
  {
606
- key: 'xpass',
607
- sourceFile: 'xpass',
608
- label: 'XPass',
609
- proxyParam: 'xp',
610
- timeout: 20000,
648
+ key: 'vuflix',
649
+ label: 'Vuflix',
650
+ sourceFile: 'vuflix',
651
+ proxyParam: 'vfx',
652
+ timeout: 25000,
611
653
  jitter: 500,
612
654
  retries: 2,
655
+ multiUrl: true,
613
656
  skipProxy: true,
657
+ cdnHeaders: [{
658
+ pattern: /vuflix\.co/i,
659
+ headers: {
660
+ Referer: 'https://vuflix.co/',
661
+ Origin: 'https://vuflix.co',
662
+ },
663
+ }],
614
664
  },
615
665
 
616
666
  {
617
- key: 'zxcstream',
618
- label: 'ZxcStream',
619
- sourceFile: 'zxcstream',
620
- proxyParam: 'zxc',
667
+ key: 'xdownloader',
668
+ label: 'XDownloader',
669
+ sourceFile: 'xdownloader',
670
+ proxyParam: 'xd',
621
671
  timeout: 25000,
622
672
  jitter: 500,
623
673
  retries: 2,
624
674
  multiUrl: true,
675
+ skipProxy: true,
676
+ cdnHeaders: [{
677
+ pattern: /films365\.org/i,
678
+ headers: {
679
+ Referer: 'https://www.films365.org/',
680
+ Origin: 'https://www.films365.org',
681
+ },
682
+ }],
625
683
  },
626
684
 
627
685
  ];
@@ -1,12 +1,53 @@
1
- import { getDownloads, getDownloadsTv } from "./sources/trendimovies.js";
2
-
3
- export async function fetchDownloads(id, s = null, e = null) {
4
- try {
5
- const res = s != null && e != null
6
- ? await getDownloadsTv(id, s, e)
7
- : await getDownloads(id);
8
- return res || [];
9
- } catch {
10
- return [];
1
+ import SOURCES from "../config.js";
2
+
3
+ export async function fetchDownloads(sdkOrId, idOrS = null, sOrE = null, maybeE = null) {
4
+ let sdk = null;
5
+ let id = sdkOrId;
6
+ let s = idOrS;
7
+ let e = sOrE;
8
+
9
+ if (sdkOrId && typeof sdkOrId === 'object' && typeof sdkOrId.getStream === 'function') {
10
+ sdk = sdkOrId;
11
+ id = idOrS;
12
+ s = sOrE;
13
+ e = maybeE;
11
14
  }
15
+
16
+ if (!sdk || !id) return [];
17
+
18
+ const activeSources = SOURCES.filter(cfg => !cfg.disabled && cfg.skipProxy);
19
+ const seenUrls = new Set();
20
+ const downloads = [];
21
+
22
+ const results = await Promise.allSettled(
23
+ activeSources.map(async (cfg) => {
24
+ try {
25
+ const res = await sdk.getStream(cfg.key, id, s, e);
26
+ if (!res) return;
27
+
28
+ const items = Array.isArray(res.allUrls) && res.allUrls.length > 0
29
+ ? res.allUrls
30
+ : (res.url ? [{ url: res.url, label: cfg.label }] : []);
31
+
32
+ for (const item of items) {
33
+ if (!item?.url || typeof item.url !== 'string') continue;
34
+ const url = item.url.trim();
35
+
36
+ if (!url.startsWith('http') || url.includes('.m3u8')) continue;
37
+ if (!/\.mp4(\?|$)/i.test(url) && !url.includes('.mp4')) continue;
38
+ if (seenUrls.has(url)) continue;
39
+
40
+ seenUrls.add(url);
41
+
42
+ downloads.push({
43
+ source: cfg.key,
44
+ label: item.label || cfg.label,
45
+ url,
46
+ });
47
+ }
48
+ } catch { }
49
+ })
50
+ );
51
+
52
+ return downloads;
12
53
  }
package/src/sdk.d.ts CHANGED
@@ -59,7 +59,6 @@ export interface VylaSDKOptions {
59
59
  tmdbApiKey?: string;
60
60
  }
61
61
 
62
- // Descriptions written with Claude.
63
62
  export default class VylaSDK {
64
63
  tmdbApiKey?: string;
65
64
 
package/src/sdk.js CHANGED
@@ -63,6 +63,6 @@ export default class VylaSDK {
63
63
  return await fetchSubtitles(paths);
64
64
  }
65
65
  async getDownloads(id, s = null, e = null) {
66
- return await fetchDownloads(id, s, e);
66
+ return await fetchDownloads(this, id, s, e);
67
67
  }
68
68
  }
@@ -0,0 +1,101 @@
1
+ import { getUA } from '../utils/helpers.js';
2
+
3
+ const SERVICE_ORIGIN = 'https://st.111477.xyz';
4
+
5
+ function generateManifestBaseUrl(tmdbKey) {
6
+ let config = 'https://a.111477.xyz/::sort=file-desc::limit=3';
7
+ if (tmdbKey) {
8
+ config += `::tmdb=${tmdbKey}`;
9
+ }
10
+ const b64 = Buffer.from(config, 'utf8')
11
+ .toString('base64')
12
+ .replace(/\+/g, '-')
13
+ .replace(/\//g, '_')
14
+ .replace(/=+$/, '');
15
+ return `${SERVICE_ORIGIN}/config/${b64}`;
16
+ }
17
+
18
+ async function resolveImdbId(sdk, id, isTv) {
19
+ const apiKey = sdk?.tmdbApiKey || process.env.TMDB_API_KEY;
20
+ if (!apiKey) return null;
21
+ const type = isTv ? 'tv' : 'movie';
22
+ try {
23
+ const res = await fetch(`https://api.themoviedb.org/3/${type}/${id}?api_key=${apiKey}&append_to_response=external_ids`, {
24
+ signal: AbortSignal.timeout(6000),
25
+ });
26
+ if (!res.ok) return null;
27
+ const data = await res.json();
28
+ return data.imdb_id || data.external_ids?.imdb_id || null;
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+
34
+ export async function getStream({ id, s, e, sdk }) {
35
+ const isTv = Boolean(s && e);
36
+ const ua = getUA();
37
+ const apiKey = sdk?.tmdbApiKey || process.env.TMDB_API_KEY;
38
+
39
+ const imdbId = await resolveImdbId(sdk, id, isTv);
40
+ const targetIds = [];
41
+
42
+ if (imdbId && imdbId.startsWith('tt')) {
43
+ targetIds.push(imdbId);
44
+ }
45
+ targetIds.push(`tmdb:${id}`);
46
+
47
+ const addonBase = generateManifestBaseUrl(apiKey);
48
+ const seenUrls = new Set();
49
+ const allUrls = [];
50
+
51
+ const defaultHeaders = {
52
+ 'User-Agent': ua,
53
+ Accept: 'application/json, text/plain, */*',
54
+ };
55
+
56
+ for (const targetId of targetIds) {
57
+ const endpoint = isTv
58
+ ? `${addonBase}/stream/series/${targetId}:${s || 1}:${e || 1}.json`
59
+ : `${addonBase}/stream/movie/${targetId}.json`;
60
+
61
+ try {
62
+ const res = await fetch(endpoint, {
63
+ headers: defaultHeaders,
64
+ signal: AbortSignal.timeout(12000),
65
+ });
66
+
67
+ if (!res.ok) continue;
68
+ const data = await res.json();
69
+
70
+ if (Array.isArray(data?.streams) && data.streams.length > 0) {
71
+ for (const item of data.streams) {
72
+ if (!item || typeof item !== 'object') continue;
73
+ const url = String(item.url || '').trim();
74
+ if (!url || !url.startsWith('http') || seenUrls.has(url)) continue;
75
+
76
+ seenUrls.add(url);
77
+
78
+ const rawTitle = item.title ? String(item.title).trim() : '';
79
+ const rawName = item.name ? String(item.name).trim() : '111477';
80
+ const label = rawTitle || rawName;
81
+
82
+ allUrls.push({
83
+ url,
84
+ label,
85
+ headers: defaultHeaders,
86
+ });
87
+ }
88
+
89
+ if (allUrls.length > 0) break;
90
+ }
91
+ } catch { }
92
+ }
93
+
94
+ if (allUrls.length === 0) return null;
95
+
96
+ return {
97
+ url: allUrls[0].url,
98
+ allUrls,
99
+ headers: allUrls[0].headers,
100
+ };
101
+ }