@vyla-entertainment/sdk 1.10.0 → 1.11.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.10.0",
3
+ "version": "1.11.0",
4
4
  "scripts": {
5
5
  "test": "node test/index.js"
6
6
  },
package/src/config.js CHANGED
@@ -103,6 +103,24 @@ export const SOURCES = [
103
103
  },
104
104
  },
105
105
 
106
+ {
107
+ key: 'bcine',
108
+ label: 'Bcine',
109
+ sourceFile: 'bcine',
110
+ proxyParam: 'bc',
111
+ timeout: 25000,
112
+ jitter: 500,
113
+ retries: 2,
114
+ multiUrl: true,
115
+ cdnHeaders: [{
116
+ pattern: /1embed\.cc|videasy\.to/i,
117
+ headers: {
118
+ Referer: 'https://bcine.ru/',
119
+ Origin: 'https://bcine.ru',
120
+ },
121
+ }],
122
+ },
123
+
106
124
  {
107
125
  key: 'cinejoy',
108
126
  label: 'Cinejoy',
@@ -115,6 +133,46 @@ export const SOURCES = [
115
133
  skipProxy: true,
116
134
  },
117
135
 
136
+ {
137
+ key: 'cinesrc',
138
+ label: 'CineSrc',
139
+ sourceFile: 'cinesrc',
140
+ proxyParam: 'csr',
141
+ timeout: 25000,
142
+ jitter: 500,
143
+ retries: 2,
144
+ multiUrl: true,
145
+ skipProxy: true,
146
+ skipVerify: true,
147
+ cdnHeaders: [{
148
+ pattern: /glendale-plumbing\.com|1embed\.cc|bright\d+\.online/i,
149
+ headers: {
150
+ Referer: 'https://cinesrc.st/',
151
+ Origin: 'https://cinesrc.st',
152
+ },
153
+ }],
154
+ },
155
+
156
+ {
157
+ key: 'cinesu',
158
+ label: 'CineSu',
159
+ sourceFile: 'cinesu',
160
+ proxyParam: 'cs',
161
+ timeout: 25000,
162
+ jitter: 500,
163
+ retries: 2,
164
+ multiUrl: true,
165
+ skipProxy: true,
166
+ skipVerify: true,
167
+ cdnHeaders: [{
168
+ pattern: /glendale-plumbing\.com/i,
169
+ headers: {
170
+ Referer: 'https://cine.su/',
171
+ Origin: 'https://cine.su',
172
+ },
173
+ }],
174
+ },
175
+
118
176
  {
119
177
  key: 'flaxmovies',
120
178
  label: 'FlaxMovies',
@@ -302,7 +360,18 @@ export const SOURCES = [
302
360
  skipProxy: true,
303
361
  disabled: false, // Enabled, but only returns streams when a manifest is provided
304
362
  },
305
-
363
+
364
+ {
365
+ key: 'pstream',
366
+ label: 'PStream',
367
+ sourceFile: 'pstream',
368
+ proxyParam: 'ps',
369
+ timeout: 35000,
370
+ jitter: 500,
371
+ retries: 1,
372
+ multiUrl: true,
373
+ },
374
+
306
375
  {
307
376
  key: 'nova',
308
377
  label: 'Nova',
@@ -313,7 +382,7 @@ export const SOURCES = [
313
382
  retries: 1,
314
383
  multiUrl: true,
315
384
  },
316
-
385
+
317
386
  {
318
387
  key: 'megasource',
319
388
  label: 'MegaSource',
@@ -456,19 +525,6 @@ export const SOURCES = [
456
525
  skipProxy: true,
457
526
  },
458
527
 
459
- {
460
- key: 'vidrift',
461
- label: 'VidRift',
462
- sourceFile: 'vidrift',
463
- proxyParam: 'vr',
464
- timeout: 20000,
465
- jitter: 500,
466
- retries: 2,
467
- multiUrl: true,
468
- skipProxy: true,
469
- disabled: true, // Temporarily disabled because their site is down, embed website does not load
470
- },
471
-
472
528
  {
473
529
  key: 'vidrock',
474
530
  label: 'VidRock',
@@ -489,17 +545,6 @@ export const SOURCES = [
489
545
  },],
490
546
  },
491
547
 
492
- {
493
- key: 'vidsync',
494
- label: 'VidSync',
495
- sourceFile: 'vidsync',
496
- proxyParam: 'vs',
497
- timeout: 20000,
498
- retries: 2,
499
- multiUrl: true,
500
- disabled: true, // Temporarily disabled due to enc dec issues
501
- },
502
-
503
548
  {
504
549
  key: 'vidup',
505
550
  label: 'VidUp',
@@ -568,6 +613,17 @@ export const SOURCES = [
568
613
  skipProxy: true,
569
614
  },
570
615
 
616
+ {
617
+ key: 'zxcstream',
618
+ label: 'ZxcStream',
619
+ sourceFile: 'zxcstream',
620
+ proxyParam: 'zxc',
621
+ timeout: 25000,
622
+ jitter: 500,
623
+ retries: 2,
624
+ multiUrl: true,
625
+ },
626
+
571
627
  ];
572
628
 
573
629
  export const HEALTH_PROBE_ID = '155';
@@ -0,0 +1,202 @@
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
+ const CORS_PROXY = 'https://eve.pstream.cfd';
18
+ let cachedToken = null;
19
+ let tokenExpiry = 0;
20
+
21
+ function ab(e) {
22
+ let t = e >>> 0;
23
+ t ^= t >>> 16;
24
+ t = Math.imul(t, 2146121005) >>> 0;
25
+ t ^= t >>> 15;
26
+ t = Math.imul(t, 2221713035) >>> 0;
27
+ return (t ^ (t >>> 16)) >>> 0;
28
+ }
29
+
30
+ function sD(e) {
31
+ const t = new TextEncoder().encode(aD);
32
+ const r = Math.max(32, Math.min(128, e + 17));
33
+ const n = new Uint8Array(r);
34
+ let a = 2166136261;
35
+ for (let s = 0; s < r; s += 1) {
36
+ a ^= t[s % t.length] ?? s;
37
+ a = ab((a + Ls[s % Ls.length] + ((2654435761 * s) >>> 0)) >>> 0);
38
+ n[s] = a & 255;
39
+ }
40
+ return n;
41
+ }
42
+
43
+ function iD(e) {
44
+ let t = '';
45
+ for (let r = 0; r < e.length; r += 3) {
46
+ const n = e[r];
47
+ const a = e[r + 1];
48
+ const s = e[r + 2];
49
+ t += wa[n >>> 2];
50
+ t += wa[((3 & n) << 4) | ((a ?? 0) >>> 4)];
51
+ if (a === undefined) break;
52
+ t += wa[((15 & a) << 2) | ((s ?? 0) >>> 6)];
53
+ if (s === undefined) break;
54
+ t += wa[63 & s];
55
+ }
56
+ return t;
57
+ }
58
+
59
+ function generateDirectHlsUrl(id, s, e) {
60
+ const isTv = s != null && e != null;
61
+ const tmdbId = Math.floor(Number(id));
62
+ const season = isTv ? Math.floor(Number(s || 1)) : 0;
63
+ const episode = isTv ? Math.floor(Number(e || 1)) : 0;
64
+
65
+ const str = `${nD}:${isTv ? 's' : 'm'}:${tmdbId}:${season}:${episode}`;
66
+ const a = new TextEncoder().encode(str);
67
+ const sArr = sD(a.length);
68
+ const i = new Uint8Array(a.length + 2);
69
+ i[0] = a.length & 255;
70
+ i[1] = (a.length >>> 8) & 255;
71
+ let o = (2654435769 ^ a.length) >>> 0;
72
+ for (let l = 0; l < a.length; l += 1) {
73
+ o = ab((o + sArr[l % sArr.length] + Ls[l % Ls.length] + l) >>> 0);
74
+ i[l + 2] = (a[l] ^ (255 & o)) ^ sArr[(7 * l + 3) % sArr.length];
75
+ }
76
+
77
+ return `https://glendale-plumbing.com/c/v1/${iD(i)}/master.m3u8`;
78
+ }
79
+
80
+ async function fetchInternalToken() {
81
+ if (cachedToken && Date.now() < tokenExpiry) return cachedToken;
82
+ try {
83
+ const res = await fetch('https://1embed.cc/api/token', {
84
+ headers: {
85
+ 'User-Agent': USER_AGENT,
86
+ 'Referer': 'https://1embed.cc/',
87
+ 'Accept': 'application/json, text/plain, */*'
88
+ },
89
+ signal: AbortSignal.timeout(4000)
90
+ });
91
+ if (res.ok) {
92
+ const data = await res.json();
93
+ if (data?.token) {
94
+ cachedToken = data.token;
95
+ tokenExpiry = Date.now() + 1800 * 1000;
96
+ return cachedToken;
97
+ }
98
+ }
99
+ } catch { }
100
+
101
+ try {
102
+ const proxiedUrl = `${CORS_PROXY}/?destination=${encodeURIComponent('https://1embed.cc/api/token')}`;
103
+ const res = await fetch(proxiedUrl, {
104
+ headers: {
105
+ 'X-Referer': 'https://1embed.cc/',
106
+ 'X-User-Agent': USER_AGENT
107
+ },
108
+ signal: AbortSignal.timeout(4000)
109
+ });
110
+ if (res.ok) {
111
+ const data = await res.json();
112
+ if (data?.token) {
113
+ cachedToken = data.token;
114
+ tokenExpiry = Date.now() + 1800 * 1000;
115
+ return cachedToken;
116
+ }
117
+ }
118
+ } catch { }
119
+
120
+ return '';
121
+ }
122
+
123
+ export async function getStream(args) {
124
+ const { id, s, e, clientIP } = args;
125
+ const isTv = s != null && e != null;
126
+ const isMovie = !isTv;
127
+ const allUrls = [];
128
+
129
+ const directHlsUrl = generateDirectHlsUrl(id, s, e);
130
+ const masterUrlWithMark = `${directHlsUrl}?${_vParam}`;
131
+
132
+ allUrls.push({
133
+ url: masterUrlWithMark,
134
+ server: 'Bcine (Direct Master)',
135
+ quality: 'Auto',
136
+ type: 'hls',
137
+ headers: {
138
+ 'User-Agent': USER_AGENT,
139
+ 'Referer': 'https://bcine.ru/',
140
+ 'Origin': 'https://bcine.ru',
141
+ ...(clientIP && { 'X-Forwarded-For': clientIP })
142
+ }
143
+ });
144
+
145
+ const token = await fetchInternalToken();
146
+
147
+ await Promise.allSettled(
148
+ SERVERS.map(async (server) => {
149
+ const query = isTv
150
+ ? `id=${id}?type=tv&s=${s || 1}&e=${e || 1}`
151
+ : `id=${id}?type=movie`;
152
+
153
+ const stParam = token ? `&_st=${token}` : '';
154
+ const targetUrl = `https://1embed.cc${server.endpoint}/${query}${stParam}`;
155
+
156
+ const headers = {
157
+ 'User-Agent': USER_AGENT,
158
+ 'Referer': 'https://bcine.ru/',
159
+ 'Accept': 'application/json, text/plain, */*',
160
+ ...(token && { 'X-Stream-Token': token }),
161
+ ...(clientIP && { 'X-Forwarded-For': clientIP })
162
+ };
163
+
164
+ let res = await fetch(targetUrl, { headers, signal: AbortSignal.timeout(5000) }).catch(() => null);
165
+ if (!res || !res.ok) {
166
+ const proxiedUrl = `${CORS_PROXY}/?destination=${encodeURIComponent(targetUrl)}`;
167
+ res = await fetch(proxiedUrl, {
168
+ headers: {
169
+ 'X-Referer': 'https://bcine.ru/',
170
+ 'X-User-Agent': USER_AGENT
171
+ },
172
+ signal: AbortSignal.timeout(5000)
173
+ }).catch(() => null);
174
+ }
175
+
176
+ if (res && res.ok) {
177
+ try {
178
+ const data = await res.json();
179
+ if (data && data.success !== false) {
180
+ const streamUrl = data.streams?.proxy_m3u8 || data.streams?.raw_m3u8 || data.streams?.m3u8 || data.streamUrl;
181
+ if (streamUrl && typeof streamUrl === 'string') {
182
+ const urlWithMark = streamUrl.includes('?') ? `${streamUrl}&${_vParam}` : `${streamUrl}?${_vParam}`;
183
+ allUrls.push({
184
+ url: urlWithMark,
185
+ server: `Bcine (${data.selectedSource || data.provider || server.id})`,
186
+ quality: 'Auto',
187
+ type: streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
188
+ headers: {
189
+ 'User-Agent': USER_AGENT,
190
+ 'Referer': 'https://bcine.ru/',
191
+ 'Origin': 'https://bcine.ru'
192
+ }
193
+ });
194
+ }
195
+ }
196
+ } catch { }
197
+ }
198
+ })
199
+ );
200
+
201
+ return allUrls.length ? { allUrls } : null;
202
+ }
@@ -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,68 @@
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;
68
+ }
@@ -0,0 +1,141 @@
1
+ import crypto from 'crypto';
2
+ import { getTmdbInfo, getUA } from '../utils/helpers.js';
3
+
4
+ const BASE_URL = 'https://player.zxcstream.xyz';
5
+ const AES_KEY = '7f4c9e2a81d63b05c4f7a9e8126d3b50e1a8c7f23d9465ab0c6e9f1d4a7b832c';
6
+ const SERVERS = ['berkas', 'orion', 'aquarius', 'resshin'];
7
+
8
+ function decryptCryptoJS(ciphertextB64, passphrase) {
9
+ try {
10
+ const buf = Buffer.from(ciphertextB64, 'base64');
11
+ if (buf.slice(0, 8).toString('utf8') !== 'Salted__') {
12
+ const key = crypto.createHash('md5').update(passphrase).digest();
13
+ const iv = Buffer.alloc(16, 0);
14
+ const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
15
+ return Buffer.concat([decipher.update(buf), decipher.final()]).toString('utf8');
16
+ }
17
+
18
+ const salt = buf.slice(8, 16);
19
+ const cipherBytes = buf.slice(16);
20
+
21
+ let hash = Buffer.alloc(0);
22
+ let keyAndIv = Buffer.alloc(0);
23
+ while (keyAndIv.length < 48) {
24
+ hash = crypto.createHash('md5').update(Buffer.concat([hash, Buffer.from(passphrase), salt])).digest();
25
+ keyAndIv = Buffer.concat([keyAndIv, hash]);
26
+ }
27
+
28
+ const key = keyAndIv.slice(0, 32);
29
+ const iv = keyAndIv.slice(32, 48);
30
+
31
+ const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
32
+ return Buffer.concat([decipher.update(cipherBytes), decipher.final()]).toString('utf8');
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ export async function getStream({ id, s, e }) {
39
+ try {
40
+ const isTv = Boolean(s && e);
41
+ const mediaType = isTv ? 'tv' : 'movie';
42
+
43
+ let title = 'Media';
44
+ let year = '2024';
45
+
46
+ try {
47
+ const info = await getTmdbInfo(id, mediaType, s);
48
+ if (info?.title) title = info.title;
49
+ if (info?.year) year = String(info.year);
50
+ } catch { }
51
+
52
+ const headers = {
53
+ 'User-Agent': getUA(),
54
+ Referer: `${BASE_URL}/`,
55
+ Origin: BASE_URL,
56
+ Accept: 'application/json, text/plain, */*',
57
+ };
58
+
59
+ const serverResults = await Promise.all(
60
+ SERVERS.map(async (server) => {
61
+ try {
62
+ const tokenRes = await fetch(`${BASE_URL}/backend/you-are-gay`, {
63
+ method: 'POST',
64
+ headers: { ...headers, 'Content-Type': 'application/json' },
65
+ body: JSON.stringify({
66
+ id,
67
+ media_type: mediaType,
68
+ path: server,
69
+ ...(isTv ? { season: Number(s || 1), episode: Number(e || 1) } : {}),
70
+ }),
71
+ signal: AbortSignal.timeout(8000),
72
+ });
73
+
74
+ if (!tokenRes.ok) return [];
75
+ const tokenData = await tokenRes.json();
76
+ if (!tokenData?.token) return [];
77
+
78
+ const params = new URLSearchParams({
79
+ id,
80
+ b: mediaType,
81
+ ts: String(tokenData.ts),
82
+ token: tokenData.token,
83
+ title,
84
+ year,
85
+ date: year,
86
+ });
87
+
88
+ if (isTv) {
89
+ params.append('season', String(s || 1));
90
+ params.append('episode', String(e || 1));
91
+ }
92
+
93
+ const sourcesRes = await fetch(`${BASE_URL}/backend_/sources/${server}?${params.toString()}`, {
94
+ headers,
95
+ signal: AbortSignal.timeout(8000),
96
+ });
97
+
98
+ if (!sourcesRes.ok) return [];
99
+ const sourcesData = await sourcesRes.json();
100
+
101
+ const links = [];
102
+ if (Array.isArray(sourcesData?.links)) {
103
+ for (const item of sourcesData.links) {
104
+ if (!item.link) continue;
105
+ const decryptedUrl = decryptCryptoJS(item.link, AES_KEY);
106
+ if (decryptedUrl && decryptedUrl.startsWith('http')) {
107
+ links.push({
108
+ url: decryptedUrl,
109
+ type: decryptedUrl.includes('.m3u8') ? 'hls' : decryptedUrl.includes('.mpd') ? 'dash' : 'mp4',
110
+ quality: item.resolution || 'Auto',
111
+ server: `ZxcStream-${server.toUpperCase()}`,
112
+ headers: {
113
+ Referer: `${BASE_URL}/`,
114
+ Origin: BASE_URL,
115
+ },
116
+ skipProxy: true,
117
+ });
118
+ }
119
+ }
120
+ }
121
+
122
+ return links;
123
+ } catch {
124
+ return [];
125
+ }
126
+ })
127
+ );
128
+
129
+ const allUrls = serverResults.flat();
130
+ if (!allUrls.length) return null;
131
+
132
+ return { allUrls };
133
+ } catch {
134
+ return null;
135
+ }
136
+ }
137
+
138
+ export async function getSources(args) {
139
+ const stream = await getStream(args);
140
+ return stream?.allUrls ? [...new Set(stream.allUrls.map(u => u.server))] : [];
141
+ }
@@ -1,95 +0,0 @@
1
- 'use strict';
2
-
3
- const BASE = "https://embed.vidrift.in";
4
-
5
- const DEFAULT_HEADERS = {
6
- "Accept": "*/*",
7
- "Accept-Language": "en-US,en;q=0.9",
8
- "Cache-Control": "no-cache",
9
- "Pragma": "no-cache",
10
- "Referer": `${BASE}/`,
11
- "Origin": BASE,
12
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36 Edg/150.0.0.0"
13
- };
14
-
15
- function decodeStreams(encodedStr) {
16
- try {
17
- const base64Str = encodedStr.replace(/-/g, '+').replace(/_/g, '/');
18
-
19
- const binaryStr = typeof atob === 'function'
20
- ? atob(base64Str)
21
- : Buffer.from(base64Str, 'base64').toString('binary');
22
-
23
- const bytes = new Uint8Array(binaryStr.length);
24
- for (let i = 0; i < binaryStr.length; i++) {
25
- bytes[i] = binaryStr.charCodeAt(i);
26
- }
27
-
28
- const key = bytes[0];
29
- let decodedStr = '';
30
- for (let i = 1; i < bytes.length; i++) {
31
- decodedStr += String.fromCharCode(bytes[i] ^ key);
32
- }
33
-
34
- return JSON.parse(decodedStr);
35
- } catch (e) {
36
- return [];
37
- }
38
- }
39
-
40
- export async function getStream(args) {
41
- const { id, s, e, server: serverName } = args;
42
- const type = s != null && e != null ? "tv" : "movie";
43
-
44
- const endpoint = type === "tv"
45
- ? `${BASE}/embed/tv/${id}/${s}/${e}`
46
- : `${BASE}/embed/movie/${id}`;
47
-
48
- try {
49
- const res = await fetch(endpoint, {
50
- headers: {
51
- ...DEFAULT_HEADERS,
52
- "Accept": "text/html",
53
- },
54
- signal: AbortSignal.timeout(10000)
55
- });
56
-
57
- if (!res.ok) return null;
58
-
59
- const html = await res.text();
60
-
61
- const match = html.match(/var\s+_s\s*=\s*['"]([^'"]+)['"]/);
62
- if (!match) return null;
63
-
64
- const encodedStreams = match[1];
65
- const streamsData = decodeStreams(encodedStreams);
66
-
67
- if (!Array.isArray(streamsData) || !streamsData.length) {
68
- return null;
69
- }
70
-
71
- const allUrls = streamsData.map((stream, index) => ({
72
- url: stream.url.startsWith("http")
73
- ? stream.url
74
- : `${BASE}${stream.url}`,
75
- server: stream.label || `VidRift - Server ${index + 1}`,
76
- type: "hls",
77
- headers: DEFAULT_HEADERS
78
- }));
79
-
80
- if (serverName && serverName !== "all") {
81
- const filtered = allUrls.filter(x => x.server === serverName);
82
- return filtered.length ? { allUrls: filtered } : null;
83
- }
84
-
85
- return { allUrls };
86
- } catch (err) {
87
- return null;
88
- }
89
- }
90
-
91
- export async function getSources(args) {
92
- const res = await getStream(args);
93
- if (!res?.allUrls) return ["VidRift - Server 1"];
94
- return res.allUrls.map(x => x.server);
95
- }
@@ -1,38 +0,0 @@
1
- import { fetchJson, fetchText, USER_AGENT, getTmdbInfo } from '../utils/helpers.js';
2
-
3
- const API_BASE = "https://enc-dec.app/api";
4
- const DOMAIN = "https://vidsync.xyz";
5
- const HEADERS = { "Accept": "*/*", "Origin": DOMAIN, "Referer": `${DOMAIN}/`, "User-Agent": USER_AGENT, "X-Requested-With": "XMLHttpRequest" };
6
- const SERVERS = ["cinevault", "cinedub", "cinebox", "cineflix", "cinevip", "cinecloud", "cine4k"];
7
-
8
- export async function getStream({ id, s, e, server }) {
9
- try {
10
- const isTv = s != null && e != null;
11
- const type = isTv ? 'tv' : 'movie';
12
- const info = await getTmdbInfo(id, type);
13
- if (!info?.titles?.length) return null;
14
- const turnstileJson = await fetchJson(`${API_BASE}/enc-vidsync`, { signal: AbortSignal.timeout(5000) });
15
- if (turnstileJson.status !== 200 || !turnstileJson.result?.token) return null;
16
- const turnstileToken = turnstileJson.result.token;
17
- let targets = SERVERS;
18
- if (server && server !== 'all') {
19
- const clean = server.replace('VidSync - ', '');
20
- targets = SERVERS.includes(clean) ? [clean] : SERVERS;
21
- }
22
- const encTitle = encodeURIComponent(info.titles[0]).replace(/%20/g, '+');
23
- const results = await Promise.allSettled(targets.map(async srv => {
24
- let url = `${DOMAIN}/api/stream/fetch?title=${encTitle}&type=${type}&releaseYear=${info.year}&mediaId=${id}&serverName=${srv}`;
25
- if (isTv) url += `&season=${s}&episode=${e}`;
26
- const encryptedText = await fetchText(url, { headers: { ...HEADERS, "X-Cf-Turnstile": turnstileToken }, signal: AbortSignal.timeout(10000) });
27
- const decJson = await fetchJson(`${API_BASE}/dec-vidsync`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: encryptedText, id: String(id) }), signal: AbortSignal.timeout(10000) });
28
- if (decJson.status !== 200 || !decJson.result) throw new Error();
29
- const streams = Array.isArray(decJson.result) ? decJson.result : [decJson.result];
30
- return streams.map(st => ({ url: st.url || st.file, server: `VidSync - ${srv}`, quality: st.quality || "Auto", type: (st.url || st.file || "").includes(".m3u8") ? "hls" : "mp4", headers: { ...HEADERS, "Origin": DOMAIN }, skipProxy: false, skipVerify: true, skipHlsCheck: true }));
31
- }));
32
- const allUrls = [];
33
- for (const r of results) if (r.status === 'fulfilled') allUrls.push(...r.value);
34
- return allUrls.length ? { allUrls } : null;
35
- } catch { return null; }
36
- }
37
-
38
- export async function getSources() { return SERVERS.map(s => `VidSync - ${s}`); }