mirror of
https://gitlab.com/vyla-entertainment/sdk.git
synced 2026-11-13 05:37:31 -05:00
added fidflix and vidlux
This commit is contained in:
@@ -759,6 +759,24 @@ export const SOURCES = [
|
||||
multiUrl: true,
|
||||
},
|
||||
|
||||
{
|
||||
key: 'vidflix',
|
||||
label: 'VidFlix',
|
||||
sourceFile: 'vidflix',
|
||||
proxyParam: 'vfl',
|
||||
timeout: 25000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: true,
|
||||
cdnHeaders: [{
|
||||
pattern: /vidflix\.club|followguchimany\.workers\.dev|hakunaymatata\.com|claritybusinessacademy\.site|fcxmb\.com/i,
|
||||
headers: {
|
||||
Referer: 'https://player.vidflix.club/',
|
||||
Origin: 'https://player.vidflix.club',
|
||||
},
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'vidlink',
|
||||
label: 'Vidlink',
|
||||
@@ -770,6 +788,24 @@ export const SOURCES = [
|
||||
multiUrl: true,
|
||||
},
|
||||
|
||||
{
|
||||
key: 'vidlux',
|
||||
label: 'VidLux',
|
||||
sourceFile: 'vidlux',
|
||||
proxyParam: 'vlx',
|
||||
timeout: 25000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: true,
|
||||
cdnHeaders: [{
|
||||
pattern: /vidlux\.xyz/i,
|
||||
headers: {
|
||||
Referer: 'https://vidlux.xyz/',
|
||||
Origin: 'https://vidlux.xyz',
|
||||
},
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'vidly',
|
||||
label: 'Vidly',
|
||||
|
||||
96
src/sources/vidflix.js
Normal file
96
src/sources/vidflix.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import { fetchJson, USER_AGENT } from '../utils/helpers.js';
|
||||
|
||||
const BASE_URL = 'https://player.vidflix.club';
|
||||
const PLAYER_KEY = 'f3b72e73c80c9a996574379798703796a1936efa3516a7105cb0e43048b46b5a';
|
||||
|
||||
const PLAYBACK_HEADERS = {
|
||||
'User-Agent': USER_AGENT,
|
||||
Referer: `${BASE_URL}/`,
|
||||
Origin: BASE_URL,
|
||||
};
|
||||
|
||||
const SERVERS = [
|
||||
{ key: 'p9fx', label: 'Vertex' },
|
||||
{ key: 'b4tz', label: 'Beta' },
|
||||
{ key: 'w7dn', label: 'Nebula' },
|
||||
{ key: 'vjej', label: 'Vega' },
|
||||
];
|
||||
|
||||
export async function getStream(args) {
|
||||
const { id, s, e } = args || {};
|
||||
if (!id) return null;
|
||||
|
||||
const isTv = s != null && e != null;
|
||||
const path = isTv
|
||||
? `/api/vidora/v1/tv/${id}/${s}/${e}`
|
||||
: `/api/vidora/v1/movie/${id}`;
|
||||
|
||||
const referer = isTv
|
||||
? `${BASE_URL}/tv/${id}/${s}/${e}`
|
||||
: `${BASE_URL}/movie/${id}`;
|
||||
|
||||
const headers = {
|
||||
'User-Agent': USER_AGENT,
|
||||
Accept: '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.9',
|
||||
Referer: referer,
|
||||
Origin: BASE_URL,
|
||||
'x-player-key': PLAYER_KEY,
|
||||
};
|
||||
|
||||
const responses = await Promise.allSettled(
|
||||
SERVERS.map(async (server) => {
|
||||
const data = await fetchJson(`${BASE_URL}${path}?source=${server.key}`, {
|
||||
headers,
|
||||
signal: AbortSignal.timeout(args?.config?.timeout || 25000),
|
||||
});
|
||||
return { server, data };
|
||||
})
|
||||
);
|
||||
|
||||
const allUrls = [];
|
||||
const seen = new Set();
|
||||
|
||||
for (const res of responses) {
|
||||
if (res.status !== 'fulfilled' || !res.value?.data?.result) continue;
|
||||
const { server, data } = res.value;
|
||||
const sources = Array.isArray(data.sources) ? data.sources : [];
|
||||
|
||||
for (const sourceItem of sources) {
|
||||
if (Array.isArray(sourceItem.qualities) && sourceItem.qualities.length > 0) {
|
||||
for (const q of sourceItem.qualities) {
|
||||
if (!q?.url || seen.has(q.url)) continue;
|
||||
seen.add(q.url);
|
||||
const qLabel = q.height ? `${q.height}p` : 'Auto';
|
||||
allUrls.push({
|
||||
url: q.url,
|
||||
server: `VidFlix - ${server.label} (${qLabel})`,
|
||||
quality: qLabel,
|
||||
type: q.url.includes('.mpd') ? 'dash' : (q.url.includes('.m3u8') ? 'hls' : 'mp4'),
|
||||
headers: PLAYBACK_HEADERS,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const streamUrl = sourceItem.url;
|
||||
if (streamUrl && typeof streamUrl === 'string' && streamUrl.startsWith('http') && !seen.has(streamUrl)) {
|
||||
seen.add(streamUrl);
|
||||
allUrls.push({
|
||||
url: streamUrl,
|
||||
server: `VidFlix - ${server.label}`,
|
||||
quality: 'Auto',
|
||||
type: streamUrl.includes('.mpd') ? 'dash' : (streamUrl.includes('.m3u8') ? 'hls' : 'mp4'),
|
||||
headers: PLAYBACK_HEADERS,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!allUrls.length) return null;
|
||||
|
||||
return {
|
||||
url: allUrls[0].url,
|
||||
headers: allUrls[0].headers,
|
||||
allUrls,
|
||||
};
|
||||
}
|
||||
156
src/sources/vidlux.js
Normal file
156
src/sources/vidlux.js
Normal file
@@ -0,0 +1,156 @@
|
||||
import crypto from 'node:crypto';
|
||||
import { fetchText, USER_AGENT } from '../utils/helpers.js';
|
||||
|
||||
const BASE_URL = 'https://vidlux.xyz';
|
||||
const ENCRYPTION_KEY = 'vidlux-stream-encryption-2026-secure-key';
|
||||
|
||||
const PLAYBACK_HEADERS = {
|
||||
'User-Agent': USER_AGENT,
|
||||
Referer: `${BASE_URL}/`,
|
||||
Origin: BASE_URL,
|
||||
};
|
||||
|
||||
const SERVERS = [
|
||||
{ id: 'robot', name: 'Robot' },
|
||||
{ id: 'titan', name: 'Titan' },
|
||||
{ id: 'spider', name: 'Spider' },
|
||||
{ id: 'dragon', name: 'Dragon' },
|
||||
{ id: 'quasar', name: 'Quasar' },
|
||||
{ id: 'vidfast', name: 'Flux' },
|
||||
{ id: 'rocket', name: 'Aether' },
|
||||
{ id: 'star', name: 'Star' },
|
||||
{ id: 'bolt', name: 'Bolt' },
|
||||
{ id: 'quilox', name: 'Quilox' },
|
||||
{ id: 'vidrock', name: 'Nova' },
|
||||
{ id: 'dubai', name: 'Dubai' },
|
||||
{ id: 'magic', name: 'Magic' },
|
||||
{ id: 'vixsrc', name: 'Aura' },
|
||||
{ id: 'astra', name: 'Astra' },
|
||||
];
|
||||
|
||||
function decryptPayload(ciphertextB64) {
|
||||
try {
|
||||
const key = crypto.createHash('sha256').update(ENCRYPTION_KEY).digest();
|
||||
const raw = Buffer.from(ciphertextB64, 'base64');
|
||||
const iv = raw.subarray(0, 12);
|
||||
const data = raw.subarray(12);
|
||||
const authTag = data.subarray(data.length - 16);
|
||||
const encrypted = data.subarray(0, data.length - 16);
|
||||
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
|
||||
decipher.setAuthTag(authTag);
|
||||
const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
||||
return JSON.parse(decrypted.toString('utf8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStream(args) {
|
||||
const { id, s, e } = args || {};
|
||||
if (!id) return null;
|
||||
|
||||
const isTv = s != null && e != null;
|
||||
const type = isTv ? 'tv' : 'movie';
|
||||
const embedUrl = isTv
|
||||
? `${BASE_URL}/embed/tv/${id}/${s}/${e}`
|
||||
: `${BASE_URL}/embed/movie/${id}`;
|
||||
|
||||
let token = null;
|
||||
try {
|
||||
const html = await fetchText(embedUrl, {
|
||||
headers: {
|
||||
'User-Agent': USER_AGENT,
|
||||
Referer: `${BASE_URL}/`,
|
||||
},
|
||||
signal: AbortSignal.timeout(8000),
|
||||
});
|
||||
const match = html.match(/(\d{13}\.[a-f0-9]{8}\.[a-f0-9]{64})/i)
|
||||
|| html.match(/requestToken["\\'\s:]+([a-zA-Z0-9._-]+)/i);
|
||||
if (match) token = match[1];
|
||||
} catch { }
|
||||
|
||||
if (!token) return null;
|
||||
|
||||
const queryParams = new URLSearchParams({
|
||||
id: String(id),
|
||||
type,
|
||||
_t: token,
|
||||
});
|
||||
|
||||
if (isTv) {
|
||||
queryParams.set('season', String(s));
|
||||
queryParams.set('episode', String(e));
|
||||
}
|
||||
|
||||
const allUrls = [];
|
||||
const seen = new Set();
|
||||
|
||||
for (const server of SERVERS) {
|
||||
try {
|
||||
const extractUrl = `${BASE_URL}/api/extract/${server.id}?${queryParams.toString()}`;
|
||||
const res = await fetch(extractUrl, {
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.9',
|
||||
'User-Agent': USER_AGENT,
|
||||
Referer: embedUrl,
|
||||
Origin: BASE_URL,
|
||||
},
|
||||
signal: AbortSignal.timeout(10000),
|
||||
});
|
||||
|
||||
if (!res.ok) continue;
|
||||
|
||||
const json = await res.json().catch(() => null);
|
||||
if (!json) continue;
|
||||
|
||||
let data = json;
|
||||
if (json.encrypted && json.data) {
|
||||
data = decryptPayload(json.data);
|
||||
}
|
||||
|
||||
if (!data) continue;
|
||||
|
||||
const streams = Array.isArray(data.streams)
|
||||
? data.streams
|
||||
: (Array.isArray(data.sources) ? data.sources : []);
|
||||
|
||||
for (const item of streams) {
|
||||
let streamUrl = item?.file || item?.url;
|
||||
if (!streamUrl || typeof streamUrl !== 'string') continue;
|
||||
|
||||
if (streamUrl.startsWith('/')) {
|
||||
streamUrl = `${BASE_URL}${streamUrl}`;
|
||||
}
|
||||
|
||||
if (!streamUrl.startsWith('http') || seen.has(streamUrl)) continue;
|
||||
seen.add(streamUrl);
|
||||
|
||||
let quality = item.quality || 'Auto';
|
||||
if (/^\d+$/.test(String(quality).trim())) {
|
||||
quality = `${quality}p`;
|
||||
}
|
||||
|
||||
const streamType = item.type || (streamUrl.includes('.mpd') ? 'dash' : (streamUrl.includes('.m3u8') ? 'hls' : 'mp4'));
|
||||
|
||||
allUrls.push({
|
||||
url: streamUrl,
|
||||
server: `VidLux - ${server.name}`,
|
||||
quality,
|
||||
type: streamType,
|
||||
headers: PLAYBACK_HEADERS,
|
||||
});
|
||||
}
|
||||
|
||||
if (allUrls.length > 0) break;
|
||||
} catch { }
|
||||
}
|
||||
|
||||
if (!allUrls.length) return null;
|
||||
|
||||
return {
|
||||
url: allUrls[0].url,
|
||||
headers: allUrls[0].headers,
|
||||
allUrls,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user