const yts = require('yt-search'); const morgan = require('morgan'); const express = require('express'); const { File } = require('megajs'); // 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})/; const megaRegex = /https:\/\/mega\.nz\/file\/([A-Za-z0-9]+)(?:#([A-Za-z0-9-_]+))?/; // 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; }; // 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 }; }; const app = express() .set('json spaces', 4) .use(morgan('dev')) .use(express.json()) .all('/', (_, res) => res.send('Hello World')) .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 }); return res.json({ ...data, download: { audio: `${host}/yt?url=${url}&type=audio&quality=`, video: `${host}/yt?url=${url}&type=video&quality=`, } }); } 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); res.json({ message: e }); } }) .get('/search', 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' }); res.json(data.all); } catch (e) { console.log(e); res.json({ message: e }); } }) .get('/megajs', async (req, res) => { try { let { url } = req.query; const match = url.match(megaRegex); if (!match) return res.json({ message: 'Invalid URL' }); const id = match[1]; const query = match[2] || ''; // Jika tidak ada query, gunakan string kosong // If there's a query, add a hash symbol to the URL const fileURL = query ? `https://mega.nz/file/${id}#${query}` : `https://mega.nz/file/${id}`; const file = File.fromURL(fileURL); await file.loadAttributes(); const data = await file.downloadBuffer(); res.json({ name: file.name, // Nama file size: file.size, // Ukuran file dalam byte contents: data.toString() // Konten file dalam format string }); } catch (error) { console.error(error); res.json({ message: error.message }); } }) .listen(7860, () => console.log('App running on port 7860'));