From 552babb44a19565b6a47fcee310603645d752005 Mon Sep 17 00:00:00 2001 From: Zero1074 Date: Wed, 20 Nov 2024 09:12:36 -0600 Subject: [PATCH] Update downloader-play.js --- plugins/downloader-play.js | 346 ++++++++++--------------------------- 1 file changed, 93 insertions(+), 253 deletions(-) diff --git a/plugins/downloader-play.js b/plugins/downloader-play.js index eb2d632e55..11a9195c57 100644 --- a/plugins/downloader-play.js +++ b/plugins/downloader-play.js @@ -1,11 +1,17 @@ -import fetch from 'node-fetch'; -import axios from 'axios'; -import { youtubedl, youtubedlv2 } from '@bochilteam/scraper'; -import fs from "fs"; +import path from 'path'; import yts from 'yt-search'; -//import ytmp33 from '../src/libraries/ytmp33.js'; -//import ytmp44 from '../src/libraries/ytmp44.js'; -import ytdl from 'ytdl-core'; +import pkg from 'youtube-dl-exec'; +import ffmpeg from 'fluent-ffmpeg'; +import ffmpegInstaller from '@ffmpeg-installer/ffmpeg'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; +import fs from 'fs'; + +const { exec } = pkg; +ffmpeg.setFfmpegPath(ffmpegInstaller.path); + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); let limit1 = 100; let limit2 = 400; @@ -18,7 +24,10 @@ const handler = async (m, { conn, command, args, text, usedPrefix }) => { const _translate = JSON.parse(fs.readFileSync(`./src/languages/${idioma}.json`)); const tradutor = _translate.plugins.descargas_play; - if (!text) throw `${tradutor.texto1[0]} _${usedPrefix + command} ${tradutor.texto1[1]}`; + if (!text) { + conn.sendMessage(m.chat, { react: { text: '❓', key: m.key } }); + return; + } const yt_play = await search(args.join(' ')); let additionalText = ''; @@ -28,159 +37,55 @@ const handler = async (m, { conn, command, args, text, usedPrefix }) => { additionalText = 'vídeo'; } - if (!yt_play || !yt_play[0]?.title) return m.reply('> *[❗] Error: Audio/Video not found.*') - - const texto1 = `${tradutor.texto2[0]} ${yt_play[0].title}\n${tradutor.texto2[1]} ${yt_play[0].ago}\n${tradutor.texto2[2]} ${secondString(yt_play[0].duration.seconds)}\n${tradutor.texto2[3]} ${MilesNumber(yt_play[0].views)}\n${tradutor.texto2[4]} ${yt_play[0].author.name}\n${tradutor.texto2[5]} ${yt_play[0].videoId}\n${tradutor.texto2[6]} ${yt_play[0].type}\n${tradutor.texto2[7]} ${yt_play[0].url}\n${tradutor.texto2[8]} ${yt_play[0].author.url}\n\n> ${tradutor.texto2[9]} ${additionalText}, ${tradutor.texto2[10]}`.trim(); + if (!yt_play || !yt_play[0]?.title) return m.reply('> *[❗] Error: Audio/Video not found.*`'); - conn.sendMessage(m.chat, { image: { url: yt_play[0].thumbnail }, caption: texto1 }, { quoted: m }); + conn.sendMessage(m.chat, { react: { text: '🔥', key: m.key } }); if (['play', 'play3', 'playdoc'].includes(command)) { - /*try { - const { status, resultados, error } = await ytmp33(yt_play[0].url); - if (!status) throw new Error(error); + try { + const buff_aud = await downloadMedia(yt_play[0].url, 'audio'); + const fileSizeInMB = (buff_aud.byteLength / (1024 * 1024)).toFixed(2); - const ttl = resultados.titulo; - const buff_aud = await getBuffer(resultados.descargar); - const fileSizeInBytes = buff_aud.byteLength; - const fileSizeInKB = fileSizeInBytes / 1024; - const fileSizeInMB = fileSizeInKB / 1024; - const size = fileSizeInMB.toFixed(2); - - if (size >= limit_a2) { - await conn.sendMessage(m.chat, { text: `${tradutor.texto3} _${resultados.descargar}_` }, { quoted: m }); + if (fileSizeInMB >= limit_a2) { + await conn.sendMessage(m.chat, { text: `${tradutor.texto3} _${yt_play[0].url}_` }, { quoted: m }); return; } - if (size >= limit_a1 && size <= limit_a2) { - await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - return; - } else { - if (['playdoc', 'play3'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - await conn.sendMessage(m.chat, { audio: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - return; - } - } catch (error) { - console.log('Fallo el 1: ' + error)*/ - try { - const audio = `${global.MyApiRestBaseUrl}/api/v2/ytmp3?url=${yt_play[0].url}&apikey=${global.MyApiRestApikey}`; - const ttl = await yt_play[0].title; - const buff_aud = await getBuffer(audio); - const fileSizeInBytes = buff_aud.byteLength; - const fileSizeInKB = fileSizeInBytes / 1024; - const fileSizeInMB = fileSizeInKB / 1024; - const size = fileSizeInMB.toFixed(2); - if (size >= limit_a2) { - await conn.sendMessage(m.chat, { text: `${tradutor.texto3} _${audio}_` }, { quoted: m }); - return; - } - if (size >= limit_a1 && size <= limit_a2) { - await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - return; - } else { - if (['playdoc', 'play3'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - await conn.sendMessage(m.chat, { audio: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - return; - } - } catch { - try { - const ttl = await yt_play[0].title; - const mediaa = await ytMp3(yt_play[0].url); - const buff_aud = await getBuffer(mediaa); - const fileSizeInBytes = buff_aud.byteLength; - const fileSizeInKB = fileSizeInBytes / 1024; - const fileSizeInMB = fileSizeInKB / 1024; - const size = fileSizeInMB.toFixed(2); - if (size >= limit_a2) { - await conn.sendMessage(m.chat, { text: `${tradutor.texto3} _${mediaa}_` }, { quoted: m }); - return; - } - if (size >= limit_a1 && size <= limit_a2) { - await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - return; - } else { - if (['playdoc', 'play3'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - await conn.sendMessage(m.chat, { audio: buff_aud, mimetype: 'audio/mpeg', fileName: ttl + `.mp3` }, { quoted: m }); - return; - } - } catch { - throw tradutor.texto4; - } - //} - } + await conn.sendMessage( + m.chat, + { + audio: buff_aud, + mimetype: 'audio/mpeg', + fileName: `${yt_play[0].title}.mp3`, + ptt: true, // Enviar como grabación de voz + }, + { quoted: m } + ); + } catch (error) { + console.error('Error fetching audio:', error); + throw tradutor.texto4; + } } if (['play2', 'play4', 'playdoc2'].includes(command)) { - /*try { - const { status, resultados, error } = await ytmp44(yt_play[0].url); - if (!status) throw new Error(error); + try { + const buff_vid = await downloadMedia(yt_play[0].url, 'video'); + const fileSizeInMB2 = (buff_vid.byteLength / (1024 * 1024)).toFixed(2); - const ttl2 = resultados.titulo; - const buff_vid = await getBuffer(resultados.descargar); - const fileSizeInBytes2 = buff_vid.byteLength; - const fileSizeInKB2 = fileSizeInBytes2 / 1024; - const fileSizeInMB2 = fileSizeInKB2 / 1024; - const size2 = fileSizeInMB2.toFixed(2); - - if (size2 >= limit2) { - await conn.sendMessage(m.chat, { text: `${tradutor.texto5} _${resultados.descargar}_` }, { quoted: m }); - return; - } - if (size2 >= limit1 && size2 <= limit2) { - await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - return; - } else { - if (['playdoc2', 'play4'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - await conn.sendMessage(m.chat, { video: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); + if (fileSizeInMB2 >= limit2) { + await conn.sendMessage(m.chat, { text: `${tradutor.texto5} _${yt_play[0].url}_` }, { quoted: m }); return; } - } catch (error) {*/ - try { - const video = `${global.MyApiRestBaseUrl}/api/v2/ytmp4?url=${yt_play[0].url}&apikey=${global.MyApiRestApikey}`; - const ttl2 = await yt_play[0].title; - const buff_vid = await getBuffer(video); - const fileSizeInBytes2 = buff_vid.byteLength; - const fileSizeInKB2 = fileSizeInBytes2 / 1024; - const fileSizeInMB2 = fileSizeInKB2 / 1024; - const size2 = fileSizeInMB2.toFixed(2); - if (size2 >= limit2) { - await conn.sendMessage(m.chat, { text: `${tradutor.texto5} _${video}_` }, { quoted: m }); - return; - } - if (size2 >= limit1 && size2 <= limit2) { - await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - return; - } else { - if (['playdoc2', 'play4'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - await conn.sendMessage(m.chat, { video: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - return; - } - } catch { - try { - const ttl = await yt_play[0].title; - const mediaa = await ytMp4(yt_play[0].url); - const buff_vid = await getBuffer(mediaa); - const fileSizeInBytes = buff_vid.byteLength; - const fileSizeInKB = fileSizeInBytes / 1024; - const fileSizeInMB = fileSizeInKB / 1024; - const size = fileSizeInMB.toFixed(2); - if (size2 >= limit2) { - await conn.sendMessage(m.chat, { text: `${tradutor.texto5} _${mediaa}_` }, { quoted: m }); - return; - } - if (size2 >= limit1 && size2 <= limit2) { - await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - return; - } else { - if (['playdoc2', 'play4'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - await conn.sendMessage(m.chat, { video: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); - return; - } - } catch { - throw tradutor.texto6; + if (fileSizeInMB2 >= limit1 && fileSizeInMB2 <= limit2) { + await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: `${yt_play[0].title}.mp4`, caption: `🎥 Aquí está el video ` }, { quoted: m }); + } else { + await conn.sendMessage(m.chat, { video: buff_vid, mimetype: 'video/mp4', fileName: `${yt_play[0].title}.mp4`, caption: `🎥 Aquí está el video ` }, { quoted: m }); } - // } - } + } catch (error) { + console.error('Error fetching video:', error); + throw tradutor.texto6; + } } }; @@ -188,117 +93,52 @@ handler.command = /^(play|play2|play3|play4|playdoc|playdoc2)$/i; export default handler; async function search(query, options = {}) { - const search = await yts.search({query, hl: 'es', gl: 'ES', ...options}); + const search = await yts.search({ query, hl: 'es', gl: 'ES', ...options }); return search.videos; } -function MilesNumber(number) { - const exp = /(\d)(?=(\d{3})+(?!\d))/g; - const rep = '$1.'; - const arr = number.toString().split('.'); - arr[0] = arr[0].replace(exp, rep); - return arr[1] ? arr.join('.') : arr[0]; -} - -function secondString(seconds) { - seconds = Number(seconds); - const d = Math.floor(seconds / (3600 * 24)); - const h = Math.floor((seconds % (3600 * 24)) / 3600); - const m = Math.floor((seconds % 3600) / 60); - const s = Math.floor(seconds % 60); - const dDisplay = d > 0 ? d + (d == 1 ? 'd ' : 'd ') : ''; - const hDisplay = h > 0 ? h + (h == 1 ? 'h ' : 'h ') : ''; - const mDisplay = m > 0 ? m + (m == 1 ? 'm ' : 'm ') : ''; - const sDisplay = s > 0 ? s + (s == 1 ? 's' : 's') : ''; - return dDisplay + hDisplay + mDisplay + sDisplay; -} - -function bytesToSize(bytes) { +async function downloadMedia(url, type) { return new Promise((resolve, reject) => { - const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; - if (bytes === 0) return 'n/a'; - const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10); - if (i === 0) resolve(`${bytes} ${sizes[i]}`); - resolve(`${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`); - }); -} - -const getBuffer = async (url, options) => { - options ? options : {}; - const res = await axios({method: 'get', url, headers: {'DNT': 1, 'Upgrade-Insecure-Request': 1,}, ...options, responseType: 'arraybuffer'}); - return res.data; -}; - -async function ytMp3(url) { - return new Promise((resolve, reject) => { - ytdl.getInfo(url).then(async (getUrl) => { - const result = []; - for (let i = 0; i < getUrl.formats.length; i++) { - const item = getUrl.formats[i]; - if (item.mimeType == 'audio/webm; codecs=\"opus\"') { - const {contentLength} = item; - const bytes = await bytesToSize(contentLength); - result[i] = {audio: item.url, size: bytes}; - } - } - const resultFix = result.filter((x) => x.audio != undefined && x.size != undefined); - const tiny = await axios.get(`https://tinyurl.com/api-create.php?url=${resultFix[0].audio}`); - const tinyUrl = tiny.data; - const title = getUrl.videoDetails.title; - const thumb = getUrl.player_response.microformat.playerMicroformatRenderer.thumbnail.thumbnails[0].url; - resolve({title, result: tinyUrl, result2: resultFix, thumb}); - }).catch(reject); - }); -} - -async function ytMp4(url) { - return new Promise(async (resolve, reject) => { - ytdl.getInfo(url).then(async (getUrl) => { - const result = []; - for (let i = 0; i < getUrl.formats.length; i++) { - const item = getUrl.formats[i]; - if (item.container == 'mp4' && item.hasVideo == true && item.hasAudio == true) { - const {qualityLabel, contentLength} = item; - const bytes = await bytesToSize(contentLength); - result[i] = {video: item.url, quality: qualityLabel, size: bytes}; - } - } - const resultFix = result.filter((x) => x.video != undefined && x.size != undefined && x.quality != undefined); - const tiny = await axios.get(`https://tinyurl.com/api-create.php?url=${resultFix[0].video}`); - const tinyUrl = tiny.data; - const title = getUrl.videoDetails.title; - const thumb = getUrl.player_response.microformat.playerMicroformatRenderer.thumbnail.thumbnails[0].url; - resolve({title, result: tinyUrl, rersult2: resultFix[0].video, thumb}); - }).catch(reject); - }); -} - -async function ytPlay(query) { - return new Promise((resolve, reject) => { - yts(query).then(async (getData) => { - const result = getData.videos.slice( 0, 5 ); - const url = []; - for (let i = 0; i < result.length; i++) { - url.push(result[i].url); - } - const random = url[0]; - const getAudio = await ytMp3(random); - resolve(getAudio); - }).catch(reject); - }); -} - -async function ytPlayVid(query) { - return new Promise((resolve, reject) => { - yts(query).then(async (getData) => { - const result = getData.videos.slice( 0, 5 ); - const url = []; - for (let i = 0; i < result.length; i++) { - url.push(result[i].url); + const tempDir = path.join(__dirname, 'temp'); + if (!fs.existsSync(tempDir)) { + fs.mkdirSync(tempDir); + } + + const outputFilePath = path.join(tempDir, `media.${type === 'audio' ? 'mp3' : 'mp4'}`); + const options = { + noPlaylist: true, + output: outputFilePath, + format: type === 'video' ? 'bestvideo[height<=420]+bestaudio' : 'bestaudio', + mergeOutputFormat: type === 'video' ? 'mp4' : undefined, + quiet: true + }; + + if (type === 'audio') { + options.extractAudio = true; + options.audioFormat = 'mp3'; + options.audioQuality = '5'; // Reduce calidad + } + + const process = exec(url, options, { stdio: ['ignore', 'pipe', 'pipe'] }); + const errors = []; + + process.stderr.on('data', chunk => errors.push(chunk)); + process.on('close', (code) => { + if (code !== 0 || errors.length > 0) { + reject(Buffer.concat(errors).toString()); + } else { + fs.readFile(outputFilePath, (err, data) => { + if (err) { + reject(err); + } else { + resolve(data); + fs.unlink(outputFilePath, (unlinkErr) => { + if (unlinkErr) console.error('Error deleting temp file:', unlinkErr); + }); + } + }); } - const random = url[0]; - const getVideo = await ytMp4(random); - resolve(getVideo); - }).catch(reject); + }); + process.on('error', reject); }); }