Advertisement
samiroexpikachu

Test tb

Oct 8th, 2024
57
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 getVideoInfo(url) {
  20.   try {
  21.     const response = await axios.get(`https://samirxpikachuiox.onrender.com/ytb?url=${encodeURIComponent(url)}`);
  22.     return response.data;
  23.   } catch (error) {
  24.     throw new Error(`Failed to get video info: ${error.message}`);
  25.   }
  26. }
  27.  
  28. async function downloadAndStreamMedia(url, type, message) {
  29.   try {
  30.     const info = await getVideoInfo(url);
  31.     const mediaURL = type === 'video' ? info.videos : info.audios;
  32.    
  33.     if (!mediaURL) {
  34.       throw new Error(`No ${type} data found`);
  35.     }
  36.  
  37.     const mediaPath = path.join(__dirname, `${type}.${type === 'video' ? 'mp4' : 'mp3'}`);
  38.     const mediaResponse = await axios.get(mediaURL, { responseType: 'stream' });
  39.     const mediaStream = fs.createWriteStream(mediaPath);
  40.     mediaResponse.data.pipe(mediaStream);
  41.  
  42.     await new Promise((resolve, reject) => {
  43.       mediaStream.on('finish', resolve);
  44.       mediaStream.on('error', reject);
  45.     });
  46.  
  47.     await message.reply({
  48.       body: info.title || `Here's your ${type}`,
  49.      attachment: fs.createReadStream(mediaPath)
  50.    });
  51.  
  52.    fs.unlinkSync(mediaPath);
  53.  } catch (error) {
  54.    throw new Error(`Failed to download ${type}: ${error.message}`);
  55.  }
  56. }
  57.  
  58. async function downloadThumbnail(url, index) {
  59.  try {
  60.    const thumbnailPath = path.join(__dirname, `thumb_${index}.jpg`);
  61.    const response = await axios.get(url, { responseType: 'stream' });
  62.    const writer = fs.createWriteStream(thumbnailPath);
  63.    response.data.pipe(writer);
  64.  
  65.    await new Promise((resolve, reject) => {
  66.      writer.on('finish', resolve);
  67.      writer.on('error', reject);
  68.    });
  69.  
  70.    return thumbnailPath;
  71.  } catch (error) {
  72.    throw new Error(`Failed to download thumbnail: ${error.message}`);
  73.  }
  74. }
  75.  
  76. module.exports = {
  77.  config: {
  78.    name: "ytb",
  79.    version: "3.30",
  80.    author: "NTKhang & Fixed by Samir Œ",
  81.    countDown: 5,
  82.    role: 0,
  83.    description: {
  84.      vi: "Tải video, audio hoặc xem thông tin video trên YouTube",
  85.      en: "Download video, audio or view video information on YouTube"
  86.    },
  87.    category: "media",
  88.    guide: {
  89.      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"
  90.    }
  91.  },
  92.  
  93.  langs: {
  94.    en: {
  95.      error: "❌ An error occurred: %1",
  96.      noResult: "⭕ No search results match the keyword %1",
  97.      choose: "%1\n\nReply with a number to choose or any other text to cancel",
  98.      searching: "🔎 Searching for your request...",
  99.      downloading: "⬇️ Downloading your %1, please wait...",
  100.      info: "💠 Title: %1\n🏪 Channel: %2\n⏱ Duration: %3\n🔠 ID: %4\n🔗 Link: %5"
  101.    }
  102.  },
  103.  
  104.  onStart: async function ({ args, message, event, commandName, getLang }) {
  105.    let type;
  106.    switch (args[0]) {
  107.      case "-v":
  108.      case "video":
  109.        type = "video";
  110.        break;
  111.      case "-a":
  112.      case "-s":
  113.      case "audio":
  114.      case "sing":
  115.        type = "audio";
  116.        break;
  117.      case "-i":
  118.      case "info":
  119.        type = "info";
  120.        break;
  121.      default:
  122.        return message.SyntaxError();
  123.    }
  124.  
  125.    const input = args.slice(1).join(" ");
  126.    if (!input) return message.SyntaxError();
  127.  
  128.    try {
  129.      const youtubeUrlPattern = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/;
  130.      if (youtubeUrlPattern.test(input)) {
  131.        await processYoutubeUrl(input, type, message, getLang);
  132.      } else {
  133.        await message.reply(getLang("searching"));
  134.        const searchResults = await searchYoutube(input);
  135.        if (searchResults.length === 0) {
  136.          return message.reply(getLang("noResult", input));
  137.        }
  138.  
  139.        let msg = "";
  140.        for (let i = 0; i < searchResults.length; i++) {
  141.          msg += `${i + 1}. ${searchResults[i].title} - ${searchResults[i].channel}\n\n`;
  142.        }
  143.  
  144.        const thumbnailPaths = await Promise.all(
  145.          searchResults.map((result, index) => downloadThumbnail(result.thumbnail, index))
  146.        );
  147.  
  148.        const response = await message.reply({
  149.          body: getLang("choose", msg),
  150.          attachment: thumbnailPaths.map(path => fs.createReadStream(path))
  151.        });
  152.  
  153.        thumbnailPaths.forEach(path => fs.unlinkSync(path));
  154.  
  155.        global.GoatBot.onReply.set(response.messageID, {
  156.          commandName,
  157.          messageID: response.messageID,
  158.          author: event.senderID,
  159.          type,
  160.          searchResults
  161.        });
  162.      }
  163.    } catch (error) {
  164.      console.error(error);
  165.      return message.reply(getLang("error", error.message));
  166.    }
  167.  },
  168.  
  169.  onReply: async function ({ message, event, getLang, Reply }) {
  170.    const { type, searchResults, messageID } = Reply;
  171.    const choice = parseInt(event.body);
  172.  
  173.    if (isNaN(choice) || choice < 1 || choice > searchResults.length) {
  174.      return message.reply(getLang("error", "Invalid choice"));
  175.    }
  176.  
  177.    await message.unsend(messageID);
  178.    await message.reply(getLang("downloading", type));
  179.  
  180.    const selectedVideo = searchResults[choice - 1];
  181.    const videoUrl = `https://youtu.be/${selectedVideo.id}`;
  182.  
  183.    try {
  184.      await processYoutubeUrl(videoUrl, type, message, getLang);
  185.    } catch (error) {
  186.      console.error(error);
  187.      return message.reply(getLang("error", error.message));
  188.    }
  189.  }
  190. };
  191.  
  192. async function processYoutubeUrl(url, type, message, getLang) {
  193.  try {
  194.    await message.reply(getLang("downloading", type));
  195.    
  196.    if (type === "video" || type === "audio") {
  197.      await downloadAndStreamMedia(url, type, message);
  198.    } else if (type === "info") {
  199.      const info = await getVideoInfo(url);
  200.      const infoMsg = getLang("info",
  201.        info.title || "N/A",
  202.        info.channel || "N/A",
  203.        info.duration || "N/A",
  204.        info.id || "N/A",
  205.        url
  206.      );
  207.      await message.reply(infoMsg);
  208.    }
  209.  } catch (error) {
  210.    throw new Error(`Failed to process YouTube URL: ${error.message}`);
  211.  }
  212. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement