fixed fmovies4u and torrentio

This commit is contained in:
2026-11-10 13:50:15 -08:00
parent 1a20acc8c3
commit 4ff64819d7
3 changed files with 178 additions and 105 deletions

58
.js Normal file
View File

@@ -0,0 +1,58 @@
const url = "https://s.torrentio.to/v1/sources/stream?type=movie&id=936075";
const headers = {
"Accept": "text/event-stream",
"Accept-Language": "en-US,en;q=0.9",
"Origin": "https://stream.vidplay.to",
"Referer": "https://stream.vidplay.to/",
"Priority": "u=1, i",
"Sec-CH-UA": '"Not-A.Brand";v="99", "Microsoft Edge";v="157", "Chromium";v="157"',
"Sec-CH-UA-Mobile": "?0",
"Sec-CH-UA-Platform": '"Windows"',
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "cross-site",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/157.0.0.0 Safari/537.36 Edg/157.0.0.0"
};
async function main() {
try {
const response = await fetch(url, {
method: "GET",
headers
});
console.log("Status:", response.status);
console.log("Content-Type:", response.headers.get("content-type"));
console.log("\n--- RESPONSE ---\n");
if (!response.ok) {
console.log(await response.text());
return;
}
if (!response.body) {
console.log("Empty response body.");
return;
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
process.stdout.write(decoder.decode(value, { stream: true }));
}
process.stdout.write(decoder.decode());
} catch (error) {
console.error("Request failed:", error.message);
}
}
main();

View File

