@vyla-entertainment/sdk 1.10.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 +2 -2
- package/src/config.js +212 -98
- package/src/downloads/downloads.js +51 -10
- package/src/sdk.d.ts +0 -1
- package/src/sdk.js +1 -1
- package/src/sources/111477.js +101 -0
- package/src/sources/4khdhub.js +324 -0
- package/src/sources/bcine.js +202 -0
- package/src/sources/cinesrc.js +212 -0
- package/src/sources/cinesu.js +148 -0
- package/src/sources/downloadeverything.js +338 -0
- package/src/sources/meowtv.js +42 -3
- package/src/sources/movienight.js +117 -0
- package/src/sources/movy.js +282 -0
- package/src/sources/pstream.js +68 -0
- package/src/sources/purstream.js +2 -2
- package/src/sources/streamaggregator.js +127 -0
- package/src/sources/vadapav.js +85 -0
- package/src/sources/vidvault.js +131 -57
- package/src/sources/vuflix.js +249 -0
- package/src/sources/xdownloader.js +129 -0
- package/src/subtitles.js +35 -40
- package/src/downloads/sources/trendimovies.js +0 -63
- package/src/sources/anipm.js +0 -70
- package/src/sources/mapple.js +0 -151
- package/src/sources/megasource.js +0 -47
- package/src/sources/nova.js +0 -46
- package/src/sources/videasy.js +0 -94
- package/src/sources/vidrift.js +0 -95
- package/src/sources/vidsync.js +0 -38
- package/src/sources/xpass.js +0 -40
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { USER_AGENT } from '../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const _sInit = [23, 27, 30, 31, 86, 28, 19, 86, 9, 18, 19, 21, 26, 27, 86, 120, 114, 120, 116, 86, 9, 18, 19, 21, 26, 27, 122, 89, 25, 23];
|
|
4
|
+
const _vParam = `_v=${(_sInit[15] ^ 0x5a)}${(_sInit[16] ^ 0x5a)}${(_sInit[17] ^ 0x5a)}${(_sInit[18] ^ 0x5a)}`;
|
|
5
|
+
|
|
6
|
+
const nD = '4860ac8bfddb';
|
|
7
|
+
const aD = '224eff10e662e9635c9f671cf46351dcd69af42b1edd56f5e5fa21751f44b9c8';
|
|
8
|
+
const Ls = [17, 91, 203, 44, 8, 177, 62, 239, 119, 3, 154, 81, 28, 210, 101, 7];
|
|
9
|
+
const wa = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
10
|
+
|
|
11
|
+
const SERVERS = [
|
|
12
|
+
{ id: 'NIGHT', endpoint: '/server/night' },
|
|
13
|
+
{ id: 'EMP', endpoint: '/server/emp' },
|
|
14
|
+
{ id: 'MAIN', endpoint: '/server/vidsrc' }
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
let cachedToken = null;
|
|
18
|
+
let tokenExpiry = 0;
|
|
19
|
+
|
|
20
|
+
function ab(e) {
|
|
21
|
+
let t = e >>> 0;
|
|
22
|
+
t ^= t >>> 16;
|
|
23
|
+
t = Math.imul(t, 2146121005) >>> 0;
|
|
24
|
+
t ^= t >>> 15;
|
|
25
|
+
t = Math.imul(t, 2221713035) >>> 0;
|
|
26
|
+
return (t ^ (t >>> 16)) >>> 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function sD(e) {
|
|
30
|
+
const t = new TextEncoder().encode(aD);
|
|
31
|
+
const r = Math.max(32, Math.min(128, e + 17));
|
|
32
|
+
const n = new Uint8Array(r);
|
|
33
|
+
let a = 2166136261;
|
|
34
|
+
for (let s = 0; s < r; s += 1) {
|
|
35
|
+
a ^= t[s % t.length] ?? s;
|
|
36
|
+
a = ab((a + Ls[s % Ls.length] + ((2654435761 * s) >>> 0)) >>> 0);
|
|
37
|
+
n[s] = a & 255;
|
|
38
|
+
}
|
|
39
|
+
return n;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function iD(e) {
|
|
43
|
+
let t = '';
|
|
44
|
+
for (let r = 0; r < e.length; r += 3) {
|
|
45
|
+
const n = e[r];
|
|
46
|
+
const a = e[r + 1];
|
|
47
|
+
const s = e[r + 2];
|
|
48
|
+
t += wa[n >>> 2];
|
|
49
|
+
t += wa[((3 & n) << 4) | ((a ?? 0) >>> 4)];
|
|
50
|
+
if (a === undefined) break;
|
|
51
|
+
t += wa[((15 & a) << 2) | ((s ?? 0) >>> 6)];
|
|
52
|
+
if (s === undefined) break;
|
|
53
|
+
t += wa[63 & s];
|
|
54
|
+
}
|
|
55
|
+
return t;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function generateCinesrcDirectHlsUrl(id, s, e) {
|
|
59
|
+
const isTv = s != null && e != null;
|
|
60
|
+
const tmdbId = Math.floor(Number(id));
|
|
61
|
+
const season = isTv ? Math.floor(Number(s || 1)) : 0;
|
|
62
|
+
const episode = isTv ? Math.floor(Number(e || 1)) : 0;
|
|
63
|
+
|
|
64
|
+
const str = `${nD}:${isTv ? 's' : 'm'}:${tmdbId}:${season}:${episode}`;
|
|
65
|
+
const a = new TextEncoder().encode(str);
|
|
66
|
+
const sArr = sD(a.length);
|
|
67
|
+
const i = new Uint8Array(a.length + 2);
|
|
68
|
+
i[0] = a.length & 255;
|
|
69
|
+
i[1] = (a.length >>> 8) & 255;
|
|
70
|
+
let o = (2654435769 ^ a.length) >>> 0;
|
|
71
|
+
for (let l = 0; l < a.length; l += 1) {
|
|
72
|
+
o = ab((o + sArr[l % sArr.length] + Ls[l % Ls.length] + l) >>> 0);
|
|
73
|
+
i[l + 2] = (a[l] ^ (255 & o)) ^ sArr[(7 * l + 3) % sArr.length];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return `https://glendale-plumbing.com/c/v1/${iD(i)}/master.m3u8`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function fetchBright67Subtitles(id, season, episode) {
|
|
80
|
+
let url = `https://subs.bright67.online/search?id=${id}`;
|
|
81
|
+
if (season != null && episode != null) {
|
|
82
|
+
url += `&season=${season}&episode=${episode}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const res = await fetch(url, {
|
|
87
|
+
headers: {
|
|
88
|
+
'User-Agent': USER_AGENT,
|
|
89
|
+
'Referer': 'https://cinesrc.st/'
|
|
90
|
+
},
|
|
91
|
+
signal: AbortSignal.timeout(4000)
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (!res.ok) return [];
|
|
95
|
+
const data = await res.json();
|
|
96
|
+
if (!Array.isArray(data)) return [];
|
|
97
|
+
|
|
98
|
+
return data.slice(0, 15).map(s => ({
|
|
99
|
+
label: s.display || s.languageName || s.language || 'English',
|
|
100
|
+
language: s.language || 'en',
|
|
101
|
+
file: s.url || s.r2Url,
|
|
102
|
+
type: (s.url || s.r2Url || '').endsWith('.vtt') ? 'vtt' : 'srt'
|
|
103
|
+
}));
|
|
104
|
+
} catch {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function fetchInternalToken() {
|
|
110
|
+
if (cachedToken && Date.now() < tokenExpiry) return cachedToken;
|
|
111
|
+
try {
|
|
112
|
+
const res = await fetch('https://1embed.cc/api/token', {
|
|
113
|
+
headers: {
|
|
114
|
+
'User-Agent': USER_AGENT,
|
|
115
|
+
'Referer': 'https://1embed.cc/',
|
|
116
|
+
'Accept': 'application/json, text/plain, */*'
|
|
117
|
+
},
|
|
118
|
+
signal: AbortSignal.timeout(4000)
|
|
119
|
+
});
|
|
120
|
+
if (res.ok) {
|
|
121
|
+
const data = await res.json();
|
|
122
|
+
if (data?.token) {
|
|
123
|
+
cachedToken = data.token;
|
|
124
|
+
tokenExpiry = Date.now() + 1800 * 1000;
|
|
125
|
+
return cachedToken;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} catch { }
|
|
129
|
+
|
|
130
|
+
return '';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function getStream(args) {
|
|
134
|
+
const { id, s, e, clientIP } = args;
|
|
135
|
+
const isTv = s != null && e != null;
|
|
136
|
+
const isMovie = !isTv;
|
|
137
|
+
const allUrls = [];
|
|
138
|
+
|
|
139
|
+
const [subtitles, directHlsUrl] = await Promise.all([
|
|
140
|
+
fetchBright67Subtitles(id, isMovie ? undefined : s, isMovie ? undefined : e),
|
|
141
|
+
Promise.resolve(generateCinesrcDirectHlsUrl(id, s, e))
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
const masterUrlWithMark = `${directHlsUrl}?${_vParam}`;
|
|
145
|
+
|
|
146
|
+
allUrls.push({
|
|
147
|
+
url: masterUrlWithMark,
|
|
148
|
+
server: 'CineSrc (Direct Master)',
|
|
149
|
+
quality: 'Auto',
|
|
150
|
+
type: 'hls',
|
|
151
|
+
headers: {
|
|
152
|
+
'User-Agent': USER_AGENT,
|
|
153
|
+
'Referer': 'https://cinesrc.st/',
|
|
154
|
+
'Origin': 'https://cinesrc.st',
|
|
155
|
+
...(clientIP && { 'X-Forwarded-For': clientIP })
|
|
156
|
+
},
|
|
157
|
+
subtitles: subtitles.length ? subtitles : undefined
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const token = await fetchInternalToken();
|
|
161
|
+
|
|
162
|
+
await Promise.allSettled(
|
|
163
|
+
SERVERS.map(async (server) => {
|
|
164
|
+
const query = isTv
|
|
165
|
+
? `id=${id}?type=tv&s=${s || 1}&e=${e || 1}`
|
|
166
|
+
: `id=${id}?type=movie`;
|
|
167
|
+
|
|
168
|
+
const stParam = token ? `&_st=${token}` : '';
|
|
169
|
+
const targetUrl = `https://1embed.cc${server.endpoint}/${query}${stParam}`;
|
|
170
|
+
|
|
171
|
+
const headers = {
|
|
172
|
+
'User-Agent': USER_AGENT,
|
|
173
|
+
'Referer': 'https://cinesrc.st/',
|
|
174
|
+
'Accept': 'application/json, text/plain, */*',
|
|
175
|
+
...(token && { 'X-Stream-Token': token }),
|
|
176
|
+
...(clientIP && { 'X-Forwarded-For': clientIP })
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const res = await fetch(targetUrl, { headers, signal: AbortSignal.timeout(5000) }).catch(() => null);
|
|
180
|
+
|
|
181
|
+
if (res && res.ok) {
|
|
182
|
+
try {
|
|
183
|
+
const data = await res.json();
|
|
184
|
+
if (data && data.success !== false) {
|
|
185
|
+
const streamUrl = data.streams?.proxy_m3u8 || data.streams?.raw_m3u8 || data.streams?.m3u8 || data.streamUrl;
|
|
186
|
+
if (streamUrl && typeof streamUrl === 'string') {
|
|
187
|
+
const urlWithMark = streamUrl.includes('?') ? `${streamUrl}&${_vParam}` : `${streamUrl}?${_vParam}`;
|
|
188
|
+
allUrls.push({
|
|
189
|
+
url: urlWithMark,
|
|
190
|
+
server: `CineSrc (${data.selectedSource || data.provider || server.id})`,
|
|
191
|
+
quality: 'Auto',
|
|
192
|
+
type: streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
|
|
193
|
+
headers: {
|
|
194
|
+
'User-Agent': USER_AGENT,
|
|
195
|
+
'Referer': 'https://cinesrc.st/',
|
|
196
|
+
'Origin': 'https://cinesrc.st'
|
|
197
|
+
},
|
|
198
|
+
subtitles: subtitles.length ? subtitles : undefined
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} catch { }
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
return allUrls.length ? { allUrls } : null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export async function getSources() {
|
|
211
|
+
return ['CineSrc (Direct Master)', 'CineSrc (NIGHT)', 'CineSrc (EMP)', 'CineSrc (MAIN)'];
|
|
212
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { USER_AGENT } from '../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const BASE_DOMAIN = 'https://glendale-plumbing.com';
|
|
4
|
+
const REFERER = 'https://cine.su/';
|
|
5
|
+
|
|
6
|
+
const nD = '4860ac8bfddb';
|
|
7
|
+
const aD = '224eff10e662e9635c9f671cf46351dcd69af42b1edd56f5e5fa21751f44b9c8';
|
|
8
|
+
const Ls = [17, 91, 203, 44, 8, 177, 62, 239, 119, 3, 154, 81, 28, 210, 101, 7];
|
|
9
|
+
const wa = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
10
|
+
|
|
11
|
+
function ab(e) {
|
|
12
|
+
let t = e >>> 0;
|
|
13
|
+
t ^= t >>> 16;
|
|
14
|
+
t = Math.imul(t, 2146121005) >>> 0;
|
|
15
|
+
t ^= t >>> 15;
|
|
16
|
+
t = Math.imul(t, 2221713035) >>> 0;
|
|
17
|
+
return (t ^ (t >>> 16)) >>> 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function sD(e) {
|
|
21
|
+
const t = new TextEncoder().encode(aD);
|
|
22
|
+
const r = Math.max(32, Math.min(128, e + 17));
|
|
23
|
+
const n = new Uint8Array(r);
|
|
24
|
+
let a = 2166136261;
|
|
25
|
+
for (let s = 0; s < r; s += 1) {
|
|
26
|
+
a ^= t[s % t.length] ?? s;
|
|
27
|
+
a = ab((a + Ls[s % Ls.length] + ((2654435761 * s) >>> 0)) >>> 0);
|
|
28
|
+
n[s] = a & 255;
|
|
29
|
+
}
|
|
30
|
+
return n;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function iD(e) {
|
|
34
|
+
let t = '';
|
|
35
|
+
for (let r = 0; r < e.length; r += 3) {
|
|
36
|
+
const n = e[r];
|
|
37
|
+
const a = e[r + 1];
|
|
38
|
+
const s = e[r + 2];
|
|
39
|
+
t += wa[n >>> 2];
|
|
40
|
+
t += wa[((3 & n) << 4) | ((a ?? 0) >>> 4)];
|
|
41
|
+
if (a === undefined) break;
|
|
42
|
+
t += wa[((15 & a) << 2) | ((s ?? 0) >>> 6)];
|
|
43
|
+
if (s === undefined) break;
|
|
44
|
+
t += wa[63 & s];
|
|
45
|
+
}
|
|
46
|
+
return t;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function generateMasterUrl(id, s, e) {
|
|
50
|
+
const isTv = s != null && e != null;
|
|
51
|
+
const tmdbId = Math.floor(Number(id));
|
|
52
|
+
const season = isTv ? Math.floor(Number(s || 1)) : 0;
|
|
53
|
+
const episode = isTv ? Math.floor(Number(e || 1)) : 0;
|
|
54
|
+
|
|
55
|
+
const str = `${nD}:${isTv ? 's' : 'm'}:${tmdbId}:${season}:${episode}`;
|
|
56
|
+
const a = new TextEncoder().encode(str);
|
|
57
|
+
const sArr = sD(a.length);
|
|
58
|
+
const i = new Uint8Array(a.length + 2);
|
|
59
|
+
i[0] = a.length & 255;
|
|
60
|
+
i[1] = (a.length >>> 8) & 255;
|
|
61
|
+
let o = (2654435769 ^ a.length) >>> 0;
|
|
62
|
+
for (let l = 0; l < a.length; l += 1) {
|
|
63
|
+
o = ab((o + sArr[l % sArr.length] + Ls[l % Ls.length] + l) >>> 0);
|
|
64
|
+
i[l + 2] = (a[l] ^ (255 & o)) ^ sArr[(7 * l + 3) % sArr.length];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return `${BASE_DOMAIN}/c/v1/${iD(i)}/master.m3u8`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function parsePlaylist(m3u8Text) {
|
|
71
|
+
const qualities = [];
|
|
72
|
+
const subtitles = [];
|
|
73
|
+
|
|
74
|
+
const subRegex = /#EXT-X-MEDIA:TYPE=SUBTITLES,[^\n]*NAME="([^"]*)"[^\n]*LANGUAGE="([^"]*)"[^\n]*URI="([^"]*)"/g;
|
|
75
|
+
let match;
|
|
76
|
+
while ((match = subRegex.exec(m3u8Text)) !== null) {
|
|
77
|
+
let uri = match[3];
|
|
78
|
+
if (uri.startsWith('/')) uri = `${BASE_DOMAIN}${uri}`;
|
|
79
|
+
subtitles.push({ label: match[1], language: match[2], file: uri, type: 'vtt' });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const streamRegex = /#EXT-X-STREAM-INF:[^\n]*RESOLUTION=\d+x(\d+)[^\n]*\r?\n([^\n#][^\n]*)/g;
|
|
83
|
+
while ((match = streamRegex.exec(m3u8Text)) !== null) {
|
|
84
|
+
let streamPath = match[2].trim();
|
|
85
|
+
if (streamPath.startsWith('/')) streamPath = `${BASE_DOMAIN}${streamPath}`;
|
|
86
|
+
qualities.push({ quality: `${match[1]}p`, url: streamPath });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return { qualities, subtitles };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export async function getStream(args) {
|
|
93
|
+
const { id, s, e, clientIP } = args;
|
|
94
|
+
const rawMasterUrl = generateMasterUrl(id, s, e);
|
|
95
|
+
|
|
96
|
+
const headers = {
|
|
97
|
+
'User-Agent': USER_AGENT,
|
|
98
|
+
'Referer': REFERER,
|
|
99
|
+
'Origin': 'https://cine.su',
|
|
100
|
+
...(clientIP && { 'X-Forwarded-For': clientIP })
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const res = await fetch(rawMasterUrl, {
|
|
105
|
+
headers,
|
|
106
|
+
signal: AbortSignal.timeout(5000)
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (res.ok) {
|
|
110
|
+
const text = await res.text();
|
|
111
|
+
const { qualities, subtitles } = parsePlaylist(text);
|
|
112
|
+
|
|
113
|
+
if (qualities.length) {
|
|
114
|
+
const allUrls = [{
|
|
115
|
+
url: rawMasterUrl,
|
|
116
|
+
server: 'CineSu (Auto)',
|
|
117
|
+
quality: 'Auto',
|
|
118
|
+
type: 'hls',
|
|
119
|
+
headers,
|
|
120
|
+
subtitles: subtitles.length ? subtitles : undefined
|
|
121
|
+
}];
|
|
122
|
+
|
|
123
|
+
for (const q of qualities) {
|
|
124
|
+
allUrls.push({
|
|
125
|
+
url: q.url,
|
|
126
|
+
server: `CineSu (${q.quality})`,
|
|
127
|
+
quality: q.quality,
|
|
128
|
+
type: 'hls',
|
|
129
|
+
headers,
|
|
130
|
+
subtitles: subtitles.length ? subtitles : undefined
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return { allUrls };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch { }
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
allUrls: [{
|
|
141
|
+
url: rawMasterUrl,
|
|
142
|
+
server: 'CineSu',
|
|
143
|
+
quality: 'Auto',
|
|
144
|
+
type: 'hls',
|
|
145
|
+
headers
|
|
146
|
+
}]
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { getUA } from '../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const SLAVE_URL = 'https://slave.downloadeverythingfromeverywhere.com/';
|
|
4
|
+
const REFERER = 'https://downloadeverythingfromeverywhere.com/';
|
|
5
|
+
const ORIGIN = 'https://downloadeverythingfromeverywhere.com';
|
|
6
|
+
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36';
|
|
7
|
+
|
|
8
|
+
function extractJsonObjects(text) {
|
|
9
|
+
const objects = [];
|
|
10
|
+
let depth = 0;
|
|
11
|
+
let start = -1;
|
|
12
|
+
let inString = false;
|
|
13
|
+
let escape = false;
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < text.length; i++) {
|
|
16
|
+
const char = text[i];
|
|
17
|
+
if (escape) {
|
|
18
|
+
escape = false;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (char === '\\') {
|
|
22
|
+
escape = true;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (char === '"') {
|
|
26
|
+
inString = !inString;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (!inString) {
|
|
30
|
+
if (char === '{') {
|
|
31
|
+
if (depth === 0) start = i;
|
|
32
|
+
depth++;
|
|
33
|
+
} else if (char === '}') {
|
|
34
|
+
depth--;
|
|
35
|
+
if (depth === 0 && start !== -1) {
|
|
36
|
+
const jsonStr = text.substring(start, i + 1);
|
|
37
|
+
try {
|
|
38
|
+
objects.push(JSON.parse(jsonStr));
|
|
39
|
+
} catch { }
|
|
40
|
+
start = -1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return objects;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function resolveDetails(sdk, id, isTv) {
|
|
49
|
+
const apiKey = sdk?.tmdbApiKey || process.env.TMDB_API_KEY;
|
|
50
|
+
if (!apiKey) return null;
|
|
51
|
+
const type = isTv ? 'tv' : 'movie';
|
|
52
|
+
try {
|
|
53
|
+
const res = await fetch(`https://api.themoviedb.org/3/${type}/${id}?api_key=${apiKey}&append_to_response=external_ids`, {
|
|
54
|
+
signal: AbortSignal.timeout(6000),
|
|
55
|
+
});
|
|
56
|
+
if (!res.ok) return null;
|
|
57
|
+
const data = await res.json();
|
|
58
|
+
const title = isTv ? data.name : data.title;
|
|
59
|
+
const releaseDate = isTv ? data.first_air_date : data.release_date;
|
|
60
|
+
const year = releaseDate ? parseInt(releaseDate.split('-')[0], 10) : null;
|
|
61
|
+
const imdbId = data.imdb_id || data.external_ids?.imdb_id || null;
|
|
62
|
+
return { title, year, imdbId };
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function resolveHubCloud(hubUrl, ua) {
|
|
69
|
+
try {
|
|
70
|
+
const res1 = await fetch(hubUrl, {
|
|
71
|
+
headers: {
|
|
72
|
+
'User-Agent': ua,
|
|
73
|
+
Referer: REFERER,
|
|
74
|
+
},
|
|
75
|
+
signal: AbortSignal.timeout(8000),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const html = await res1.text();
|
|
79
|
+
const hubPhpMatch = html.match(/https?:\/\/[^\s"<>]+\/hubcloud\.php\?[^\s"<>]+/i);
|
|
80
|
+
if (!hubPhpMatch) return null;
|
|
81
|
+
|
|
82
|
+
const phpUrl = hubPhpMatch[0];
|
|
83
|
+
const phpRes = await fetch(phpUrl, {
|
|
84
|
+
headers: {
|
|
85
|
+
'User-Agent': ua,
|
|
86
|
+
Referer: hubUrl,
|
|
87
|
+
},
|
|
88
|
+
signal: AbortSignal.timeout(8000),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const phpBody = await phpRes.text();
|
|
92
|
+
|
|
93
|
+
const r2Match = phpBody.match(/https?:\/\/[a-zA-Z0-9.\-_]+\.r2\.cloudflarestorage\.com\/[^\s"<>]+/i);
|
|
94
|
+
if (r2Match) {
|
|
95
|
+
return r2Match[0].replaceAll('&', '&');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const pixelMatch = phpBody.match(/https?:\/\/pixel\.hubcloud\.[a-z]+\/\?id=[^\s"<>]+/i);
|
|
99
|
+
if (pixelMatch) {
|
|
100
|
+
return pixelMatch[0];
|
|
101
|
+
}
|
|
102
|
+
} catch { }
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function resolveClicknUpload(clicknUrl, ua) {
|
|
107
|
+
try {
|
|
108
|
+
const res1 = await fetch(clicknUrl, {
|
|
109
|
+
headers: {
|
|
110
|
+
'User-Agent': ua,
|
|
111
|
+
Referer: REFERER,
|
|
112
|
+
},
|
|
113
|
+
signal: AbortSignal.timeout(8000),
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const body1 = await res1.text();
|
|
117
|
+
const formMatch1 = body1.match(/<form[^>]+method=["']POST["'][^>]*>([\s\S]*?)<\/form>/i);
|
|
118
|
+
if (!formMatch1) return null;
|
|
119
|
+
|
|
120
|
+
const inputMatches1 = [...formMatch1[1].matchAll(/<input[^>]+name=["']([^"']+)["'][^>]+value=["']([^"']*)["']/gi)];
|
|
121
|
+
const params1 = new URLSearchParams();
|
|
122
|
+
for (const m of inputMatches1) {
|
|
123
|
+
params1.set(m[1], m[2]);
|
|
124
|
+
}
|
|
125
|
+
params1.set('method_free', 'Slow Download');
|
|
126
|
+
|
|
127
|
+
const rawCookies = res1.headers.getSetCookie?.() || [res1.headers.get('set-cookie')].filter(Boolean);
|
|
128
|
+
const cookieHeader = rawCookies.join('; ');
|
|
129
|
+
|
|
130
|
+
const res2 = await fetch(clicknUrl, {
|
|
131
|
+
method: 'POST',
|
|
132
|
+
headers: {
|
|
133
|
+
'User-Agent': ua,
|
|
134
|
+
Referer: clicknUrl,
|
|
135
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
136
|
+
...(cookieHeader ? { Cookie: cookieHeader } : {}),
|
|
137
|
+
},
|
|
138
|
+
body: params1.toString(),
|
|
139
|
+
signal: AbortSignal.timeout(8000),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const body2 = await res2.text();
|
|
143
|
+
const formMatch2 = body2.match(/<form[^>]+method=["']POST["'][^>]*>([\s\S]*?)<\/form>/i);
|
|
144
|
+
if (!formMatch2) return null;
|
|
145
|
+
|
|
146
|
+
const inputMatches2 = [...formMatch2[1].matchAll(/<input[^>]+name=["']([^"']+)["'][^>]+value=["']([^"']*)["']/gi)];
|
|
147
|
+
const params2 = new URLSearchParams();
|
|
148
|
+
for (const m of inputMatches2) {
|
|
149
|
+
params2.set(m[1], m[2]);
|
|
150
|
+
}
|
|
151
|
+
params2.set('down_script', '1');
|
|
152
|
+
|
|
153
|
+
await new Promise(r => setTimeout(r, 4500));
|
|
154
|
+
|
|
155
|
+
const res3 = await fetch(clicknUrl, {
|
|
156
|
+
method: 'POST',
|
|
157
|
+
headers: {
|
|
158
|
+
'User-Agent': ua,
|
|
159
|
+
Referer: clicknUrl,
|
|
160
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
161
|
+
...(cookieHeader ? { Cookie: cookieHeader } : {}),
|
|
162
|
+
},
|
|
163
|
+
body: params2.toString(),
|
|
164
|
+
signal: AbortSignal.timeout(8000),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const body3 = await res3.text();
|
|
168
|
+
const directMatch = body3.match(/https?:\/\/[a-zA-Z0-9.\-_:]+\/d\/[a-zA-Z0-9_\-\/]+/i) ||
|
|
169
|
+
body3.match(/window\.open\(["'](https?:\/\/[^"']+)["']\)/i);
|
|
170
|
+
|
|
171
|
+
if (directMatch) {
|
|
172
|
+
const found = directMatch[1] || directMatch[0];
|
|
173
|
+
if (found.includes('clicknupload.') && !found.includes('/d/')) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
return found;
|
|
177
|
+
}
|
|
178
|
+
} catch { }
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function resolveItem(item, fallbackTitle, ua) {
|
|
183
|
+
const rawUrl = String(item.url || '').trim();
|
|
184
|
+
if (!rawUrl) return null;
|
|
185
|
+
|
|
186
|
+
if (
|
|
187
|
+
rawUrl.includes('111477.xyz') ||
|
|
188
|
+
rawUrl.includes('vadapav.mov') ||
|
|
189
|
+
rawUrl.includes('driveseed.org') ||
|
|
190
|
+
rawUrl.includes('new3.gdflix.io') ||
|
|
191
|
+
rawUrl.includes('rapidrar.cr') ||
|
|
192
|
+
rawUrl.includes('megaup.net') ||
|
|
193
|
+
rawUrl.includes('telegram.dog') ||
|
|
194
|
+
rawUrl.includes('t.me')
|
|
195
|
+
) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let directStreamUrl = null;
|
|
200
|
+
let provider = item.site || 'DownloadEverything';
|
|
201
|
+
let streamHeaders = { 'User-Agent': ua };
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
if (rawUrl.includes('hakunaymatata.com')) {
|
|
205
|
+
directStreamUrl = rawUrl;
|
|
206
|
+
provider = 'Moviebox';
|
|
207
|
+
streamHeaders = { 'User-Agent': 'Lavf/60.16.100' };
|
|
208
|
+
} else if (rawUrl.includes('pixeldrain.dev') || rawUrl.includes('pixeldrain.com')) {
|
|
209
|
+
const m = rawUrl.match(/pixeldrain\.(?:dev|com)\/(?:u|l)\/([a-zA-Z0-9_-]+)/);
|
|
210
|
+
if (m) {
|
|
211
|
+
directStreamUrl = `https://pixeldrain.com/api/file/${m[1]}`;
|
|
212
|
+
provider = 'Pixeldrain';
|
|
213
|
+
}
|
|
214
|
+
} else if (rawUrl.includes('hubcloud.') || rawUrl.includes('vcloud.zip')) {
|
|
215
|
+
directStreamUrl = await resolveHubCloud(rawUrl, ua);
|
|
216
|
+
if (directStreamUrl) {
|
|
217
|
+
provider = 'HubCloud';
|
|
218
|
+
}
|
|
219
|
+
} else if (rawUrl.includes('clicknupload.')) {
|
|
220
|
+
directStreamUrl = await resolveClicknUpload(rawUrl, ua);
|
|
221
|
+
if (directStreamUrl) {
|
|
222
|
+
provider = 'ClicknUpload';
|
|
223
|
+
}
|
|
224
|
+
} else if (
|
|
225
|
+
/\.(?:mp4|mkv)(?:\?|$)/i.test(rawUrl) &&
|
|
226
|
+
!rawUrl.includes('111477.xyz') &&
|
|
227
|
+
!rawUrl.includes('vadapav.mov') &&
|
|
228
|
+
!rawUrl.includes('.cyou/res/')
|
|
229
|
+
) {
|
|
230
|
+
try {
|
|
231
|
+
const check = await fetch(rawUrl, {
|
|
232
|
+
method: 'HEAD',
|
|
233
|
+
headers: { 'User-Agent': ua },
|
|
234
|
+
signal: AbortSignal.timeout(2000),
|
|
235
|
+
});
|
|
236
|
+
if (check.status === 200 || check.status === 206 || (check.status >= 300 && check.status < 400)) {
|
|
237
|
+
directStreamUrl = rawUrl;
|
|
238
|
+
provider = item.site || 'DirectStream';
|
|
239
|
+
}
|
|
240
|
+
} catch { }
|
|
241
|
+
}
|
|
242
|
+
} catch { }
|
|
243
|
+
|
|
244
|
+
if (!directStreamUrl) return null;
|
|
245
|
+
|
|
246
|
+
const tags = Array.isArray(item.tags) ? item.tags.map(String) : [];
|
|
247
|
+
const qualityMatch = tags.find(t => /2160p|4k|1080p|720p|480p/i.test(t)) || '1080p';
|
|
248
|
+
const rawTitle = item.name || item.release || fallbackTitle;
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
url: directStreamUrl,
|
|
252
|
+
label: `[${provider}] ${rawTitle} (${qualityMatch})`,
|
|
253
|
+
headers: streamHeaders,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export async function getStream({ id, s, e, sdk }) {
|
|
258
|
+
const isTv = Boolean(s && e);
|
|
259
|
+
const mediaType = isTv ? 'series' : 'movie';
|
|
260
|
+
const ua = USER_AGENT;
|
|
261
|
+
|
|
262
|
+
const details = await resolveDetails(sdk, id, isTv);
|
|
263
|
+
const title = details?.title || String(id);
|
|
264
|
+
const tmdbId = parseInt(id, 10);
|
|
265
|
+
|
|
266
|
+
const payload = {
|
|
267
|
+
mode: mediaType,
|
|
268
|
+
title,
|
|
269
|
+
...(details?.year ? { year: String(details.year) } : {}),
|
|
270
|
+
...(tmdbId ? { tmdb_id: tmdbId } : {}),
|
|
271
|
+
...(details?.imdbId ? { imdb_id: details.imdbId } : {}),
|
|
272
|
+
...(isTv && s != null ? { season: Number(s) } : {}),
|
|
273
|
+
...(isTv && e != null ? { episode: Number(e) } : {}),
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const res = await fetch(SLAVE_URL, {
|
|
277
|
+
method: 'POST',
|
|
278
|
+
headers: {
|
|
279
|
+
'User-Agent': ua,
|
|
280
|
+
Origin: ORIGIN,
|
|
281
|
+
Referer: REFERER,
|
|
282
|
+
'Content-Type': 'application/json',
|
|
283
|
+
Accept: 'application/x-ndjson',
|
|
284
|
+
'x-defe-manual': '1',
|
|
285
|
+
'sec-ch-ua': '"Microsoft Edge";v="153", "Not_A Brand";v="8", "Chromium";v="153"',
|
|
286
|
+
'sec-ch-ua-mobile': '?0',
|
|
287
|
+
'sec-ch-ua-platform': '"Windows"',
|
|
288
|
+
'sec-fetch-dest': 'empty',
|
|
289
|
+
'sec-fetch-mode': 'cors',
|
|
290
|
+
'sec-fetch-site': 'same-site',
|
|
291
|
+
},
|
|
292
|
+
body: JSON.stringify(payload),
|
|
293
|
+
signal: AbortSignal.timeout(16000),
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
if (!res.ok) return null;
|
|
297
|
+
|
|
298
|
+
let fullText = '';
|
|
299
|
+
if (res.body?.getReader) {
|
|
300
|
+
const reader = res.body.getReader();
|
|
301
|
+
const decoder = new TextDecoder();
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
while (true) {
|
|
305
|
+
const { done, value } = await reader.read();
|
|
306
|
+
if (done) break;
|
|
307
|
+
fullText += decoder.decode(value, { stream: true });
|
|
308
|
+
}
|
|
309
|
+
} catch { }
|
|
310
|
+
} else {
|
|
311
|
+
fullText = await res.text();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const objects = extractJsonObjects(fullText);
|
|
315
|
+
const candidateItems = [];
|
|
316
|
+
|
|
317
|
+
for (const parsed of objects) {
|
|
318
|
+
if (parsed?.t === 'hit' && Array.isArray(parsed.links)) {
|
|
319
|
+
const site = parsed.site || 'DownloadEverything';
|
|
320
|
+
for (const l of parsed.links) {
|
|
321
|
+
if (l && typeof l === 'object') {
|
|
322
|
+
candidateItems.push({ site, ...l });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const resolved = await Promise.all(candidateItems.map(item => resolveItem(item, title, ua)));
|
|
329
|
+
const allUrls = resolved.filter(Boolean);
|
|
330
|
+
|
|
331
|
+
if (allUrls.length === 0) return null;
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
url: allUrls[0].url,
|
|
335
|
+
allUrls,
|
|
336
|
+
headers: allUrls[0].headers,
|
|
337
|
+
};
|
|
338
|
+
}
|