@vyla-entertainment/sdk 1.17.0 → 1.19.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/README.md +5 -5
- package/package.json +1 -1
- package/src/config.js +187 -118
- package/src/sources/cinecat.js +19 -0
- package/src/sources/cinesrc.js +398 -0
- package/src/sources/cinezo.js +55 -0
- package/src/sources/cno.js +95 -0
- package/src/sources/flaxmovies.js +91 -103
- package/src/sources/hexa.js +54 -0
- package/src/sources/hyper.js +36 -0
- package/src/sources/kickassanime.js +125 -0
- package/src/sources/lmscript.js +53 -25
- package/src/sources/movy.js +161 -233
- package/src/sources/net79.js +56 -0
- package/src/sources/rivo.js +54 -0
- package/src/sources/thugtv.js +56 -55
- package/src/sources/vidora.js +62 -0
- package/src/sources/yapgrid.js +63 -0
- package/src/sources/yastream.js +30 -0
- package/src/sources/anihq.js +0 -124
- package/src/sources/anineko.js +0 -190
- package/src/sources/movienight.js +0 -117
- package/src/sources/vidgod.js +0 -147
- package/src/sources/vidnest.js +0 -79
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { getUA } from '../utils/helpers.js';
|
|
2
|
-
|
|
3
|
-
const BASE_URL = 'https://movienig.ht';
|
|
4
|
-
|
|
5
|
-
const PRIORITY_SERVERS = [
|
|
6
|
-
{ id: 'dallas', label: 'Dallas 4K' },
|
|
7
|
-
{ id: 'austin', label: 'Austin' },
|
|
8
|
-
{ id: 'helena', label: 'Helena' },
|
|
9
|
-
{ id: 'seattle', label: 'Seattle 4K' },
|
|
10
|
-
{ id: 'vixsrc-1', label: 'Newport Beach' },
|
|
11
|
-
{ id: 'tucson', label: 'Tucson' },
|
|
12
|
-
{ id: 'salem', label: 'Salem' },
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
async function resolveDetails(sdk, id, isTv) {
|
|
16
|
-
const apiKey = sdk?.tmdbApiKey || process.env.TMDB_API_KEY;
|
|
17
|
-
if (!apiKey) return null;
|
|
18
|
-
const type = isTv ? 'tv' : 'movie';
|
|
19
|
-
try {
|
|
20
|
-
const res = await fetch(`https://api.themoviedb.org/3/${type}/${id}?api_key=${apiKey}&append_to_response=external_ids`, {
|
|
21
|
-
signal: AbortSignal.timeout(6000),
|
|
22
|
-
});
|
|
23
|
-
if (!res.ok) return null;
|
|
24
|
-
const data = await res.json();
|
|
25
|
-
const title = isTv ? data.name : data.title;
|
|
26
|
-
const releaseDate = isTv ? data.first_air_date : data.release_date;
|
|
27
|
-
const year = releaseDate ? parseInt(releaseDate.split('-')[0], 10) : null;
|
|
28
|
-
const imdbId = data.imdb_id || data.external_ids?.imdb_id || null;
|
|
29
|
-
return { title, year, imdbId };
|
|
30
|
-
} catch {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function getStream({ id, s, e, sdk }) {
|
|
36
|
-
const isTv = Boolean(s && e);
|
|
37
|
-
const ua = getUA();
|
|
38
|
-
|
|
39
|
-
const details = await resolveDetails(sdk, id, isTv);
|
|
40
|
-
const title = details?.title || String(id);
|
|
41
|
-
const year = details?.year;
|
|
42
|
-
const imdbId = details?.imdbId;
|
|
43
|
-
|
|
44
|
-
const encTitle = encodeURIComponent(title);
|
|
45
|
-
const yearQuery = year ? `&year=${year}` : '';
|
|
46
|
-
const imdbQuery = imdbId ? `&imdbId=${imdbId}` : '';
|
|
47
|
-
|
|
48
|
-
const seenUrls = new Set();
|
|
49
|
-
const allUrls = [];
|
|
50
|
-
|
|
51
|
-
const defaultHeaders = {
|
|
52
|
-
'User-Agent': ua,
|
|
53
|
-
Referer: `${BASE_URL}/`,
|
|
54
|
-
Origin: BASE_URL,
|
|
55
|
-
Accept: 'text/event-stream',
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const tasks = PRIORITY_SERVERS.map(async (server) => {
|
|
59
|
-
try {
|
|
60
|
-
const url = isTv
|
|
61
|
-
? `${BASE_URL}/api/stream/v1/tv/${id}/${s}/${e}?title=${encTitle}${yearQuery}${imdbQuery}&server=${server.id}&only=1`
|
|
62
|
-
: `${BASE_URL}/api/stream/v1/movie/${id}?title=${encTitle}${yearQuery}${imdbQuery}&server=${server.id}&only=1`;
|
|
63
|
-
|
|
64
|
-
const res = await fetch(url, {
|
|
65
|
-
headers: defaultHeaders,
|
|
66
|
-
signal: AbortSignal.timeout(6000),
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
if (!res.ok) return;
|
|
70
|
-
const bodyStr = await res.text();
|
|
71
|
-
|
|
72
|
-
if (bodyStr.includes('event: done')) {
|
|
73
|
-
const doneIdx = bodyStr.indexOf('event: done');
|
|
74
|
-
const dataIdx = bodyStr.indexOf('data: ', doneIdx);
|
|
75
|
-
|
|
76
|
-
if (dataIdx !== -1) {
|
|
77
|
-
const jsonStart = dataIdx + 6;
|
|
78
|
-
const jsonEnd = bodyStr.indexOf('\n', jsonStart);
|
|
79
|
-
const jsonText = (jsonEnd !== -1 ? bodyStr.substring(jsonStart, jsonEnd) : bodyStr.substring(jsonStart)).trim();
|
|
80
|
-
|
|
81
|
-
const data = JSON.parse(jsonText);
|
|
82
|
-
if (Array.isArray(data?.sources)) {
|
|
83
|
-
for (const src of data.sources) {
|
|
84
|
-
if (!src || typeof src !== 'object') continue;
|
|
85
|
-
const rawUrl = String(src.url || '').trim();
|
|
86
|
-
if (!rawUrl || seenUrls.has(rawUrl)) continue;
|
|
87
|
-
|
|
88
|
-
seenUrls.add(rawUrl);
|
|
89
|
-
|
|
90
|
-
const quality = src.quality ? String(src.quality) : 'Auto';
|
|
91
|
-
const titleQuality = quality !== 'Auto' ? ` (${quality})` : '';
|
|
92
|
-
|
|
93
|
-
allUrls.push({
|
|
94
|
-
url: rawUrl,
|
|
95
|
-
label: `MovieNight ${server.label}${titleQuality}`,
|
|
96
|
-
headers: {
|
|
97
|
-
'User-Agent': ua,
|
|
98
|
-
Referer: `${BASE_URL}/`,
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
} catch { }
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
await Promise.all(tasks);
|
|
109
|
-
|
|
110
|
-
if (allUrls.length === 0) return null;
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
url: allUrls[0].url,
|
|
114
|
-
allUrls,
|
|
115
|
-
headers: allUrls[0].headers,
|
|
116
|
-
};
|
|
117
|
-
}
|
package/src/sources/vidgod.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { USER_AGENT } from '../utils/helpers.js';
|
|
2
|
-
|
|
3
|
-
const REDIS_URL = 'https://vidnest-redis-fell-prism-rest.cloud.layerbase.dev/';
|
|
4
|
-
const REDIS_AUTH = 'Bearer ve8z9XSKatu74M7FjLU8eQ29';
|
|
5
|
-
const ORIGIN = 'https://vidgod.space';
|
|
6
|
-
|
|
7
|
-
const SERVERS = [
|
|
8
|
-
{
|
|
9
|
-
name: 'Pulsar',
|
|
10
|
-
key: 'pulsar',
|
|
11
|
-
base: 'https://vidnest-extractor.vividdubbing.workers.dev/api',
|
|
12
|
-
serverParam: 'prime'
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
name: 'Orion',
|
|
16
|
-
key: 'orion',
|
|
17
|
-
base: 'https://404-vidnest.lofiserver.workers.dev/api',
|
|
18
|
-
serverParam: 'gama'
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: 'Stellar',
|
|
22
|
-
key: 'stellar',
|
|
23
|
-
base: 'https://404-vidnest.lofiserver.workers.dev/api',
|
|
24
|
-
serverParam: 'sigma'
|
|
25
|
-
}
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
function buildCacheKey(serverKey, type, id, s, e) {
|
|
29
|
-
const parts = [serverKey, type, id];
|
|
30
|
-
if (type === 'tv') {
|
|
31
|
-
parts.push(s || '1', e || '1');
|
|
32
|
-
}
|
|
33
|
-
return parts.join(':');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function getFromCache(key) {
|
|
37
|
-
try {
|
|
38
|
-
const res = await fetch(REDIS_URL, {
|
|
39
|
-
method: 'POST',
|
|
40
|
-
headers: {
|
|
41
|
-
'Authorization': REDIS_AUTH,
|
|
42
|
-
'Content-Type': 'application/json',
|
|
43
|
-
'Accept': '*/*',
|
|
44
|
-
'Origin': ORIGIN,
|
|
45
|
-
'Referer': `${ORIGIN}/`,
|
|
46
|
-
'User-Agent': USER_AGENT
|
|
47
|
-
},
|
|
48
|
-
body: JSON.stringify(['GET', key]),
|
|
49
|
-
signal: AbortSignal.timeout(6000)
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
if (!res.ok) return null;
|
|
53
|
-
const data = await res.json();
|
|
54
|
-
if (!data || !data.result) return null;
|
|
55
|
-
|
|
56
|
-
const parsed = typeof data.result === 'string' ? JSON.parse(data.result) : data.result;
|
|
57
|
-
return parsed?.streams?.length ? parsed : null;
|
|
58
|
-
} catch {
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function fetchFromWorker(srv, type, id, s, e) {
|
|
64
|
-
try {
|
|
65
|
-
const endpoint = type === 'movie'
|
|
66
|
-
? `${srv.base}/movie/${id}?server=${srv.serverParam}`
|
|
67
|
-
: `${srv.base}/tv/${id}/${s || '1'}/${e || '1'}?server=${srv.serverParam}`;
|
|
68
|
-
|
|
69
|
-
const res = await fetch(endpoint, {
|
|
70
|
-
headers: {
|
|
71
|
-
'Accept': 'application/json',
|
|
72
|
-
'Origin': ORIGIN,
|
|
73
|
-
'Referer': `${ORIGIN}/`,
|
|
74
|
-
'User-Agent': USER_AGENT
|
|
75
|
-
},
|
|
76
|
-
signal: AbortSignal.timeout(8000)
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
if (!res.ok) return null;
|
|
80
|
-
const data = await res.json();
|
|
81
|
-
return data?.streams?.length ? data : null;
|
|
82
|
-
} catch {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async function resolveServer(srv, type, id, s, e) {
|
|
88
|
-
const cacheKey = buildCacheKey(srv.key, type, id, s, e);
|
|
89
|
-
const cached = await getFromCache(cacheKey);
|
|
90
|
-
if (cached) return { server: srv.name, data: cached };
|
|
91
|
-
|
|
92
|
-
const live = await fetchFromWorker(srv, type, id, s, e);
|
|
93
|
-
if (live) return { server: srv.name, data: live };
|
|
94
|
-
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export async function getStream(args) {
|
|
99
|
-
const { id, s, e, server } = args;
|
|
100
|
-
const isTv = s != null && e != null;
|
|
101
|
-
const type = isTv ? 'tv' : 'movie';
|
|
102
|
-
|
|
103
|
-
let targets = SERVERS;
|
|
104
|
-
if (server && server !== 'all') {
|
|
105
|
-
const clean = server.toLowerCase().trim();
|
|
106
|
-
targets = SERVERS.filter(srv => srv.name.toLowerCase() === clean || srv.key.toLowerCase() === clean);
|
|
107
|
-
if (!targets.length) targets = SERVERS;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const settled = await Promise.allSettled(
|
|
111
|
-
targets.map(srv => resolveServer(srv, type, id, s, e))
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const allUrls = [];
|
|
115
|
-
|
|
116
|
-
for (const r of settled) {
|
|
117
|
-
if (r.status !== 'fulfilled' || !r.value) continue;
|
|
118
|
-
const { server: serverName, data } = r.value;
|
|
119
|
-
|
|
120
|
-
for (const item of data.streams || []) {
|
|
121
|
-
if (!item || !item.url) continue;
|
|
122
|
-
|
|
123
|
-
const typeStr = String(item.type || '').toLowerCase();
|
|
124
|
-
const urlStr = String(item.url || '').toLowerCase();
|
|
125
|
-
const isM3U8 =
|
|
126
|
-
typeStr === 'hls' ||
|
|
127
|
-
typeStr === 'application/vnd.apple.mpegurl' ||
|
|
128
|
-
typeStr === 'cloudflare' ||
|
|
129
|
-
typeStr === 'tiktok' ||
|
|
130
|
-
urlStr.includes('.m3u8') ||
|
|
131
|
-
urlStr.includes('.txt');
|
|
132
|
-
|
|
133
|
-
allUrls.push({
|
|
134
|
-
url: item.url,
|
|
135
|
-
server: serverName,
|
|
136
|
-
quality: item.quality || 'Auto',
|
|
137
|
-
type: isM3U8 ? 'hls' : 'mp4',
|
|
138
|
-
headers: item.headers || {
|
|
139
|
-
'User-Agent': USER_AGENT,
|
|
140
|
-
'Referer': `${ORIGIN}/`
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return allUrls.length ? { allUrls } : null;
|
|
147
|
-
}
|
package/src/sources/vidnest.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { fetchJson, fetchText, USER_AGENT } from '../utils/helpers.js';
|
|
2
|
-
|
|
3
|
-
const BASE_URL = 'https://vidnest.fun';
|
|
4
|
-
const API_BASE_URL = 'https://new.vidnest.fun';
|
|
5
|
-
const REQUEST_HEADERS = { 'User-Agent': USER_AGENT, 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Language': 'en-US,en;q=0.9', 'Referer': `${BASE_URL}/`, 'Origin': BASE_URL };
|
|
6
|
-
const CDN_PROXY_HEADERS = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0', 'accept': '*/*', 'accept-language': 'en-US,en;q=0.5', 'origin': 'https://megaplay.buzz', 'referer': 'https://megaplay.buzz/' };
|
|
7
|
-
|
|
8
|
-
export const CDN_HEADERS = [
|
|
9
|
-
{ pattern: /letsgocdn\d+\.shop/i, headers: { 'Referer': BASE_URL, 'Origin': BASE_URL, 'User-Agent': USER_AGENT } },
|
|
10
|
-
{ pattern: /cdn\.mewstream\.buzz/i, headers: { 'Referer': BASE_URL, 'Origin': BASE_URL, 'User-Agent': USER_AGENT } }
|
|
11
|
-
];
|
|
12
|
-
|
|
13
|
-
const ALPHABET = 'RB0fpH8ZEyVLkv7c2i6MAJ5u3IKFDxlS1NTsnGaqmXYdUrtzjwObCgQP94hoeW+/=';
|
|
14
|
-
const REV_MAP = new Uint8Array(256);
|
|
15
|
-
for (let i = 0; i < ALPHABET.length; i++) REV_MAP[ALPHABET.charCodeAt(i)] = i;
|
|
16
|
-
|
|
17
|
-
function decrypt(payload) {
|
|
18
|
-
const len = payload.length;
|
|
19
|
-
const bytes = new Uint8Array(len);
|
|
20
|
-
let j = 0;
|
|
21
|
-
for (let i = 0; i < len; i += 4) {
|
|
22
|
-
const c0 = REV_MAP[payload.charCodeAt(i)] ?? 64;
|
|
23
|
-
const c1 = REV_MAP[payload.charCodeAt(i + 1)] ?? 64;
|
|
24
|
-
const c2 = REV_MAP[payload.charCodeAt(i + 2)] ?? 64;
|
|
25
|
-
const c3 = REV_MAP[payload.charCodeAt(i + 3)] ?? 64;
|
|
26
|
-
bytes[j++] = (c0 << 2) | (c1 >> 4);
|
|
27
|
-
if (c2 !== 64) bytes[j++] = ((c1 & 15) << 4) | (c2 >> 2);
|
|
28
|
-
if (c3 !== 64) bytes[j++] = ((c2 & 3) << 6) | c3;
|
|
29
|
-
}
|
|
30
|
-
return JSON.parse(new TextDecoder().decode(bytes.subarray(0, j)));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function tmdbToAnilist(tmdbId, season) {
|
|
34
|
-
try {
|
|
35
|
-
const data = await fetchJson(`https://api.ani.zip/mappings?tmdb_id=${tmdbId}&type=tv&season=${season || 1}`, { signal: AbortSignal.timeout(6000) });
|
|
36
|
-
return data?.mappings?.[0]?.anilist_id || null;
|
|
37
|
-
} catch { return null; }
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const SERVER_KEYS = ['hollymoviehd', 'allmovies', 'catflix', 'purstream', 'lamda', 'vidlink', 'klikxxi'];
|
|
41
|
-
|
|
42
|
-
export async function getStream({ id, s, e, sdk, audio }) {
|
|
43
|
-
const tmdbApiKey = sdk?.tmdbApiKey || null;
|
|
44
|
-
if (!tmdbApiKey) return null;
|
|
45
|
-
if (s) {
|
|
46
|
-
const k = tmdbApiKey;
|
|
47
|
-
const showData = k ? await fetchJson(`https://api.themoviedb.org/3/tv/${id}?api_key=${k}`, { signal: AbortSignal.timeout(5000) }).catch(() => null) : null;
|
|
48
|
-
if (showData?.genres?.some(g => g.id === 16)) {
|
|
49
|
-
const anilistId = await tmdbToAnilist(id, s);
|
|
50
|
-
if (anilistId) {
|
|
51
|
-
try {
|
|
52
|
-
const json = await fetchJson(`${API_BASE_URL}/hianime/anime/${anilistId}/${e || 1}/${audio === 'dub' ? 'dub' : 'sub'}`, { headers: REQUEST_HEADERS, signal: AbortSignal.timeout(15000) });
|
|
53
|
-
const data = json.encrypted ? decrypt(json.data) : json.data;
|
|
54
|
-
const file = data?.sources?.[0]?.file;
|
|
55
|
-
if (file) return { url: `https://megacloud.animanga.fun/proxy?url=${encodeURIComponent(file)}&headers=${encodeURIComponent(JSON.stringify(CDN_PROXY_HEADERS))}`, headers: REQUEST_HEADERS };
|
|
56
|
-
} catch { }
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (audio === 'dub') return null;
|
|
61
|
-
const segment = s ? `tv/${id}/${s}/${e || 1}` : `movie/${id}`;
|
|
62
|
-
const settled = await Promise.allSettled(SERVER_KEYS.map(async server => {
|
|
63
|
-
const json = await fetchJson(`${API_BASE_URL}/${server}/${segment}`, { headers: REQUEST_HEADERS, signal: AbortSignal.timeout(10000) });
|
|
64
|
-
const data = json.encrypted ? decrypt(json.data) : json.data;
|
|
65
|
-
const file = data?.sources?.[0]?.file ?? data?.streams?.[0]?.url ?? data?.url?.[0]?.link ?? data?.data?.stream?.playlist;
|
|
66
|
-
if (file) return { url: file, server, headers: REQUEST_HEADERS };
|
|
67
|
-
throw new Error();
|
|
68
|
-
}));
|
|
69
|
-
const allUrls = [];
|
|
70
|
-
for (const r of settled) if (r.status === 'fulfilled') allUrls.push(r.value);
|
|
71
|
-
return allUrls.length ? { allUrls } : null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function getSources(args) {
|
|
75
|
-
const res = await getStream(args);
|
|
76
|
-
return res?.allUrls ? res.allUrls.map(u => u.server) : [];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export const VERIFY_HEADERS = { ...REQUEST_HEADERS };
|