|
|
const express = require("express"); |
|
|
const axios = require("axios"); |
|
|
const path = require("path"); |
|
|
const cheerio = require('cheerio'); |
|
|
const FormData = require('form-data'); |
|
|
|
|
|
const app = express(); |
|
|
app.set('json spaces', 4); |
|
|
const PORT = 7860; |
|
|
|
|
|
async function yt5sIo(url) { |
|
|
try { |
|
|
const form = new URLSearchParams(); |
|
|
form.append("q", url); |
|
|
form.append("vt", "home"); |
|
|
|
|
|
const response = await axios.post('https://yt5s.io/api/ajaxSearch', form, { |
|
|
headers: { |
|
|
"Accept": "application/json", |
|
|
"X-Requested-With": "XMLHttpRequest", |
|
|
"Content-Type": "application/x-www-form-urlencoded", |
|
|
}, |
|
|
}); |
|
|
|
|
|
if (response.data.status === "ok") { |
|
|
const $ = cheerio.load(response.data.data); |
|
|
|
|
|
if (/^(https?:\/\/)?(www\.)?(facebook\.com|fb\.watch)\/.+/i.test(url)) { |
|
|
const videoQualities = []; |
|
|
$('table tbody tr').each((index, element) => { |
|
|
const quality = $(element).find('.video-quality').text().trim(); |
|
|
const downloadLink = $(element).find('a.download-link-fb').attr("href"); |
|
|
if (quality && downloadLink) { |
|
|
videoQualities.push({ quality, downloadLink }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
const hdVideo = videoQualities.find(v => v.quality.toLowerCase().includes('hd')); |
|
|
const sdVideo = videoQualities.find(v => v.quality.toLowerCase().includes('sd')); |
|
|
const videoUrl = hdVideo ? hdVideo.downloadLink : sdVideo ? sdVideo.downloadLink : null; |
|
|
|
|
|
if (!videoUrl) throw new Error("Tidak ada link download yang tersedia."); |
|
|
return { videoUrl }; |
|
|
|
|
|
} else { |
|
|
throw new Error("URL tidak valid. Harap masukkan URL Facebook atau Instagram."); |
|
|
} |
|
|
} else { |
|
|
throw new Error("Gagal mengambil video: " + response.data.message); |
|
|
} |
|
|
} catch (error) { |
|
|
throw error; |
|
|
} |
|
|
} |
|
|
|
|
|
const ytdl = async(url) => { |
|
|
const { data } = await axios.post('https://www.clipto.com/api/youtube', { url }, |
|
|
{ |
|
|
headers: { |
|
|
'accept': 'application/json, text/plain, */*', |
|
|
'content-type': 'application/json', |
|
|
'origin': 'https://www.clipto.com', |
|
|
'referer': 'https://www.clipto.com/id/media-downloader/youtube-downloader', |
|
|
'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Mobile Safari/537.36' |
|
|
} |
|
|
} |
|
|
); |
|
|
return data?.medias |
|
|
} |
|
|
|
|
|
const ttdl = async(url) => { |
|
|
const { data } = await axios.get('https://www.tikwm.com/api/?url=' + url + '&hd=1') |
|
|
return { play: data.data.play, hd: data.data.hdplay } |
|
|
} |
|
|
|
|
|
const snapinst = { |
|
|
async app(url) { |
|
|
const { data } = await axios.get('https://snapinst.app/'); |
|
|
const $ = cheerio.load(data); |
|
|
const form = new FormData(); |
|
|
|
|
|
form.append('url', url); |
|
|
form.append('action', 'post'); |
|
|
form.append('lang', ''); |
|
|
form.append('cf-turnstile-response', ''); |
|
|
form.append('token', $('input[name=token]').attr('value')); |
|
|
|
|
|
const headers = { |
|
|
...form.getHeaders(), |
|
|
'accept': '*/*', |
|
|
'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7', |
|
|
'sec-ch-ua': '"Not A(Brand";v="8", "Chromium";v="132"', |
|
|
'sec-ch-ua-mobile': '?1', |
|
|
'sec-ch-ua-platform': '"Android"', |
|
|
'sec-fetch-dest': 'empty', |
|
|
'sec-fetch-mode': 'cors', |
|
|
'sec-fetch-site': 'same-origin', |
|
|
'Referer': 'https://snapinst.app/', |
|
|
'Referrer-Policy': 'strict-origin-when-cross-origin' |
|
|
}; |
|
|
|
|
|
const jsbejad = await axios.post('https://snapinst.app/action2.php', form, { headers }); |
|
|
const ayok = new Function('callbuk', jsbejad.data.replace('eval', 'callbuk')); |
|
|
|
|
|
const html = await new Promise((resolve, reject) => { |
|
|
ayok(t=>{ |
|
|
const code = t.split(".innerHTML = ")[1].split("; document.")[0]; |
|
|
resolve(eval(code)); |
|
|
}); |
|
|
}); |
|
|
|
|
|
const _ = cheerio.load(html); |
|
|
const res = []; |
|
|
_('.row .download-item').each((i, e)=>{ |
|
|
res.push(_(e).find('.download-bottom a').attr('href')); |
|
|
}); |
|
|
|
|
|
return res |
|
|
}, |
|
|
}; |
|
|
|
|
|
const twitter = { |
|
|
extract: (url) => { |
|
|
const regex = /https?:\/\/?(?:mobile\.)?(?:www\.)?(?:twitter\.com|x\.com)\/(?:\w+\/status\/)?(\d+)/; |
|
|
if(!regex.test(url)) return "Invalid url"; |
|
|
const match = url.match(regex); |
|
|
return match ? match[1] : null; |
|
|
}, |
|
|
video: async(url) => { |
|
|
const id = twitter.extract(url) |
|
|
const res = (await axios.get(`https://tweeload.com/download/${id}`)).data |
|
|
const $ = cheerio.load(res); |
|
|
const section = $('section.content__section.download_result_section'); |
|
|
const link = section.find('a.btn').attr('href'); |
|
|
const name = section.find('.download__item__profile_pic span').first().text(); |
|
|
const username = section.find('.download__item__profile_pic span').last().text(); |
|
|
return { |
|
|
link |
|
|
} |
|
|
}, |
|
|
} |
|
|
|
|
|
app.all("/", async (req, res) => { |
|
|
const { url } = req.query || req.body; |
|
|
if(/^(https?:\/\/)?(www\.)?instagram\.com\/(p|reel)\/.+/i.test(url)) res.json(await snapinst.app(url)) |
|
|
if(/^(https?:\/\/)?(www\.)?(facebook\.com|fb\.watch)\/.+/i.test(url)) res.json(await yt5sIo(url)) |
|
|
if(/(?:https?:)?(?:\/\/)?(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*?[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/gim.test(url)) res.json(await ytdl(url)) |
|
|
if(/https?:\/\/(?:www|m|vt)\.tiktok\.com\//gi.test(url)) res.json(await ttdl(url)) |
|
|
if(/(?:https?:\/\/)?(?:mobile\.)?(?:www\.)?(?:twitter|x)\.com\/(?:@?(\w{1,15})\/)?status\/\d{10,20}/gim.test(url)) res.json(await twitter.video(url)) |
|
|
res.json({ service: ["facebook", "instagram", "youtube", "tiktok", "twitter"] }); |
|
|
}); |
|
|
|
|
|
app.listen(PORT, () => console.log(`Server berjalan di http://localhost:${PORT}`)); |