Advertisement
samiroexpikachu

Ytb

Sep 15th, 2024 (edited)
604
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const axios = require("axios");
  2. const fs = require("fs-extra");
  3. const path = require("path");
  4.  
  5. async function searchYoutube(query) {
  6.   try {
  7.     const response = await axios.get(`https://www.googleapis.com/youtube/v3/search?part=snippet&q=${encodeURIComponent(query)}&key=AIzaSyC_CVzKGFtLAqxNdAZ_EyLbL0VRGJ-FaMU&type=video&maxResults=6`);
  8.     return response.data.items.map(item => ({
  9.       id: item.id.videoId,
  10.       title: item.snippet.title,
  11.       channel: item.snippet.channelTitle,
  12.       thumbnail: item.snippet.thumbnails.high.url
  13.     }));
  14.   } catch (error) {
  15.     throw new Error(`Failed to search YouTube: ${error.message}`);
  16.   }
  17. }
  18.  
  19. async function downloadAndStreamVideo(videoUrl, message) {
  20.   const apiUrl = `https://samirxpikachuiox.onrender.com/ytb?url=${encodeURIComponent(videoUrl)}`;
  21.  
  22.   try {
  23.     const response = await axios.get(apiUrl);
  24.  
  25.     if (response.data && response.data.videos) {
  26.       const videoURL = response.data.videos;
  27.       const videoPath = path.join(__dirname, 'video.mp4');
  28.  
  29.       const videoResponse = await axios.get(videoURL, { responseType: 'stream' });
  30.       const videoStream = fs.createWriteStream(videoPath);
  31.       videoResponse.data.pipe(videoStream);
  32.  
  33.       await new Promise((resolve, reject) => {
  34.         videoStream.on('finish', resolve);
  35.         videoStream.on('error', reject);
  36.       });
  37.  
  38.       await message.reply({
  39.         body: response.data.title || "Here's your video",
  40.         attachment: fs.createReadStream(videoPath)
  41.       });
  42.  
  43.       fs.unlinkSync(videoPath);
  44.     } else {
  45.       throw new Error('No video data found');
  46.     }
  47.   } catch (error) {
  48.     throw new Error(`Failed to download: ${error.message}`);
  49.   }
  50. }
  51.  
  52. async function downloadAndStreamAudio(videoUrl, message) {
  53.   const apiUrl = `https://samirxpikachuiox.onrender.com/ytb?url=${encodeURIComponent(videoUrl)}`;
  54.  
  55.   try {
  56.     const response = await axios.get(apiUrl);
  57.  
  58.     if (response.data && response.data.audios) {
  59.       const audioURL = response.data.audios;
  60.       const audioPath = path.join(__dirname, 'audio.mp3');
  61.  
  62.       const audioResponse = await axios.get(audioURL, { responseType: 'stream' });
  63.       const audioStream = fs.createWriteStream(audioPath);
  64.       audioResponse.data.pipe(audioStream);
  65.  
  66.       await new Promise((resolve, reject) => {
  67.         audioStream.on('finish', resolve);
  68.         audioStream.on('error', reject);
  69.       });
  70.  
  71.       await message.reply({
  72.         body: response.data.title || "Here's your audio",
  73.         attachment: fs.createReadStream(audioPath)
  74.       });
  75.  
  76.       fs.unlinkSync(audioPath);
  77.     } else {
  78.       throw new Error('No audio data found');
  79.     }
  80.   } catch (error) {
  81.     throw new Error(`Failed to download: ${error.message}`);
  82.   }
  83. }
  84.  
  85. async function downloadThumbnail(url, index) {
  86.   try {
  87.     const thumbnailPath = path.join(__dirname, `thumb_${index}.jpg`);
  88.     const response = await axios.get(url, { responseType: 'stream' });
  89.     const writer = fs.createWriteStream(thumbnailPath);
  90.     response.data.pipe(writer);
  91.  
  92.     await new Promise((resolve, reject) => {
  93.       writer.on('finish', resolve);
  94.       writer.on('error', reject);
  95.     });
  96.  
  97.     return thumbnailPath;
  98.   } catch (error) {
  99.     throw new Error(`Failed to download thumbnail: ${error.message}`);
  100.   }
  101. }
  102. //inspired from ntkhangs ytb
  103.  
  104.  
  105. module.exports = {
  106.   config: {
  107.     name: "ytb",
  108.     version: "3.29",
  109.     author: "Samir Œ",
  110.     countDown: 5,
  111.     role: 0,
  112.     description: {
  113.       vi: "Tải video, audio hoặc xem thông tin video trên YouTube",
  114.       en: "Download video, audio or view video information on YouTube"
  115.     },
  116.     category: "media",
  117.     guide: {
  118.       en: "   {pn} [video|-v] [<video name>|<video link>]: download video\n   {pn} [audio|-a] [<video name>|<video link>]: download audio\n   {pn} [info|-i] [<video name>|<video link>]: view info"
  119.     }
  120.   },
  121.  
  122.   langs: {
  123.     en: {
  124.       error: "❌ An error occurred: %1",
  125.       noResult: "⭕ No search results match the keyword %1",
  126.       choose: "%1\n\nReply with a number to choose or any other text to cancel",
  127.       searching: "🔎 Searching for your request...",
  128.       downloading: "⬇️ Downloading your %1, please wait...",
  129.       info: "💠 Title: %1\n🏪 Channel: %2\n⏱ Duration: %3\n🔠 ID: %4\n🔗 Link: %5"
  130.     }
  131.   },
  132.  
  133.   onStart: async function ({ args, message, event, commandName, getLang }) {
  134.     let type;
  135.     switch (args[0]) {
  136.       case "-v":
  137.       case "video":
  138.         type = "video";
  139.         break;
  140.       case "-a":
  141.       case "-s":
  142.       case "audio":
  143.       case "sing":
  144.         type = "audio";
  145.         break;
  146.       case "-i":
  147.       case "info":
  148.         type = "info";
  149.         break;
  150.       default:
  151.         return message.SyntaxError();
  152.     }
  153.  
  154.     const input = args.slice(1).join(" ");
  155.     if (!input) return message.SyntaxError();
  156.  
  157.     try {
  158.    
  159.       const youtubeUrlPattern = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/;
  160.       if (youtubeUrlPattern.test(input)) {
  161.      
  162.         await processYoutubeUrl(input, type, message, getLang);
  163.       } else {
  164.        
  165.         await message.reply(getLang("searching"));
  166.         const searchResults = await searchYoutube(input);
  167.         if (searchResults.length === 0) {
  168.           return message.reply(getLang("noResult", input));
  169.         }
  170.  
  171.         let msg = "";
  172.         for (let i = 0; i < searchResults.length; i++) {
  173.           msg += `${i + 1}. ${searchResults[i].title} - ${searchResults[i].channel}\n\n`;
  174.         }
  175.  
  176.      
  177.         const thumbnailPaths = await Promise.all(
  178.           searchResults.map((result, index) => downloadThumbnail(result.thumbnail, index))
  179.         );
  180.  
  181.         const response = await message.reply({
  182.           body: getLang("choose", msg),
  183.           attachment: thumbnailPaths.map(path => fs.createReadStream(path))
  184.         });
  185.  
  186.      
  187.         thumbnailPaths.forEach(path => fs.unlinkSync(path));
  188.  
  189.         global.GoatBot.onReply.set(response.messageID, {
  190.           commandName,
  191.           messageID: response.messageID,
  192.           author: event.senderID,
  193.           type,
  194.           searchResults
  195.         });
  196.       }
  197.     } catch (error) {
  198.       console.error(error);
  199.       return message.reply(getLang("error", error.message));
  200.     }
  201.   },
  202.  
  203.   onReply: async function ({ message, event, getLang, Reply }) {
  204.     const { type, searchResults, messageID } = Reply;
  205.     const choice = parseInt(event.body);
  206.  
  207.     if (isNaN(choice) || choice < 1 || choice > searchResults.length) {
  208.       return message.reply(getLang("error", "Invalid choice"));
  209.     }
  210.  
  211.     await message.unsend(messageID);
  212.     await message.reply(getLang("downloading", type));
  213.  
  214.     const selectedVideo = searchResults[choice - 1];
  215.     const videoUrl = `https://youtu.be/${selectedVideo.id}`;
  216.  
  217.     try {
  218.       await processYoutubeUrl(videoUrl, type, message, getLang);
  219.     } catch (error) {
  220.       console.error(error);
  221.       return message.reply(getLang("error", error.message));
  222.     }
  223.   }
  224. };
  225.  
  226. async function processYoutubeUrl(url, type, message, getLang) {
  227.   try {
  228.     if (type === "video") {
  229.       await downloadAndStreamVideo(url, message);
  230.     } else if (type === "audio") {
  231.       await downloadAndStreamAudio(url, message);
  232.     } else if (type === "info") {
  233.       const apiUrl = `https://samirxpikachuiox.onrender.com/ytb?url=${encodeURIComponent(url)}`;
  234.       const response = await axios.get(apiUrl);
  235.       const infoMsg = getLang("info",
  236.         response.data.title || "N/A",
  237.         response.data.channel || "N/A",
  238.         response.data.duration || "N/A",
  239.         response.data.id || "N/A",
  240.         url
  241.       );
  242.       await message.reply(infoMsg);
  243.     }
  244.   } catch (error) {
  245.     throw new Error(`Failed to process YouTube URL: ${error.message}`);
  246.   }
  247. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement