// code from goatstore // api: https://store.agi.bd const axios = require("axios"); const yts = require("yt-search"); const fs = require("fs"); const path = require("path"); const CACHE_DIR = path.join(__dirname, "cache"); const VIDEO_API = "https://eryxenx.agi.bd/api/video"; const ALBUMS = { 1: { name: "Anime Edit ๐ŸŒธ", query: "anime edit AMV" }, 2: { name: "Anime Fight โš”๏ธ", query: "anime fight scene" }, 3: { name: "Romantic Anime ๐Ÿ’•", query: "romantic anime edit" }, 4: { name: "Sad Anime ๐Ÿฅ€", query: "sad anime edit" }, 5: { name: "Bike Edit ๐Ÿ๏ธ", query: "sport bike cinematic edit" }, 6: { name: "Superbike ๐Ÿ”ฅ", query: "superbike cinematic" }, 7: { name: "Car Edit ๐Ÿš˜", query: "supercar cinematic edit" }, 8: { name: "Luxury Cars ๐Ÿ’Ž", query: "luxury car cinematic" }, 9: { name: "Nature ๐ŸŒฟ", query: "beautiful nature cinematic" }, 10: { name: "Rain Aesthetic ๐ŸŒง๏ธ", query: "rain aesthetic video" }, 11: { name: "Love Status ๐Ÿ’—", query: "romantic love status video" }, 12: { name: "Sad Status ๐Ÿ’”", query: "sad status video" }, 13: { name: "Funny Clips ๐Ÿ˜‚", query: "funny clean clips" }, 14: { name: "Football โšฝ", query: "football skills edit" }, 15: { name: "Cricket ๐Ÿ", query: "cricket best moments" }, 16: { name: "Gaming ๐ŸŽฎ", query: "gaming montage edit" }, 17: { name: "Travel ๐ŸŒ", query: "travel cinematic video" }, 18: { name: "Sky & Moon ๐ŸŒ™", query: "moon sky aesthetic video" }, 19: { name: "Motivation ๐Ÿ‘‘", query: "motivational cinematic video" }, 20: { name: "Dance ๐Ÿ’ƒ", query: "dance performance video" } }; const STYLE = { menu: () => `โ•ญโ”โ”โ”ใ€Ž ๐ŸŽ€ ๐‡๐ˆ๐๐€๐“๐€ ๐€๐‹๐๐”๐Œ ๐ŸŽ€ ใ€โ”โ”โ”โ•ฎ โ”‚ โ”‚ ๐ŸŒธ Choose Your Favourite Video โ”‚ ๐Ÿ’Œ Reply with a number โ”‚ ${Object.entries(ALBUMS) .map(([number, item]) => `โ”‚ ${number}. ${item.name}`) .join("\n")} โ”‚ โ•ฐโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•ฏ ๐Ÿ’— ๐‘€๐‘Ž๐‘‘๐‘’ ๐‘ค๐‘–๐‘กโ„Ž ๐‘™๐‘œ๐‘ฃ๐‘’ โ™ก`, loading: name => `โ•ญโ”โ”โ”ใ€Ž ๐ŸŽฌ ๐€๐‹๐๐”๐Œ ๐ŸŽฌ ใ€โ”โ”โ”โ•ฎ โ”‚ ๐ŸŒธ Category: ${name} โ”‚ ๐Ÿ’— Searching your video... โ•ฐโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•ฏ`, error: `โ•ญโ”โ”โ”ใ€Ž ๐Ÿฅบ ๐Ž๐Ž๐๐’! ใ€โ”โ”โ”โ•ฎ โ”‚ ๐Ÿ’” Video download failed. โ”‚ ๐ŸŒท Please try again later. โ•ฐโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•ฏ` }; async function getDownloadInfo(videoUrl) { const response = await axios.get(VIDEO_API, { params: { url: videoUrl }, timeout: 60000 }); const data = response.data; if (!data?.success || !data?.downloadUrl) { throw new Error("Video download link not found"); } return data; } async function downloadVideo(url, destination) { const response = await axios.get(url, { responseType: "stream", timeout: 300000, maxContentLength: Infinity, maxBodyLength: Infinity }); const writer = fs.createWriteStream(destination); await new Promise((resolve, reject) => { response.data.on("error", reject); writer.on("error", reject); writer.on("finish", resolve); response.data.pipe(writer); }); if (fs.statSync(destination).size < 1024) { throw new Error("Invalid or empty video file"); } } async function sendVideo({ message, selection }) { const album = ALBUMS[selection]; if (!album) { return message.reply( "๐Ÿฅบ Valid number dao! 1 theke 20 porjonto.\n๐ŸŽ€ Type album to open the menu." ); } let filePath; try { await message.reply(STYLE.loading(album.name)); const results = await yts(album.query); const video = results.videos?.find(item => item.url); if (!video) { return message.reply("๐Ÿฅ€ Sorry! Ei category-te video paini."); } const info = await getDownloadInfo(video.url); fs.mkdirSync(CACHE_DIR, { recursive: true }); filePath = path.join( CACHE_DIR, `album_${Date.now()}.mp4` ); await downloadVideo(info.downloadUrl, filePath); await message.reply({ body: `โ•ญโ”โ”โ”ใ€Ž ๐ŸŽ€ ๐•๐ˆ๐ƒ๐„๐Ž ๐‘๐„๐€๐ƒ๐˜ ๐ŸŽ€ ใ€โ”โ”โ”โ•ฎ โ”‚ โ”‚ ๐ŸŽฌ ${info.title || video.title} โ”‚ ๐ŸŒธ Category: ${album.name} โ”‚ โฑ๏ธ Duration: ${video.timestamp || "Unknown"} โ”‚ โ•ฐโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•ฏ ๐Ÿ’— ๐„๐ง๐ฃ๐จ๐ฒ ๐˜๐จ๐ฎ๐ซ ๐•๐ข๐๐ž๐จ โ™ก`, attachment: fs.createReadStream(filePath) }); } catch (error) { console.error("[ALBUM ERROR]", error); await message.reply(STYLE.error); } finally { if (filePath) { try { fs.unlinkSync(filePath); } catch (_) {} } } } module.exports = { config: { name: "album", aliases: ["videos", "videomenu"], version: "1.0.0", author: "Saju", countDown: 5, role: 0, shortDescription: "Cute video album ๐ŸŽ€", longDescription: "Search and send videos from 20 categories", category: "media", guide: { en: "{pn} โ€” open menu, then reply with a number from 1 to 20" } }, onStart: async function ({ message, event }) { const sent = await message.reply(STYLE.menu()); if (sent?.messageID && global.GoatBot?.onReply) { global.GoatBot.onReply.set(sent.messageID, { commandName: "album", type: "albumMenu", author: event.senderID }); } }, onReply: async function ({ message, event, Reply }) { if (!Reply || Reply.type !== "albumMenu") return; if ( Reply.author && String(event.senderID) !== String(Reply.author) ) { return message.reply( "๐Ÿ’— Ei menu-ta je open koreche, shei person reply koruk. ๐ŸŒธ" ); } const selection = String(event.body || "") .trim() .split(/\s+/)[0]; await sendVideo({ message, selection }); } };