← back to browse
goat command

youtube

No description

0
views
0
likes
0
installs

Aliases: ytb

raw source
const ytSearch = require("yt-search");
const axios = require("axios");
const fs = require("fs");
const path = require("path");

const API_BASE = process.env.API_BASE || "https://azadx69x-ytb-api.vercel.app";

async function fetchStream(url) {
  const res = await axios({ url, responseType: "stream" });
  return res.data;
}

module.exports = {
  config: {
    name: "youtube",
    aliases: ["ytb"],
    version: "1.1.1",
    author: "Azadx69x",
    countDown: 5,
    role: 0,
    description: { en: "Search and download YouTube video/audio" },
    category: "media",
    guide: { en: "{pn} -v <query|url>\n{pn} -a <query|url>" }
  },

  onStart: async function ({ api, args, event, commandName }) {
    try {
      const typeFlag = args[0];
      if (!["-v", "-a"].includes(typeFlag)) {
        return api.sendMessage(
          "❌ Usage:\n)ytb -v <query|url>\n)ytb -a <query|url>",
          event.threadID,
          event.messageID
        );
      }

      const query = args.slice(1).join(" ");
      if (!query) {
        return api.sendMessage(
          "❌ Provide a search query or YouTube URL.",
          event.threadID,
          event.messageID
        );
      }
      
      if (query.startsWith("http")) {
        return await downloadMedia(
          query,
          typeFlag === "-v" ? "mp4" : "mp3",
          api,
          event
        );
      }
      
      const searchRes = await ytSearch(query);
      const results = searchRes.videos.slice(0, 6);

      if (!results.length) {
        return api.sendMessage(
          "❌ No results found.",
          event.threadID,
          event.messageID
        );
      }

      let msg = "🎵 YouTube Results\n\n";
      results.forEach((v, i) => {
        msg += `${i + 1}. ${v.title}\n⏱ ${v.timestamp}\n\n`;
      });
      msg += "Reply with number (1-6) to download.";

      const attachments = await Promise.all(
        results.map(v => fetchStream(v.thumbnail))
      );

      api.sendMessage(
        { body: msg, attachment: attachments },
        event.threadID,
        (err, sent) => {
          if (err) return console.error(err);
          global.GoatBot.onReply.set(sent.messageID, {
            commandName,
            results,
            type: typeFlag,
            messageID: sent.messageID
          });
        },
        event.messageID
      );

    } catch (err) {
      console.error("[YT] onStart error:", err);
      api.sendMessage(
        "❌ Failed to execute YouTube command.",
        event.threadID,
        event.messageID
      );
    }
  },

  onReply: async function ({ event, api, Reply }) {
    try {
      const { results, type, messageID } = Reply;
      const choice = parseInt(event.body);

      if (isNaN(choice) || choice < 1 || choice > results.length) {
        return api.sendMessage(
          "❌ Invalid choice. Reply 1-6.",
          event.threadID,
          event.messageID
        );
      }

      await api.unsendMessage(messageID);
      const selected = results[choice - 1];

      await downloadMedia(
        selected.url,
        type === "-v" ? "mp4" : "mp3",
        api,
        event
      );

    } catch (err) {
      console.error("[YT] onReply error:", err);
      api.sendMessage(
        "❌ Error processing selection.",
        event.threadID,
        event.messageID
      );
    }
  }
};

async function downloadMedia(url, type, api, event) {
  try {
    const res = await axios.get(
      `${API_BASE}/download?url=${encodeURIComponent(url)}&type=${type}`,
      { responseType: "stream" }
    );

    const fileName = `yt_${Date.now()}.${type}`;
    const filePath = path.join(__dirname, fileName);
    const writer = fs.createWriteStream(filePath);

    res.data.pipe(writer);

    await new Promise((resolve, reject) => {
      writer.on("finish", resolve);
      writer.on("error", reject);
    });

    await api.sendMessage(
      { attachment: fs.createReadStream(filePath) },
      event.threadID,
      () => fs.unlinkSync(filePath),
      event.messageID
    );

  } catch (err) {
    console.error("[YT] download error:", err);
    api.sendMessage(
      `❌ Failed to download ${type}.`,
      event.threadID,
      event.messageID
    );
  }
}

View raw file