@vyla-entertainment/sdk 1.20.0 → 1.22.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.
Files changed (58) hide show
  1. package/package.json +3 -2
  2. package/src/config.js +99 -67
  3. package/src/health.js +60 -20
  4. package/src/sdk.d.ts +94 -121
  5. package/src/sdk.js +82 -78
  6. package/src/sources/111477.js +88 -100
  7. package/src/sources/123anime.js +120 -56
  8. package/src/sources/3eyedraven.js +82 -135
  9. package/src/sources/4movies.js +77 -0
  10. package/src/sources/aether.js +99 -0
  11. package/src/sources/castle.js +415 -0
  12. package/src/sources/cinecat.js +37 -18
  13. package/src/sources/cinemaarmy.js +179 -180
  14. package/src/sources/cinesrc.js +401 -397
  15. package/src/sources/cno.js +101 -94
  16. package/src/sources/dulo.js +134 -149
  17. package/src/sources/flaxmovies.js +114 -105
  18. package/src/sources/framextv.js +126 -0
  19. package/src/sources/frost.js +38 -29
  20. package/src/sources/fsonline.js +95 -47
  21. package/src/sources/hdhub.js +43 -36
  22. package/src/sources/hexa.js +60 -53
  23. package/src/sources/hyper.js +42 -35
  24. package/src/sources/kickassanime.js +117 -124
  25. package/src/sources/kisskh.js +114 -59
  26. package/src/sources/lmscript.js +72 -70
  27. package/src/sources/lookmovie.js +80 -79
  28. package/src/sources/meowtv.js +140 -0
  29. package/src/sources/movenerds.js +74 -124
  30. package/src/sources/movy.js +197 -209
  31. package/src/sources/net79.js +59 -55
  32. package/src/sources/peestream.js +126 -138
  33. package/src/sources/pengu.js +46 -49
  34. package/src/sources/pstream.js +73 -67
  35. package/src/sources/purstream.js +96 -104
  36. package/src/sources/rivestream.js +182 -176
  37. package/src/sources/rivo.js +58 -53
  38. package/src/sources/streamaggregator.js +114 -128
  39. package/src/sources/thugtv.js +70 -62
  40. package/src/sources/vidapi.js +122 -114
  41. package/src/sources/vidcore.js +14 -122
  42. package/src/sources/vidfast.js +14 -122
  43. package/src/sources/vidlink.js +78 -27
  44. package/src/sources/vidora.js +74 -42
  45. package/src/sources/vidup.js +14 -122
  46. package/src/sources/vidvault.js +133 -187
  47. package/src/sources/vidy.js +192 -187
  48. package/src/sources/vidzee.js +189 -183
  49. package/src/sources/vixsrc.js +123 -113
  50. package/src/sources/watchout.js +60 -46
  51. package/src/sources/xdownloader.js +127 -128
  52. package/src/sources/yapgrid.js +68 -62
  53. package/src/sources/yastream.js +35 -29
  54. package/src/subtitles.js +105 -122
  55. package/src/utils/helpers.js +586 -247
  56. package/src/sources/bcine.js +0 -202
  57. package/src/sources/cinezo.js +0 -55
  58. package/src/sources/vidrock.js +0 -145
