Isla Chan - Sharing
Isla Chan - Sharing
February 27, 2025 at 11:25 AM
/* - Fitur: YouTube Play & Ytmp3|Ytmp4 With Button - Info: Downloader Ytmp3 Ytmp4 & Play Dengan Button yang di sesuaikan dengan switch (command) case untuk mempermudah untuk pengguna case type tapi sesuaikan aja sama bot kamu 😇 - Type: Plugins `ESM` - By:HamzDxD - [ `SUMBER CODE` ] - https://whatsapp.com/channel/0029Vb1NWzkCRs1ifTWBb13u - [ `SUMBER SCRAPE` ] - https://whatsapp.com/channel/0029Vb5EZCjIiRotHCI1213L/121 */ import axios from 'axios' import crypto from 'crypto' import yts from 'yt-search' const handler = async (m, { conn, args, command }) => { if (args.length < 1) return m.reply(`🔎 *Pencarian YouTube:*\n- *.play *\n\n📥 *Download Video/Audio:*\n- *.ytmp3 *\n- *.ytmp4 [quality]\n\n📌 *Quality:* 144, 240, 360, 480, 720, 1080 (default: 720p untuk video)`); let query = args.join(' '); let who = m.mentionedJid && m.mentionedJid[0] ? m.mentionedJid[0] : m.sender; let username = conn.getName(who); let fkon = { key: { fromMe: false, participant: `[email protected]`, ...(m.chat ? { remoteJid: `status@broadcast` } : {}) }, message: { contactMessage: { displayName: username, vcard: `BEGIN:VCARD\nVERSION:3.0\nN:;${username},;;;\nFN:${username}\nitem1.TEL;waid=${who.split('@')[0]}:${who.split('@')[0]}\nitem1.X-ABLabel:Ponsel\nEND:VCARD` } } }; switch (command) { case 'play': try { let searchResults = await yts(query); let video = searchResults.videos[0]; if (!video) return m.reply("⚠️ *Tidak ada hasil untuk pencarian itu!*"); let buttons = [ { buttonId: `.ytmp3 ${video.url}`, buttonText: { displayText: ` Play MP3 ` }, type: 1 }, { buttonId: `.ytmp4 ${video.url}`, buttonText: { displayText: ` Play MP4 ` }, type: 1 } ]; let caption = `📌 *Hasil Pencarian:*\n\n📽 *Judul:* ${video.title}\n📅 *Upload:* ${video.ago}\n🛰️ *Durasi:* ${video.timestamp}\n🔭 *Views:* ${video.views.toLocaleString()}\n🎥 *Channel:* ${video.author.name}\n🔗 *Source:* ${video.url}`; await conn.sendMessage(m.chat, { text: caption, footer: 'Silahkan pilih formatnya:', buttons: buttons, headerType: 1 }, { quoted: fkon }); } catch (e) { return m.reply(`❌ *Gagal mencari video!*`); } break; case 'ytmp3': case 'ytmp4': let format = command === 'ytmp3' ? 'mp3' : args[1] || '720'; if (!/^https?:\/\/(www\.)?youtube\.com|youtu\.be/.test(query)) return m.reply("⚠️ *Masukkan link YouTube yang valid!*"); try { let res = await downloadYouTube(query, format); if (!res.status) return m.reply(`❌ *Error:* ${res.error}`); let { title, download, type } = res.result; if (type === 'video') { await conn.sendMessage(m.chat, { video: { url: download }, caption: `🎬 *${title}*` }, { quoted: fkon }); } else { await conn.sendMessage(m.chat, { audio: { url: download }, mimetype: 'audio/mp4', fileName: `${title}.mp3` }, { quoted: fkon }); } } catch (e) { m.reply(`*Gagal mengunduh!*`); } break; default: m.reply("*Command tidak dikenal!*"); } }; handler.menudownload = ['play', 'ytmp3', 'ytmp4']; handler.command = ['play', 'ytmp3', 'ytmp4']; export default handler; // ========================================= async function downloadYouTube(link, format = '720') { const apiBase = "https://media.savetube.me/api"; const apiCDN = "/random-cdn"; const apiInfo = "/v2/info"; const apiDownload = "/download"; const decryptData = async (enc) => { try { const key = Buffer.from('C5D58EF67A7584E4A29F6C35BBC4EB12', 'hex'); const data = Buffer.from(enc, 'base64'); const iv = data.slice(0, 16); const content = data.slice(16); const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv); let decrypted = decipher.update(content); decrypted = Buffer.concat([decrypted, decipher.final()]); return JSON.parse(decrypted.toString()); } catch (error) { return null; } }; const request = async (endpoint, data = {}, method = 'post') => { try { const { data: response } = await axios({ method, url: `${endpoint.startsWith('http') ? '' : apiBase}${endpoint}`, data: method === 'post' ? data : undefined, params: method === 'get' ? data : undefined, headers: { 'accept': '*/*', 'content-type': 'application/json', 'origin': 'https://yt.savetube.me', 'referer': 'https://yt.savetube.me/', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36' } }); return { status: true, data: response }; } catch (error) { return { status: false, error: error.message }; } }; const youtubeID = link.match(/(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/))([a-zA-Z0-9_-]{11})/); if (!youtubeID) return { status: false, error: "Gagal mengekstrak ID video dari URL." }; try { const cdnRes = await request(apiCDN, {}, 'get'); if (!cdnRes.status) return cdnRes; const cdn = cdnRes.data.cdn; const infoRes = await request(`https://${cdn}${apiInfo}`, { url: `https://www.youtube.com/watch?v=${youtubeID[1]}` }); if (!infoRes.status) return infoRes; const decrypted = await decryptData(infoRes.data.data); if (!decrypted) return { status: false, error: "Gagal mendekripsi data video." }; const downloadRes = await request(`https://${cdn}${apiDownload}`, { id: youtubeID[1], downloadType: format === 'mp3' ? 'audio' : 'video', quality: format, key: decrypted.key }); return { status: true, result: { title: decrypted.title || "Tidak diketahui", type: format === 'mp3' ? 'audio' : 'video', format: format, download: downloadRes.data.data.downloadUrl } }; } catch (error) { return { status: false, error: error.message }; } }

Comments