added fidflix and vidlux

This commit is contained in:
2026-11-10 20:47:00 -08:00
parent 95bea6b8b7
commit ed5685b284
3 changed files with 288 additions and 0 deletions

View File

@@ -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
View 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
View 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,
};
}