| const express = require("express"); |
| const { chromium } = require("playwright-core"); |
| const cors = require("cors"); |
| const { execSync } = require("child_process"); |
| const axios = require("axios"); |
|
|
| const app = express(); |
| const PORT = process.env.PORT || 7860; |
|
|
| app.use(cors()); |
|
|
| app.get("/download-links", async (req, res) => { |
| const { url } = req.query; |
|
|
| if (!url) { |
| return res.status(400).json({ error: "Missing 'url' query parameter" }); |
| } |
|
|
| try { |
| console.log(`Scraping: ${url}`); |
| const downloadLinks = await getVideoLinks(url); |
| res.json({ downloadLinks }); |
| } catch (error) { |
| res.status(500).json({ error: "Failed to fetch download links", details: error.message }); |
| } |
| }); |
|
|
| async function getChromiumPath() { |
| try { |
| return execSync("which chromium-browser || which google-chrome || which chromium") |
| .toString() |
| .trim(); |
| } catch { |
| return null; |
| } |
| } |
|
|
| async function getVideoLinks(downloadPageUrl) { |
| console.log(`Opening Playwright: ${downloadPageUrl}`); |
|
|
| 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 { |
| await page.goto(downloadPageUrl, { waitUntil: "domcontentloaded", timeout: 60000 }); |
|
|
| |
| await page.waitForTimeout(5000); |
| await page.waitForSelector('a[href*="ggredi.info/download.php"]', { timeout: 60000 }); |
|
|
| |
| const videoLinks = await page.evaluate(() => |
| Array.from(document.querySelectorAll('a[href*="ggredi.info/download.php"]')).map(link => ({ |
| quality: link.innerText.trim(), |
| url: link.href |
| })) |
| ); |
|
|
| await browser.close(); |
|
|
| |
| const directDownloadLinks = {}; |
| const promises = videoLinks |
| .filter(link => link.quality.includes("360") || link.quality.includes("720")) |
| .map(async link => { |
| const finalLink = await getFinalMp4Link(link.url); |
| if (finalLink) { |
| directDownloadLinks[link.quality.replace(/\D/g, "") + "p"] = finalLink; |
| } |
| }); |
|
|
| await Promise.all(promises); |
| return directDownloadLinks; |
| } catch (error) { |
| console.error("Error extracting video links:", error.message); |
| await browser.close(); |
| return { "360p": "Not available", "720p": "Not available" }; |
| } |
| } |
|
|
| async function getFinalMp4Link(redirectLink) { |
| try { |
| console.log(`Following redirect: ${redirectLink}`); |
|
|
| const response = await axios.get(redirectLink, { maxRedirects: 5 }); |
|
|
| const finalUrl = response.request.res.responseUrl || response.config.url; |
|
|
| if (finalUrl && finalUrl.includes(".mp4")) { |
| console.log(`Final MP4 Link: ${finalUrl}`); |
| return finalUrl; |
| } else { |
| console.log("No valid MP4 link found."); |
| return null; |
| } |
| } catch (error) { |
| console.error("Error fetching final MP4 link:", error.message); |
| return null; |
| } |
| } |
|
|
| |
| app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`)); |