@@ -16,14 +16,27 @@ const PLAYBACK_HEADERS = {
};
const PROVIDERS = [
'moovie',
'mapple',
'anikoto',
'anikototv',
'anistream',
'aniwave',
'animex',
'yenime',
'otakutsu',
'vidnest',
'phantomflix',
'movy',
'cinetaro',
'filmu',
'streamingunity',
'vaultplayer',
'vixsrc',
'ernax',
'phantomflix',
'moovie',
'watchflux',
'xtream',
'rarefilmm'
];
function extractStreams(data, providerName) {

View File

@@ -1,18 +1,9 @@
const BASE_URL = 'https://s.torrentio.to';
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36';
const HEADERS = {
'User-Agent': UA,
Referer: 'https://stream.vidplay.to/',
Origin: 'https://stream.vidplay.to',
Accept: 'text/event-stream, */*',
'Accept-Language': 'en-US,en;q=0.9',
};
import https from 'node:https';
const PLAYBACK_HEADERS = {
'User-Agent': UA,
Referer: 'https://stream.vidplay.to/',
Origin: 'https://stream.vidplay.to',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/157.0.0.0 Safari/537.36 Edg/157.0.0.0',
'Referer': 'https://stream.vidplay.to/',
'Origin': 'https://stream.vidplay.to',
};
export async function getStream(args) {
@@ -20,109 +11,120 @@ export async function getStream(args) {
if (!id) return null;
const isTv = s != null && e != null;
const targetUrl = isTv
? `${BASE_URL}/v1/sources/stream?type=tv&id=${id}&s=${s}&e=${e}`
: `${BASE_URL}/v1/sources/stream?type=movie&id=${id}`;
const requestPath = isTv
? `/v1/sources/stream?type=tv&id=${id}&s=${s}&e=${e}`
: `/v1/sources/stream?type=movie&id=${id}`;
try {
const res = await fetch(targetUrl, {
headers: HEADERS,
signal: AbortSignal.timeout(args?.config?.timeout || 25000),
});
return new Promise((resolve) => {
const options = {
hostname: 's.torrentio.to',
port: 443,
path: requestPath,
method: 'GET',
headers: {
'Accept': 'text/event-stream',
'Accept-Language': 'en-US,en;q=0.9',
'Origin': 'https://stream.vidplay.to',
'Referer': 'https://stream.vidplay.to/',
'Sec-CH-UA': '"Not-A.Brand";v="99", "Microsoft Edge";v="157", "Chromium";v="157"',
'Sec-CH-UA-Mobile': '?0',
'Sec-CH-UA-Platform': '"Windows"',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/157.0.0.0 Safari/537.36 Edg/157.0.0.0',
'Connection': 'keep-alive',
},
timeout: 25000,
};
if (!res.ok || !res.body) return null;
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
const allUrls = [];
const seen = new Set();
let buffer = '';
let resolved = false;
outer: while (true) {
const { done, value } = await reader.read();
if (done) break;
const done = (result) => {
if (resolved) return;
resolved = true;
try { req.destroy(); } catch { }
resolve(result);
};
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
const trimmed = line.trim();
if (trimmed === 'event: done') {
try { await reader.cancel(); } catch { }
break outer;
}
if (trimmed.startsWith('data: ')) {
try {
const data = JSON.parse(trimmed.slice(6));
if (Array.isArray(data?.sources)) {
for (const src of data.sources) {
if (!src?.url || seen.has(src.url)) continue;
seen.add(src.url);
const provName = src.provider?.name || data.provider?.name || 'Server';
const rawQ = src.quality ? String(src.quality).trim() : 'Auto';
const quality = /^\d+$/i.test(rawQ)
? `${rawQ}p`
: /^\d+p$/i.test(rawQ)
? rawQ.toLowerCase()
: rawQ;
const type = src.type || (src.url.includes('.m3u8') ? 'hls' : (src.url.includes('.mpd') ? 'dash' : 'mp4'));
allUrls.push({
url: src.url,
server: `Torrentio - ${provName}`,
quality,
type,
headers: PLAYBACK_HEADERS,
});
}
}
} catch { }
}
const req = https.request(options, (res) => {
if (res.statusCode !== 200) {
return done(null);
}
}
if (buffer.trim().startsWith('data: ')) {
try {
const data = JSON.parse(buffer.trim().slice(6));
if (Array.isArray(data?.sources)) {
for (const src of data.sources) {
if (!src?.url || seen.has(src.url)) continue;
seen.add(src.url);
res.setEncoding('utf8');
const provName = src.provider?.name || data.provider?.name || 'Server';
const rawQ = src.quality ? String(src.quality).trim() : 'Auto';
const quality = /^\d+$/i.test(rawQ)
? `${rawQ}p`
: /^\d+p$/i.test(rawQ)
? rawQ.toLowerCase()
: rawQ;
res.on('data', (chunk) => {
buffer += chunk;
const lines = buffer.split('\n');
buffer = lines.pop() || '';
const type = src.type || (src.url.includes('.m3u8') ? 'hls' : (src.url.includes('.mpd') ? 'dash' : 'mp4'));
for (const line of lines) {
const trimmed = line.trim();
allUrls.push({
url: src.url,
server: `Torrentio - ${provName}`,
quality,
type,
headers: PLAYBACK_HEADERS,
});
if (trimmed.startsWith('data: ')) {
try {
const data = JSON.parse(trimmed.slice(6));
if (Array.isArray(data?.sources)) {
for (const src of data.sources) {
if (!src?.url || seen.has(src.url)) continue;
seen.add(src.url);
const provName = src.provider?.name || data.provider?.name || 'Server';
const rawQ = src.quality ? String(src.quality).trim() : 'Auto';
const quality = /^\d+$/i.test(rawQ) ? `${rawQ}p` : rawQ;
const type = src.type || (src.url.includes('.m3u8') ? 'hls' : 'mp4');
allUrls.push({
url: src.url,
server: `Torrentio - ${provName}`,
quality,
type,
headers: PLAYBACK_HEADERS,
});
}
}
} catch { }
if (allUrls.length > 0) {
return done({
url: allUrls[0].url,
headers: allUrls[0].headers,
allUrls,
});
}
}
}
} catch { }
}
});
if (!allUrls.length) return null;
res.on('end', () => {
if (allUrls.length > 0) {
done({
url: allUrls[0].url,
headers: allUrls[0].headers,
allUrls,
});
} else {
done(null);
}
});
return {
url: allUrls[0].url,
headers: allUrls[0].headers,
allUrls,
};
} catch {
return null;
}
res.on('error', () => {
done(allUrls.length ? { url: allUrls[0].url, headers: allUrls[0].headers, allUrls } : null);
});
});
req.on('timeout', () => {
done(allUrls.length ? { url: allUrls[0].url, headers: allUrls[0].headers, allUrls } : null);
});
req.on('error', () => {
done(allUrls.length ? { url: allUrls[0].url, headers: allUrls[0].headers, allUrls } : null);
});
req.end();
});
}