diff --git a/.js b/.js new file mode 100644 index 0000000..f6774f9 --- /dev/null +++ b/.js @@ -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(); diff --git a/src/sources/fmovies4u.js b/src/sources/fmovies4u.js index 44a4b2d..c0d496a 100644 --- a/src/sources/fmovies4u.js +++ b/src/sources/fmovies4u.js @@ -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) { diff --git a/src/sources/torrentio.js b/src/sources/torrentio.js index 5dea949..3ef7b88 100644 --- a/src/sources/torrentio.js +++ b/src/sources/torrentio.js @@ -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(); + }); } \ No newline at end of file