Spaces:
Paused
Paused
| const express = require("express"); | |
| const { chromium } = require("playwright-core"); | |
| const { execSync } = require("child_process"); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| async function getChromiumPath() { | |
| try { | |
| return execSync("which chromium-browser || which google-chrome || which chromium") | |
| .toString() | |
| .trim(); | |
| } catch { | |
| return null; | |
| } | |
| } | |
| app.get("/search", async (req, res) => { | |
| const movieName = req.query.movie; | |
| if (!movieName) { | |
| return res.status(400).json({ error: "Missing 'movie' query parameter" }); | |
| } | |
| const chromiumPath = await getChromiumPath(); | |
| console.log(`Chromium Path: ${chromiumPath || "Using Playwright's default"}`); | |
| const browser = await chromium.launch({ | |
| headless: true, | |
| executablePath: chromiumPath || undefined, | |
| args: ["--no-sandbox", "--disable-blink-features=AutomationControlled", "--disable-dev-shm-usage"] | |
| }); | |
| const context = await browser.newContext({ | |
| userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" | |
| }); | |
| const page = await context.newPage(); | |
| try { | |
| console.log(`Searching for: ${movieName}`); | |
| await page.goto("https://www.fzmovies.net/csearch.php", { waitUntil: "domcontentloaded", timeout: 60000 }); | |
| await page.fill("#searchname", movieName); | |
| await Promise.all([ | |
| page.click('input[type="submit"][name="Search"]'), | |
| page.waitForNavigation({ waitUntil: "domcontentloaded", timeout: 60000 }) | |
| ]); | |
| // Step 1: Get first movie result link | |
| const movieData = await page.evaluate(() => { | |
| const firstResult = document.querySelector(".mainbox a"); | |
| return firstResult ? { title: firstResult.innerText.trim(), link: firstResult.href } : null; | |
| }); | |
| if (!movieData) { | |
| console.log("No movie found!"); | |
| await browser.close(); | |
| return res.status(404).json({ error: "Movie not found" }); | |
| } | |
| console.log(`Movie Found: ${movieData.title}`); | |
| await page.goto(movieData.link, { waitUntil: "domcontentloaded", timeout: 60000 }); | |
| // Step 2: Extract the LAST download1.php link | |
| const downloadPageLink = await page.evaluate(() => { | |
| const baseURL = "https://www.fzmovies.net/"; | |
| const links = document.querySelectorAll('a[href*="download1.php?downloadoptionskey="]'); | |
| return links.length ? baseURL + links[links.length - 1].getAttribute("href") : null; | |
| }); | |
| if (!downloadPageLink) { | |
| await browser.close(); | |
| return res.status(404).json({ error: "Download link not found" }); | |
| } | |
| await page.goto(downloadPageLink, { waitUntil: "domcontentloaded", timeout: 60000 }); | |
| // Step 3: Extract "download.php" page link (LAST one) | |
| const finalDownloadPage = await page.evaluate(() => { | |
| const baseURL = "https://www.fzmovies.net/"; | |
| const links = document.querySelectorAll('a[href*="download.php?downloadkey="]'); | |
| return links.length ? baseURL + links[links.length - 1].getAttribute("href") : null; | |
| }); | |
| if (!finalDownloadPage) { | |
| await browser.close(); | |
| return res.status(404).json({ error: "Final download page not found" }); | |
| } | |
| await page.goto(finalDownloadPage, { waitUntil: "domcontentloaded", timeout: 60000 }); | |
| // Step 4: Extract LAST redirection link (dlink.php) | |
| const redirectedDownloadLink = await page.evaluate(() => { | |
| const links = document.querySelectorAll('a[href*="dlink.php?id="]'); | |
| return links.length ? links[links.length - 1].href : null; | |
| }); | |
| if (!redirectedDownloadLink) { | |
| await browser.close(); | |
| return res.status(404).json({ error: "Redirected download link not found" }); | |
| } | |
| console.log(`Redirecting to final download page: ${redirectedDownloadLink}`); | |
| // Step 5: Follow the redirection, intercept network requests, and extract the REAL file URL | |
| const downloadPage = await context.newPage(); | |
| let finalDownloadURL = null; | |
| // Capture the final URL using network interception | |
| downloadPage.on("response", async (response) => { | |
| const url = response.url(); | |
| if (url.match(/\.(mp4|mkv|avi|mov)$/i)) { | |
| console.log(`Final File Found: ${url}`); | |
| finalDownloadURL = url; | |
| } | |
| }); | |
| await downloadPage.goto(redirectedDownloadLink, { waitUntil: "domcontentloaded", timeout: 60000 }); | |
| // If no final URL is found, check the current page URL (sometimes it's a direct link) | |
| if (!finalDownloadURL) { | |
| finalDownloadURL = downloadPage.url(); | |
| } | |
| await downloadPage.close(); | |
| if (!finalDownloadURL) { | |
| await browser.close(); | |
| return res.status(500).json({ error: "Failed to retrieve final download link" }); | |
| } | |
| // Extract movie name from filename in URL | |
| let cleanedMovieTitle = movieData.title | |
| .replace(/[_\.-]/g, " ") // Replace underscores and hyphens with spaces | |
| .replace(/\b(BluRay|HD|720p|1080p|480p|fzmovies|net|mp4|mkv|avi|mov)\b/gi, "") // Remove extra words | |
| .replace(/\(\s*\)/g, "") // Remove empty parentheses | |
| .replace(/\s+/g, " ") // Remove extra spaces | |
| .replace(/\b[a-f0-9]{32}\b/, "") // Remove hash codes | |
| .trim(); | |
| console.log(`Movie Title: ${cleanedMovieTitle}`); | |
| console.log(`Final Download Link: ${finalDownloadURL}`); | |
| await browser.close(); | |
| return res.json({ | |
| movieTitle: cleanedMovieTitle, | |
| downloadLink: finalDownloadURL | |
| }); | |
| } catch (error) { | |
| console.error("Error:", error.message); | |
| await browser.close(); | |
| return res.status(500).json({ error: "Internal server error", details: error.message }); | |
| } | |
| }); | |
| // Start the Express server | |
| app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`)); |