From 4cb99902adf918864070736cc3e45eb0d950e9dc Mon Sep 17 00:00:00 2001 From: Zerita233 Date: Mon, 4 Nov 2024 11:45:08 -0600 Subject: [PATCH] Update downloader-play.js --- plugins/downloader-play.js | 501 ++++++++++++++++++++++--------------- 1 file changed, 304 insertions(+), 197 deletions(-) diff --git a/plugins/downloader-play.js b/plugins/downloader-play.js index eb2d632e55..383ba7df06 100644 --- a/plugins/downloader-play.js +++ b/plugins/downloader-play.js @@ -1,304 +1,411 @@ -import fetch from 'node-fetch'; -import axios from 'axios'; -import { youtubedl, youtubedlv2 } from '@bochilteam/scraper'; -import fs from "fs"; -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 path from 'path'; + +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'; + + + +const { exec } = pkg; + +ffmpeg.setFfmpegPath(ffmpegInstaller.path); + + + +// Definir __dirname manualmente + +const __filename = fileURLToPath(import.meta.url); + +const __dirname = dirname(__filename); + + let limit1 = 100; + let limit2 = 400; + let limit_a1 = 50; + let limit_a2 = 400; + + const handler = async (m, { conn, command, args, text, usedPrefix }) => { + const datas = global; + const idioma = datas.db.data.users[m.sender].language || global.defaultLenguaje; + 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]}`; + + const yt_play = await search(args.join(' ')); + let additionalText = ''; + if (['play', 'play3', 'playdoc'].includes(command)) { + additionalText = 'audio'; + } else if (['play2', 'play4', 'playdoc2'].includes(command)) { + additionalText = 'vídeo'; + } - if (!yt_play || !yt_play[0]?.title) return m.reply('> *[❗] Error: Audio/Video not found.*') + + + 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(); + + conn.sendMessage(m.chat, { image: { url: yt_play[0].thumbnail }, caption: texto1 }, { quoted: m }); + + if (['play', 'play3', 'playdoc'].includes(command)) { - /*try { - const { status, resultados, error } = await ytmp33(yt_play[0].url); - if (!status) throw new Error(error); - const ttl = resultados.titulo; - const buff_aud = await getBuffer(resultados.descargar); + try { + + const buff_aud = await downloadMedia(yt_play[0].url, '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} _${resultados.descargar}_` }, { quoted: m }); + + 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 }); + + await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: `${yt_play[0].title}.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 }); + + if (['playdoc', 'play3'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_aud, mimetype: 'audio/mpeg', fileName: `${yt_play[0].title}.mp3` }, { quoted: m }); + + await conn.sendMessage(m.chat, { audio: buff_aud, mimetype: 'audio/mpeg', fileName: `${yt_play[0].title}.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; - } - //} - } + + 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); - const ttl2 = resultados.titulo; - const buff_vid = await getBuffer(resultados.descargar); + try { + + const buff_vid = await downloadMedia(yt_play[0].url, 'video'); + const fileSizeInBytes2 = buff_vid.byteLength; + const fileSizeInKB2 = fileSizeInBytes2 / 1024; + const fileSizeInMB2 = fileSizeInKB2 / 1024; + const size2 = fileSizeInMB2.toFixed(2); + const duration = secondString(yt_play[0].duration.seconds); + + + if (size2 >= limit2) { - await conn.sendMessage(m.chat, { text: `${tradutor.texto5} _${resultados.descargar}_` }, { quoted: m }); + + await conn.sendMessage(m.chat, { text: `${tradutor.texto5} _${yt_play[0].url}_` }, { quoted: m }); + return; + } + if (size2 >= limit1 && size2 <= limit2) { - await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: ttl2 + `.mp4` }, { quoted: m }); + + await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: `${yt_play[0].title}.mp4`, caption: `🎥 Aquí está el video ` }, { 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 (['playdoc2', 'play4'].includes(command)) return await conn.sendMessage(m.chat, { document: buff_vid, mimetype: 'video/mp4', fileName: `${yt_play[0].title}.mp4`, caption: `🎥 Aquí está el video ` }, { quoted: m }); + + await conn.sendMessage(m.chat, { video: buff_vid, mimetype: 'video/mp4', fileName: `${yt_play[0].title}.mp4`, caption: `🎥 Aquí está el video ` }, { 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; - } - // } - } + + } catch (error) { + + console.error('Error fetching video:', error); + + throw tradutor.texto6; + + } + } + }; + + 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}); + return search.videos; + } + + +async function downloadMedia(url, type) { + + return new Promise((resolve, reject) => { + + 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<=480]+bestaudio' : 'bestaudio', // Reducir calidad de video a 480p + + mergeOutputFormat: type === 'video' ? 'mp4' : undefined + + }; + + + + if (type === 'audio') { + + options.extractAudio = true; + + options.audioFormat = 'mp3'; + + } + + + + 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 { + + if (type === 'video') { + + const convertedFilePath = path.join(tempDir, `converted_media.mp4`); + + ffmpeg(outputFilePath) + + .output(convertedFilePath) + + .on('end', () => { + + fs.readFile(convertedFilePath, (err, data) => { + + if (err) { + + reject(err); + + } else { + + resolve(data); + + fs.unlink(outputFilePath, (unlinkErr) => { + + if (unlinkErr) console.error('Error deleting temp file:', unlinkErr); + + }); + + fs.unlink(convertedFilePath, (unlinkErr) => { + + if (unlinkErr) console.error('Error deleting converted temp file:', unlinkErr); + + }); + + } + + }); + + }) + + .on('error', reject) + + .run(); + + } 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); + + }); + + } + + }); + + } + + } + + }); + + process.on('error', reject); + + }); + +} + + + 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) { + 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); - }); -} + options ? options : {}; -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); - }); -} + const res = await axios({method: 'get', url, headers: {'DNT': 1, 'Upgrade-Insecure-Request': 1,}, ...options, responseType: 'arraybuffer'}); -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); - }); -} + return res.data; -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 random = url[0]; - const getVideo = await ytMp4(random); - resolve(getVideo); - }).catch(reject); - }); -} +};