import express from 'express'; import { chromium } from 'playwright'; import cors from 'cors'; import axios from 'axios'; import fetch from 'node-fetch'; import * as cheerio from 'cheerio'; import fakeUa from 'fake-useragent'; import { FormData } from 'formdata-node'; import dotenv from 'dotenv'; import os from 'os'; import { io } from "socket.io-client"; import ytSearch from 'yt-search'; import pkg from 'fast-levenshtein'; const { get: levenshtein } = pkg; dotenv.config(); const app = express(); app.use(express.json()); app.use(cors()); app.get('/', async (req, res) => { return res.status(200).json({ success: true, message: 'DOWNLOADER' }); }); app.get('/mediafire', async (req, res) => { const { url } = req.query; if (!url) { return res.status(400).json({ success: false, message: 'URL is required' }); } try { const downloadInfo = await mediafire(url); return res.json(downloadInfo); } catch (error) { console.error('Error:', error); return res.status(500).json({ success: false, message: error.message }); } }); async function mediafire(url) { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ userAgent: 'Mozilla/5.0 (Linux; Android 6.0; iris50) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36', }); const page = await context.newPage(); try { await page.goto(url); let downloadInfo = await page.evaluate(() => { const fileNameElement = document.querySelector('.dl-btn-label'); const fileName = fileNameElement ? fileNameElement.textContent.trim() : ''; const downloadLinkElement = document.querySelector('#downloadButton'); const downloadLink = downloadLinkElement ? downloadLinkElement.href : ''; const fileSizeText = downloadLinkElement ? downloadLinkElement.textContent : ''; const sizeMatch = fileSizeText.match(/\(([^)]+)\)/); const fileSize = sizeMatch ? sizeMatch[1] : ''; const metaTags = Array.from(document.querySelectorAll('meta')).reduce((acc, meta) => { const name = meta.getAttribute('name') || meta.getAttribute('property'); const content = meta.getAttribute('content'); if (name && content) acc[name.split(':')[1]] = content; return acc; }, {}); return { fileName, downloadLink, fileSize, meta: metaTags, }; }); if (!downloadInfo.downloadLink.startsWith('https://down')) { await browser.close(); const newBrowser = await chromium.launch({ headless: true }); const newContext = await newBrowser.newContext({ userAgent: 'Mozilla/5.0 (Linux; Android 6.0; iris50) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Mobile Safari/537.36', }); const newPage = await newContext.newPage(); await newPage.goto(downloadInfo.downloadLink); const updatedInfo = await newPage.evaluate(() => { const downloadLink = document.querySelector('#downloadButton')?.href || ''; return { downloadLink }; }); downloadInfo.downloadLink = updatedInfo.downloadLink; await newBrowser.close(); } return downloadInfo; } catch (error) { console.error('Error:', error.message); return { success: false, message: error.message }; } finally { if (browser) { await browser.close(); } } } app.get('/ytdl', async (req, res) => { const id = req.query.id; if (!id) { return res.status(400).send('Parameter "id" is required.'); } try { const response = await fetch(`https://api.allorigins.win/raw?url=https://ytdlp.online/stream?command=https://www.youtube.com/watch?v=${id} --get-url`, { timeout: 1000, cache: 'no-store' }); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const responseText = await response.text(); const urls = responseText.split('\n') .filter(line => line.trim().startsWith('data:')) .map(line => line.substring(5).trim()) .filter(url => url.startsWith('http')); res.json({ data: urls }); } catch (error) { console.error(error); res.status(500).send('Something went wrong while processing the request.'); } }); app.get('/ytdl/v1', async (req, res) => { const id = req.query.id; if (!id) { return res.status(400).json({ error: 'Parameter "id" is required.' }); } try { const response = await fetch( `https://api.allorigins.win/raw?url=https://ytdlp.online/stream?command=https://www.youtube.com/watch?v=${id} -j`, { timeout: 1000, cache: 'no-store' } ); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const responseText = await response.text(); const parsedData = responseText .split('\n') .map(line => line.trim().substring(5).trim()) .filter(line => { try { JSON.parse(line); return true; } catch { return false; } }) .map(line => JSON.parse(line)); if (parsedData.length === 0) { return res.status(404).json({ error: 'No valid data found.' }); } res.json({ data: parsedData }); } catch (error) { console.error(error); res.status(500).json({ error: 'Something went wrong while processing the request.' }); } }); app.get('/ytdl/v2', async (req, res) => { const id = req.query.id; if (!id) { return res.status(400).json({ error: 'Parameter "id" is required.' }); } try { const response = await fetch( `https://api.allorigins.win/raw?url=https://ytdlp.online/stream?command=https://www.youtube.com/watch?v=${id}`, { timeout: 1000, cache: 'no-store' } ); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const responseText = await response.text(); const lastLine = responseText .split('\n') .map(line => line.trim().substring(5).trim()) .filter(Boolean); const extractDownloadLinks = (data) => { return [...new Set(data.flatMap(item => { const $ = cheerio.load(item); return $("a[href^='/download/']").map((_, el) => "https://ytdlp.online" + $(el).attr("href")).get(); }))]; }; if (!lastLine) return res.status(404).json({ error: 'No valid data found.' }); res.json({ data: extractDownloadLinks(lastLine)[0] }); } catch (error) { console.error(error); res.status(500).json({ error: 'Something went wrong while processing the request.' }); } }); app.get('/ytdl/search', async (req, res) => { const { query, limit = 5 } = req.query; if (!query) return res.status(400).json({ error: 'Parameter "query" is required.' }); try { const result = await ytSearch(query); if (!result.videos || result.videos.length === 0) { return res.status(404).json({ error: 'No results found.' }); } const cos = levenshtein; const videosWithSimilarity = result.videos.map(video => { const videoId = video.url.split('v=')[1]; return { id: videoId, title: video.title, url: video.url, duration: video.timestamp, views: video.views, uploaded: video.ago, author: video.author.name, similarity: 1 - (cos(query, video.title) / Math.max(query.length, video.title.length)) }; }); const sortedVideos = videosWithSimilarity.sort((a, b) => b.similarity - a.similarity).sort((a, b) => b.views - a.views); const topVideos = sortedVideos.slice(0, parseInt(limit)); res.json({ query, limit: parseInt(limit), videos: topVideos }); } catch (error) { console.error(error); res.status(500).json({ error: 'Failed to fetch YouTube search results.' }); } }); app.get('/ace', async (req, res) => { const id = req.query.id; if (!id) { return res.status(400).send('Parameter "id" is required.'); } try { const apiUrl = `https://www.acethinker.com/downloader/api/video_info.php?url=https://www.youtube.com/watch?v=${id}&israpid=1&ismp3=0`; const response = await fetch(apiUrl); if (!response.ok) throw new Error('AceThinker API request failed'); const processedData = await response.json(); res.json(processedData); } catch (error) { console.error(error); res.status(500).send('Something went wrong while processing the request.'); } }); const genSpinner = () => Math.random().toString(36).substring(2, 10); app.get("/y232", async (req, res) => { const id = req.query.id; if (!id) { return res.status(400).send('Parameter "id" is required.'); } try { const spinnerid = genSpinner(); const socket = io("https://api.y232.live"); const data = { url: `https://www.youtube.com/watch?v=${id}`, spinnerid, method: "streams" }; socket.emit("getInfoEvent", data); socket.on("done", (response) => { res.status(200).send(response); socket.close(); }); socket.on("error", (err) => { res.status(500).send({ success: false, error: err.message }); socket.close(); }); } catch (error) { console.error(error); res.status(500).send('Something went wrong while processing the request.'); } }); class Luluvdo { async download(url, output = 'json') { try { console.log(`[LOG] Memulai proses untuk URL: ${url}`); const idMatch = url.match(/(?:\/[de])\/([a-zA-Z0-9_-]+)/); const id = idMatch?.[1]; if (!id) throw new Error('Invalid URL: ID not found'); const client = axios.create({ headers: { 'User-Agent': fakeUa() }, withCredentials: true, }); console.log(`[LOG] Mengambil form dari halaman: https://luluvdo.com/d/${id}_h`); let formResult; do { const { data: pageData } = await client.get(`https://luluvdo.com/d/${id}_h`); const $ = cheerio.load(pageData); formResult = new FormData(); $('form#F1 input').each((_, el) => { const name = $(el).attr('name'); const value = $(el).val(); if (name && value) formResult.append(name, value); }); console.log(`[LOG] Form yang diambil: ${JSON.stringify(formResult, null, 2)}`); if (!formResult.has('hash')) { console.log('[LOG] Form tidak valid, mencoba lagi...'); await new Promise(resolve => setTimeout(resolve, 2000)); } } while (!formResult.has('hash')); console.log('[LOG] Form berhasil diambil, mengirimkan permintaan untuk mendapatkan link unduhan'); let result; do { const { data: postData } = await client.post(`https://luluvdo.com/d/${id}_h`, formResult); const $$ = cheerio.load(postData); result = { size: $$('table tr:nth-child(1) td:nth-child(2)').text().trim() || 'N/A', bytes: $$('table tr:nth-child(2) td:nth-child(2)').text().trim() || 'N/A', ip: $$('table tr:nth-child(3) td:nth-child(2)').text().trim() || 'N/A', link: $$('a.btn.btn-gradient.submit-btn').attr('href') || 'N/A', expired: $$('div.text-center.text-danger').text().trim() || 'N/A', }; console.log(`[LOG] Hasil: ${JSON.stringify(result, null, 2)}`); if (result.link === 'N/A') { console.log('[LOG] Link unduhan belum tersedia, mencoba lagi...'); await new Promise(resolve => setTimeout(resolve, 2000)); } } while (result.link === 'N/A'); console.log(`[LOG] Link unduhan berhasil ditemukan: ${result.link}`); let media = null; if (output === 'file') { console.log('[LOG] Mengunduh file...'); const { data: buffer, headers } = await client.get(result.link, { headers: { Referer: `https://luluvdo.com/d/${id}_h`, 'X-Forwarded-For': result.ip, }, responseType: 'arraybuffer', }); media = { buffer: Buffer.from(buffer), contentType: headers['content-type'] || 'application/octet-stream', fileName: result.link.split('/').pop() || 'downloaded_file', }; console.log('[LOG] File berhasil diunduh'); } return media ? { ...result, ...media } : result; } catch (error) { console.error(`[ERROR] Proses gagal: ${error.message}`); throw new Error(`Download failed: ${error.message}`); } } } app.get('/luluvdo', async (req, res) => { const { url, output } = req.query; const luluvdo = new Luluvdo(); if (!url) { return res.status(400).json({ error: 'URL is required' }); } try { const result = await luluvdo.download(url, output || 'json'); res.status(200).json(result); } catch (error) { console.error(`[ERROR] Download failed: ${error.message}`); res.status(500).json({ error: error.message }); } }); const PORT = process.env.PORT || 7860; app.listen(PORT, async () => { console.log(`Server running on port ${PORT}`); }); process.on('SIGINT', async () => { process.exit(0); });