@vyla-entertainment/sdk 1.18.0 → 1.20.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,118 +1,106 @@
1
- import { USER_AGENT, fetchJson } from '../utils/helpers.js';
1
+ import { fetchJson } from '../utils/helpers.js';
2
2
 
3
- const BASE_URL = 'https://flaxmovies.xyz';
3
+ export async function getStream({ id, s, e }) {
4
+ const isTv = s != null && e != null;
5
+ const allUrls = [];
4
6
 
5
- async function getWorkerUrls(embedUrl) {
6
- const foundUrls = [];
7
- try {
8
- const res = await fetch(embedUrl, {
9
- headers: {
10
- 'User-Agent': USER_AGENT,
11
- 'Referer': `${BASE_URL}/`,
12
- 'Origin': BASE_URL
13
- },
14
- signal: AbortSignal.timeout(8000)
15
- });
16
- if (res.ok) {
17
- const html = await res.text();
18
- const directMatch = html.match(/WORKER_URL\s*[:=]\s*["'](https?:\/\/[^"']+)["']/i);
19
- if (directMatch && directMatch[1]) {
20
- foundUrls.push(directMatch[1].replace(/\/+$/, ''));
7
+ const endpoints = [
8
+ async () => {
9
+ const url = isTv
10
+ ? `https://themoviebox.uk/api/resolve?type=tv&id=${id}&season=${s}&episode=${e}`
11
+ : `https://themoviebox.uk/api/resolve?type=movie&id=${id}`;
12
+ const res = await fetchJson(url);
13
+ if (res?.success && Array.isArray(res.sources)) {
14
+ for (const item of res.sources) {
15
+ const streamUrl = item.url || item.original_url;
16
+ if (streamUrl) {
17
+ allUrls.push({
18
+ url: streamUrl,
19
+ server: `TheMovieBox - ${item.server || item.provider || 'Server'}`,
20
+ headers: {
21
+ Referer: 'https://themoviebox.uk/',
22
+ Origin: 'https://themoviebox.uk'
23
+ }
24
+ });
25
+ }
26
+ }
21
27
  }
28
+ },
22
29
 
23
- const scriptMatches = [...html.matchAll(/<script[^>]+src=["']([^"']+)["']/gi)];
24
- for (const sm of scriptMatches) {
25
- let scriptUrl = sm[1];
26
- if (scriptUrl.startsWith('//')) scriptUrl = `https:${scriptUrl}`;
27
- else if (scriptUrl.startsWith('/')) scriptUrl = `${BASE_URL}${scriptUrl}`;
28
- else if (!scriptUrl.startsWith('http')) scriptUrl = `${BASE_URL}/${scriptUrl}`;
29
-
30
- if (scriptUrl.includes('jsdelivr') || scriptUrl.includes('google') || scriptUrl.includes('cloudflare')) continue;
31
-
32
- try {
33
- const sRes = await fetch(scriptUrl, {
34
- headers: { 'User-Agent': USER_AGENT, 'Referer': embedUrl },
35
- signal: AbortSignal.timeout(6000)
36
- });
37
- if (sRes.ok) {
38
- const sCode = await sRes.text();
39
- const m = sCode.match(/WORKER_URL\s*[:=]\s*["'](https?:\/\/[^"']+)["']/i);
40
- if (m && m[1]) {
41
- const wUrl = m[1].replace(/\/+$/, '');
42
- if (!foundUrls.includes(wUrl)) foundUrls.push(wUrl);
43
- }
30
+ async () => {
31
+ const url = isTv
32
+ ? `https://pro2.nabilekson.workers.dev/tv/${id}/${s}/${e}`
33
+ : `https://pro2.nabilekson.workers.dev/movie/${id}`;
34
+ const res = await fetchJson(url);
35
+ if (res?.success && Array.isArray(res.primarySources)) {
36
+ for (const item of res.primarySources) {
37
+ const streamUrl = item.url || item.originalUrl;
38
+ if (streamUrl) {
39
+ allUrls.push({
40
+ url: streamUrl,
41
+ server: `CineBros - ${item.name || item.quality || 'Server'}`,
42
+ headers: item.headers || {
43
+ Referer: 'https://pro2.nabilekson.workers.dev/',
44
+ Origin: 'https://pro2.nabilekson.workers.dev'
45
+ }
46
+ });
44
47
  }
45
- } catch { }
48
+ }
46
49
  }
47
- }
48
- } catch { }
49
-
50
- const defaults = ['https://freakyniki.elaxo.lol', 'https://vidlove.nabilekson.workers.dev'];
51
- for (const d of defaults) {
52
- if (!foundUrls.includes(d)) foundUrls.push(d);
53
- }
54
- return foundUrls;
55
- }
56
-
57
- export async function getStream(args) {
58
- const { id, s, e, server } = args;
59
- const isTv = s != null && e != null;
60
- const embedUrl = isTv
61
- ? `${BASE_URL}/embed/tv/${id}/${s}/${e}`
62
- : `${BASE_URL}/embed/movie/${id}`;
63
-
64
- const workerUrls = await getWorkerUrls(embedUrl);
65
- const query = isTv
66
- ? `tmdb_id=${id}&tmdbId=${id}&season=${s}&episode=${e}`
67
- : `tmdb_id=${id}&tmdbId=${id}`;
68
-
69
- for (const worker of workerUrls) {
70
- try {
71
- const url = `${worker}/?${query}`;
72
- const data = await fetchJson(url, {
73
- headers: {
74
- 'User-Agent': USER_AGENT,
75
- 'Referer': `${BASE_URL}/`,
76
- 'Origin': BASE_URL,
77
- 'Accept': 'application/json, text/plain, */*'
78
- },
79
- signal: AbortSignal.timeout(12000)
80
- });
50
+ },
81
51
 
82
- if (data && Array.isArray(data.streams) && data.streams.length > 0) {
83
- let allUrls = data.streams
84
- .filter(st => st && typeof st.url === 'string')
85
- .map(st => {
86
- const isHls = (st.format || '').toLowerCase().includes('hls') || st.url.includes('.m3u8');
87
- return {
88
- url: st.url,
89
- server: `FlaxMovies - ${st.provider || 'Default'}`,
90
- quality: st.resolution || 'Auto',
91
- type: isHls ? 'hls' : 'mp4',
92
- headers: {
93
- 'User-Agent': USER_AGENT,
94
- 'Referer': `${BASE_URL}/`,
95
- 'Origin': BASE_URL
52
+ async () => {
53
+ const url = isTv
54
+ ? `https://praxi.nabilekson.workers.dev/tv/${id}/${s}/${e}`
55
+ : `https://praxi.nabilekson.workers.dev/movie/${id}`;
56
+ const res = await fetchJson(url);
57
+ if (res?.success && Array.isArray(res.primarySources)) {
58
+ for (const item of res.primarySources) {
59
+ const streamUrl = item.url || item.originalUrl;
60
+ if (streamUrl) {
61
+ allUrls.push({
62
+ url: streamUrl,
63
+ server: `Praxi - ${item.name || item.providerName || 'Server'}`,
64
+ headers: item.headers || {
65
+ Referer: 'https://praxi.nabilekson.workers.dev/',
66
+ Origin: 'https://praxi.nabilekson.workers.dev'
96
67
  }
97
- };
98
- });
99
-
100
- if (server && server !== 'all') {
101
- const clean = server.toLowerCase().replace('flaxmovies - ', '');
102
- const filtered = allUrls.filter(u => u.server.toLowerCase().includes(clean));
103
- if (filtered.length) allUrls = filtered;
68
+ });
69
+ }
104
70
  }
71
+ }
72
+ },
105
73
 
106
- if (allUrls.length) {
107
- return { allUrls };
74
+ async () => {
75
+ const url = isTv
76
+ ? `https://freakyniki.elaxo.lol/?tmdb_id=${id}&season=${s}&episode=${e}`
77
+ : `https://freakyniki.elaxo.lol/?tmdb_id=${id}`;
78
+ const res = await fetchJson(url);
79
+ if (Array.isArray(res?.streams)) {
80
+ for (const item of res.streams) {
81
+ const streamUrl = item.url || item.raw_url;
82
+ if (streamUrl) {
83
+ allUrls.push({
84
+ url: streamUrl,
85
+ server: `FreakyNiki - ${item.server || item.provider || 'Server'}`,
86
+ headers: {
87
+ Referer: 'https://freakyniki.elaxo.lol/',
88
+ Origin: 'https://freakyniki.elaxo.lol'
89
+ }
90
+ });
91
+ }
108
92
  }
109
93
  }
110
- } catch { }
111
- }
94
+ }
95
+ ];
96
+
97
+ await Promise.allSettled(endpoints.map(fn => fn().catch(() => { })));
112
98
 
113
- return null;
114
- }
99
+ if (!allUrls.length) return null;
115
100
 
116
- export async function getSources() {
117
- return ['FlaxMovies - Airflix', 'FlaxMovies - Xpass-VIP 1'];
101
+ return {
102
+ url: allUrls[0].url,
103
+ headers: allUrls[0].headers,
104
+ allUrls
105
+ };
118
106
  }
@@ -0,0 +1,30 @@
1
+ import { fetchJson, resolveImdbId } from '../utils/helpers.js';
2
+
3
+ export async function getStream({ id, s, e, tmdbApiKey, sdk }) {
4
+ const isTv = s != null && e != null;
5
+ const type = isTv ? 'series' : 'movie';
6
+ const imdb = await resolveImdbId(id, isTv, tmdbApiKey || sdk?.tmdbApiKey);
7
+ if (!imdb) return null;
8
+
9
+ const url = isTv
10
+ ? `https://froststream.cloutteam.com/stream/series/${imdb}:${s}:${e}.json`
11
+ : `https://froststream.cloutteam.com/stream/movie/${imdb}.json`;
12
+
13
+ const res = await fetchJson(url).catch(() => null);
14
+ if (!res || !Array.isArray(res.streams) || !res.streams.length) return null;
15
+
16
+ const allUrls = res.streams.filter(st => st.url).map(st => ({
17
+ url: st.url,
18
+ server: `Frost - ${st.name || 'Server'} ${st.title ? `- ${st.title}` : ''}`,
19
+ headers: st.behaviorHints?.proxyHeaders?.request || undefined,
20
+ skipProxy: st.behaviorHints?.notWebReady === false
21
+ }));
22
+
23
+ if (!allUrls.length) return null;
24
+
25
+ return {
26
+ url: allUrls[0].url,
27
+ headers: allUrls[0].headers,
28
+ allUrls
29
+ };
30
+ }
@@ -0,0 +1,36 @@
1
+ import { fetchJson, resolveImdbId } from '../utils/helpers.js';
2
+
3
+ export async function getStream({ id, s, e, tmdbApiKey, sdk }) {
4
+ const isTv = s != null && e != null;
5
+ const type = isTv ? 'series' : 'movie';
6
+ const imdb = await resolveImdbId(id, isTv, tmdbApiKey || sdk?.tmdbApiKey);
7
+ if (!imdb) return null;
8
+
9
+ const CONFIG = btoa(JSON.stringify({ "torbox": "unset", "qualities": "2160p,1080p,720p", "sort": "desc", "catalogs": "featured,popular" }));
10
+ const url = `https://hdhub.thevolecitor.qzz.io/${CONFIG}/stream/${type}/${imdb}${isTv ? `:${s}:${e}` : ""}.json`;
11
+
12
+ const res = await fetchJson(url).catch(() => null);
13
+ if (!res || !Array.isArray(res.streams) || !res.streams.length) return null;
14
+
15
+ const validStreams = res.streams.filter(st => {
16
+ if (!st.url || !st.url.trim()) return false;
17
+ const lower = st.url.toLowerCase();
18
+ if (lower.includes('hubcloud') || lower.includes('pixeldrain.dev') || lower.endsWith('.zip')) return false;
19
+ return true;
20
+ });
21
+
22
+ if (!validStreams.length) return null;
23
+
24
+ const allUrls = validStreams.map(st => ({
25
+ url: st.url,
26
+ server: `HDHub - ${st.name || 'Server'}`,
27
+ headers: st.behaviorHints?.proxyHeaders?.request || undefined,
28
+ skipProxy: st.behaviorHints?.notWebReady === false
29
+ }));
30
+
31
+ return {
32
+ url: allUrls[0].url,
33
+ headers: allUrls[0].headers,
34
+ allUrls
35
+ };
36
+ }
@@ -0,0 +1,125 @@
1
+ import { fetchJson, USER_AGENT } from '../utils/helpers.js';
2
+
3
+ const BASE = "https://kaa.lt";
4
+ const HLS_BASE = "https://hls.krussdomi.com/manifest";
5
+ const HEADERS = { "User-Agent": USER_AGENT, Accept: "application/json" };
6
+
7
+ async function kaaSearch(query) {
8
+ const res = await fetchJson(`${BASE}/api/fsearch`, {
9
+ method: "POST",
10
+ headers: { ...HEADERS, "Content-Type": "application/json" },
11
+ body: JSON.stringify({ page: 1, query }),
12
+ }).catch(() => null);
13
+ return Array.isArray(res?.result) ? res.result : [];
14
+ }
15
+
16
+ async function kaaShowInfo(showSlug) {
17
+ return fetchJson(`${BASE}/api/show/${showSlug}`, { headers: HEADERS }).catch(() => null);
18
+ }
19
+
20
+ async function kaaEpisodePage(showSlug, ep) {
21
+ return fetchJson(`${BASE}/api/show/${showSlug}/episodes?ep=${ep}&lang=ja-JP`, { headers: HEADERS }).catch(() => null);
22
+ }
23
+
24
+ async function kaaAllEpisodes(showSlug) {
25
+ const first = await kaaEpisodePage(showSlug, 1);
26
+ if (!first) return [];
27
+ const pages = Array.isArray(first.pages) ? first.pages : [];
28
+ const all = Array.isArray(first.result) ? [...first.result] : [];
29
+
30
+ if (pages.length > 1) {
31
+ const rest = await Promise.all(
32
+ pages.slice(1).map(async (pg) => {
33
+ const startEp = pg.eps?.[0];
34
+ if (!startEp) return [];
35
+ const d = await kaaEpisodePage(showSlug, startEp);
36
+ return Array.isArray(d?.result) ? d.result : [];
37
+ })
38
+ );
39
+ for (const batch of rest) all.push(...batch);
40
+ }
41
+
42
+ return all;
43
+ }
44
+
45
+ async function kaaEpisodeServers(showSlug, fullEpSlug) {
46
+ return fetchJson(`${BASE}/api/show/${showSlug}/episode/${fullEpSlug}`, { headers: HEADERS }).catch(() => null);
47
+ }
48
+
49
+ export async function getStream({ id, s, e, tmdbApiKey, sdk }) {
50
+ try {
51
+ const apiKey = tmdbApiKey || sdk?.tmdbApiKey || process.env.TMDB_API_KEY || '45dbdd5e714da212424bda0336167447';
52
+ const isTv = !!s;
53
+ const mediaType = isTv ? 'tv' : 'movie';
54
+ const epNum = e ? Number(e) : 1;
55
+
56
+ let titles = [];
57
+ try {
58
+ const tmdbRes = await fetchJson(`https://api.themoviedb.org/3/${mediaType}/${id}?api_key=${apiKey}&append_to_response=alternative_titles`);
59
+ if (tmdbRes) {
60
+ const primary = tmdbRes.title || tmdbRes.name;
61
+ const original = tmdbRes.original_title || tmdbRes.original_name;
62
+ if (primary) titles.push(primary);
63
+ if (original && !titles.includes(original)) titles.push(original);
64
+
65
+ const alts = tmdbRes.alternative_titles?.titles || tmdbRes.alternative_titles?.results || [];
66
+ for (const alt of alts) {
67
+ const candidate = alt.title || alt.name;
68
+ if (candidate && !titles.includes(candidate)) {
69
+ titles.push(candidate);
70
+ }
71
+ }
72
+ }
73
+ } catch { }
74
+
75
+ if (!titles.length) return null;
76
+
77
+ let showSlug = null;
78
+ for (const title of titles) {
79
+ const results = await kaaSearch(title);
80
+ if (results.length) {
81
+ showSlug = results[0].slug;
82
+ break;
83
+ }
84
+ }
85
+
86
+ if (!showSlug) return null;
87
+
88
+ const showInfo = await kaaShowInfo(showSlug);
89
+ let fullEpSlug = null;
90
+
91
+ if (showInfo?.type === "movie") {
92
+ const m = (showInfo.watch_uri || "").match(/\/(ep-(\d+)-([a-f0-9]+))$/i);
93
+ if (m) fullEpSlug = m[1];
94
+ } else {
95
+ const episodes = await kaaAllEpisodes(showSlug);
96
+ const epItem = episodes.find((item) => item.episode_number === epNum);
97
+ if (epItem) fullEpSlug = `ep-${epItem.episode_number}-${epItem.slug}`;
98
+ }
99
+
100
+ if (!fullEpSlug) return null;
101
+
102
+ const episodeData = await kaaEpisodeServers(showSlug, fullEpSlug);
103
+ const servers = Array.isArray(episodeData?.servers) ? episodeData.servers : [];
104
+
105
+ const urls = [];
106
+ for (const srv of servers) {
107
+ if (!srv.src) continue;
108
+ const m = srv.src.match(/[?&]id=([^&]+)/);
109
+ if (m) {
110
+ urls.push({
111
+ url: `${HLS_BASE}/${m[1]}/master.m3u8`,
112
+ server: `KickAssAnime (${srv.name || 'Server'})`,
113
+ });
114
+ }
115
+ }
116
+
117
+ return urls.length ? { allUrls: urls } : null;
118
+ } catch (err) {
119
+ return null;
120
+ }
121
+ }
122
+
123
+ export async function getSources() {
124
+ return ['KickAssAnime'];
125
+ }
@@ -1,43 +1,71 @@
1
1
  import { getTmdbInfo } from '../utils/helpers.js';
2
2
 
3
3
  export async function getStream(args) {
4
- const { id, s, e, tmdbApiKey } = args;
4
+ const { id, s, e, tmdbApiKey, sdk } = args;
5
5
  const type = (s != null && e != null) ? 'tv' : 'movie';
6
+ const apiKey = tmdbApiKey || sdk?.tmdbApiKey || process.env.TMDB_API_KEY || '45dbdd5e714da212424bda0336167447';
6
7
 
7
8
  try {
8
- const tmdbInfo = await getTmdbInfo(tmdbApiKey, id, type, s);
9
- const name = tmdbInfo.titles[0] || '';
10
- if (!name) return null;
11
-
12
9
  if (type === 'tv') {
13
10
  return null;
14
- } else {
15
- const url = `https://lmscript.xyz/v1/movies?filters[q]=${encodeURIComponent(name)}&expand=streams`;
11
+ }
12
+
13
+ const tmdbInfo = await getTmdbInfo(apiKey, id, type, s);
14
+ const titles = tmdbInfo?.titles || [];
15
+ if (!titles.length) return null;
16
+
17
+ let movie = null;
18
+ for (const title of titles) {
19
+ const url = `https://lmscript.xyz/v1/movies?filters[q]=${encodeURIComponent(title)}&expand=streams`;
16
20
  const response = await fetch(url);
21
+ if (!response.ok) continue;
17
22
  const data = await response.json();
18
23
 
19
- const movie = data.items?.find(item => `${item.tmdb_prefix}` === `${id}` || `${item.tmdb_id}` === `${id}`);
20
- if (!movie) return null;
24
+ const found = data.items?.find(item => {
25
+ const tmdbPrefixMatch = `${item.tmdb_prefix}` === `${id}`;
26
+ const tmdbIdMatch = `${item.tmdb_id}` === `${id}`;
27
+ const titleMatch = item.title?.toLowerCase() === title.toLowerCase();
28
+ return tmdbPrefixMatch || tmdbIdMatch || titleMatch;
29
+ });
30
+
31
+ if (found) {
32
+ movie = found;
33
+ break;
34
+ }
35
+ }
21
36
 
22
- const streams = movie.streams || {};
23
- const SOURCE_ORDER = ["1080p", "720p", "480p", "360p"];
24
- const sortedStreams = Object.keys(streams).sort((a, b) => SOURCE_ORDER.indexOf(a) - SOURCE_ORDER.indexOf(b));
37
+ if (!movie) return null;
25
38
 
26
- if (!sortedStreams.length) return null;
39
+ const streams = movie.streams || {};
40
+ const SOURCE_ORDER = ["1080p", "720p", "480p", "360p"];
41
+ const sortedStreams = Object.keys(streams).sort((a, b) => {
42
+ const indexA = SOURCE_ORDER.indexOf(a);
43
+ const indexB = SOURCE_ORDER.indexOf(b);
44
+ return (indexA === -1 ? 99 : indexA) - (indexB === -1 ? 99 : indexB);
45
+ });
27
46
 
28
- const allUrls = sortedStreams.map(quality => {
29
- const streamUrl = streams[quality];
30
- return {
31
- url: streamUrl,
32
- quality,
33
- type: streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
34
- headers: {}
35
- };
36
- });
47
+ if (!sortedStreams.length) return null;
37
48
 
38
- return { allUrls };
39
- }
40
- } catch (err) {
49
+ const allUrls = sortedStreams.map(quality => {
50
+ const streamUrl = streams[quality];
51
+ return {
52
+ url: streamUrl,
53
+ quality,
54
+ server: `LMScript - ${quality}`,
55
+ type: streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
56
+ headers: {
57
+ Referer: 'https://lookmovie2.to/',
58
+ Origin: 'https://lookmovie2.to'
59
+ }
60
+ };
61
+ });
62
+
63
+ return {
64
+ url: allUrls[0].url,
65
+ headers: allUrls[0].headers,
66
+ allUrls
67
+ };
68
+ } catch {
41
69
  return null;
42
70
  }
43
71
  }