mirror of
https://gitlab.com/vyla-entertainment/sdk.git
synced 2026-11-12 21:27:28 -05:00
added cinecat, cinesrc, cinezo, hexa, hyper, and yastream
This commit is contained in:
104
src/config.js
104
src/config.js
@@ -118,6 +118,25 @@ export const SOURCES = [
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'cinecat',
|
||||
label: 'Cinecat',
|
||||
sourceFile: 'cinecat',
|
||||
proxyParam: 'ccat',
|
||||
timeout: 25000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: false,
|
||||
skipProxy: true,
|
||||
cdnHeaders: [{
|
||||
pattern: /bluevelvet\.space/i,
|
||||
headers: {
|
||||
Referer: 'https://zcdn.bluevelvet.space/',
|
||||
Origin: 'https://zcdn.bluevelvet.space',
|
||||
},
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'cinemaarmy',
|
||||
label: 'CinemaArmy',
|
||||
@@ -137,6 +156,43 @@ export const SOURCES = [
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'cinesrc',
|
||||
label: 'CineSrc',
|
||||
sourceFile: 'cinesrc',
|
||||
proxyParam: 'cs',
|
||||
timeout: 35000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: true,
|
||||
skipProxy: true,
|
||||
cdnHeaders: [{
|
||||
pattern: /cinesrc\.st/i,
|
||||
headers: {
|
||||
Referer: 'https://cinesrc.st/',
|
||||
Origin: 'https://cinesrc.st',
|
||||
},
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'cinezo',
|
||||
label: 'Cinezo',
|
||||
sourceFile: 'cinezo',
|
||||
proxyParam: 'czo',
|
||||
timeout: 25000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: true,
|
||||
cdnHeaders: [{
|
||||
pattern: /yenime\.net|flikhub\.net|hakunaymatata\.com/i,
|
||||
headers: {
|
||||
Referer: 'https://player.cinezo.live/',
|
||||
Origin: 'https://player.cinezo.live',
|
||||
},
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'dulo',
|
||||
label: 'Dulo',
|
||||
@@ -187,6 +243,43 @@ export const SOURCES = [
|
||||
skipProxy: true,
|
||||
},
|
||||
|
||||
{
|
||||
key: 'hexa',
|
||||
label: 'Hexa',
|
||||
sourceFile: 'hexa',
|
||||
proxyParam: 'hx',
|
||||
timeout: 30000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: true,
|
||||
skipProxy: true,
|
||||
cdnHeaders: [{
|
||||
pattern: /hexa\.su|flixer\.su/i,
|
||||
headers: {
|
||||
Referer: 'https://hexa.su/',
|
||||
Origin: 'https://hexa.su',
|
||||
},
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'hyper',
|
||||
label: 'Hyper',
|
||||
sourceFile: 'hyper',
|
||||
proxyParam: 'hyp',
|
||||
timeout: 25000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: true,
|
||||
cdnHeaders: [{
|
||||
pattern: /hakunaymatata\.com/i,
|
||||
headers: {
|
||||
Referer: 'https://mzfi.me/',
|
||||
Origin: 'https://mzfi.me',
|
||||
},
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'kisskh',
|
||||
label: 'KissKH',
|
||||
@@ -588,6 +681,17 @@ export const SOURCES = [
|
||||
}],
|
||||
},
|
||||
|
||||
{
|
||||
key: 'yastream',
|
||||
label: 'YaStream',
|
||||
sourceFile: 'yastream',
|
||||
proxyParam: 'ya',
|
||||
timeout: 25000,
|
||||
jitter: 500,
|
||||
retries: 2,
|
||||
multiUrl: true,
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export const HEALTH_PROBE_ID = '155';
|
||||
|
||||
19
src/sources/cinecat.js
Normal file
19
src/sources/cinecat.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { fetchJson } from '../utils/helpers.js';
|
||||
|
||||
export async function getStream({ id, s, e }) {
|
||||
const isTv = s != null && e != null;
|
||||
const url = isTv
|
||||
? `https://zcdn.bluevelvet.space/cdn?tmdb=${id}&type=tv&season=${s}&episode=${e}`
|
||||
: `https://zcdn.bluevelvet.space/cdn?tmdb=${id}&type=movie`;
|
||||
|
||||
const res = await fetchJson(url);
|
||||
if (!res || !res.ready || !res.url) return null;
|
||||
|
||||
return {
|
||||
url: res.url,
|
||||
headers: {
|
||||
Referer: 'https://zcdn.bluevelvet.space/',
|
||||
Origin: 'https://zcdn.bluevelvet.space',
|
||||
}
|
||||
};
|
||||
}
|
||||
398
src/sources/cinesrc.js
Normal file
398
src/sources/cinesrc.js
Normal file
@@ -0,0 +1,398 @@
|
||||
import { fetchJson, fetchText } from '../utils/helpers.js';
|
||||
|
||||
const API = "https://enc-dec.app/api";
|
||||
|
||||
async function solveStage1(challenge1, seed) {
|
||||
const K = [
|
||||
0x46C6C721, 0x4230C311, 0x18223A1D, 0x56389BA7,
|
||||
0xD4A87103, 0x07CB9E2F, 0x73085F9D, 0xD2396A1F,
|
||||
0x23AE5ADD, 0x4646C48F, 0x0F4E0903, 0x808F5F31,
|
||||
0x953D4E07, 0x7E238FFF, 0x634595DF, 0xCB5E4301,
|
||||
];
|
||||
|
||||
const SCHEDULES = [
|
||||
[0, 7, 6, 3, 2, 1, 5, 4, 0, 2, 4, 6, 5, 1, 7, 3],
|
||||
[5, 2, 1, 3, 0, 4, 6, 7, 4, 1, 0, 7, 3, 6, 5, 2],
|
||||
[4, 0, 2, 1, 5, 7, 6, 3, 2, 6, 0, 7, 4, 3, 5, 1],
|
||||
[5, 4, 7, 0, 2, 3, 1, 6, 5, 1, 4, 0, 7, 2, 3, 6],
|
||||
[4, 7, 0, 2, 1, 6, 5, 3, 6, 1, 3, 2, 0, 7, 4, 5],
|
||||
[0, 7, 2, 6, 3, 4, 5, 1, 6, 5, 0, 2, 7, 1, 4, 3],
|
||||
[0, 4, 5, 3, 1, 7, 2, 6, 3, 7, 5, 6, 1, 0, 2, 4],
|
||||
[7, 6, 0, 4, 2, 5, 1, 3, 7, 5, 3, 4, 2, 6, 0, 1],
|
||||
];
|
||||
|
||||
const PERMUTATIONS = [
|
||||
[3, 5, 1, 0, 2, 4],
|
||||
[2, 0, 4, 5, 3, 1],
|
||||
[1, 4, 5, 3, 0, 2],
|
||||
[2, 0, 1, 5, 4, 3],
|
||||
[4, 2, 1, 0, 3, 5],
|
||||
[5, 0, 2, 1, 3, 4],
|
||||
[4, 5, 1, 0, 3, 2],
|
||||
[4, 0, 3, 5, 1, 2],
|
||||
];
|
||||
|
||||
const u32 = x => x >>> 0;
|
||||
const rotl = (x, n) => u32((x << (n & 31)) | (x >>> (32 - (n & 31))));
|
||||
const imul = (a, b) => {
|
||||
const ah = (a >>> 16) & 0xffff;
|
||||
const al = a & 0xffff;
|
||||
const bh = (b >>> 16) & 0xffff;
|
||||
const bl = b & 0xffff;
|
||||
return u32((ah * bl + al * bh) << 16) + al * bl;
|
||||
};
|
||||
|
||||
const b64dec = s => {
|
||||
const bin = atob(s.replace(/-/g, '+').replace(/_/g, '/'));
|
||||
const bytes = new Uint8Array(bin.length);
|
||||
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
||||
return bytes;
|
||||
};
|
||||
|
||||
const c = b64dec(challenge1.w);
|
||||
const view = new DataView(c.buffer);
|
||||
const mode = c[21];
|
||||
const diffVal = c[22];
|
||||
const var_ = c[23];
|
||||
const rnd = c[24];
|
||||
const m_b = c[25];
|
||||
const s_i = c[26];
|
||||
const p_i = c[27];
|
||||
|
||||
const w0 = view.getUint32(0, true);
|
||||
const w1 = view.getUint32(4, true);
|
||||
const w2 = view.getUint32(8, true);
|
||||
const w3 = view.getUint32(12, true);
|
||||
const w = [w0, w1, w2, w3];
|
||||
|
||||
const size = 1 << m_b;
|
||||
const s = new Uint32Array(size);
|
||||
let x = u32(w[var_ & 3] ^ K[s_i] ^ imul(K[8 + s_i], var_ + 1));
|
||||
let y = u32(w[(var_ + 1) & 3] ^ K[15 - s_i]);
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
x = u32(w[(i + s_i) & 3] + x + imul(K[(i + var_) & 15], i + 1));
|
||||
x = u32(x ^ (x << 13));
|
||||
x = u32(x ^ (x >>> 17));
|
||||
x = u32(x ^ (x << 5));
|
||||
y = rotl(imul(K[(i + 9) & 15], i + 3) ^ y ^ x, i + var_ + s_i);
|
||||
s[i] = u32(imul(K[(i + 5) & 15], i ^ var_) ^ rotl(w[(i + var_) & 3], i + s_i) ^ x ^ y);
|
||||
}
|
||||
|
||||
const seedBytes = new Uint8Array(seed.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
||||
const msg = new Uint8Array(88);
|
||||
msg.set(c.slice(0, 16), 24);
|
||||
|
||||
const cfg = m_b ^ 0x6B29;
|
||||
msg[48] = 4;
|
||||
msg[49] = mode;
|
||||
msg[50] = var_;
|
||||
msg[51] = s_i;
|
||||
msg[52] = p_i;
|
||||
msg[53] = rnd;
|
||||
msg[54] = cfg & 0xff;
|
||||
msg[55] = cfg >> 8;
|
||||
msg.set(seedBytes, 56);
|
||||
|
||||
const mask = size - 1;
|
||||
const sch = SCHEDULES[s_i];
|
||||
const perm = PERMUTATIONS[p_i];
|
||||
|
||||
let n = 0n;
|
||||
while (true) {
|
||||
const lo = Number(n & 0xffffffffn);
|
||||
const hi = Number(n >> 32n);
|
||||
|
||||
let ma = u32(w[0] ^ K[var_] ^ lo);
|
||||
let mb = u32(rotl(lo, var_ + 7) ^ w[2]);
|
||||
let mc = u32(w[1] ^ K[8 + s_i] ^ hi);
|
||||
let md = u32(rotl(lo ^ hi, s_i + 11) ^ w[3]);
|
||||
let me = u32(K[s_i + var_] ^ lo ^ hi);
|
||||
let mf = u32(K[15 - var_] ^ w[s_i & 3]);
|
||||
|
||||
for (let r = 0; r < rnd; r++) {
|
||||
const i1 = u32(rotl(mb, r + 1) ^ imul(K[r & 15], mf) ^ me ^ ma) & mask;
|
||||
const v1 = s[i1];
|
||||
const i2 = u32(rotl(me, var_ + r + 3) ^ imul(K[(r + 7) & 15], md) ^ mc ^ v1) & mask;
|
||||
const op = sch[r];
|
||||
|
||||
if (op === 0) {
|
||||
ma = rotl(u32(ma + md + v1), 5);
|
||||
mc = u32(imul(mc ^ mf ^ ma, 1187432225) + mb);
|
||||
} else if (op === 1) {
|
||||
mb = rotl(mc ^ me ^ mb ^ v1, 11);
|
||||
md = u32(imul(mb ^ ma, 1110491921) + md);
|
||||
} else if (op === 2) {
|
||||
mc = rotl(u32(mc + mb + v1), 17);
|
||||
ma = u32(imul(md ^ mf ^ mc, 404896285) ^ ma);
|
||||
} else if (op === 3) {
|
||||
md = rotl(ma ^ md ^ v1, 23);
|
||||
mb = u32(imul(mc ^ me ^ md, 1446550439) + mb);
|
||||
} else if (op === 4) {
|
||||
ma = u32(imul(ma ^ me ^ v1, -727158525) + rotl(mb, 7));
|
||||
md = u32(rotl(u32(mc + mf + ma), 13) ^ md);
|
||||
} else if (op === 5) {
|
||||
mc = u32(imul(u32(mc + mf + v1), 130784815) ^ rotl(md, 9));
|
||||
mb = u32(rotl(ma ^ me ^ mc, 19) + mb);
|
||||
} else if (op === 6) {
|
||||
mb = u32(imul(mb ^ mf ^ v1, 1929928605) + rotl(ma, 3));
|
||||
mc = u32(rotl(u32(md + me + mb), 15) ^ mc);
|
||||
} else {
|
||||
md = u32(imul(u32(md + me + v1), -767989217) ^ rotl(mc, 21));
|
||||
ma = u32(rotl(mb ^ mf ^ md, 27) + ma);
|
||||
}
|
||||
|
||||
const v2 = s[i2];
|
||||
if (((mf ^ r ^ v1) & 1) === 0) {
|
||||
mf = rotl(u32(v2 + mf + ma), r + 5);
|
||||
me = u32(imul(K[8 + op], v2 ^ me ^ mf) + md);
|
||||
} else {
|
||||
me = rotl(v2 ^ me ^ mb, r + 9);
|
||||
mf = u32(imul(K[(op + 11) & 15], u32(v2 + mf + me)) ^ mc);
|
||||
}
|
||||
}
|
||||
|
||||
const mArr = [ma, mc, mb, md, mf, me];
|
||||
const v = perm.map(idx => mArr[idx]);
|
||||
|
||||
const msgView = new DataView(msg.buffer);
|
||||
msgView.setUint32(0, v[0], true);
|
||||
msgView.setUint32(4, v[1], true);
|
||||
msgView.setUint32(8, v[2], true);
|
||||
msgView.setUint32(12, v[3], true);
|
||||
msgView.setUint32(16, v[4], true);
|
||||
msgView.setUint32(20, v[5], true);
|
||||
msgView.setBigUint64(40, n, true);
|
||||
|
||||
const hashBuf = await crypto.subtle.digest('SHA-256', msg);
|
||||
const hashBytes = new Uint8Array(hashBuf);
|
||||
|
||||
const b = Math.floor(diffVal / 8);
|
||||
const rBits = diffVal % 8;
|
||||
let ok = true;
|
||||
for (let i = 0; i < b; i++) {
|
||||
if (hashBytes[i] !== 0) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok && (rBits === 0 || (hashBytes[b] >> (8 - rBits)) === 0)) {
|
||||
return `m4.${n.toString(16)}`;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
async function solveStage2(data) {
|
||||
const target = data.pack[0].split('').reverse().join('');
|
||||
const salt = data.pack[3].split('').reverse().join('');
|
||||
const r = data.pack[4].split('').reverse().join('');
|
||||
|
||||
const b64decStr = s => decodeURIComponent(escape(atob(s.replace(/-/g, '+').replace(/_/g, '/'))));
|
||||
const body = b64decStr(r.split('.')[1]);
|
||||
const payload = b64decStr(body.split('.')[1]);
|
||||
const difficulty = JSON.parse(payload).d;
|
||||
|
||||
const width = Math.floor((difficulty + 3) / 4);
|
||||
const limit = 1 << difficulty;
|
||||
|
||||
for (let counter = 0; counter < limit; counter++) {
|
||||
const key = counter.toString(16).padStart(width, '0');
|
||||
const msgUint8 = new TextEncoder().encode(salt + key);
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
const digest = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
if (digest === target) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
throw new Error('no solution found');
|
||||
}
|
||||
|
||||
export async function getStream({ id, s, e }) {
|
||||
const isTv = s != null && e != null;
|
||||
const type = isTv ? 'tv' : 'movie';
|
||||
const url = isTv
|
||||
? `https://cinesrc.st/embed/tv/${id}?s=${s}&e=${e}`
|
||||
: `https://cinesrc.st/embed/movie/${id}`;
|
||||
|
||||
const headers = {
|
||||
"Origin": "https://cinesrc.st",
|
||||
"Referer": "https://cinesrc.st/",
|
||||
"Content-Type": "text/plain;charset=UTF-8",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.37 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.37"
|
||||
};
|
||||
|
||||
const fields = [type, id, s ? String(s) : null, e ? String(e) : null];
|
||||
const encoded = btoa(JSON.stringify(fields).replace(/ /g, '')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||
|
||||
const bootstrapHeaders = { ...headers, "x-cs-q": encoded };
|
||||
const bootstrap = await fetchJson("https://cinesrc.st/api/c/bootstrap", {
|
||||
method: "POST",
|
||||
headers: bootstrapHeaders,
|
||||
body: "{}"
|
||||
});
|
||||
|
||||
const cookies = {
|
||||
"x-cs-b": "20261014-a",
|
||||
"x-cs-q": encoded,
|
||||
"x-cs-r": bootstrap.r,
|
||||
"x-cs-p": bootstrap.p,
|
||||
};
|
||||
|
||||
const challenge1 = await fetchJson("https://cinesrc.st/api/c/issue", {
|
||||
headers: { ...headers, ...cookies }
|
||||
});
|
||||
|
||||
const payload1 = {
|
||||
data: {
|
||||
url,
|
||||
user_agent: headers["User-Agent"],
|
||||
challenge_data: challenge1
|
||||
},
|
||||
type: "seed"
|
||||
};
|
||||
|
||||
const seedRes = await fetchJson(`${API}/enc-cinesrc`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload1)
|
||||
});
|
||||
|
||||
const seedData = seedRes.result;
|
||||
const solution1 = await solveStage1(challenge1, seedData.seed);
|
||||
|
||||
const challenge2 = await fetchJson("https://cinesrc.st/api/c/stage2/issue", {
|
||||
headers: { ...headers, ...cookies }
|
||||
});
|
||||
const solution2 = await solveStage2(challenge2);
|
||||
|
||||
const payload2 = {
|
||||
data: {
|
||||
url,
|
||||
user_agent: headers["User-Agent"],
|
||||
challenge_data: {
|
||||
stage1: { challenge: challenge1, solution: solution1 },
|
||||
stage2: { challenge: challenge2, solution: solution2 }
|
||||
},
|
||||
state: seedData.state
|
||||
},
|
||||
type: "encrypt"
|
||||
};
|
||||
|
||||
const encryptRes = await fetchJson(`${API}/enc-cinesrc`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload2)
|
||||
});
|
||||
|
||||
const encData = encryptRes.result;
|
||||
const token = `${encData.token}::c3::${cookies["x-cs-r"]}`;
|
||||
const nextActions = encData.headers;
|
||||
|
||||
const providersText = await fetchText(url, {
|
||||
method: "POST",
|
||||
headers: { ...headers, ...cookies, "Next-Action": nextActions.getProviderList },
|
||||
body: JSON.stringify([])
|
||||
});
|
||||
|
||||
const lines = providersText.split('\n');
|
||||
let providers = null;
|
||||
for (const rawLine of lines) {
|
||||
const colonIndex = rawLine.indexOf(':');
|
||||
if (colonIndex !== -1) {
|
||||
const candidate = rawLine.slice(colonIndex + 1).trim();
|
||||
if (candidate.startsWith('[') && candidate.endsWith(']')) {
|
||||
try {
|
||||
providers = JSON.parse(candidate);
|
||||
break;
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(providers) || providers.length === 0) return null;
|
||||
|
||||
const allUrls = [];
|
||||
|
||||
for (const providerObj of providers) {
|
||||
const provider = providerObj.id;
|
||||
const streamPayload = [
|
||||
id,
|
||||
isTv ? "show" : type,
|
||||
isTv ? String(s) : "$undefined",
|
||||
isTv ? String(e) : "$undefined",
|
||||
token,
|
||||
provider
|
||||
];
|
||||
|
||||
let streamRes;
|
||||
try {
|
||||
streamRes = await fetchText(url, {
|
||||
method: "POST",
|
||||
headers: { ...headers, ...cookies, "Next-Action": nextActions.getStream },
|
||||
body: JSON.stringify(streamPayload)
|
||||
});
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!streamRes || streamRes.includes('"status":500') || streamRes.includes('invalid_challenge') || streamRes.length < 10) continue;
|
||||
|
||||
let decryptRes;
|
||||
try {
|
||||
decryptRes = await fetchJson(`${API}/dec-cinesrc`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ text: streamRes, state: encData.state })
|
||||
});
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (decryptRes && decryptRes.status === 200 && decryptRes.result) {
|
||||
let resultData = decryptRes.result;
|
||||
if (typeof resultData === 'string') {
|
||||
try {
|
||||
resultData = JSON.parse(resultData);
|
||||
} catch { }
|
||||
}
|
||||
|
||||
let streamUrl = null;
|
||||
if (Array.isArray(resultData?.url)) {
|
||||
streamUrl = resultData.url[0]?.url;
|
||||
} else if (typeof resultData?.url === 'string') {
|
||||
streamUrl = resultData.url;
|
||||
} else if (resultData?.file) {
|
||||
streamUrl = resultData.file;
|
||||
} else if (Array.isArray(resultData?.sources)) {
|
||||
streamUrl = resultData.sources[0]?.url;
|
||||
}
|
||||
|
||||
if (streamUrl) {
|
||||
if (streamUrl.startsWith('/')) {
|
||||
streamUrl = `https://cinesrc.st${streamUrl}`;
|
||||
}
|
||||
|
||||
allUrls.push({
|
||||
url: streamUrl,
|
||||
server: `CineSrc - ${providerObj.name || provider}`,
|
||||
headers: resultData.headers || {
|
||||
Referer: "https://cinesrc.st/",
|
||||
Origin: "https://cinesrc.st"
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!allUrls.length) return null;
|
||||
|
||||
return {
|
||||
url: allUrls[0].url,
|
||||
headers: allUrls[0].headers,
|
||||
allUrls
|
||||
};
|
||||
}
|
||||
55
src/sources/cinezo.js
Normal file
55
src/sources/cinezo.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import { fetchJson } from '../utils/helpers.js';
|
||||
|
||||
export async function getStream({ id, s, e }) {
|
||||
const isTv = s != null && e != null;
|
||||
const referer = isTv
|
||||
? `https://player.cinezo.live/embed/tv/${id}?s=${s}&e=${e}`
|
||||
: `https://player.cinezo.live/embed/movie/${id}`;
|
||||
|
||||
const headers = {
|
||||
'Accept': '*/*',
|
||||
'Origin': 'https://player.cinezo.live',
|
||||
'Referer': referer,
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36 Edg/155.0.0.0'
|
||||
};
|
||||
|
||||
const hosts = [
|
||||
'https://proxy.yenime.net',
|
||||
'https://proxy1.flikhub.net'
|
||||
];
|
||||
|
||||
const sources = ['zendaya', 'berlin', 'jennifer', 'scarlet'];
|
||||
const allUrls = [];
|
||||
|
||||
for (const host of hosts) {
|
||||
for (const source of sources) {
|
||||
const url = isTv
|
||||
? `${host}/tv?id=${id}&season=${s}&episode=${e}&mode=json&sources=${source}&hevc=1`
|
||||
: `${host}/movie?id=${id}&mode=json&sources=${source}&hevc=1`;
|
||||
|
||||
try {
|
||||
const res = await fetchJson(url, { headers });
|
||||
const streamUrl = res?.source?.url;
|
||||
if (streamUrl) {
|
||||
allUrls.push({
|
||||
url: streamUrl,
|
||||
server: `Cinezo - ${res.source.label || source}`,
|
||||
headers: {
|
||||
Referer: 'https://player.cinezo.live/',
|
||||
Origin: 'https://player.cinezo.live'
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
if (allUrls.length) break;
|
||||
}
|
||||
|
||||
if (!allUrls.length) return null;
|
||||
|
||||
return {
|
||||
url: allUrls[0].url,
|
||||
headers: allUrls[0].headers,
|
||||
allUrls
|
||||
};
|
||||
}
|
||||
54
src/sources/hexa.js
Normal file
54
src/sources/hexa.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import { fetchJson, fetchText } from '../utils/helpers.js';
|
||||
|
||||
const API = "https://enc-dec.app/api";
|
||||
|
||||
function getRandomHex(size = 32) {
|
||||
const array = new Uint8Array(size);
|
||||
crypto.getRandomValues(array);
|
||||
return Array.from(array).map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
|
||||
export async function getStream({ id, s, e }) {
|
||||
const isTv = s != null && e != null;
|
||||
const key = getRandomHex(32);
|
||||
|
||||
const headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
|
||||
"Referer": "https://hexa.su/",
|
||||
"Accept": "text/plain",
|
||||
"X-Fingerprint-Lite": "e9136c41504646444",
|
||||
"X-Api-Key": key
|
||||
};
|
||||
|
||||
const encHexaRes = await fetchJson(`${API}/enc-hexa`);
|
||||
if (!encHexaRes || encHexaRes.status !== 200) return null;
|
||||
headers["X-Cap-Token"] = encHexaRes.result.token;
|
||||
|
||||
const url = isTv
|
||||
? `https://theemoviedb.hexa.su/api/tmdb/tv/${id}/season/${s}/episode/${e}/images`
|
||||
: `https://theemoviedb.hexa.su/api/tmdb/movie/${id}/images`;
|
||||
|
||||
const encrypted = await fetchText(url, { headers });
|
||||
if (!encrypted) return null;
|
||||
|
||||
const decRes = await fetchJson(`${API}/dec-hexa`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ text: encrypted, key })
|
||||
});
|
||||
|
||||
if (!decRes || decRes.status !== 200 || !decRes.result) return null;
|
||||
|
||||
const data = decRes.result;
|
||||
const streamUrl = data.url || data.file || (Array.isArray(data.sources) ? data.sources[0]?.url : null);
|
||||
|
||||
if (!streamUrl) return null;
|
||||
|
||||
return {
|
||||
url: streamUrl,
|
||||
headers: {
|
||||
Referer: "https://hexa.su/",
|
||||
Origin: "https://hexa.su"
|
||||
}
|
||||
};
|
||||
}
|
||||
36
src/sources/hyper.js
Normal file
36
src/sources/hyper.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { fetchJson } from '../utils/helpers.js';
|
||||
|
||||
export async function getStream({ id, s, e }) {
|
||||
const isTv = s != null && e != null;
|
||||
const path = isTv
|
||||
? `/local/stream/series/tmdb:${id}:${s}:${e}.json`
|
||||
: `/local/stream/movie/tmdb:${id}.json`;
|
||||
|
||||
const url = `https://hyper.stravo.site${path}`;
|
||||
const res = await fetchJson(url);
|
||||
if (!res || !Array.isArray(res.streams)) return null;
|
||||
|
||||
const validStreams = res.streams.filter(item => {
|
||||
if (!item.url || item.externalUrl) return false;
|
||||
if (typeof item.title === 'string' && item.title.includes('🔒')) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!validStreams.length) return null;
|
||||
|
||||
const allUrls = validStreams.map(item => ({
|
||||
url: item.url,
|
||||
server: `Hyper - ${item.title?.replace(/[^\x20-\x7E]+/g, '').trim() || 'Server'}`,
|
||||
headers: item.behaviorHints?.proxyHeaders?.request || {
|
||||
Referer: 'https://mzfi.me/',
|
||||
Accept: '*/*'
|
||||
},
|
||||
skipProxy: item.behaviorHints?.notWebReady === false
|
||||
}));
|
||||
|
||||
return {
|
||||
url: allUrls[0].url,
|
||||
headers: allUrls[0].headers,
|
||||
allUrls
|
||||
};
|
||||
}
|
||||
30
src/sources/yastream.js
Normal file
30
src/sources/yastream.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { fetchJson } from '../utils/helpers.js';
|
||||
|
||||
export async function getStream({ id, s, e }) {
|
||||
const isTv = s != null && e != null;
|
||||
const path = isTv
|
||||
? `/stream/series/tmdb:${id}:${s}:${e}.json`
|
||||
: `/stream/movie/tmdb:${id}.json`;
|
||||
|
||||
const url = `https://yastream.tamthai.de${path}`;
|
||||
const res = await fetchJson(url);
|
||||
if (!res || !Array.isArray(res.streams) || !res.streams.length) return null;
|
||||
|
||||
const allUrls = res.streams.map(item => {
|
||||
if (!item.url) return null;
|
||||
return {
|
||||
url: item.url,
|
||||
server: `YaStream - ${item.name?.replace(/\n/g, ' ') || 'Server'}`,
|
||||
headers: item.behaviorHints?.proxyHeaders?.request || undefined,
|
||||
skipProxy: item.behaviorHints?.notWebReady === false
|
||||
};
|
||||
}).filter(Boolean);
|
||||
|
||||
if (!allUrls.length) return null;
|
||||
|
||||
return {
|
||||
url: allUrls[0].url,
|
||||
headers: allUrls[0].headers,
|
||||
allUrls
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// usage: npm test
|
||||
// Configure the variables below to customize your testing environment
|
||||
|
||||
import fs from "fs";
|
||||
import fs, { truncate } from "fs";
|
||||
import path from "path";
|
||||
import VylaSDK from "../src/sdk.js";
|
||||
import dotenv from "dotenv";
|
||||
@@ -13,13 +13,13 @@ const CONFIG = {
|
||||
TV_ID: "37854", // TV TMDB ID to test, for anime I recommend using a random ID like 37854
|
||||
TV_SEASON: "1", // TV Season to test
|
||||
TV_EPISODE: "1", // TV Episode to test
|
||||
STREAM_SOURCE: "atsu", // Source key to test
|
||||
STREAM_SOURCE: "cinezo", // Source key to test
|
||||
|
||||
TEST_SUBTITLE: false,
|
||||
TEST_DOWNLOAD: false,
|
||||
TEST_MOVIE: false,
|
||||
TEST_TV: false,
|
||||
TEST_MANGA: true,
|
||||
TEST_MOVIE: true,
|
||||
TEST_TV: true,
|
||||
TEST_MANGA: false,
|
||||
MANGA_QUERY: "Steel Ball Run",
|
||||
|
||||
EXTRA_SDK_PARAMS: {
|
||||
|
||||
Reference in New Issue
Block a user