@vyla-entertainment/sdk 1.8.0 → 1.10.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.
@@ -0,0 +1,122 @@
1
+ import { USER_AGENT, fetchJson, getTmdbInfo } from '../utils/helpers.js';
2
+
3
+ const BASE_URL = 'https://providers.peestream.in';
4
+
5
+ export async function getStream(args) {
6
+ const { id, s, e, server, tmdbApiKey } = args;
7
+ const isTv = s != null && e != null;
8
+ const type = isTv ? 'tv' : 'movie';
9
+
10
+ let title = args.title || '';
11
+ let releaseYear = args.year || '';
12
+ let imdbId = args.imdbId || '';
13
+
14
+ if (!title) {
15
+ try {
16
+ const info = await getTmdbInfo(id, type, s, tmdbApiKey);
17
+ if (info) {
18
+ title = info.title || '';
19
+ if (info.year) releaseYear = info.year;
20
+ if (info.imdbId) imdbId = info.imdbId;
21
+ }
22
+ } catch { }
23
+ }
24
+
25
+ const queryParams = new URLSearchParams({
26
+ type,
27
+ tmdbId: String(id),
28
+ title: title || String(id)
29
+ });
30
+ if (releaseYear) queryParams.set('releaseYear', String(releaseYear));
31
+ if (imdbId) queryParams.set('imdbId', String(imdbId));
32
+ if (isTv) {
33
+ queryParams.set('season', String(s));
34
+ queryParams.set('episode', String(e));
35
+ }
36
+
37
+ const allUrls = [];
38
+
39
+ try {
40
+ const scrapeUrl = `${BASE_URL}/scrape?${queryParams.toString()}`;
41
+ const res = await fetch(scrapeUrl, {
42
+ headers: {
43
+ 'User-Agent': USER_AGENT,
44
+ 'Accept': 'text/event-stream',
45
+ 'Referer': `${BASE_URL}/`
46
+ },
47
+ signal: AbortSignal.timeout(15000)
48
+ });
49
+
50
+ if (res.ok) {
51
+ const text = await res.text();
52
+ const events = text.split('\n\n');
53
+ for (const ev of events) {
54
+ if (ev.includes('event: completed')) {
55
+ const dataMatch = ev.match(/data:\s*(.+)/);
56
+ if (dataMatch) {
57
+ try {
58
+ const parsed = JSON.parse(dataMatch[1].trim());
59
+ const stream = parsed.stream;
60
+ const streamUrl = stream?.playlist || stream?.url || stream?.file;
61
+ if (streamUrl) {
62
+ allUrls.push({
63
+ url: streamUrl,
64
+ server: `PeeStream - ${parsed.sourceId || 'Poseidon'}`,
65
+ quality: 'Auto',
66
+ type: stream.type === 'hls' || streamUrl.includes('.m3u8') ? 'hls' : 'mp4',
67
+ headers: stream.headers || {
68
+ 'User-Agent': USER_AGENT
69
+ }
70
+ });
71
+ }
72
+ } catch { }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ } catch { }
78
+
79
+ if (!allUrls.length) {
80
+ try {
81
+ const searchUrl = `${BASE_URL}/api/search?q=${encodeURIComponent(title || id)}&type=${type}&tmdbId=${id}${isTv ? `&season=${s}&episode=${e}` : ''}`;
82
+ const data = await fetchJson(searchUrl, {
83
+ headers: {
84
+ 'User-Agent': USER_AGENT,
85
+ 'Accept': 'application/json',
86
+ 'Referer': `${BASE_URL}/`
87
+ },
88
+ signal: AbortSignal.timeout(10000)
89
+ });
90
+
91
+ if (data && Array.isArray(data.results)) {
92
+ for (const result of data.results) {
93
+ const pName = result.providerName || result.provider || 'PeeStream';
94
+ for (const stream of result.streams || []) {
95
+ if (!stream || !stream.url) continue;
96
+ allUrls.push({
97
+ url: stream.url,
98
+ server: `PeeStream - ${stream.name || pName}`,
99
+ quality: stream.quality || 'Auto',
100
+ type: stream.type === 'm3u8' || stream.url.includes('.m3u8') ? 'hls' : 'mp4',
101
+ headers: stream.headers || {
102
+ 'User-Agent': USER_AGENT
103
+ }
104
+ });
105
+ }
106
+ }
107
+ }
108
+ } catch { }
109
+ }
110
+
111
+ if (server && server !== 'all') {
112
+ const clean = server.toLowerCase().replace('peestream - ', '');
113
+ const filtered = allUrls.filter(u => u.server.toLowerCase().includes(clean));
114
+ if (filtered.length) return { allUrls: filtered };
115
+ }
116
+
117
+ return allUrls.length ? { allUrls } : null;
118
+ }
119
+
120
+ export async function getSources() {
121
+ return ['PeeStream - vaplayer'];
122
+ }
@@ -1,7 +1,7 @@
1
1
  import { fetchJson } from '../utils/helpers.js';
2
2
 
3
- const PENGU_CONFIG = '%7B%22source_4khdhub%22%3A%22on%22%2C%22source_moviebox%22%3A%22on%22%2C%22source_moviesdrives%22%3A%22on%22%2C%22source_vaplayer%22%3A%22on%22%2C%22source_hdghartv%22%3A%22on%22%2C%22res_2160%22%3A%22on%22%2C%22res_1080%22%3A%22on%22%2C%22res_720%22%3A%22on%22%2C%22disable_direct%22%3A%22on%22%7D';
4
- const BASE_URL = `https://pengu.uk/${PENGU_CONFIG}`;
3
+ // const PENGU_CONFIG = '%7B%22source_4khdhub%22%3A%22on%22%2C%22source_moviebox%22%3A%22on%22%2C%22source_moviesdrives%22%3A%22on%22%2C%22source_vaplayer%22%3A%22on%22%2C%22source_hdghartv%22%3A%22on%22%2C%22res_2160%22%3A%22on%22%2C%22res_1080%22%3A%22on%22%2C%22res_720%22%3A%22on%22%2C%22disable_direct%22%3A%22on%22%7D';
4
+ // const BASE_URL = `https://pengu.uk/${PENGU_CONFIG}`;
5
5
 
6
6
  async function getImdbId(tmdbApiKey, tmdbId, s, e) {
7
7
  const key = tmdbApiKey;
@@ -15,7 +15,12 @@ async function getImdbId(tmdbApiKey, tmdbId, s, e) {
15
15
  } catch { return null; }
16
16
  }
17
17
 
18
- export async function getStream({ id, s, e, tmdbApiKey }) {
18
+ export async function getStream({ id, s, e, sdk }) {
19
+ const tmdbApiKey = sdk?.tmdbApiKey || null;
20
+ const manifest = sdk?.penguManifest || null;
21
+ if (!tmdbApiKey || !manifest || (manifest && !manifest.endsWith('manifest.json'))) return null;
22
+ const BASE_URL = manifest ? manifest.split('/manifest.json')[0] : null;
23
+ if (!BASE_URL) return null;
19
24
  try {
20
25
  const imdbId = await getImdbId(tmdbApiKey, id, s, e);
21
26
  if (!imdbId) return null;
@@ -0,0 +1,179 @@
1
+ // im being salty
2
+
3
+ import { USER_AGENT, fetchJson } from '../utils/helpers.js';
4
+
5
+ const C_ARRAY = [
6
+ '4Z7lUo', 'gwIVSMD', 'PLmz2elE2v', 'Z4OFV0', 'SZ6RZq6Zc', 'zhJEFYxrz8', 'FOm7b0', 'axHS3q4KDq', 'o9zuXQ', '4Aebt',
7
+ 'wgjjWwKKx', 'rY4VIxqSN', 'kfjbnSo', '2DyrFA1M', 'YUixDM9B', 'JQvgEj0', 'mcuFx6JIek', 'eoTKe26gL', 'qaI9EVO1rB', '0xl33btZL',
8
+ '1fszuAU', 'a7jnHzst6P', 'wQuJkX', 'cBNhTJlEOf', 'KNcFWhDvgT', 'XipDGjST', 'PCZJlbHoyt', '2AYnMZkqd', 'HIpJh', 'KH0C3iztrG',
9
+ 'W81hjts92', 'rJhAT', 'NON7LKoMQ', 'NMdY3nsKzI', 't4En5v', 'Qq5cOQ9H', 'Y9nwrp', 'VX5FYVfsf', 'cE5SJG', 'x1vj1',
10
+ 'HegbLe', 'zJ3nmt4OA', 'gt7rxW57dq', 'clIE9b', 'jyJ9g', 'B5jXjMCSx', 'cOzZBZTV', 'FTXGy', 'Dfh1q1', 'ny9jqZ2POI',
11
+ 'X2NnMn', 'MBtoyD', 'qz4Ilys7wB', '68lbOMye', '3YUJnmxp', '1fv5Imona', 'PlfvvXD7mA', 'ZarKfHCaPR', 'owORnX', 'dQP1YU',
12
+ 'dVdkx', 'qgiK0E', 'cx9wQ', '5F9bGa', '7UjkKrp', 'Yvhrj', 'wYXez5Dg3', 'pG4GMU', 'MwMAu', 'rFRD5wlM'
13
+ ];
14
+
15
+ const DEFAULT_SERVICES = [
16
+ 'apex', 'pulse', 'solstice', 'quasar', 'horizon', 'primevids',
17
+ 'flowcast', 'asiacloud', 'citadel', 'hindicast', 'guru'
18
+ ];
19
+
20
+ function generateRiveSecretKey(e) {
21
+ if (e === undefined || e === null) return 'rive';
22
+ try {
23
+ let t, n;
24
+ const r = String(e);
25
+ if (isNaN(Number(e))) {
26
+ const sum = r.split('').reduce((acc, ch) => acc + ch.charCodeAt(0), 0);
27
+ t = C_ARRAY[sum % C_ARRAY.length] || Buffer.from(r).toString('base64');
28
+ n = Math.floor((sum % r.length) / 2);
29
+ } else {
30
+ const i = Number(e);
31
+ t = C_ARRAY[i % C_ARRAY.length] || Buffer.from(r).toString('base64');
32
+ n = Math.floor((i % r.length) / 2);
33
+ }
34
+ const i = r.slice(0, n) + t + r.slice(n);
35
+ const o = (function (str) {
36
+ const t = String(str);
37
+ let n = 3735928559 ^ t.length;
38
+ for (let e = 0; e < t.length; e++) {
39
+ const r = t.charCodeAt(e);
40
+ const rXor = (131 * e + 89 ^ (r << (e % 5))) & 255;
41
+ const r2 = r ^ rXor;
42
+ n = (((n << 7) | (n >>> 25)) >>> 0) ^ r2;
43
+ const idx = (65535 & n) * 60205;
44
+ const o2 = ((n >>> 16) * 60205) << 16;
45
+ n = (idx + o2) >>> 0;
46
+ n ^= n >>> 11;
47
+ }
48
+ n ^= n >>> 15;
49
+ n = ((65535 & n) * 49842 + (((n >>> 16) * 49842) << 16)) >>> 0;
50
+ n ^= n >>> 13;
51
+ n = ((65535 & n) * 40503 + (((n >>> 16) * 40503) << 16)) >>> 0;
52
+ n ^= n >>> 16;
53
+ n = ((65535 & n) * 10196 + (((n >>> 16) * 10196) << 16)) >>> 0;
54
+ return ((n ^= n >>> 15)).toString(16).padStart(8, '0');
55
+ })(
56
+ (function (str) {
57
+ const s = String(str);
58
+ let t = 0;
59
+ for (let n = 0; n < s.length; n++) {
60
+ const r = s.charCodeAt(n);
61
+ const i = (((t = (r + (t << 6) + (t << 16) - t) >>> 0) << (n % 5)) | (t >>> (32 - (n % 5)))) >>> 0;
62
+ t ^= (i ^ ((r << (n % 7)) | (r >>> (8 - (n % 7))))) >>> 0;
63
+ t = (t + ((t >>> 11) ^ (t << 3))) >>> 0;
64
+ }
65
+ t ^= t >>> 15;
66
+ t = ((65535 & t) * 49842 + ((((t >>> 16) * 49842) & 65535) << 16)) >>> 0;
67
+ t ^= t >>> 13;
68
+ t = ((65535 & t) * 40503 + ((((t >>> 16) * 40503) & 65535) << 16)) >>> 0;
69
+ return ((t ^= t >>> 16)).toString(16).padStart(8, '0');
70
+ })(i)
71
+ );
72
+ return Buffer.from(o, 'utf-8').toString('base64');
73
+ } catch {
74
+ return 'topSecret';
75
+ }
76
+ }
77
+
78
+ async function fetchRiveServices() {
79
+ try {
80
+ const secretKey = generateRiveSecretKey();
81
+ const url = `https://www.rivestream.app/api/backendfetch?requestID=VideoProviderServices&secretKey=${encodeURIComponent(secretKey)}`;
82
+ const res = await fetchJson(url, {
83
+ headers: {
84
+ 'User-Agent': USER_AGENT,
85
+ 'Referer': 'https://www.rivestream.app/',
86
+ 'Accept': 'application/json, text/plain, */*'
87
+ },
88
+ signal: AbortSignal.timeout(6000)
89
+ });
90
+ return Array.isArray(res?.data) && res.data.length ? res.data : DEFAULT_SERVICES;
91
+ } catch {
92
+ return DEFAULT_SERVICES;
93
+ }
94
+ }
95
+
96
+ async function fetchServiceStreams(service, isMovie, id, s, e, secretKey, referer) {
97
+ try {
98
+ const cb = (service === 'primevids' || service === 'citadel')
99
+ ? `&cb=${Math.floor(Date.now() / 3e6)}`
100
+ : '';
101
+
102
+ const reqID = isMovie ? 'movieVideoProvider' : 'tvVideoProvider';
103
+ const params = isMovie
104
+ ? `requestID=${reqID}&id=${encodeURIComponent(id)}&service=${service}${cb}&secretKey=${encodeURIComponent(secretKey)}`
105
+ : `requestID=${reqID}&id=${encodeURIComponent(id)}&season=${encodeURIComponent(s)}&episode=${encodeURIComponent(e)}&service=${service}${cb}&secretKey=${encodeURIComponent(secretKey)}`;
106
+
107
+ const url = `https://www.rivestream.app/api/backendfetch?${params}`;
108
+ const res = await fetchJson(url, {
109
+ headers: {
110
+ 'User-Agent': USER_AGENT,
111
+ 'Referer': referer,
112
+ 'Accept': 'application/json, text/plain, */*'
113
+ },
114
+ signal: AbortSignal.timeout(10000)
115
+ });
116
+
117
+ if (!res?.data?.sources || !Array.isArray(res.data.sources)) return [];
118
+
119
+ const streams = [];
120
+ for (const item of res.data.sources) {
121
+ if (!item || !item.url) continue;
122
+
123
+ const format = String(item.format || '').toLowerCase();
124
+ const urlStr = String(item.url || '').toLowerCase();
125
+ const isM3U8 = format === 'hls' || format === 'm3u8' || urlStr.includes('.m3u8') || urlStr.includes('.txt');
126
+
127
+ streams.push({
128
+ url: item.url,
129
+ server: `Rive (${item.source || service})`,
130
+ quality: String(item.quality || 'Auto'),
131
+ type: isM3U8 ? 'hls' : 'mp4',
132
+ headers: {
133
+ 'User-Agent': USER_AGENT,
134
+ 'Referer': referer
135
+ }
136
+ });
137
+ }
138
+ return streams;
139
+ } catch {
140
+ return [];
141
+ }
142
+ }
143
+
144
+ export async function getStream(args) {
145
+ const { id, s, e, server } = args;
146
+ const isTv = s != null && e != null;
147
+ const isMovie = !isTv;
148
+
149
+ const secretKey = generateRiveSecretKey(id);
150
+ const referer = isMovie
151
+ ? `https://www.rivestream.app/watch?type=movie&id=${id}`
152
+ : `https://www.rivestream.app/watch?type=tv&id=${id}&season=${s}&episode=${e}`;
153
+
154
+ let services = await fetchRiveServices();
155
+
156
+ if (server && server !== 'all') {
157
+ const clean = server.toLowerCase().replace('rive (', '').replace(')', '').replace('rive', '').trim();
158
+ services = services.filter(srv => srv.toLowerCase().includes(clean));
159
+ if (!services.length) services = await fetchRiveServices();
160
+ }
161
+
162
+ const settled = await Promise.allSettled(
163
+ services.map(srv => fetchServiceStreams(srv, isMovie, id, s, e, secretKey, referer))
164
+ );
165
+
166
+ const allUrls = [];
167
+ for (const r of settled) {
168
+ if (r.status === 'fulfilled' && Array.isArray(r.value)) {
169
+ allUrls.push(...r.value);
170
+ }
171
+ }
172
+
173
+ return allUrls.length ? { allUrls } : null;
174
+ }
175
+
176
+ export async function getSources() {
177
+ const services = await fetchRiveServices();
178
+ return services.map(s => `Rive (${s})`);
179
+ }
@@ -12,7 +12,9 @@ const SERVERS = [
12
12
  { id: 'superflix', name: 'Raze' }
13
13
  ];
14
14
 
15
- export async function getStream({ id, s, e, server, tmdbApiKey }) {
15
+ export async function getStream({ id, s, e, server, sdk }) {
16
+ const tmdbApiKey = sdk?.tmdbApiKey || null;
17
+ if (!tmdbApiKey) return null;
16
18
  try {
17
19
  const isTv = s != null && e != null;
18
20
  const info = await getTmdbInfo(tmdbApiKey, id, isTv ? 'tv' : 'movie');
@@ -0,0 +1,147 @@
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
+ }
@@ -39,7 +39,9 @@ async function tmdbToAnilist(tmdbId, season) {
39
39
 
40
40
  const SERVER_KEYS = ['hollymoviehd', 'allmovies', 'catflix', 'purstream', 'lamda', 'vidlink', 'klikxxi'];
41
41
 
42
- export async function getStream({ id, s, e, tmdbApiKey, audio }) {
42
+ export async function getStream({ id, s, e, sdk, audio }) {
43
+ const tmdbApiKey = sdk?.tmdbApiKey || null;
44
+ if (!tmdbApiKey) return null;
43
45
  if (s) {
44
46
  const k = tmdbApiKey;
45
47
  const showData = k ? await fetchJson(`https://api.themoviedb.org/3/tv/${id}?api_key=${k}`, { signal: AbortSignal.timeout(5000) }).catch(() => null) : null;