down / app.js
wudysoft's picture
Update app.js
953204b verified
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);
});