@vyla-entertainment/sdk 1.20.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +3 -2
  2. package/src/config.js +99 -67
  3. package/src/health.js +60 -20
  4. package/src/sdk.d.ts +94 -121
  5. package/src/sdk.js +82 -78
  6. package/src/sources/111477.js +88 -100
  7. package/src/sources/123anime.js +120 -56
  8. package/src/sources/3eyedraven.js +82 -135
  9. package/src/sources/4movies.js +77 -0
  10. package/src/sources/aether.js +99 -0
  11. package/src/sources/castle.js +415 -0
  12. package/src/sources/cinecat.js +37 -18
  13. package/src/sources/cinemaarmy.js +179 -180
  14. package/src/sources/cinesrc.js +401 -397
  15. package/src/sources/cno.js +101 -94
  16. package/src/sources/dulo.js +134 -149
  17. package/src/sources/flaxmovies.js +114 -105
  18. package/src/sources/framextv.js +126 -0
  19. package/src/sources/frost.js +38 -29
  20. package/src/sources/fsonline.js +95 -47
  21. package/src/sources/hdhub.js +43 -36
  22. package/src/sources/hexa.js +60 -53
  23. package/src/sources/hyper.js +42 -35
  24. package/src/sources/kickassanime.js +117 -124
  25. package/src/sources/kisskh.js +114 -59
  26. package/src/sources/lmscript.js +72 -70
  27. package/src/sources/lookmovie.js +80 -79
  28. package/src/sources/meowtv.js +140 -0
  29. package/src/sources/movenerds.js +74 -124
  30. package/src/sources/movy.js +197 -209
  31. package/src/sources/net79.js +59 -55
  32. package/src/sources/peestream.js +126 -138
  33. package/src/sources/pengu.js +46 -49
  34. package/src/sources/pstream.js +73 -67
  35. package/src/sources/purstream.js +96 -104
  36. package/src/sources/rivestream.js +182 -176
  37. package/src/sources/rivo.js +58 -53
  38. package/src/sources/streamaggregator.js +114 -128
  39. package/src/sources/thugtv.js +70 -62
  40. package/src/sources/vidapi.js +122 -114
  41. package/src/sources/vidcore.js +14 -122
  42. package/src/sources/vidfast.js +14 -122
  43. package/src/sources/vidlink.js +78 -27
  44. package/src/sources/vidora.js +74 -42
  45. package/src/sources/vidup.js +14 -122
  46. package/src/sources/vidvault.js +133 -187
  47. package/src/sources/vidy.js +192 -187
  48. package/src/sources/vidzee.js +189 -183
  49. package/src/sources/vixsrc.js +123 -113
  50. package/src/sources/watchout.js +60 -46
  51. package/src/sources/xdownloader.js +127 -128
  52. package/src/sources/yapgrid.js +68 -62
  53. package/src/sources/yastream.js +35 -29
  54. package/src/subtitles.js +105 -122
  55. package/src/utils/helpers.js +586 -247
  56. package/src/sources/bcine.js +0 -202
  57. package/src/sources/cinezo.js +0 -55
  58. package/src/sources/vidrock.js +0 -145