@@ -1,56 +1,60 @@
1
- import { fetchJson } from '../utils/helpers.js';
2
-
3
- export async function getStream({ id, s, e }) {
4
- const isTv = s != null && e != null;
5
- const url = isTv
6
- ? `https://net79.cc/api/embed-tmdb/${id}?type=tv&se=${s}&ep=${e}`
7
- : `https://net79.cc/api/embed-tmdb/${id}?type=movie`;
8
-
9
- const headers = {
10
- 'Accept': 'application/json',
11
- 'Referer': 'https://net79.cc/',
12
- 'Origin': 'https://net79.cc',
13
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'
14
- };
15
-
16
- const res = await fetchJson(url, { headers }).catch(() => null);
17
- if (!res || !res.ok || res.noSource) return null;
18
-
19
- const allUrls = [];
20
-
21
- if (Array.isArray(res.streams) && res.streams.length > 0) {
22
- for (const stream of res.streams) {
23
- if (stream?.url) {
24
- allUrls.push({
25
- url: stream.url,
26
- quality: stream.resolution ? `${stream.resolution}p` : 'Auto',
27
- server: `Net79 - ${stream.resolution ? `${stream.resolution}p` : 'MP4'}`,
28
- type: stream.url.includes('.m3u8') ? 'hls' : 'mp4',
29
- headers: {
30
- Referer: 'https://net79.cc/',
31
- Origin: 'https://net79.cc'
32
- }
33
- });
34
- }
35
- }
36
- } else if (res.mp4) {
37
- allUrls.push({
38
- url: res.mp4,
39
- quality: res.resolution ? `${res.resolution}p` : 'Auto',
40
- server: `Net79 - ${res.resolution ? `${res.resolution}p` : 'MP4'}`,
41
- type: res.mp4.includes('.m3u8') ? 'hls' : 'mp4',
42
- headers: {
43
- Referer: 'https://net79.cc/',
44
- Origin: 'https://net79.cc'
45
- }
46
- });
47
- }
48
-
49
- if (!allUrls.length) return null;
50
-
51
- return {
52
- url: allUrls[0].url,
53
- headers: allUrls[0].headers,
54
- allUrls
55
- };
1
+ import { fetchJson } from '../utils/helpers.js';
2
+
3
+ const BASE_URL = 'https://net79.cc';
4
+
5
+ export async function getStream(args) {
6
+ const { id, s, e } = args || {};
7
+ const isTv = s != null && e != null;
8
+
9
+ const url = isTv
10
+ ? `${BASE_URL}/api/embed-tmdb/${id}?type=tv&se=${s}&ep=${e}`
11
+ : `${BASE_URL}/api/embed-tmdb/${id}?type=movie`;
12
+
13
+ const headers = {
14
+ Accept: 'application/json',
15
+ Referer: `${BASE_URL}/`,
16
+ Origin: BASE_URL,
17
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36',
18
+ };
19
+
20
+ const res = await fetchJson(url, { headers }).catch(() => null);
21
+ if (!res || !res.ok || res.noSource) return null;
22
+
23
+ const allUrls = [];
24
+
25
+ if (Array.isArray(res.streams) && res.streams.length > 0) {
26
+ for (const stream of res.streams) {
27
+ if (stream?.url) {
28
+ allUrls.push({
29
+ url: stream.url,
30
+ quality: stream.resolution ? `${stream.resolution}p` : 'Auto',
31
+ server: `Net79 - ${stream.resolution ? `${stream.resolution}p` : 'MP4'}`,
32
+ type: stream.url.includes('.m3u8') ? 'hls' : 'mp4',
33
+ headers: {
34
+ Referer: `${BASE_URL}/`,
35
+ Origin: BASE_URL,
36
+ },
37
+ });
38
+ }
39
+ }
40
+ } else if (res.mp4) {
41
+ allUrls.push({
42
+ url: res.mp4,
43
+ quality: res.resolution ? `${res.resolution}p` : 'Auto',
44
+ server: `Net79 - ${res.resolution ? `${res.resolution}p` : 'MP4'}`,
45
+ type: res.mp4.includes('.m3u8') ? 'hls' : 'mp4',
46
+ headers: {
47
+ Referer: `${BASE_URL}/`,
48
+ Origin: BASE_URL,
49
+ },
50
+ });
51
+ }
52
+
53
+ if (!allUrls.length) return null;
54
+
55
+ return {
56
+ url: allUrls[0].url,
57
+ headers: allUrls[0].headers,
58
+ allUrls,
59
+ };
56
60
  }
@@ -1,139 +1,127 @@
1
- import { USER_AGENT, fetchJson, getTmdbInfo } from '../utils/helpers.js';
2
-
3
- const BASE_URL = 'https://providers.peestream.in';
4
-
5
- const PROVIDERS = {
6
- purstream: 'Athena',
7
- vidrock: 'Thor',
8
- vaplayer: 'Poseidon',
9
- netmirror: 'Ra'
10
- };
11
-
12
- export async function getStream(args) {
13
- const { id, s, e, server, tmdbApiKey } = args;
14
- const isTv = s != null && e != null;
15
- const type = isTv ? 'tv' : 'movie';
16
-
17
- let title = args.title || '';
18
- let releaseYear = args.year || '';
19
- let imdbId = args.imdbId || '';
20
- let seasonTmdbId = args.seasonTmdbId || '';
21
- let episodeTmdbId = args.episodeTmdbId || '';
22
-
23
- try {
24
- const info = await getTmdbInfo(id, type, s, tmdbApiKey);
25
- if (info) {
26
- title = title || info.name || info.title || '';
27
-
28
- if (!releaseYear) {
29
- const date = info.release_date || info.first_air_date || '';
30
- releaseYear = date ? date.split('-')[0] : (info.year || '');
31
- }
32
-
33
- if (!imdbId && info.external_ids?.imdb_id) {
34
- imdbId = info.external_ids.imdb_id;
35
- } else if (!imdbId && info.imdb_id) {
36
- imdbId = info.imdb_id;
37
- }
38
-
39
- if (isTv) {
40
- if (!seasonTmdbId && Array.isArray(info.seasons)) {
41
- const matchedSeason = info.seasons.find(
42
- item => item.season_number === Number(s)
43
- );
44
- if (matchedSeason) {
45
- seasonTmdbId = String(matchedSeason.id);
46
- }
47
- }
48
-
49
- if (!episodeTmdbId && tmdbApiKey) {
50
- try {
51
- const seasonData = await fetchJson(
52
- `https://api.themoviedb.org/3/tv/${id}/season/${s}?api_key=${tmdbApiKey}`
53
- );
54
- if (seasonData?.episodes) {
55
- const matchedEp = seasonData.episodes.find(
56
- ep => ep.episode_number === Number(e)
57
- );
58
- if (matchedEp) {
59
- episodeTmdbId = String(matchedEp.id);
60
- }
61
- }
62
- } catch { }
63
- }
64
- }
65
- }
66
- } catch { }
67
-
68
- const queryParams = new URLSearchParams({
69
- type,
70
- tmdbId: String(id),
71
- title: title || String(id)
72
- });
73
-
74
- if (releaseYear) queryParams.set('releaseYear', String(releaseYear));
75
- if (imdbId) queryParams.set('imdbId', String(imdbId));
76
-
77
- if (isTv) {
78
- queryParams.set('seasonNumber', String(s));
79
- queryParams.set('episodeNumber', String(e));
80
- if (seasonTmdbId) queryParams.set('seasonTmdbId', String(seasonTmdbId));
81
- if (episodeTmdbId) queryParams.set('episodeTmdbId', String(episodeTmdbId));
82
- }
83
-
84
- const allUrls = [];
85
-
86
- try {
87
- const scrapeUrl = `${BASE_URL}/scrape?${queryParams.toString()}`;
88
- const res = await fetch(scrapeUrl, {
89
- headers: {
90
- 'User-Agent': USER_AGENT,
91
- 'Accept': 'text/event-stream',
92
- 'Referer': `${BASE_URL}/`
93
- },
94
- signal: AbortSignal.timeout(20000)
95
- });
96
-
97
- if (res.ok) {
98
- const text = await res.text();
99
- const events = text.split('\n\n');
100
-
101
- for (const ev of events) {
102
- if (ev.includes('event: completed')) {
103
- const dataMatch = ev.match(/data:\s*(.+)/);
104
- if (dataMatch) {
105
- try {
106
- const parsed = JSON.parse(dataMatch[1].trim());
107
- const stream = parsed.stream;
108
- const streamUrl = stream?.playlist || stream?.url || stream?.file;
109
- if (streamUrl) {
110
- const sourceName = PROVIDERS[parsed.sourceId] || parsed.sourceId || 'Poseidon';
111
- allUrls.push({
112
- url: streamUrl,
113
- server: `PeeStream - ${sourceName}`,
114
- quality: 'Auto',
115
- type: stream.type === 'hls' || streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
116
- headers: stream.headers || {
117
- 'User-Agent': USER_AGENT
118
- }
119
- });
120
- }
121
- } catch { }
122
- }
123
- }
124
- }
125
- }
126
- } catch { }
127
-
128
- if (server && server !== 'all') {
129
- const clean = server.toLowerCase().replace('peestream - ', '').trim();
130
- const filtered = allUrls.filter(u => u.server.toLowerCase().includes(clean));
131
- if (filtered.length) return { allUrls: filtered };
132
- }
133
-
134
- return allUrls.length ? { allUrls } : null;
135
- }
136
-
137
- export async function getSources() {
138
- return Object.values(PROVIDERS).map(name => `PeeStream - ${name}`);
1
+ import { fetchJson, getTmdbMetadata, resolveTmdbKey, USER_AGENT } from '../utils/helpers.js';
2
+
3
+ const BASE_URL = 'https://providers.peestream.in';
4
+
5
+ const PROVIDERS = {
6
+ purstream: 'Athena',
7
+ vidrock: 'Thor',
8
+ vaplayer: 'Poseidon',
9
+ netmirror: 'Ra',
10
+ };
11
+
12
+ export async function getStream(args) {
13
+ const { id, s, e, server, sdk } = args || {};
14
+ const isTv = s != null && e != null;
15
+ const type = isTv ? 'tv' : 'movie';
16
+ const apiKey = resolveTmdbKey(args, sdk);
17
+
18
+ let title = args?.title || '';
19
+ let releaseYear = args?.year || '';
20
+ let imdbId = args?.imdbId || '';
21
+ let seasonTmdbId = args?.seasonTmdbId || '';
22
+ let episodeTmdbId = args?.episodeTmdbId || '';
23
+
24
+ try {
25
+ const meta = await getTmdbMetadata(id, isTv, apiKey);
26
+ if (meta) {
27
+ title = title || meta.title || '';
28
+ if (!releaseYear && meta.year) releaseYear = String(meta.year);
29
+ if (!imdbId && meta.imdbId) imdbId = meta.imdbId;
30
+
31
+ if (isTv) {
32
+ if (!seasonTmdbId && Array.isArray(meta.seasons)) {
33
+ const matchedSeason = meta.seasons.find(item => item.season_number === Number(s));
34
+ if (matchedSeason) seasonTmdbId = String(matchedSeason.id);
35
+ }
36
+
37
+ if (!episodeTmdbId && apiKey) {
38
+ try {
39
+ const seasonData = await fetchJson(`https://api.themoviedb.org/3/tv/${id}/season/${s}?api_key=${apiKey}`);
40
+ if (seasonData?.episodes) {
41
+ const matchedEp = seasonData.episodes.find(ep => ep.episode_number === Number(e));
42
+ if (matchedEp) episodeTmdbId = String(matchedEp.id);
43
+ }
44
+ } catch { }
45
+ }
46
+ }
47
+ }
48
+ } catch { }
49
+
50
+ const queryParams = new URLSearchParams({
51
+ type,
52
+ tmdbId: String(id),
53
+ title: title || String(id),
54
+ });
55
+
56
+ if (releaseYear) queryParams.set('releaseYear', String(releaseYear));
57
+ if (imdbId) queryParams.set('imdbId', String(imdbId));
58
+
59
+ if (isTv) {
60
+ queryParams.set('seasonNumber', String(s));
61
+ queryParams.set('episodeNumber', String(e));
62
+ if (seasonTmdbId) queryParams.set('seasonTmdbId', String(seasonTmdbId));
63
+ if (episodeTmdbId) queryParams.set('episodeTmdbId', String(episodeTmdbId));
64
+ }
65
+
66
+ const allUrls = [];
67
+
68
+ try {
69
+ const scrapeUrl = `${BASE_URL}/scrape?${queryParams.toString()}`;
70
+ const res = await fetch(scrapeUrl, {
71
+ headers: {
72
+ 'User-Agent': USER_AGENT,
73
+ Accept: 'text/event-stream',
74
+ Referer: `${BASE_URL}/`,
75
+ },
76
+ signal: AbortSignal.timeout(20000),
77
+ });
78
+
79
+ if (res.ok) {
80
+ const text = await res.text();
81
+ const events = text.split('\n\n');
82
+
83
+ for (const ev of events) {
84
+ if (ev.includes('event: completed')) {
85
+ const dataMatch = ev.match(/data:\s*(.+)/);
86
+ if (dataMatch) {
87
+ try {
88
+ const parsed = JSON.parse(dataMatch[1].trim());
89
+ const stream = parsed.stream;
90
+ const streamUrl = stream?.playlist || stream?.url || stream?.file;
91
+ if (streamUrl) {
92
+ const sourceName = PROVIDERS[parsed.sourceId] || parsed.sourceId || 'Poseidon';
93
+ allUrls.push({
94
+ url: streamUrl,
95
+ server: `PeeStream - ${sourceName}`,
96
+ quality: 'Auto',
97
+ type: stream.type === 'hls' || streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
98
+ headers: stream.headers || {
99
+ 'User-Agent': USER_AGENT,
100
+ },
101
+ });
102
+ }
103
+ } catch { }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ } catch { }
109
+
110
+ if (server && server !== 'all') {
111
+ const clean = server.toLowerCase().replace('peestream - ', '').trim();
112
+ const filtered = allUrls.filter(u => u.server.toLowerCase().includes(clean));
113
+ if (filtered.length) return { url: filtered[0].url, headers: filtered[0].headers, allUrls: filtered };
114
+ }
115
+
116
+ if (!allUrls.length) return null;
117
+
118
+ return {
119
+ url: allUrls[0].url,
120
+ headers: allUrls[0].headers,
121
+ allUrls,
122
+ };
123
+ }
124
+
125
+ export async function getSources() {
126
+ return Object.values(PROVIDERS).map(name => `PeeStream - ${name}`);
139
127
  }
@@ -1,50 +1,47 @@
1
- import { fetchJson } from '../utils/helpers.js';
2
-
3
- // const PENGU_CONFIG = '%7B%22source_4khdhub%22%3A%22on%22%2C%22source_moviebox%22%3A%22on%22%2C%22source_moviesdrives%22%3A%22on%22%2C%22source_vaplayer%22%3A%22on%22%2C%22source_hdghartv%22%3A%22on%22%2C%22res_2160%22%3A%22on%22%2C%22res_1080%22%3A%22on%22%2C%22res_720%22%3A%22on%22%2C%22disable_direct%22%3A%22on%22%7D';
4
- // const BASE_URL = `https://pengu.uk/${PENGU_CONFIG}`;
5
-
6
- async function getImdbId(tmdbApiKey, tmdbId, s, e) {
7
- const key = tmdbApiKey;
8
- if (!key) return null;
9
- try {
10
- const url = s != null && e != null
11
- ? `https://api.themoviedb.org/3/tv/${tmdbId}/external_ids?api_key=${key}`
12
- : `https://api.themoviedb.org/3/movie/${tmdbId}?api_key=${key}`;
13
- const res = await fetchJson(url);
14
- return res?.imdb_id || null;
15
- } catch { return null; }
16
- }
17
-
18
- export async function getStream({ id, s, e, sdk }) {
19
- const tmdbApiKey = sdk?.tmdbApiKey || null;
20
- const manifest = sdk?.penguManifest || null;
21
- if (!tmdbApiKey || !manifest || (manifest && !manifest.endsWith('manifest.json'))) return null;
22
- const BASE_URL = manifest ? manifest.split('/manifest.json')[0] : null;
23
- if (!BASE_URL) return null;
24
- try {
25
- const imdbId = await getImdbId(tmdbApiKey, id, s, e);
26
- if (!imdbId) return null;
27
-
28
- const path = s != null && e != null
29
- ? `/stream/series/${imdbId}:${s}:${e}.json`
30
- : `/stream/movie/${imdbId}.json`;
31
-
32
- const res = await fetchJson(`${BASE_URL}${path}`);
33
- if (!res?.streams?.length) return null;
34
-
35
- const allUrls = res.streams.map(stream => {
36
- if (!stream.url) return null;
37
- const headers = stream.behaviorHints?.proxyHeaders?.request || {};
38
- return {
39
- url: stream.url,
40
- server: `Pengu - ${stream.name || 'Server'}`,
41
- headers: Object.keys(headers).length > 0 ? headers : undefined,
42
- skipProxy: stream.behaviorHints?.notWebReady === false
43
- };
44
- }).filter(Boolean);
45
-
46
- return allUrls.length ? { allUrls } : null;
47
- } catch {
48
- return null;
49
- }
1
+ import { fetchJson, resolveImdbId, resolveTmdbKey } from '../utils/helpers.js';
2
+
3
+ export async function getStream(args) {
4
+ const { id, s, e, sdk } = args || {};
5
+ const isTv = s != null && e != null;
6
+ const apiKey = resolveTmdbKey(args, sdk);
7
+ const manifest = sdk?.penguManifest || null;
8
+
9
+ if (!apiKey || !manifest || !manifest.endsWith('manifest.json')) return null;
10
+ const baseUrl = manifest.split('/manifest.json')[0];
11
+ if (!baseUrl) return null;
12
+
13
+ try {
14
+ const imdbId = await resolveImdbId(id, isTv, apiKey);
15
+ if (!imdbId) return null;
16
+
17
+ const path = isTv
18
+ ? `/stream/series/${imdbId}:${s}:${e}.json`
19
+ : `/stream/movie/${imdbId}.json`;
20
+
21
+ const res = await fetchJson(`${baseUrl}${path}`);
22
+ if (!res?.streams?.length) return null;
23
+
24
+ const allUrls = res.streams.map(stream => {
25
+ if (!stream.url) return null;
26
+ const headers = stream.behaviorHints?.proxyHeaders?.request || {};
27
+ return {
28
+ url: stream.url,
29
+ server: `Pengu - ${stream.name || 'Server'}`,
30
+ quality: 'Auto',
31
+ type: stream.url.includes('.m3u8') ? 'hls' : 'mp4',
32
+ headers: Object.keys(headers).length > 0 ? headers : undefined,
33
+ skipProxy: stream.behaviorHints?.notWebReady === false,
34
+ };
35
+ }).filter(Boolean);
36
+
37
+ if (!allUrls.length) return null;
38
+
39
+ return {
40
+ url: allUrls[0].url,
41
+ headers: allUrls[0].headers,
42
+ allUrls,
43
+ };
44
+ } catch {
45
+ return null;
46
+ }
50
47
  }
@@ -1,68 +1,74 @@
1
- import { USER_AGENT } from '../utils/helpers.js';
2
-
3
- async function safeImport(moduleName) {
4
- try {
5
- return await import(`./${moduleName}.js`);
6
- } catch {
7
- return null;
8
- }
9
- }
10
-
11
- export async function getStream(args) {
12
- const { id, s, e, clientIP, sdk } = args;
13
- const isTv = s != null && e != null;
14
- const type = isTv ? 'tv' : 'movie';
15
- const allUrls = [];
16
-
17
- const providers = [
18
- { name: 'CineSu', key: 'cinesu', fnName: 'fetchCineSuStreams' },
19
- { name: 'ZxcStream', key: 'zxcstream', fnName: 'fetchZxcStreams' },
20
- { name: 'VidFast', key: 'vidfast', fnName: 'fetchVidFastStreams' },
21
- { name: '1Embed', key: '1embed', fnName: 'fetchOneEmbedStreams' },
22
- ];
23
-
24
- await Promise.all(
25
- providers.map(async ({ name, key, fnName }) => {
26
- try {
27
- let streamResult = null;
28
-
29
- if (sdk) {
30
- try {
31
- streamResult = await sdk.getStream(key, id, s, e, clientIP);
32
- } catch { }
33
- }
34
-
35
- if (!streamResult) {
36
- const mod = await safeImport(key);
37
- if (mod) {
38
- if (typeof mod.getStream === 'function') {
39
- streamResult = await mod.getStream(args);
40
- } else if (typeof mod[fnName] === 'function') {
41
- const raw = await mod[fnName]({ type, id, season: s, episode: e });
42
- if (Array.isArray(raw)) {
43
- streamResult = { allUrls: raw };
44
- }
45
- }
46
- }
47
- }
48
-
49
- if (!streamResult) return;
50
-
51
- const streams = streamResult.allUrls || (streamResult.url ? [streamResult] : []);
52
- for (const item of streams) {
53
- allUrls.push({
54
- url: item.url,
55
- server: `FlyStream (${item.source || item.server || name})`,
56
- quality: item.quality || 'Auto',
57
- type: item.type || item.format || (item.url?.includes('.m3u8') ? 'hls' : 'mp4'),
58
- headers: item.headers || {
59
- 'User-Agent': USER_AGENT,
60
- },
61
- });
62
- }
63
- } catch { }
64
- })
65
- );
66
-
67
- return allUrls.length ? { allUrls } : null;
1
+ import { USER_AGENT } from '../utils/helpers.js';
2
+
3
+ async function safeImport(moduleName) {
4
+ try {
5
+ return await import(`./${moduleName}.js`);
6
+ } catch {
7
+ return null;
8
+ }
9
+ }
10
+
11
+ export async function getStream(args) {
12
+ const { id, s, e, clientIP, sdk } = args || {};
13
+ const isTv = s != null && e != null;
14
+ const type = isTv ? 'tv' : 'movie';
15
+ const allUrls = [];
16
+
17
+ const providers = [
18
+ { name: 'CineSu', key: 'cinesu', fnName: 'fetchCineSuStreams' },
19
+ { name: 'ZxcStream', key: 'zxcstream', fnName: 'fetchZxcStreams' },
20
+ { name: 'VidFast', key: 'vidfast', fnName: 'fetchVidFastStreams' },
21
+ { name: '1Embed', key: '1embed', fnName: 'fetchOneEmbedStreams' },
22
+ ];
23
+
24
+ await Promise.all(
25
+ providers.map(async ({ name, key, fnName }) => {
26
+ try {
27
+ let streamResult = null;
28
+
29
+ if (sdk) {
30
+ try {
31
+ streamResult = await sdk.getStream(key, id, s, e, clientIP);
32
+ } catch { }
33
+ }
34
+
35
+ if (!streamResult) {
36
+ const mod = await safeImport(key);
37
+ if (mod) {
38
+ if (typeof mod.getStream === 'function') {
39
+ streamResult = await mod.getStream(args);
40
+ } else if (typeof mod[fnName] === 'function') {
41
+ const raw = await mod[fnName]({ type, id, season: s, episode: e });
42
+ if (Array.isArray(raw)) {
43
+ streamResult = { allUrls: raw };
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ if (!streamResult) return;
50
+
51
+ const streams = streamResult.allUrls || (streamResult.url ? [streamResult] : []);
52
+ for (const item of streams) {
53
+ allUrls.push({
54
+ url: item.url,
55
+ server: `FlyStream (${item.source || item.server || name})`,
56
+ quality: item.quality || 'Auto',
57
+ type: item.type || item.format || (item.url?.includes('.m3u8') ? 'hls' : 'mp4'),
58
+ headers: item.headers || {
59
+ 'User-Agent': USER_AGENT,
60
+ },
61
+ });
62
+ }
63
+ } catch { }
64
+ })
65
+ );
66
+
67
+ if (!allUrls.length) return null;
68
+
69
+ return {
70
+ url: allUrls[0].url,
71
+ headers: allUrls[0].headers,
72
+ allUrls,
73
+ };
68
74
  }