const axios = require("axios"); const fs = require('fs-extra'); const path = require('path'); const GoatStor = "https://goatstore.vercel.app"; // Helper function to get modules/cmds directory path safely function getCmdsDir() { const mainPath = global.GoatBot?.mainPath || process.cwd(); const possibleDir = path.join(mainPath, "modules", "cmds"); // Ensure directory exists fs.ensureDirSync(possibleDir); return possibleDir; } // Helper function to dynamically register and load new command into GoatBot memory function autoLoadCommand(filePath, fileName) { try { // Clear node require cache to load fresh file delete require.cache[require.resolve(filePath)]; const command = require(filePath); if (!command || !command.config || !command.config.name) { return { success: false, error: "Invalid command file format or missing config.name" }; } const cmdName = command.config.name.toLowerCase(); // 1. Try standard GoatBot loadCommand method if available if (global.GoatBot && typeof global.GoatBot.loadCommand === 'function') { try { global.GoatBot.loadCommand({ api: global.GoatBot.api, threadModel: global.GoatBot.threadModel, userModel: global.GoatBot.userModel, dashBoardModel: global.GoatBot.dashBoardModel, globalModel: global.GoatBot.globalModel, threadsData: global.GoatBot.threadsData, usersData: global.GoatBot.usersData, dashBoardData: global.GoatBot.dashBoardData, globalData: global.GoatBot.globalData, fileName: `${fileName}.js`, path: filePath }); } catch (e) { console.warn("Standard loadCommand failed, switching to manual map insertion:", e.message); } } // 2. Fallback / Direct insertion into GoatBot Global Memory Collections if (global.GoatBot) { // Register main command name if (global.GoatBot.commands) global.GoatBot.commands.set(cmdName, command); if (global.GoatBot.cmds) global.GoatBot.cmds.set(cmdName, command); // Register command aliases if (command.config.aliases && Array.isArray(command.config.aliases)) { for (const alias of command.config.aliases) { const cleanAlias = alias.toLowerCase(); if (global.GoatBot.aliases) global.GoatBot.aliases.set(cleanAlias, cmdName); } } } return { success: true, name: cmdName }; } catch (e) { return { success: false, error: e.message }; } } module.exports = { config: { name: "commandstore", aliases: ["cs", "ogs", "cmdtore"], version: "0.0.6", role: 1, author: "ArYAN", shortDescription: { en: "๐Ÿ“Œ Goatstore - Your Command Marketplace" }, longDescription: { en: "๐Ÿ“Œ Browse, search, upload, install and manage your commands in the GoatStore marketplace with easy sharing cmds." }, category: "๐— ๐—ฎ๐—ฟ๐—ธ๐—ฒ๐˜", cooldowns: 0, }, onStart: async ({ api, event, args, message }) => { const sendBeautifulMessage = (content) => { const header = "โ•ญโ”€โ”€ใ€Ž ๐ŸGoatStore ใ€โ”€โ”€โ•ฎ\n"; const footer = "\nโ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ"; return message.reply(header + content + footer); }; try { if (!args[0]) { return sendBeautifulMessage( "\n" + `โ•ญโ”€โฏ ${event.body} show \nโ”œ ๐Ÿ“ฆ Get command code info\nโ•ฐ Example: show 1\n\n` + `โ•ญโ”€โฏ ${event.body} install [fileName]\nโ”œ ๐Ÿ“ฅ Install command directly\nโ•ฐ Example: install 1 or install 1 music\n\n` + `โ•ญโ”€โฏ ${event.body} page \nโ”œ ๐Ÿ“„ Browse commands\nโ•ฐ Example: page 1\n\n` + `โ•ญโ”€โฏ ${event.body} search \nโ”œ ๐Ÿ” Search commands\nโ•ฐ Example: search music\n\n` + `โ•ญโ”€โฏ ${event.body} trending\nโ”œ ๐Ÿ”ฅ View trending\nโ•ฐ Most popular commands\n\n` + `โ•ญโ”€โฏ ${event.body} status\nโ”œ ๐Ÿ“Š View statistics\nโ•ฐ Marketplace insights\n\n` + `โ•ญโ”€โฏ ${event.body} like \nโ”œ ๐Ÿ’ Like a command\nโ•ฐ Example: like 1\n\n` + `โ•ญโ”€โฏ ${event.body} upload \nโ”œ โฌ†๏ธ Upload command\nโ•ฐ Example: upload goatstore\n\n` + "๐Ÿ’ซ ๐—ง๐—ถ๐—ฝ: Use `goatstore` menu for options" ); } const command = args[0].toLowerCase(); const commandsDir = getCmdsDir(); switch (command) { case "show": { const itemID = parseInt(args[1]); if (isNaN(itemID)) return sendBeautifulMessage("\n[โš ๏ธ]โžœ Please provide a valid item ID."); const response = await axios.get(`${GoatStor}/api/item/${itemID}`); const item = response.data; const bangladeshTime = new Date(item.createdAt).toLocaleString('en-US', { timeZone: 'Asia/Dhaka' }); return sendBeautifulMessage( "\n" + `โ•ญโ”€โฏ ๐Ÿ‘‘ ๐—ก๐—ฎ๐—บ๐—ฒ\nโ•ฐ ${item.itemName}\n\n` + `โ•ญโ”€โฏ ๐Ÿ†” ๐—œ๐——\nโ•ฐ ${item.itemID}\n\n` + `โ•ญโ”€โฏ โš™๏ธ ๐—ง๐˜†๐—ฝ๐—ฒ\nโ•ฐ ${item.type || 'Unknown'}\n\n` + `โ•ญโ”€โฏ ๐Ÿ“ ๐——๐—ฒ๐˜€๐—ฐ๐—ฟ๐—ถ๐—ฝ๐˜๐—ถ๐—ผ๐—ป\nโ•ฐ ${item.description}\n\n` + `โ•ญโ”€โฏ ๐Ÿ‘จโ€๐Ÿ’ป ๐—”๐˜‚๐˜๐—ต๐—ผ๐—ฟ\nโ•ฐ ${item.authorName}\n\n` + `โ•ญโ”€โฏ ๐Ÿ“… ๐—”๐—ฑ๐—ฑ๐—ฒ๐—ฑ\nโ•ฐ ${bangladeshTime}\n\n` + `โ•ญโ”€โฏ ๐Ÿ‘€ ๐—ฉ๐—ถ๐—ฒ๐˜„๐˜€\nโ•ฐ ${item.views}\n\n` + `โ•ญโ”€โฏ ๐Ÿ’ ๐—Ÿ๐—ถ๐—ธ๐—ฒ๐˜€\nโ•ฐ ${item.likes}\n\n` + `โ•ญโ”€โฏ ๐Ÿ”— ๐—ฅ๐—ฎ๐˜„ ๐—Ÿ๐—ถ๐—ป๐—ธ\nโ•ฐ ${GoatStor}/raw/${item.rawID}` ); } case "install": { let itemID; let customFileName; if (!args[1]) { return sendBeautifulMessage("\n[โš ๏ธ]โžœ Please provide an Item ID.\nExample: `goatstore install 1` or `goatstore install 1 mycmd`"); } if (!isNaN(parseInt(args[1]))) { itemID = parseInt(args[1]); customFileName = args[2] ? args[2].replace(/\.js$/i, "") : null; } else if (args[2] && !isNaN(parseInt(args[2]))) { customFileName = args[1].replace(/\.js$/i, ""); itemID = parseInt(args[2]); } else { return sendBeautifulMessage("\n[โš ๏ธ]โžœ Please provide a valid numerical Item ID."); } try { message.reply("โณ Fetching command code from GoatStore..."); const response = await axios.get(`${GoatStor}/api/item/${itemID}`); const item = response.data; if (!item || !item.rawID) { return sendBeautifulMessage("\nโŒ Command not found on GoatStore."); } // Fetch raw code const rawResponse = await axios.get(`${GoatStor}/raw/${item.rawID}`); const code = typeof rawResponse.data === 'object' ? JSON.stringify(rawResponse.data, null, 2) : rawResponse.data; if (!code) { return sendBeautifulMessage("\nโŒ Failed to retrieve code from GoatStore."); } // Determine file name const fileName = (customFileName || item.itemName || `cmd_${itemID}`).toLowerCase().replace(/[^a-z0-9_-]/gi, ""); const filePath = path.join(commandsDir, `${fileName}.js`); // Write file into modules/cmds fs.ensureDirSync(commandsDir); fs.writeFileSync(filePath, code, 'utf8'); // Load and activate in memory const loadResult = autoLoadCommand(filePath, fileName); let loadStatusText = `โšก๏ธ Command '${loadResult.name || fileName}' loaded & activated in memory!`; if (!loadResult.success) { loadStatusText = `โš ๏ธ Saved to modules/cmds, but auto-load failed: ${loadResult.error}`; } return sendBeautifulMessage( "\n" + `โ•ญโ”€โฏ โœ… ๐—ฆ๐˜๐—ฎ๐˜๐˜‚๐˜€\nโ•ฐ Installed & Activated successfully!\n\n` + `โ•ญโ”€โฏ ๐Ÿ“ฆ ๐—™๐—ถ๐—น๐—ฒ ๐—ก๐—ฎ๐—บ๐—ฒ\nโ•ฐ ${fileName}.js\n\n` + `โ•ญโ”€โฏ ๐Ÿ†” ๐—œ๐——\nโ•ฐ ${item.itemID}\n\n` + `โ•ญโ”€โฏ ๐Ÿ“ ๐—ฃ๐—ฎ๐˜๐—ต\nโ•ฐ modules/cmds/${fileName}.js\n\n` + `๐Ÿš€ ${loadStatusText}` ); } catch (err) { console.error("Install Error:", err); return sendBeautifulMessage(`\nโŒ Failed to install command: ${err.message}`); } } case "page": { const page = parseInt(args[1]) || 1; const { data: { items, total } } = await axios.get(`${GoatStor}/api/items?page=${page}&limit=5`); const totalPages = Math.ceil(total / 5); if (page <= 0 || page > totalPages) { return sendBeautifulMessage("\n[โš ๏ธ]โžœ Invalid page number."); } const itemsList = items.map((item, index) => `โ•ญโ”€โฏ ${index + 1}. ๐Ÿ“ฆ ${item.itemName}\n` + `โ”œ ๐Ÿ†” ๐—œ๐——: ${item.itemID}\n` + `โ”œ โš™๏ธ ๐—ง๐˜†๐—ฝ๐—ฒ: ${item.type}\n` + `โ”œ ๐Ÿ“ ๐——๐—ฒ๐˜€๐—ฐ๐—ฟ๐—ถ๐—ฝ๐˜๐—ถ๐—ผ๐—ป: ${item.description}\n` + `โ”œ ๐Ÿ‘€ ๐—ฉ๐—ถ๐—ฒ๐˜„๐˜€: ${item.views}\n` + `โ”œ ๐Ÿ’ ๐—Ÿ๐—ถ๐—ธ๐—ฒ๐˜€: ${item.likes}\n` + `โ•ฐ ๐Ÿ‘จโ€๐Ÿ’ป ๐—”๐˜‚๐˜๐—ต๐—ผ๐—ฟ: ${item.authorName}\n` ).join("\n"); return sendBeautifulMessage(`\n๐Ÿ“„ ๐—ฃ๐—ฎ๐—ด๐—ฒ ${page}/${totalPages}\n\n${itemsList}`); } case "search": { const query = args.slice(1).join(" "); if (!query) return sendBeautifulMessage("\n[โš ๏ธ]โžœ Please provide a search query."); const { data } = await axios.get(`${GoatStor}/api/items?search=${encodeURIComponent(query)}`); const results = data.items || data; if (!results || !results.length) return sendBeautifulMessage("\nโŒ No matching results found."); const searchList = results.slice(0, 5).map((item, index) => `โ•ญโ”€โฏ ${index + 1}. ๐Ÿ“ฆ ${item.itemName}\n` + `โ”œ ๐Ÿ†” ๐—œ๐——: ${item.itemID}\n` + `โ”œ โš™๏ธ ๐—ง๐˜†๐—ฝ๐—ฒ: ${item.type || 'GoatBot'}\n` + `โ”œ ๐Ÿ‘€ ๐—ฉ๐—ถ๐—ฒ๐˜„๐˜€: ${item.views || 0}\n` + `โ”œ ๐Ÿ’ ๐—Ÿ๐—ถ๐—ธ๐—ฒ๐˜€: ${item.likes || 0}\n` + `โ•ฐ ๐Ÿ‘จโ€๐Ÿ’ป ๐—”๐˜‚๐˜๐—ต๐—ผ๐—ฟ: ${item.authorName || 'Unknown'}\n` ).join("\n"); return sendBeautifulMessage(`\n๐Ÿ“ Query: "${query}"\n\n${searchList}`); } case "trending": { const { data } = await axios.get(`${GoatStor}/api/trending`); const trendingList = data.slice(0, 5).map((item, index) => `โ•ญโ”€โฏ ${index + 1}. ๐Ÿ”ฅ ${item.itemName}\n` + `โ”œ ๐Ÿ†” ๐—œ๐——: ${item.itemID}\n` + `โ”œ ๐Ÿ’ ๐—Ÿ๐—ถ๐—ธ๐—ฒ๐˜€: ${item.likes}\n` + `โ•ฐ ๐Ÿ‘€ ๐—ฉ๐—ถ๐—ฒ๐˜„๐˜€: ${item.views}\n` ).join("\n"); return sendBeautifulMessage(`\n${trendingList}`); } case "status": { const { data: stats } = await axios.get(`${GoatStor}/api/stats`); const { hosting, totalCommands, totalLikes, dailyActiveUsers, topAuthors, topViewed } = stats; const uptimeStr = hosting?.uptime ? `${hosting.uptime.years || 0}y ${hosting.uptime.months || 0}m ${hosting.uptime.days || 0}d ${hosting.uptime.hours || 0}h ${hosting.uptime.minutes || 0}m ${hosting.uptime.seconds || 0}s` : "N/A"; const authorList = (topAuthors || []).map((a, i) => `${i + 1}. ${a._id || 'Unknown'} (${a.count})` ).join('\n') || 'None'; const viewedList = (topViewed || []).map((v, i) => `${i + 1}. ${v.itemName} ๐—œ๐——: ${v.itemID}\n ๐—ฉ๐—ถ๐—ฒ๐˜„๐˜€: ${v.views}` ).join('\n\n') || 'None'; return sendBeautifulMessage( `\nโ•ญโ”€โฏ ๐Ÿ“ฆ Total Commands: ${totalCommands || 0}\n` + `โ”œโ”€โฏ ๐Ÿ’ Total Likes: ${totalLikes || 0}\n` + `โ”œโ”€โฏ ๐Ÿ‘ฅ Daily Users: ${dailyActiveUsers || 0}\n` + `โ•ฐโ”€โฏ โฐ Uptime: ${uptimeStr}\n\n` + `โ•โ•ใ€Ž ๐ŸŒŸ Top Authors ใ€โ•โ•\nโ•ฐ${authorList}\n\n` + `โ•โ•ใ€Ž ๐Ÿ”ฅ Most Viewed ใ€โ•โ•\nโ•ฐ${viewedList}\n` + (hosting?.system ? ( `\n ๐ŸŒ ๐—›๐—ผ๐˜€๐˜๐—ถ๐—ป๐—ด ๐—œ๐—ป๐—ณ๐—ผ\n` + `โ•ญโ”€โฏ ๐Ÿ’ป ๐—ฆ๐˜†๐˜€๐˜๐—ฒ๐—บ\n` + `โ”œ ๐Ÿ”ง ${hosting.system.platform} (${hosting.system.arch})\n` + `โ”œ ๐Ÿ“Œ Node ${hosting.system.nodeVersion}\n` + `โ•ฐ ๐Ÿ–ฅ๏ธ CPU Cores: ${hosting.system.cpuCores}` ) : "") ); } case "like": { const likeItemId = parseInt(args[1]); if (isNaN(likeItemId)) return sendBeautifulMessage("\n[โš ๏ธ]โžœ Please provide a valid item ID."); const { data } = await axios.post(`${GoatStor}/api/items/${likeItemId}/like`); if (data.success) { return sendBeautifulMessage( `\nโ•ญโ”€โฏ โœจ ๐—ฆ๐˜๐—ฎ๐˜๐˜‚๐˜€\nโ•ฐ Successfully liked!\n\nโ•ญโ”€โฏ ๐Ÿ’ ๐—ง๐—ผ๐˜๐—ฎ๐—น ๐—Ÿ๐—ถ๐—ธ๐—ฒ๐˜€\nโ•ฐ ${data.likes}` ); } else { return sendBeautifulMessage("\n[โš ๏ธ]โžœ Failed to like the command."); } } case "upload": { const commandName = args[1]; if (!commandName) return sendBeautifulMessage("\n[โš ๏ธ]โžœ Please provide a command name.\nExample: `goatstore upload testCmd`"); const cleanCmdName = commandName.replace(/\.js$/i, ""); const commandPath = path.join(commandsDir, `${cleanCmdName}.js`); if (!fs.existsSync(commandPath)) return sendBeautifulMessage(`\nโŒ File '${cleanCmdName}.js' not found in modules/cmds directory.`); try { const code = fs.readFileSync(commandPath, 'utf8'); let commandFile; try { delete require.cache[require.resolve(commandPath)]; commandFile = require(commandPath); } catch (err) { return sendBeautifulMessage(`\n[โš ๏ธ]โžœ Invalid command file structure: ${err.message}`); } const uploadData = { itemName: commandFile.config?.name || cleanCmdName, description: commandFile.config?.longDescription?.en || commandFile.config?.shortDescription?.en || "No description provided", type: "GoatBot", code: code, authorName: commandFile.config?.author || "Unknown" }; let response; try { response = await axios.post(`${GoatStor}/v1/paste`, uploadData); } catch (postErr) { response = await axios.post(`${GoatStor}/api/upload`, uploadData); } if (response.data && (response.data.success || response.data.itemID)) { const itemID = response.data.itemID || response.data.id; const link = response.data.link || `${GoatStor}/raw/${response.data.rawID || itemID}`; return sendBeautifulMessage( "\n" + `โ•ญโ”€โฏ โœ… ๐—ฆ๐˜๐—ฎ๐˜๐˜‚๐˜€\nโ•ฐ Command uploaded successfully!\n\n` + `โ•ญโ”€โฏ ๐Ÿ‘‘ ๐—ก๐—ฎ๐—บ๐—ฒ\nโ•ฐ ${uploadData.itemName}\n\n` + `โ•ญโ”€โฏ ๐Ÿ†” ๐—œ๐——\nโ•ฐ ${itemID}\n\n` + `โ•ญโ”€โฏ ๐Ÿ‘จโ€๐Ÿ’ป ๐—”๐˜‚๐˜๐—ต๐—ผ๐—ฟ\nโ•ฐ ${uploadData.authorName}\n\n` + `โ•ญโ”€โฏ ๐Ÿ”— ๐—ฅ๐—ฎ๐˜„ ๐—Ÿ๐—ถ๐—ป๐—ธ\nโ•ฐ ${link}` ); } return sendBeautifulMessage("\n[โš ๏ธ]โžœ Failed to upload the command. Server returned an invalid response."); } catch (error) { console.error("Upload error:", error?.response?.data || error.message); return sendBeautifulMessage(`\n[โš ๏ธ]โžœ Upload error: ${error?.response?.data?.message || error.message}`); } } default: return sendBeautifulMessage("\n[โš ๏ธ]โžœ Invalid subcommand. Use `goatstore` menu for options"); } } catch (err) { console.error("GoatStore Error:", err); return sendBeautifulMessage("\n[โš ๏ธ]โžœ An unexpected error occurred."); } } };