const yts = require('yt-search'); const morgan = require('morgan'); const express = require('express'); const ytdl = require('ytdl-core'); const { Writable, pipeline } = require('stream'); const util = require('util'); const axios = require('axios'); const FormData = require('form-data') const cp = require('child_process') const os = require('os') const cheerio = require('cheerio') const cloudscraper = require('cloudscraper') const { File } = require('megajs') const { BingChat } = require("bing-chat-cjs-rnz"); let fetch; (async () => { fetch = (await import('node-fetch')).default; })(); // Regex untuk mengidentifikasi URL YouTube dan Mega const ytIdRegex = /(?:http(?:s|):\/\/|)(?:(?:www\.|)?youtube(?:\-nocookie|)\.com\/(?:shorts\/)?(?:watch\?.*(?:|\&)v=|embed\/|v\/)?|youtu\.be\/)([-_0-9A-Za-z]{11})/; // Fungsi untuk melakukan HTTP POST request const post = async (url, form, headers = {}) => { const response = await fetch(url, { method: 'post', body: new URLSearchParams(form), headers }); return response; }; //BIMG async function bimg(query) { let bimg = await import('bimg-new') let data = await bimg.generateImagesLinks(query) // Filter out links that end with '.svg' let filteredData = data.filter(i => !i.includes('.svg')); return filteredData } async function bingChat(text) { const api = new BingChat({ cookie: process.env.BING_IMAGE_COOKIE || "1hPKd66tX-wvyQtYG5F-UIzIYgcsNB1rgZ5jAGGDCu30pMnoh-X8tHkZ92BNUmQ_MlPKKMrERVXwPqf4XhUZRTjrfOrrAxH4CCqoJfdfDptUXPJXJOQ7duuJEy-2C4uSabwUjuvkRIlifbB-3WEa4Y4dTpcNm9dVnkT14Lawhf4ceGJax0IXF5gbgnlhtLZdUJ08WyGQSnllQVNc-IzsVbQ" }) const res = await api.sendMessage(text, { variant: 'Precise' }) return res?.text } // MEDIAFIRE DL async function mediafire(url) { return new Promise(async(resolve, reject) => { var a, b; if (!/https?:\/\/(www\.)?mediafire\.com/.test(url)) return resolve() const data = await axios.get(url).catch(function (error) {}) if (!data) { resolve() } else { const $ = cheerio.load(data.data); const Url = ($('#downloadButton').attr('href') || '').trim(); const url2 = ($('#download_link > a.retry').attr('href') || '').trim(); const $intro = $('div.dl-info > div.intro'); const filename = $intro.find('div.filename').text().trim(); const filetype = $intro.find('div.filetype > span').eq(0).text().trim(); const ext = ((b = (a = /\(\.(.*?)\)/.exec($intro.find('div.filetype > span').eq(1).text())) === null || a === void 0 ? void 0 : a[1]) === null || b === void 0 ? void 0 : b.trim()) || 'bin'; const $li = $('div.dl-info > ul.details > li'); const aploud = $li.eq(1).find('span').text().trim(); const filesize = $li.eq(0).find('span').text().trim(); const filesizeB = (0, formatSize)(filesize); const result = { url: Url || url2, url2, filename, filetype, ext, upload_date: aploud, filesize, filesizeB }; resolve(result) } }) } //SAVEIG async function igdl(query) { url_dl = []; let headers = { 'Accept': '*/*', 'Accept-Language': 'en-US,en;q=0.9', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Referer': 'https://saveig.app/', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'X-Requested-With': 'XMLHttpRequest' } let options = { method: 'POST', uri: 'https://saveig.app/api/ajaxSearch', headers: headers, formData: { q: query } } ch = cheerio.load(JSON.parse(await cloudscraper(options)).data); ch('.download-items__btn').each(function(a,b) { url_dl.push(ch(b).find('a').attr('href'))}) return url_dl; } //FBDL async function fby2mate(url) { try { let form = new FormData() form.append('q', url) form.append('vt', 'facebook') let data = await fetch(`https://y2mate.mx/api/ajaxSearch/facebook`, { method: 'POST', body: form, headers: { ...form.getHeaders() } }) data = await data.json() return data } catch (e) { return e } } //YTDL-CORE async function uploadBuffer(buffer) { return new Promise(async (resolve, reject) => { let res = await axios.post('https://ilhamdev-up.hf.space/upload', { file: buffer.toString('base64'), headers: { 'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0" } }).catch(e => reject(e)) if (res.status !== 200) { resolve(res?.statusText) } else { resolve(res?.data?.url) } }) } async function streamToBuffer(stream) { const chunks = []; const captureChunks = new Writable({ write(chunk, encoding, callback) { chunks.push(chunk); callback(); } }); await util.promisify(pipeline)(stream, captureChunks); return Buffer.concat(chunks); } function formatViews(viewCount) { if (viewCount >= 1000000000) { return (viewCount / 1000000000).toFixed(1) + 'B'; } else if (viewCount >= 1000000) { return (viewCount / 1000000).toFixed(1) + 'M'; } else { return viewCount >= 1000 ? (viewCount / 1000).toFixed(1) + 'K' : viewCount.toString(); } } function formatDuration(durationInSeconds) { const hours = Math.floor(durationInSeconds / 3600); const minutes = Math.floor((durationInSeconds % 3600) / 60); const seconds = durationInSeconds % 60; return hours > 0 ? hours + ':' + minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0') : minutes + ':' + seconds.toString().padStart(2, '0'); } function formatSize(bytes, si = false, dp = 2) { const thresh = si ? 1000 : 1024; if (Math.abs(bytes) < thresh) { return `${bytes} B`; } const units = si ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; let u = -1; const r = 10 ** dp; do { bytes /= thresh; ++u; } while ( Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1 ); return `${bytes.toFixed(dp)} ${units[u]}`; } async function ytmp4(url, quality = 'highestvideo') { try { const ID = ytdl.getVideoID(url), data = await ytdl.getInfo('https://www.youtube.com/watch?v=' + ID) const videoStream = await ytdl(ID, { filter: 'videoandaudio', quality: 'highestvideo' }); let buffer = await streamToBuffer(videoStream) let upload = await uploadBuffer(buffer) let format = ytdl.chooseFormat(data.formats, { filter: 'videoandaudio', quality: quality }); if (format) { return { title: data.videoDetails.title, description: data.videoDetails.description, channel: data.videoDetails.ownerChannelName, views: formatViews(data.videoDetails.viewCount), publish: data.videoDetails.publishDate, duration: formatDuration(data.videoDetails.lengthSeconds), size: format.contentLength ? formatSize(format.contentLength) : 0, quality: format.qualityLabel, thumb: data.videoDetails.thumbnails[0].url, dl_url: format.url, url_v2: upload, } } else { throw new Error('No suitable format found'); } } catch (error) { console.error('Error occurred:', error); return null; } } async function ytmp3(url, bitrate = 'lowestaudio') { try { const ID = ytdl.getVideoID(url), data = await ytdl.getInfo('https://www.youtube.com/watch?v=' + ID) let audioStream = await ytdl(ID, { filter: 'audioonly', quality: 'lowestaudio', }); let buffer = await streamToBuffer(audioStream) let upload = await uploadBuffer(buffer) let format = ytdl.chooseFormat(data.formats, { filter: 'audioonly', quality: bitrate }); if (format) { return { title: data.videoDetails.title, description: data.videoDetails.description, channel: data.videoDetails.ownerChannelName, views: formatViews(data.videoDetails.viewCount), publish: data.videoDetails.publishDate, duration: formatDuration(data.videoDetails.lengthSeconds), size: format.contentLength ? formatSize(format.contentLength) : 0, quality: format.audioQuality, thumb: data.videoDetails.thumbnails[0].url, dl_url: format.url, url_v2: upload } } else { throw new Error('No suitable format found'); } } catch (error) { console.error('Error occurred:', error); return null; } } // Fungsi untuk mengkonversi video dari YouTube const convert = async (url, v_id, ftype, fquality, fname, token, timeExpire) => { let params = { v_id, ftype, fquality, fname, token, timeExpire, client: 'yt5s.com' }; // Mengirim permintaan konversi let resServer = await (await post(url, params, { 'x-requested-key': 'de0cfuirtgf67a' })).json(); let server = resServer.c_server; // Jika tidak ada server dan tipe file adalah mp3, kembalikan null if (!server && ftype === 'mp3') return server || resServer.d_url || ''; // Mengambil data hasil konversi let data = await (await post(`${server}/api/json/convert`, params)).json(); let result; // Memeriksa status kode hasil konversi if (data.statusCode === 200) result = data.result; while (!result) { let json = await (await post(`${server}/api/json/convert`, params)).json(); if (json.statusCode === 200) { result = json.result; break; } await new Promise(resolve => setTimeout(resolve, 2000)); } return result; }; // Fungsi untuk mendownload video dari YouTube const youtubedl = async (url) => { let html = await (await fetch('https://yt5s.com/en32')).text(); let urlAjax = (html.match(/k_url_search="(.*?)"/) || [])[1]; let urlConvert = (html.match(/k_url_convert="(.*?)"/) || [])[1]; let json = await (await post(urlAjax, { q: url, vt: 'home' })).json(); let video = {}, audio = {}; if (!json?.links) throw json.mess; Object.values(json.links.mp4).map(({ k, size }) => video[k] = { quality: k, fileSizeH: size, fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1), download: convert.bind(null, urlConvert, json.vid, 'mp4', k, json.fn, json.token, parseInt(json.timeExpires)) }); Object.values(json.links.mp3).map(({ key, size }) => audio[key] = { quality: key, fileSizeH: size, fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1), download: convert.bind(null, urlConvert, json.vid, 'mp3', key.replace(/kbps/i, ''), json.fn, json.token, parseInt(json.timeExpires)) }); return { id: json.vid, title: json.title, thumbnail: `https://i.ytimg.com/vi/${json.vid}/0.jpg`, video, audio }; }; //TWITTER API async function twitterDL(url) { try { let form = new FormData(); form.append('q', url); form.append('lang', 'en'); let response = await fetch('https://x2twitter.com/api/ajaxSearch', { method: 'POST', body: form, headers: form.getHeaders() }); let data = await response.json(); const $ = cheerio.load(data?.data); const downloads = []; $('.dl-action a').each((index, element) => { const format = $(element).text().trim(); const url = $(element).attr('href'); downloads.push({ format, url }); }); const convertToMP3 = { url: $('.tw-middle a').attr('href') }; const result = { downloads, convert_to_mp3: convertToMP3 }; const hrefArray = []; $('a').each((index, element) => { const href = $(element).attr('href'); if (href && href !== '/' && href !== '#') { hrefArray.push(href); } }); return { result, hrefArray }; } catch (error) { return error; } } const app = express(); app.set('json spaces', 4); app.use(morgan('dev')); app.use(express.json()); const v8 = require('v8'); const start = Date.now() app.all('/', async (req, res) => { const status = {} status['diskUsage'] = cp.execSync('du -sh').toString().split('M')[0] + ' MB' const used = process.memoryUsage() for (let x in used) status[x] = formatSize(used[x]) const totalmem = os.totalmem() const freemem = os.freemem() status['memoryUsage'] = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}` // Menambahkan statistik heap V8 const heapStats = v8.getHeapStatistics(); for (let x in heapStats) status[x] = formatSize(heapStats[x]) // Menambahkan semua properti dan metode dari v8 for (let x in v8) { if (typeof v8[x] !== 'function') { status[x] = v8[x] } } const host = 'https://' + req.get('host'); const end = Date.now(); // Selesai menghitung waktu const latency = Math.abs((end - start) / 1000)+ ' ms'; // Menghitung latency res.json({ creator: `@${process.env['SPACE_AUTHOR_NAME'] || 'ALOK FF'}`, message: 'Hello World!', uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4], latency, status, // Menambahkan latency ke JSON "list": [ { "title": "BING AI", "method": "GET", "example": `${host}/bing?q=` }, { "title": "Facebook Downloader", "method": "GET", "example": `${host}/fb?url=` }, { "title": "Instagram Downloader", "method": "GET", "example": `${host}/ig?url=` }, { "title": "Mediafire Downloader", "method": "GET", "example": `${host}/mediafire?url=` }, { "title": "Mega Downloader", "method": "GET", "example": `${host}/mega?url=`+ '${encodeURIComponent("url")}', }, { "title": "Pinterest Downloader", "method": "GET", "example": `${host}/pindl?url=` }, { "title": "Tiktok Downloader", "method": "GET", "example": `${host}/tt?url=` }, { "title": "Twitter/X Downloader", "method": "GET", "example": `${host}/twitter?url=`, }, { "title": "Youtube Downloader", "method": "GET", "example": `${host}/ytdl?url=` }, { "title": "Youtube Search", "method": "GET", "example": `${host}/ytsearch?q=` } ] }); }); app.get('/yt', async (req, res) => { const host = 'https://' + req.get('host'); try { let { url, type, quality, json } = req.query; if (!ytIdRegex.test(url)) return res.json({ message: 'Invalid URL' }); if (!!json) { let ytId = ytIdRegex.exec(url)?.[1]; if (!ytId) return res.json({ message: 'No video id found' }); let data = await yts({ videoId: ytId }); const downloadUrls = { audio: `${host}/yt?url=${url}&type=audio&quality=128kbps`, video: `${host}/yt?url=${url}&type=video&quality=`, }; return res.json({ ...data, download: downloadUrls }); } if (!type || !/audio|video/i.test(type)) type = 'video'; let data = await youtubedl(url).catch(e => console.log(e)); if (!data) return res.json({ message: 'Error: link download not found' }); type = type.toLowerCase(); let result = quality ? Object.values(data[type]).find(x => x.quality == quality) : Object.values(data[type])[0]; if (quality && !result) return res.json({ message: `Invalid quality: ${quality}, available quality (${Object.keys(data[type]).join('/')})` }); if (!result) return res.json({ message: 'Error: can\'t download' }); res.redirect(await result.download()); } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/ig', async (req,res) => { try { let {url} = req.query let regex = /https?:\/\/(www\.)?instagram\.com\/(p|reel|tv)/; if (!regex.test(url)) return res.json({ message: 'Invalid URL' }); let data = await igdl(url) return res.json(data) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/tt', async (req, res) => { try { let { url } = req.query let regex = /https?:\/\/(www\.|v(t|m|vt)\.|t\.)?tiktok\.com/; if (!regex.test(url)) return res.json({ message: 'Invalid URL' }); let data = await fetch(`https://tikwm.com/api/?url=` + url) data = await data.json() if (!data) return res.json({ message: 'API TO API KOID:v' }); return res.json(data) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/pindl', async (req, res) => { try { let { url } = req.query let regex = /https:\/\/pin\.it\/\w+|https:\/\/[a-z]{2}\.pinterest\.com\/pin\/\d+/; if (!regex.test(url)) return res.json({ message: 'Invalid URL' }); let data = await fetch(`https://pinterestdownloader.io/id/frontendService/DownloaderService?url=` + url) data = await data.json() if (!data) return res.json({ message: 'API TO API KOID:v' }); return res.json(data) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/fb', async (req, res) => { try { let {url} = req.query let regex = /https?:\/\/(fb\.watch|(www\.|web\.|m\.)?facebook\.com)/; if (!regex.test(url)) return res.json({ message: 'Invalid URL' }); let data = await fby2mate(url) return res.json(data) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/bimg', async (req, res) => { try { let q = req.query.q || req.query.query; if (!q) return res.json({ message: 'Input parameter q' }); let data = await bimg(q) return res.json(data) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/bing', async (req, res) => { try { let q = req.query.q || req.query.query; if (!q) return res.json({ message: 'Input parameter q' }); let data = await bingChat(q) if (data.length === 0) return res.json({message: 'Terkena Chaptcha BOT!!!'}) return res.json({result:data}) } catch (e) { console.log(e); return res.json({ message: e.message }); } }) app.get('/ytsearch', async (req, res) => { try { let q = req.query.q || req.query.query; if (!q) return res.json({ message: 'Input parameter q' }); let data = await yts(q); if (!data.all[0]) return res.json({ message: 'Not found' }); return res.json(data.all); } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/mediafire', async (req, res) => { try { let { url } = req.query //console.log(url) if (!/https?:\/\/(www\.)?mediafire\.com\/(file|download)/i.test(url)) { return res.json({ message: 'Invalid URL' }); } let data = await mediafire(url) return res.json(data) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/ytdl', async (req, res) => { try { let { url } = req.query if (!ytIdRegex.test(url)) return res.json({ message: 'Invalid URL' }); let video = await ytmp4(url) let audio = await ytmp3(url) return res.json({ video: video, audio: audio }) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/twitter', async (req, res) => { try { let { url } = req.query; url = url.replace('x.com', 'twitter.com'); // Mengganti x.com dengan twitter.com dalam URL if (!/https?:\/\/(www\.)?(twitter|x)\.com\/.*\/status/.test(url)) { return res.json({ message: 'Invalid URL' }); } let data = await twitterDL(url); return res.json(data); } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.get('/mega', async (req, res) => { try { let { url } = req.query; if (!/https:\/\/mega\.nz\/file\/[a-zA-Z0-9]{8}#[a-zA-Z0-9-_]{43}/.test(url)) { return res.json({ message: 'Invalid URL' }); } const file = File.fromURL(url); await file.loadAttributes(); let data = await file.downloadBuffer(); return res.json({ title: file.name, size: formatSize(file.size), base64: data.toString('base64') }) } catch (e) { console.log(e); return res.json({ message: e.message }); } }); app.listen(7860, () => console.log('App running on port 7860'));