@@ -1,104 +1,96 @@
1
- import { fetchJson, USER_AGENT, getTmdbInfo } from '../utils/helpers.js';
2
-
3
- const DOMAIN = 'https://purstream.ad';
4
- const API_BASE = 'https://api.purstream.ad/api/v1';
5
-
6
- const HEADERS = {
7
- 'User-Agent': USER_AGENT,
8
- 'Accept': 'application/json, text/plain, */*',
9
- 'Referer': `${DOMAIN}/`,
10
- 'Origin': DOMAIN,
11
- 'X-Requested-With': 'XMLHttpRequest',
12
- 'Sec-Fetch-Dest': 'empty',
13
- 'Sec-Fetch-Mode': 'cors',
14
- 'Sec-Fetch-Site': 'same-site'
15
- };
16
-
17
- export async function getStream({ id, s, e }) {
18
- try {
19
- const isTv = s != null;
20
-
21
- const info = await getTmdbInfo(id, isTv ? 'tv' : 'movie');
22
-
23
-
24
- if (!info?.titles?.length) {
25
- return null;
26
- }
27
-
28
- const title = info.titles[0];
29
-
30
- const searchUrl = `${API_BASE}/search-bar/search/${encodeURIComponent(title)}`;
31
-
32
- const searchData = await fetchJson(searchUrl, {
33
- headers: HEADERS,
34
- signal: AbortSignal.timeout(10000)
35
- });
36
-
37
- const items = searchData?.data?.items?.movies?.items || [];
38
-
39
- const type = isTv ? 'tv' : 'movie';
40
- const lowerTitle = title.toLowerCase();
41
-
42
- let match = items.find(item =>
43
- item.type === type &&
44
- item.title?.toLowerCase() === lowerTitle &&
45
- (!info.year || item.release_date?.startsWith(String(info.year)))
46
- );
47
-
48
- if (!match) {
49
- match = items.find(item => item.type === type);
50
- }
51
-
52
- if (!match?.id) {
53
- return null;
54
- }
55
-
56
- const streamUrl = isTv
57
- ? `${API_BASE}/stream/${match.id}/episode?season=${s}&episode=${e}`
58
- : `${API_BASE}/stream/${match.id}`;
59
-
60
- const json = await fetchJson(streamUrl, {
61
- headers: HEADERS,
62
- signal: AbortSignal.timeout(10000)
63
- });
64
-
65
- const sources = json?.data?.items?.sources;
66
-
67
- if (json?.type !== 'success' || !Array.isArray(sources) || !sources.length) {
68
- return null;
69
- }
70
-
71
- const chosen = sources.find(src => src.stream_url);
72
-
73
- if (!chosen?.stream_url) {
74
- return null;
75
- }
76
-
77
- const result = {
78
- url: chosen.stream_url,
79
- headers: {
80
- 'User-Agent': USER_AGENT,
81
- 'Referer': `${DOMAIN}/`
82
- },
83
- server: 'purstream',
84
- quality: chosen.source_name || 'Auto',
85
- type: chosen.format || 'hls',
86
- skipProxy: true
87
- };
88
-
89
- return result;
90
-
91
- } catch (err) {
92
- return null;
93
- }
94
- }
95
-
96
- export async function getSources(args) {
97
- const stream = await getStream(args);
98
-
99
- return stream ? [stream] : [];
100
- }
101
-
102
- export const VERIFY_HEADERS = {
103
- ...HEADERS
104
- };
1
+ import { fetchJson, getTmdbMetadata, resolveTmdbKey, USER_AGENT } from '../utils/helpers.js';
2
+
3
+ const DOMAIN = 'https://purstream.ad';
4
+ const API_BASE = 'https://api.purstream.ad/api/v1';
5
+
6
+ const HEADERS = {
7
+ 'User-Agent': USER_AGENT,
8
+ Accept: 'application/json, text/plain, */*',
9
+ Referer: `${DOMAIN}/`,
10
+ Origin: DOMAIN,
11
+ 'X-Requested-With': 'XMLHttpRequest',
12
+ 'Sec-Fetch-Dest': 'empty',
13
+ 'Sec-Fetch-Mode': 'cors',
14
+ 'Sec-Fetch-Site': 'same-site',
15
+ };
16
+
17
+ export async function getStream(args) {
18
+ const { id, s, e, sdk } = args || {};
19
+ const isTv = s != null && e != null;
20
+ const type = isTv ? 'tv' : 'movie';
21
+ const apiKey = resolveTmdbKey(args, sdk);
22
+
23
+ try {
24
+ const meta = await getTmdbMetadata(id, isTv, apiKey);
25
+ if (!meta?.titles?.length) return null;
26
+
27
+ const title = meta.titles[0];
28
+ const searchUrl = `${API_BASE}/search-bar/search/${encodeURIComponent(title)}`;
29
+
30
+ const searchData = await fetchJson(searchUrl, {
31
+ headers: HEADERS,
32
+ signal: AbortSignal.timeout(10000),
33
+ });
34
+
35
+ const items = searchData?.data?.items?.movies?.items || [];
36
+ const lowerTitle = title.toLowerCase();
37
+
38
+ let match = items.find(item =>
39
+ item.type === type &&
40
+ item.title?.toLowerCase() === lowerTitle &&
41
+ (!meta.year || item.release_date?.startsWith(String(meta.year)))
42
+ );
43
+
44
+ if (!match) {
45
+ match = items.find(item => item.type === type);
46
+ }
47
+
48
+ if (!match?.id) return null;
49
+
50
+ const streamUrl = isTv
51
+ ? `${API_BASE}/stream/${match.id}/episode?season=${s}&episode=${e}`
52
+ : `${API_BASE}/stream/${match.id}`;
53
+
54
+ const json = await fetchJson(streamUrl, {
55
+ headers: HEADERS,
56
+ signal: AbortSignal.timeout(10000),
57
+ });
58
+
59
+ const sources = json?.data?.items?.sources;
60
+ if (json?.type !== 'success' || !Array.isArray(sources) || !sources.length) return null;
61
+
62
+ const chosen = sources.find(src => src.stream_url);
63
+ if (!chosen?.stream_url) return null;
64
+
65
+ const streamHeaders = {
66
+ 'User-Agent': USER_AGENT,
67
+ Referer: `${DOMAIN}/`,
68
+ };
69
+
70
+ const allUrls = [{
71
+ url: chosen.stream_url,
72
+ headers: streamHeaders,
73
+ server: 'purstream',
74
+ quality: chosen.source_name || 'Auto',
75
+ type: chosen.format || 'hls',
76
+ skipProxy: true,
77
+ }];
78
+
79
+ return {
80
+ url: chosen.stream_url,
81
+ headers: streamHeaders,
82
+ server: 'purstream',
83
+ quality: chosen.source_name || 'Auto',
84
+ type: chosen.format || 'hls',
85
+ skipProxy: true,
86
+ allUrls,
87
+ };
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+
93
+ export async function getSources(args) {
94
+ const stream = await getStream(args);
95
+ return stream?.allUrls ? stream.allUrls.map(u => u.server) : ['purstream'];
96
+ }
@@ -1,177 +1,183 @@
1
- import { USER_AGENT, fetchJson } from '../utils/helpers.js';
2
-
3
- const C_ARRAY = [
4
- '4Z7lUo', 'gwIVSMD', 'PLmz2elE2v', 'Z4OFV0', 'SZ6RZq6Zc', 'zhJEFYxrz8', 'FOm7b0', 'axHS3q4KDq', 'o9zuXQ', '4Aebt',
5
- 'wgjjWwKKx', 'rY4VIxqSN', 'kfjbnSo', '2DyrFA1M', 'YUixDM9B', 'JQvgEj0', 'mcuFx6JIek', 'eoTKe26gL', 'qaI9EVO1rB', '0xl33btZL',
6
- '1fszuAU', 'a7jnHzst6P', 'wQuJkX', 'cBNhTJlEOf', 'KNcFWhDvgT', 'XipDGjST', 'PCZJlbHoyt', '2AYnMZkqd', 'HIpJh', 'KH0C3iztrG',
7
- 'W81hjts92', 'rJhAT', 'NON7LKoMQ', 'NMdY3nsKzI', 't4En5v', 'Qq5cOQ9H', 'Y9nwrp', 'VX5FYVfsf', 'cE5SJG', 'x1vj1',
8
- 'HegbLe', 'zJ3nmt4OA', 'gt7rxW57dq', 'clIE9b', 'jyJ9g', 'B5jXjMCSx', 'cOzZBZTV', 'FTXGy', 'Dfh1q1', 'ny9jqZ2POI',
9
- 'X2NnMn', 'MBtoyD', 'qz4Ilys7wB', '68lbOMye', '3YUJnmxp', '1fv5Imona', 'PlfvvXD7mA', 'ZarKfHCaPR', 'owORnX', 'dQP1YU',
10
- 'dVdkx', 'qgiK0E', 'cx9wQ', '5F9bGa', '7UjkKrp', 'Yvhrj', 'wYXez5Dg3', 'pG4GMU', 'MwMAu', 'rFRD5wlM'
11
- ];
12
-
13
- const DEFAULT_SERVICES = [
14
- 'apex', 'pulse', 'solstice', 'quasar', 'horizon', 'primevids',
15
- 'flowcast', 'asiacloud', 'citadel', 'hindicast', 'guru'
16
- ];
17
-
18
- function generateRiveSecretKey(e) {
19
- if (e === undefined || e === null) return 'rive';
20
- try {
21
- let t, n;
22
- const r = String(e);
23
- if (isNaN(Number(e))) {
24
- const sum = r.split('').reduce((acc, ch) => acc + ch.charCodeAt(0), 0);
25
- t = C_ARRAY[sum % C_ARRAY.length] || Buffer.from(r).toString('base64');
26
- n = Math.floor((sum % r.length) / 2);
27
- } else {
28
- const i = Number(e);
29
- t = C_ARRAY[i % C_ARRAY.length] || Buffer.from(r).toString('base64');
30
- n = Math.floor((i % r.length) / 2);
31
- }
32
- const i = r.slice(0, n) + t + r.slice(n);
33
- const o = (function (str) {
34
- const t = String(str);
35
- let n = 3735928559 ^ t.length;
36
- for (let e = 0; e < t.length; e++) {
37
- const r = t.charCodeAt(e);
38
- const rXor = (131 * e + 89 ^ (r << (e % 5))) & 255;
39
- const r2 = r ^ rXor;
40
- n = (((n << 7) | (n >>> 25)) >>> 0) ^ r2;
41
- const idx = (65535 & n) * 60205;
42
- const o2 = ((n >>> 16) * 60205) << 16;
43
- n = (idx + o2) >>> 0;
44
- n ^= n >>> 11;
45
- }
46
- n ^= n >>> 15;
47
- n = ((65535 & n) * 49842 + (((n >>> 16) * 49842) << 16)) >>> 0;
48
- n ^= n >>> 13;
49
- n = ((65535 & n) * 40503 + (((n >>> 16) * 40503) << 16)) >>> 0;
50
- n ^= n >>> 16;
51
- n = ((65535 & n) * 10196 + (((n >>> 16) * 10196) << 16)) >>> 0;
52
- return ((n ^= n >>> 15)).toString(16).padStart(8, '0');
53
- })(
54
- (function (str) {
55
- const s = String(str);
56
- let t = 0;
57
- for (let n = 0; n < s.length; n++) {
58
- const r = s.charCodeAt(n);
59
- const i = (((t = (r + (t << 6) + (t << 16) - t) >>> 0) << (n % 5)) | (t >>> (32 - (n % 5)))) >>> 0;
60
- t ^= (i ^ ((r << (n % 7)) | (r >>> (8 - (n % 7))))) >>> 0;
61
- t = (t + ((t >>> 11) ^ (t << 3))) >>> 0;
62
- }
63
- t ^= t >>> 15;
64
- t = ((65535 & t) * 49842 + ((((t >>> 16) * 49842) & 65535) << 16)) >>> 0;
65
- t ^= t >>> 13;
66
- t = ((65535 & t) * 40503 + ((((t >>> 16) * 40503) & 65535) << 16)) >>> 0;
67
- return ((t ^= t >>> 16)).toString(16).padStart(8, '0');
68
- })(i)
69
- );
70
- return Buffer.from(o, 'utf-8').toString('base64');
71
- } catch {
72
- return 'topSecret';
73
- }
74
- }
75
-
76
- async function fetchRiveServices() {
77
- try {
78
- const secretKey = generateRiveSecretKey();
79
- const url = `https://www.rivestream.app/api/backendfetch?requestID=VideoProviderServices&secretKey=${encodeURIComponent(secretKey)}`;
80
- const res = await fetchJson(url, {
81
- headers: {
82
- 'User-Agent': USER_AGENT,
83
- 'Referer': 'https://www.rivestream.app/',
84
- 'Accept': 'application/json, text/plain, */*'
85
- },
86
- signal: AbortSignal.timeout(6000)
87
- });
88
- return Array.isArray(res?.data) && res.data.length ? res.data : DEFAULT_SERVICES;
89
- } catch {
90
- return DEFAULT_SERVICES;
91
- }
92
- }
93
-
94
- async function fetchServiceStreams(service, isMovie, id, s, e, secretKey, referer) {
95
- try {
96
- const cb = (service === 'primevids' || service === 'citadel')
97
- ? `&cb=${Math.floor(Date.now() / 3e6)}`
98
- : '';
99
-
100
- const reqID = isMovie ? 'movieVideoProvider' : 'tvVideoProvider';
101
- const params = isMovie
102
- ? `requestID=${reqID}&id=${encodeURIComponent(id)}&service=${service}${cb}&secretKey=${encodeURIComponent(secretKey)}`
103
- : `requestID=${reqID}&id=${encodeURIComponent(id)}&season=${encodeURIComponent(s)}&episode=${encodeURIComponent(e)}&service=${service}${cb}&secretKey=${encodeURIComponent(secretKey)}`;
104
-
105
- const url = `https://www.rivestream.app/api/backendfetch?${params}`;
106
- const res = await fetchJson(url, {
107
- headers: {
108
- 'User-Agent': USER_AGENT,
109
- 'Referer': referer,
110
- 'Accept': 'application/json, text/plain, */*'
111
- },
112
- signal: AbortSignal.timeout(10000)
113
- });
114
-
115
- if (!res?.data?.sources || !Array.isArray(res.data.sources)) return [];
116
-
117
- const streams = [];
118
- for (const item of res.data.sources) {
119
- if (!item || !item.url) continue;
120
-
121
- const format = String(item.format || '').toLowerCase();
122
- const urlStr = String(item.url || '').toLowerCase();
123
- const isM3U8 = format === 'hls' || format === 'm3u8' || urlStr.includes('.m3u8') || urlStr.includes('.txt');
124
-
125
- streams.push({
126
- url: item.url,
127
- server: `Rive (${item.source || service})`,
128
- quality: String(item.quality || 'Auto'),
129
- type: isM3U8 ? 'hls' : 'mp4',
130
- headers: {
131
- 'User-Agent': USER_AGENT,
132
- 'Referer': referer
133
- }
134
- });
135
- }
136
- return streams;
137
- } catch {
138
- return [];
139
- }
140
- }
141
-
142
- export async function getStream(args) {
143
- const { id, s, e, server } = args;
144
- const isTv = s != null && e != null;
145
- const isMovie = !isTv;
146
-
147
- const secretKey = generateRiveSecretKey(id);
148
- const referer = isMovie
149
- ? `https://www.rivestream.app/watch?type=movie&id=${id}`
150
- : `https://www.rivestream.app/watch?type=tv&id=${id}&season=${s}&episode=${e}`;
151
-
152
- let services = await fetchRiveServices();
153
-
154
- if (server && server !== 'all') {
155
- const clean = server.toLowerCase().replace('rive (', '').replace(')', '').replace('rive', '').trim();
156
- services = services.filter(srv => srv.toLowerCase().includes(clean));
157
- if (!services.length) services = await fetchRiveServices();
158
- }
159
-
160
- const settled = await Promise.allSettled(
161
- services.map(srv => fetchServiceStreams(srv, isMovie, id, s, e, secretKey, referer))
162
- );
163
-
164
- const allUrls = [];
165
- for (const r of settled) {
166
- if (r.status === 'fulfilled' && Array.isArray(r.value)) {
167
- allUrls.push(...r.value);
168
- }
169
- }
170
-
171
- return allUrls.length ? { allUrls } : null;
172
- }
173
-
174
- export async function getSources() {
175
- const services = await fetchRiveServices();
176
- return services.map(s => `Rive (${s})`);
1
+ import { fetchJson, USER_AGENT } from '../utils/helpers.js';
2
+
3
+ const C_ARRAY = [
4
+ '4Z7lUo', 'gwIVSMD', 'PLmz2elE2v', 'Z4OFV0', 'SZ6RZq6Zc', 'zhJEFYxrz8', 'FOm7b0', 'axHS3q4KDq', 'o9zuXQ', '4Aebt',
5
+ 'wgjjWwKKx', 'rY4VIxqSN', 'kfjbnSo', '2DyrFA1M', 'YUixDM9B', 'JQvgEj0', 'mcuFx6JIek', 'eoTKe26gL', 'qaI9EVO1rB', '0xl33btZL',
6
+ '1fszuAU', 'a7jnHzst6P', 'wQuJkX', 'cBNhTJlEOf', 'KNcFWhDvgT', 'XipDGjST', 'PCZJlbHoyt', '2AYnMZkqd', 'HIpJh', 'KH0C3iztrG',
7
+ 'W81hjts92', 'rJhAT', 'NON7LKoMQ', 'NMdY3nsKzI', 't4En5v', 'Qq5cOQ9H', 'Y9nwrp', 'VX5FYVfsf', 'cE5SJG', 'x1vj1',
8
+ 'HegbLe', 'zJ3nmt4OA', 'gt7rxW57dq', 'clIE9b', 'jyJ9g', 'B5jXjMCSx', 'cOzZBZTV', 'FTXGy', 'Dfh1q1', 'ny9jqZ2POI',
9
+ 'X2NnMn', 'MBtoyD', 'qz4Ilys7wB', '68lbOMye', '3YUJnmxp', '1fv5Imona', 'PlfvvXD7mA', 'ZarKfHCaPR', 'owORnX', 'dQP1YU',
10
+ 'dVdkx', 'qgiK0E', 'cx9wQ', '5F9bGa', '7UjkKrp', 'Yvhrj', 'wYXez5Dg3', 'pG4GMU', 'MwMAu', 'rFRD5wlM',
11
+ ];
12
+
13
+ const DEFAULT_SERVICES = [
14
+ 'apex', 'pulse', 'solstice', 'quasar', 'horizon', 'primevids',
15
+ 'flowcast', 'asiacloud', 'citadel', 'hindicast', 'guru',
16
+ ];
17
+
18
+ function generateRiveSecretKey(e) {
19
+ if (e === undefined || e === null) return 'rive';
20
+ try {
21
+ let t, n;
22
+ const r = String(e);
23
+ if (isNaN(Number(e))) {
24
+ const sum = r.split('').reduce((acc, ch) => acc + ch.charCodeAt(0), 0);
25
+ t = C_ARRAY[sum % C_ARRAY.length] || Buffer.from(r).toString('base64');
26
+ n = Math.floor((sum % r.length) / 2);
27
+ } else {
28
+ const i = Number(e);
29
+ t = C_ARRAY[i % C_ARRAY.length] || Buffer.from(r).toString('base64');
30
+ n = Math.floor((i % r.length) / 2);
31
+ }
32
+ const i = r.slice(0, n) + t + r.slice(n);
33
+ const o = (function (str) {
34
+ const t = String(str);
35
+ let n = 3735928559 ^ t.length;
36
+ for (let e = 0; e < t.length; e++) {
37
+ const r = t.charCodeAt(e);
38
+ const rXor = (131 * e + 89 ^ (r << (e % 5))) & 255;
39
+ const r2 = r ^ rXor;
40
+ n = (((n << 7) | (n >>> 25)) >>> 0) ^ r2;
41
+ const idx = (65535 & n) * 60205;
42
+ const o2 = ((n >>> 16) * 60205) << 16;
43
+ n = (idx + o2) >>> 0;
44
+ n ^= n >>> 11;
45
+ }
46
+ n ^= n >>> 15;
47
+ n = ((65535 & n) * 49842 + (((n >>> 16) * 49842) << 16)) >>> 0;
48
+ n ^= n >>> 13;
49
+ n = ((65535 & n) * 40503 + (((n >>> 16) * 40503) << 16)) >>> 0;
50
+ n ^= n >>> 16;
51
+ n = ((65535 & n) * 10196 + (((n >>> 16) * 10196) << 16)) >>> 0;
52
+ return ((n ^= n >>> 15)).toString(16).padStart(8, '0');
53
+ })(
54
+ (function (str) {
55
+ const s = String(str);
56
+ let t = 0;
57
+ for (let n = 0; n < s.length; n++) {
58
+ const r = s.charCodeAt(n);
59
+ const i = (((t = (r + (t << 6) + (t << 16) - t) >>> 0) << (n % 5)) | (t >>> (32 - (n % 5)))) >>> 0;
60
+ t ^= (i ^ ((r << (n % 7)) | (r >>> (8 - (n % 7))))) >>> 0;
61
+ t = (t + ((t >>> 11) ^ (t << 3))) >>> 0;
62
+ }
63
+ t ^= t >>> 15;
64
+ t = ((65535 & t) * 49842 + ((((t >>> 16) * 49842) & 65535) << 16)) >>> 0;
65
+ t ^= t >>> 13;
66
+ t = ((65535 & t) * 40503 + ((((t >>> 16) * 40503) & 65535) << 16)) >>> 0;
67
+ return ((t ^= t >>> 16)).toString(16).padStart(8, '0');
68
+ })(i)
69
+ );
70
+ return Buffer.from(o, 'utf-8').toString('base64');
71
+ } catch {
72
+ return 'topSecret';
73
+ }
74
+ }
75
+
76
+ async function fetchRiveServices() {
77
+ try {
78
+ const secretKey = generateRiveSecretKey();
79
+ const url = `https://www.rivestream.app/api/backendfetch?requestID=VideoProviderServices&secretKey=${encodeURIComponent(secretKey)}`;
80
+ const res = await fetchJson(url, {
81
+ headers: {
82
+ 'User-Agent': USER_AGENT,
83
+ Referer: 'https://www.rivestream.app/',
84
+ Accept: 'application/json, text/plain, */*',
85
+ },
86
+ signal: AbortSignal.timeout(6000),
87
+ });
88
+ return Array.isArray(res?.data) && res.data.length ? res.data : DEFAULT_SERVICES;
89
+ } catch {
90
+ return DEFAULT_SERVICES;
91
+ }
92
+ }
93
+
94
+ async function fetchServiceStreams(service, isMovie, id, s, e, secretKey, referer) {
95
+ try {
96
+ const cb = (service === 'primevids' || service === 'citadel')
97
+ ? `&cb=${Math.floor(Date.now() / 3e6)}`
98
+ : '';
99
+
100
+ const reqID = isMovie ? 'movieVideoProvider' : 'tvVideoProvider';
101
+ const params = isMovie
102
+ ? `requestID=${reqID}&id=${encodeURIComponent(id)}&service=${service}${cb}&secretKey=${encodeURIComponent(secretKey)}`
103
+ : `requestID=${reqID}&id=${encodeURIComponent(id)}&season=${encodeURIComponent(s)}&episode=${encodeURIComponent(e)}&service=${service}${cb}&secretKey=${encodeURIComponent(secretKey)}`;
104
+
105
+ const url = `https://www.rivestream.app/api/backendfetch?${params}`;
106
+ const res = await fetchJson(url, {
107
+ headers: {
108
+ 'User-Agent': USER_AGENT,
109
+ Referer: referer,
110
+ Accept: 'application/json, text/plain, */*',
111
+ },
112
+ signal: AbortSignal.timeout(10000),
113
+ });
114
+
115
+ if (!res?.data?.sources || !Array.isArray(res.data.sources)) return [];
116
+
117
+ const streams = [];
118
+ for (const item of res.data.sources) {
119
+ if (!item || !item.url) continue;
120
+
121
+ const format = String(item.format || '').toLowerCase();
122
+ const urlStr = String(item.url || '').toLowerCase();
123
+ const isM3U8 = format === 'hls' || format === 'm3u8' || urlStr.includes('.m3u8') || urlStr.includes('.txt');
124
+
125
+ streams.push({
126
+ url: item.url,
127
+ server: `Rive (${item.source || service})`,
128
+ quality: String(item.quality || 'Auto'),
129
+ type: isM3U8 ? 'hls' : 'mp4',
130
+ headers: {
131
+ 'User-Agent': USER_AGENT,
132
+ Referer: referer,
133
+ },
134
+ });
135
+ }
136
+ return streams;
137
+ } catch {
138
+ return [];
139
+ }
140
+ }
141
+
142
+ export async function getStream(args) {
143
+ const { id, s, e, server } = args || {};
144
+ const isTv = s != null && e != null;
145
+ const isMovie = !isTv;
146
+
147
+ const secretKey = generateRiveSecretKey(id);
148
+ const referer = isMovie
149
+ ? `https://www.rivestream.app/watch?type=movie&id=${id}`
150
+ : `https://www.rivestream.app/watch?type=tv&id=${id}&season=${s}&episode=${e}`;
151
+
152
+ let services = await fetchRiveServices();
153
+
154
+ if (server && server !== 'all') {
155
+ const clean = server.toLowerCase().replace('rive (', '').replace(')', '').replace('rive', '').trim();
156
+ services = services.filter(srv => srv.toLowerCase().includes(clean));
157
+ if (!services.length) services = await fetchRiveServices();
158
+ }
159
+
160
+ const settled = await Promise.allSettled(
161
+ services.map(srv => fetchServiceStreams(srv, isMovie, id, s, e, secretKey, referer))
162
+ );
163
+
164
+ const allUrls = [];
165
+ for (const r of settled) {
166
+ if (r.status === 'fulfilled' && Array.isArray(r.value)) {
167
+ allUrls.push(...r.value);
168
+ }
169
+ }
170
+
171
+ if (!allUrls.length) return null;
172
+
173
+ return {
174
+ url: allUrls[0].url,
175
+ headers: allUrls[0].headers,
176
+ allUrls,
177
+ };
178
+ }
179
+
180
+ export async function getSources() {
181
+ const services = await fetchRiveServices();
182
+ return services.map(s => `Rive (${s})`);
177
183
  }