From 5b9a21310c113de482f8d049fc33a0e9df324548 Mon Sep 17 00:00:00 2001 From: aka paul <50n50@noreply.localhost> Date: Fri, 24 Oct 2025 20:08:38 +0000 Subject: [PATCH] Update vidfast/vidfast.js --- vidfast/vidfast.js | 135 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 13 deletions(-) diff --git a/vidfast/vidfast.js b/vidfast/vidfast.js index 5804590..e1ca9d3 100644 --- a/vidfast/vidfast.js +++ b/vidfast/vidfast.js @@ -16,7 +16,6 @@ async function searchResults(keyword) { const shouldFilter = !matchesKeyword(keyword, skipTitleFilter); - // --- TMDB Section --- const encodedKeyword = encodeURIComponent(keyword); let baseUrl = null; @@ -184,6 +183,8 @@ async function extractEpisodes(url) { } async function extractStreamUrl(ID) { + const startTime = Date.now(); + if (ID.includes('movie')) { const tmdbID = ID.replace('/movie/', ''); const headersOne = { @@ -202,14 +203,26 @@ async function extractStreamUrl(ID) { const streams = []; - if (streamResponse) { - streams.push("Default", streamResponse.url); - }; + if (streamResponse && streamResponse.defaultUrl) { + streams.push("1080p", streamResponse.defaultUrl); + } + + if (streamResponse && streamResponse.vFastUrl) { + const fourKResult = await ilovearmpits(streamResponse.vFastUrl); + if (fourKResult.available && fourKResult.url) { + streams.push("4K", fourKResult.url); + } + } const final = { streams, subtitles: streamResponse.subtitles || "None" }; + + const endTime = Date.now(); + const elapsed = ((endTime - startTime) / 1000).toFixed(2); + console.log(`Stream fetched in ${elapsed}s`); + console.log(JSON.stringify(final)); return JSON.stringify(final); } else if (ID.includes('tv')) { @@ -231,18 +244,29 @@ async function extractStreamUrl(ID) { const imdbID = tmdbData.external_ids.imdb_id; const streamResponse = await ilovefeet(imdbID, true, seasonNumber, episodeNumber, 'm3u8'); - const stream = streamResponse.url; const streams = []; - if (stream) { - streams.push("Default", stream); - }; + if (streamResponse && streamResponse.defaultUrl) { + streams.push("1080p", streamResponse.defaultUrl); + } + + if (streamResponse && streamResponse.vFastUrl) { + const fourKResult = await ilovearmpits(streamResponse.vFastUrl); + if (fourKResult.available && fourKResult.url) { + streams.push("4K", fourKResult.url); + } + } const final = { streams, subtitles: streamResponse.subtitles || "None" }; + + const endTime = Date.now(); + const elapsed = ((endTime - startTime) / 1000).toFixed(2); + console.log(`Stream fetched in ${elapsed}s`); + console.log(JSON.stringify(final)); return JSON.stringify(final); } @@ -267,6 +291,76 @@ async function soraFetch(url, options = { headers: {}, method: 'GET', body: null } } +async function ilovearmpits(m3u8Url) { + try { + const headers = { + "Accept": "*/*", + "User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36", + "Referer": "https://vidfast.pro/" + }; + + const response = await fetchv2(m3u8Url, headers); + const playlistContent = await response.text(); + + const has4K = playlistContent.includes('RESOLUTION=3840x2160'); + + if (!has4K) { + console.log(`4K Check for ${m3u8Url}: NO`); + return { available: false, url: null }; + } + + const lines = playlistContent.split('\n'); + let fourKPath = null; + let fourKCount = 0; + + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes('RESOLUTION=3840x2160')) { + fourKCount++; + if (fourKCount === 2 && i + 1 < lines.length) { + fourKPath = lines[i + 1].trim(); + break; + } + } + } + + if (!fourKPath && fourKCount === 1) { + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes('RESOLUTION=3840x2160')) { + if (i + 1 < lines.length) { + fourKPath = lines[i + 1].trim(); + break; + } + } + } + } + + if (!fourKPath) { + console.log('4K resolution found but could not extract path'); + return { available: false, url: null }; + } + + let baseUrl = ''; + if (m3u8Url.startsWith('https://')) { + const afterProtocol = m3u8Url.substring(8); + const hostEnd = afterProtocol.indexOf('/'); + const host = hostEnd !== -1 ? afterProtocol.substring(0, hostEnd) : afterProtocol; + baseUrl = 'https://' + host; + } else if (m3u8Url.startsWith('http://')) { + const afterProtocol = m3u8Url.substring(7); + const hostEnd = afterProtocol.indexOf('/'); + const host = hostEnd !== -1 ? afterProtocol.substring(0, hostEnd) : afterProtocol; + baseUrl = 'http://' + host; + } + + const full4KUrl = fourKPath.startsWith('http') ? fourKPath : `${baseUrl}${fourKPath}`; + + return { available: true, url: full4KUrl }; + } catch (error) { + console.log('Error checking 4K availability: ' + error); + return { available: false, url: null }; + } +} + async function ilovefeet(imdbId, isSeries = false, season = null, episode = null, preferredFormat = null) { const configUrl = 'https://raw.githubusercontent.com/yogesh-hacker/MediaVanced/refs/heads/main/sites/vidfast.py'; const configResponse = await fetchv2(configUrl); @@ -421,11 +515,24 @@ async function ilovefeet(imdbId, isSeries = false, season = null, episode = null }; let selectedServer = null; + let vFastServer = null; try { if (preferredFormat === 'm3u8') { const serverPromises = serverList.map((serverObj, index) => testServer(serverObj, index)); + const vFastServerObj = serverList.find(server => server.name === 'vFast'); + if (vFastServerObj) { + const vFastIndex = serverList.indexOf(vFastServerObj); + try { + vFastServer = await testServer(vFastServerObj, vFastIndex); + } catch (error) { + console.log('vFast server failed: ' + error.message); + } + } else { + console.log('vFast server not found in server list'); + } + const raceForSubtitles = new Promise((resolve, reject) => { let completedCount = 0; let firstWorkingServer = null; @@ -508,17 +615,19 @@ async function ilovefeet(imdbId, isSeries = false, season = null, episode = null } return { - url: selectedServer.data.url, - originalUrl: selectedServer.data.url, + defaultUrl: selectedServer.data.url, + vFastUrl: vFastServer ? vFastServer.data.url : null, referer: "https://vidfast.pro/", format: selectedServer.format, subtitles: englishSubtitles, fullData: selectedServer.data, + vFastData: vFastServer ? vFastServer.data : null, serverStats: { total: serverList.length, - working: 1, - failed: serverList.length - 1, - selectedServerIndex: selectedServer.index + working: vFastServer ? 2 : 1, + failed: serverList.length - (vFastServer ? 2 : 1), + selectedServerIndex: selectedServer.index, + vFastServerIndex: vFastServer ? vFastServer.index : null } }; }