const fs = require("fs-extra"); const path = require("path"); const axios = require("axios"); // šŸŽ„ Put your direct mp4 video link here (e.g., https://files.catbox.moe/xxxxxx.mp4) const HELP_VIDEO_URL = "https://files.catbox.moe/euhp0a.mp4"; module.exports = { config: { name: "help", aliases: ["menu", "commands"], version: "5.0", author: "Protik shah", countDown: 3, role: 0, shortDescription: "Show all available commands", longDescription: "Displays a ultra-stylish, categorized list of commands with video attachment support.", category: "system", guide: "{pn}help [command name]" }, onStart: async function ({ api, message, args, prefix }) { const sendMsg = (txt) => message && typeof message.reply === "function" ? message.reply(txt) : api.sendMessage(txt, event.threadID, event.messageID); const allCommands = global.GoatBot.commands; const categories = {}; const emojiMap = { ai: "šŸ¤–", "ai-image": "šŸŽØ", group: "šŸ‘„", system: "āš™ļø", fun: "šŸŽ®", owner: "šŸ‘‘", config: "šŸ› ļø", economy: "šŸ’°", media: "šŸŽ„", "18+": "šŸ”ž", tools: "🧰", utility: "šŸ”§", info: "ā„¹ļø", image: "šŸ–¼ļø", game: "šŸŽ²", admin: "šŸ›”ļø", rank: "šŸ†", boxchat: "šŸ’¬", others: "šŸ“Œ" }; const cleanCategoryName = (text) => { if (!text) return "others"; return text .normalize("NFKD") .replace(/[^\w\s-]/g, "") .replace(/\s+/g, " ") .trim() .toLowerCase(); }; for (const [name, cmd] of allCommands) { const cat = cleanCategoryName(cmd.config.category); if (!categories[cat]) categories[cat] = []; categories[cat].push(cmd.config.name); } // Detailed Command Info View if (args[0]) { const query = args[0].toLowerCase(); const cmd = allCommands.get(query) || [...allCommands.values()].find((c) => (c.config.aliases || []).includes(query)); if (!cmd) return sendMsg(`āŒ š—–š—¼š—ŗš—ŗš—®š—»š—± "${query}" š—»š—¼š˜ š—³š—¼š˜‚š—»š—±.`); const { name, version, author, guide, category, shortDescription, longDescription, aliases, role } = cmd.config; const desc = typeof longDescription === "string" ? longDescription : longDescription?.en || shortDescription?.en || shortDescription || "No description available."; const usage = typeof guide === "string" ? guide.replace(/{pn}/g, prefix) : guide?.en?.replace(/{pn}/g, prefix) || `${prefix}${name}`; const requiredRole = role !== undefined ? role : 0; const roleText = requiredRole === 0 ? "Everyone (Member)" : requiredRole === 1 ? "Group Admin" : "Bot Admin / Owner"; return sendMsg( `āš™ļø š—¦š—§š—¬š—Ÿš—œš—¦š—› š—–š—¢š— š— š—”š—”š—— š—œš—”š—™š—¢ āš™ļø\n` + `━━━━━━━━━━━━━━━━━━━\n` + `šŸ“Œ š—”š—®š—ŗš—²: ${name.toUpperCase()}\n` + `šŸ·ļø š—–š—®š˜š—²š—“š—¼š—æš˜†: ${(category || "Uncategorized").toUpperCase()}\n` + `šŸ“ š——š—²š˜€š—°š—æš—¶š—½š˜š—¶š—¼š—»: ${desc}\n` + `šŸ”€ š—”š—¹š—¶š—®š˜€š—²š˜€: ${aliases?.length ? aliases.join(", ") : "None"}\n` + `šŸ’” š—Øš˜€š—®š—“š—²: ${usage}\n` + `šŸ”‘ š—£š—²š—æš—ŗš—¶š˜€š˜€š—¶š—¼š—»: ${roleText}\n` + `šŸ‘¤ š—”š˜‚š˜š—µš—¼š—æ: ${author}\n` + `šŸš€ š—©š—²š—æš˜€š—¶š—¼š—»: v${version}\n` + `━━━━━━━━━━━━━━━━━━━` ); } // Main Categorized Help Menu View const formatCommands = (cmds) => cmds.sort().map((cmd) => `↬ ${cmd}`); let msg = `⚔ š——š—œš—”š—•š—Ÿš—¢ š— š—˜š—”š—Ø ⚔\n`; msg += `ā‡ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā‡œ\n`; const sortedCategories = Object.keys(categories).sort(); for (const cat of sortedCategories) { const emoji = emojiMap[cat] || "☃"; msg += `\n╭───↱ ${emoji} ${cat.toUpperCase()}↲ \n`; msg += `${formatCommands(categories[cat]).join(" ")}\n`; msg += `╰━━━━━━━━━━━━━━━━⋙\n`; } msg += `\n≾━━━━━━━━━━━━━━━━━━━≿\n`; msg += `šŸ’” š—Øš˜€š—²: ${prefix}help for detailed usage.\n`; msg += `šŸ“ž š—Øš˜€š—²: ${prefix}callad to talk directly with my boss DI-ABLO.`; // Handle Media Attachment (Video) if (HELP_VIDEO_URL && HELP_VIDEO_URL.trim() !== "") { const cacheDir = path.join(__dirname, "cache"); await fs.ensureDir(cacheDir); const videoPath = path.join(cacheDir, `help_menu_${Date.now()}.mp4`); try { const res = await axios({ url: HELP_VIDEO_URL, responseType: "stream" }); const writer = fs.createWriteStream(videoPath); res.data.pipe(writer); await new Promise((resolve, reject) => { writer.on("finish", resolve); writer.on("error", reject); }); const payload = { body: msg, attachment: fs.createReadStream(videoPath) }; const callback = () => { if (fs.existsSync(videoPath)) fs.unlinkSync(videoPath); }; return message && typeof message.reply === "function" ? message.reply(payload, callback) : api.sendMessage(payload, event.threadID, callback, event.messageID); } catch (err) { console.error("Help video attachment failed, sending text only:", err); if (fs.existsSync(videoPath)) fs.unlinkSync(videoPath); return sendMsg(msg); } } else { return sendMsg(msg); } } };