almtools
Version:
Tools Downloader For WhatsApp Bot
455 lines (394 loc) • 13.2 kB
JavaScript
const axios = require("axios")
const FormData = require("form-data");
const cheerio = require("cheerio");
async function getTokenAndCookie() {
const res = await axios.get('https://tmate.cc', {
headers: {
'User-Agent': 'Mozilla/5.0'
}
})
const cookie = res.headers['set-cookie']?.map(c => c.split(';')[0]).join('; ') || ''
const tokenMatch = res.data.match(/<input[^>]+name="token"[^>]+value="([^"]+)"/i)
const token = tokenMatch?.[1]
if (!token) throw new Error('token ga ada')
return { token, cookie }
}
async function getBuffer(url) {
const res = await axios.get(url, { responseType: 'arraybuffer' })
return Buffer.from(res.data)
}
async function tiktok(tiktokUrl) {
const { token, cookie } = await getTokenAndCookie();
const params = new URLSearchParams();
params.append('url', tiktokUrl);
params.append('token', token);
const res = await axios.post('https://tmate.cc/action', params.toString(), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0',
'Referer': 'https://tmate.cc/id',
'Origin': 'https://tmate.cc',
'Cookie': cookie
}
});
const html = res.data?.data;
if (!html) throw new Error('ga ada data');
const titleMatch = html.match(/<h1[^>]*>(.*?)<\/h1>/i);
const title = titleMatch?.[1]?.replace(/<[^>]+>/g, '').trim() || 'Tanpa Judul';
// === STEP 1: Coba ambil gambar dari dlpanda.com ===
const dlpandaRes = await axios.get(`https://dlpanda.com/id?token=hy5EGGKC&url=${encodeURIComponent(tiktokUrl)}`, {
headers: {
'User-Agent': 'Mozilla/5.0'
}
});
const $ = cheerio.load(dlpandaRes.data);
const imageUrls = [];
$('.col-md-12.col-lg-6 img').each((i, el) => {
const src = $(el).attr('src');
if (src && src.startsWith('http')) {
imageUrls.push(src);
}
});
if (imageUrls.length > 0) {
const audioMatch = html.match(/<a[^>]+href="(https:\/\/[^"]+)"[^>]*>\s*<span>\s*<span>Download MP3 Audio<\/span><\/span><\/a>/i);
const mp3Link = audioMatch?.[1];
return {
status: true,
result: {
mediatype: 'image',
media: imageUrls,
title,
audio: mp3Link
}
};
}
// === STEP 2: Jika tidak ada gambar, fallback ke video ===
const matches = [...html.matchAll(/<a[^>]+href="(https:\/\/[^"]+)"[^>]*>\s*<span>\s*<span>([^<]*)<\/span><\/span><\/a>/gi)];
const seen = new Set();
const links = matches
.map(([_, href, label]) => ({ href, label: label.trim() }))
.filter(({ href }) => !href.includes('play.google.com') && !seen.has(href) && seen.add(href));
const mp4Link = links.find(v => /download without watermark/i.test(v.label))?.href;
const mp4HdLink = links.find(v => /download hd/i.test(v.label))?.href || mp4Link;
const mp3Link = links.find(v => /download mp3 audio/i.test(v.label))?.href;
if (mp4Link) {
return {
status: true,
result: {
mediatype: 'video',
media: mp4Link,
mediaHd: mp4HdLink,
title,
audio: mp3Link
}
};
}
throw new Error('ga ada respon, mungkin link salah');
}
async function instagram(url) {
try {
if (!url.match(/https?:\/\/(www\.)?(instagram\.com|facebook\.com)/i)) {
throw 'URL yang Anda masukkan tidak valid!';
}
const { data } = await axios.post(
'https://yt1s.io/api/ajaxSearch',
new URLSearchParams({ p: 'home', q: url, w: '', lang: 'en' }),
{
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
}
}
);
if (data.status !== 'ok') throw 'Gagal mendapatkan data dari server!';
const $ = cheerio.load(data.data);
const downloads = $('a.abutton.is-success.is-fullwidth.btn-premium')
.map((_, el) => ({
title: $(el).attr('title'),
url: $(el).attr('href'),
}))
.get();
if (!downloads || downloads.length === 0) {
throw 'Tidak dapat menemukan media untuk diunduh!';
}
const media = [];
for (const dl of downloads) {
try {
const head = await axios.head(dl.url);
const mimeType = head.headers['content-type'];
if (dl.title == "Download Thumbnail") continue
if (mimeType.includes('image')) {
media.push({
mediatype: 'image',
url: dl.url
});
} else if (mimeType.includes('video')) {
media.push({
mediatype: 'video',
url: dl.url
});
} else {
continue;
}
} catch (err) {
console.error('Failed to get content type:', err.message);
}
}
const result = { status: true, media };
if (media.length === 0) {
throw 'No valid media found.';
}
return result
} catch (error) {
console.error(error);
return {
status: false,
error: error
}
}
};
async function douyin(url) {
try {
const { data } = await axios.get(
"https://dlpanda.com/id?token=hy5EGGKC&url=" + encodeURIComponent(url)
);
const $ = cheerio.load(data);
const imageUrls = [];
$('.single-popular-domain .card-body img').each((_, el) => {
const src = $(el).attr('src');
if (src) imageUrls.push(src);
});
const video = $('video source').attr('src');
if (imageUrls.length > 0) {
return {
status: true,
result: {
mediatype: "image",
media: imageUrls
}
};
} else {
return {
status: true,
result: {
mediatype: "video",
media: video?.startsWith("//") ? "https:" + video : video
}
};
}
} catch (error) {
return {
status: false,
error
};
}
}
const fb = {
tokens: async () => {
const {
data: a
} = await axios.get("https://fbdown.me/");
const $ = cheerio.load(a);
return $('#token')
.val();
},
dl: async (urls) => {
const tokens = await fb.tokens();
const d = new FormData();
d.append("url", urls);
d.append("token", tokens);
const headers = {
headers: {
...d.getHeaders()
}
};
const {
data: s
} = await axios.post(
"https://fbdown.me/wp-json/aio-dl/video-data", d,
headers);
return { status: true, result: s }
}
};
class SpotMate {
constructor() {
this._cookie = null;
this._token = null;
}
async _visit() {
try {
const response = await axios.get('https://spotmate.online/en', {
headers: {
'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Mobile Safari/537.36',
},
});
const setCookieHeader = response.headers['set-cookie'];
if (setCookieHeader) {
this._cookie = setCookieHeader
.map((cookie) => cookie.split(';')[0])
.join('; ');
}
const $ = cheerio.load(response.data);
this._token = $('meta[name="csrf-token"]').attr('content');
if (!this._token) {
throw new Error('Token CSRF tidak ditemukan.');
}
console.log('Berhasil mendapatkan cookie dan token.');
} catch (error) {
throw new Error(`Gagal mengunjungi halaman: ${error.message}`);
}
}
async info(spotifyUrl) {
if (!this._cookie || !this._token) {
await this._visit();
}
try {
const response = await axios.post(
'https://spotmate.online/getTrackData',
{ spotify_url: spotifyUrl },
{
headers: this._getHeaders(),
}
);
return response.data;
} catch (error) {
throw new Error(`Gagal mendapatkan info track: ${error.message}`);
}
}
async convert(spotifyUrl) {
if (!this._cookie || !this._token) {
await this._visit();
}
try {
const response = await axios.post(
'https://spotmate.online/convert',
{ urls: spotifyUrl },
{
headers: this._getHeaders(),
}
);
return response.data;
} catch (error) {
throw new Error(`Gagal mengonversi track: ${error.message}`);
}
}
clear() {
this._cookie = null;
this._token = null;
console.log('Cookie dan token telah dihapus.');
}
_getHeaders() {
return {
'authority': 'spotmate.online',
'accept': '*/*',
'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
'content-type': 'application/json',
'cookie': this._cookie,
'origin': 'https://spotmate.online',
'referer': 'https://spotmate.online/en',
'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',
'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Mobile Safari/537.36',
'x-csrf-token': this._token,
};
}
}
async function contol(url) {
try {
let spotMate = new SpotMate();
let info = await spotMate.info(url);
let track = await spotMate.convert(url);
if (track.error) throw "Error While Downloading Audio";
let artists = []
let artist = info?.artists.forEach((i) => artists.push(i.name)) || null;
let data = {
title: info?.name || null,
album: info?.album.name || null,
thumbnail: info?.album.images || null,
artists: artists.filter(_ => _),
duration: info.duration_ms || null,
url: track.url
}
return { status: true, result: data }
} catch (e) {
throw e
}
}
async function snack(url) {
const res = await fetch(url);
const body = await res.text();
const $ = cheerio.load(body);
const video = $("div.video-box").find("a-video-player");
const author = $("div.author-info");
const attr = $("div.action");
const data = {
title: $(author).find("div.author-desc > span").children("span").eq(0).text().trim(),
thumbnail: $(video).parent().siblings("div.background-mask").children("img").attr("src"),
media: $(video).attr("src"),
author: $("div.author-name").text().trim(),
authorImage: $(attr).find("div.avatar > img").attr("src"),
like: $(attr).find("div.common").eq(0).text().trim(),
comment: $(attr).find("div.common").eq(1).text().trim(),
share: $(attr).find("div.common").eq(2).text().trim(),
};
return { status: true, result: data }
}
async function twitter(link) {
try {
const apiUrl = "https://www.twitterdown.com/api/parse";
const headers = {
"Content-Type": "application/json",
"User-Agent":
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, seperti Gecko) Chrome/134.0.0.0 Mobile Safari/537.36",
"Referer": `https://www.twitterdown.com/${link.split("/").slice(-2).join("/")}`,
};
const postData = { url: link };
const response = await axios.post(apiUrl, postData, { headers });
if (!response.data || !response.data.resolutions) {
throw new Error("Gagal mengambil data dari TwitterDown.");
}
const thumbnail = response.data.thumbnail || null;
const text = response.data.text || null;
const username = response.data.username || null;
const statusId = response.data.statusId || null;
const downloadLinks = response.data.resolutions.reduce((acc, media) => {
acc[media.resolution] = media.url;
return acc;
}, {});
let sta = {
username,
statusId,
title: text,
thumbnail,
url: downloadLinks,
}
return { status: true, result: sta }
} catch (error) {
throw error
}
}
async function capcut(url) {
if (!url) throw new Error('URL cannot be empty');
const response = await axios.get(url);
const data = response.data;
const $ = cheerio.load(data);
return {
url: $("video").attr("src") || null,
description: $('meta[name="keywords"]').attr("content") || null
};
}
module.exports = {
facebook: fb.dl,
instagram,
tiktok,
douyin,
spotify: contol,
snackvideo: snack,
twitter,
capcut
}