// code from goatstore // api: https://store.agi.bd const os = require("os"); const fs = require("fs"); const http = require("http"); const crypto = require("crypto"); const { execSync } = require("child_process"); // ================= কনফিগ ================= const WEB_PORT = parseInt(process.env.SYSINFO_PORT) || 3099; // হোস্টিংয়ে খোলা পোর্ট দিন const PUBLIC_URL = process.env.SYSINFO_URL || ""; // যেমন: https://myapp.example.com (ফাঁকা থাকলে IP দিয়ে বানাবে) const WEB_LIFETIME_MS = 10 * 60 * 1000; // ওয়েব ড্যাশবোর্ড ১০ মিনিট পর বন্ধ const EDIT_INTERVAL_MS = 3000; // মেসেজ এডিটের ব্যবধান const EDIT_TICKS = 10; // মোট কতবার আপডেট (৩০ সেকেন্ড) // ================= ডাটা সংগ্রহ ================= const fmtBytes = (b) => { const u = ["B", "KB", "MB", "GB", "TB"]; let i = 0; while (b >= 1024 && i < u.length - 1) { b /= 1024; i++; } return b.toFixed(i >= 3 ? 2 : 1) + " " + u[i]; }; const fmtUptime = (s) => { const d = Math.floor(s / 86400), h = Math.floor((s % 86400) / 3600); const m = Math.floor((s % 3600) / 60), sec = Math.floor(s % 60); return `${d}d ${h}h ${m}m ${sec}s`; }; function createSampler() { let prev = os.cpus().map((c) => ({ ...c.times })); let diskCache = null, diskAt = 0; const getDisk = () => { if (diskCache && Date.now() - diskAt < 30000) return diskCache; let r = null; try { if (typeof fs.statfsSync === "function") { const s = fs.statfsSync(process.cwd()); const total = s.blocks * s.bsize; r = { total, used: total - s.bavail * s.bsize }; } } catch (e) {} if (!r) { try { const o = execSync(`df -k "${process.cwd()}" | tail -1`).toString().trim().split(/\s+/); r = { total: parseInt(o[1]) * 1024, used: parseInt(o[2]) * 1024 }; } catch (e) {} } diskCache = r; diskAt = Date.now(); return r; }; return function sample() { const now = os.cpus(); const perCore = now.map((c, i) => { const p = prev[i] || c.times; let total = 0; for (const k in c.times) total += c.times[k] - (p[k] || 0); const idle = c.times.idle - (p.idle || 0); return total > 0 ? Math.max(0, Math.min(100, (1 - idle / total) * 100)) : 0; }); prev = now.map((c) => ({ ...c.times })); const cpu = perCore.length ? perCore.reduce((a, b) => a + b, 0) / perCore.length : 0; const total = os.totalmem(), free = os.freemem(), used = total - free; const disk = getDisk(); return { cpu, perCore, cpuModel: (now[0] ? now[0].model : "Unknown").replace(/\s+/g, " ").trim(), cores: now.length, ramTotal: total, ramUsed: used, ram: (used / total) * 100, diskTotal: disk ? disk.total : 0, diskUsed: disk ? disk.used : 0, disk: disk ? (disk.used / disk.total) * 100 : 0, load: os.loadavg(), platform: `${os.platform()} ${os.arch()}`, node: process.version, botRam: process.memoryUsage().rss, botUptime: process.uptime(), sysUptime: os.uptime(), t: Date.now() }; }; } // ================= মেসেজ-এডিট লাইভ মোড ================= const bar = (p, n = 14) => { const f = Math.round((Math.max(0, Math.min(100, p)) / 100) * n); return "█".repeat(f) + "░".repeat(n - f); }; const icon = (p) => (p < 50 ? "🟢" : p < 80 ? "🟡" : "🔴"); function buildText(s, left) { return ( `🖥️ SYSTEM MONITOR 🔴 LIVE\n` + `━━━━━━━━━━━━━━━━━━\n` + `${icon(s.cpu)} CPU ${bar(s.cpu)} ${s.cpu.toFixed(1)}%\n` + `${icon(s.ram)} RAM ${bar(s.ram)} ${s.ram.toFixed(1)}%\n` + ` ${fmtBytes(s.ramUsed)} / ${fmtBytes(s.ramTotal)}\n` + `${icon(s.disk)} DISK ${bar(s.disk)} ${s.disk.toFixed(1)}%\n` + ` ${fmtBytes(s.diskUsed)} / ${fmtBytes(s.diskTotal)}\n` + `━━━━━━━━━━━━━━━━━━\n` + `⚙️ ${s.cores} cores • load ${s.load.map((x) => x.toFixed(2)).join(" ")}\n` + `🤖 Bot RAM: ${fmtBytes(s.botRam)}\n` + `⏱️ Bot: ${fmtUptime(s.botUptime)}\n` + `🕒 Sys: ${fmtUptime(s.sysUptime)}\n` + (left > 0 ? `\n🔄 আপডেট চলছে... (${left})` : `\n✅ লাইভ শেষ — আবার দেখতে sysinfo লিখুন`) ); } async function runLiveEdit({ message, api }) { const sample = createSampler(); await new Promise((r) => setTimeout(r, 800)); const first = await message.reply(buildText(sample(), EDIT_TICKS)); const mid = first && first.messageID; if (!mid || typeof api.editMessage !== "function") { return message.reply("⚠️ এই বটের লাইব্রেরিতে মেসেজ এডিট সাপোর্ট নেই। ওয়েব লাইভ ড্যাশবোর্ডের জন্য লিখুন: sysinfo web"); } for (let i = EDIT_TICKS - 1; i >= 0; i--) { await new Promise((r) => setTimeout(r, EDIT_INTERVAL_MS)); try { await new Promise((res, rej) => { const out = api.editMessage(buildText(sample(), i), mid, (err) => (err ? rej(err) : res())); if (out && typeof out.then === "function") out.then(res).catch(rej); }); } catch (e) { // এডিট ফেল করলে চুপচাপ থামো return; } } } // ================= ওয়েব লাইভ ড্যাশবোর্ড ================= const HTML = ` Live System Monitor

SYSTEM MONITOR

LIVE
...

CPU HISTORY (শেষ ৬০ সেকেন্ড)

প্রতিটি কোর

`; let server = null, stopTimer = null, activeToken = null; function getLinkBase() { if (PUBLIC_URL) return PUBLIC_URL.replace(/\/+$/, ""); let ip = "localhost"; const ifs = os.networkInterfaces(); for (const n in ifs) for (const a of ifs[n]) { if (a.family === "IPv4" && !a.internal) { ip = a.address; break; } } return `http://${ip}:${WEB_PORT}`; } function stopServer() { if (stopTimer) clearTimeout(stopTimer); stopTimer = null; if (server) { try { server.closeAllConnections && server.closeAllConnections(); } catch (e) {} try { server.close(); } catch (e) {} } server = null; activeToken = null; } function startServer() { return new Promise((resolve, reject) => { if (server && activeToken) { // মেয়াদ নতুন করে শুরু clearTimeout(stopTimer); stopTimer = setTimeout(stopServer, WEB_LIFETIME_MS); return resolve(activeToken); } const token = crypto.randomBytes(8).toString("hex"); const sample = createSampler(); const clients = new Set(); let ticker = null; const srv = http.createServer((req, res) => { const url = (req.url || "").split("?")[0]; if (url === `/sysinfo/${token}` || url === `/sysinfo/${token}/`) { res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" }); return res.end(HTML); } if (url === `/sysinfo/${token}/stream`) { res.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-store", Connection: "keep-alive", "X-Accel-Buffering": "no" }); res.write(`data: ${JSON.stringify(sample())}\n\n`); clients.add(res); req.on("close", () => clients.delete(res)); return; } res.writeHead(404); res.end("Not found"); }); srv.on("error", (err) => { stopServer(); reject(err); }); srv.listen(WEB_PORT, "0.0.0.0", () => { server = srv; activeToken = token; ticker = setInterval(() => { const data = `data: ${JSON.stringify(sample())}\n\n`; for (const c of clients) { try { c.write(data); } catch (e) { clients.delete(c); } } }, 1000); srv.on("close", () => clearInterval(ticker)); stopTimer = setTimeout(() => { for (const c of clients) { try { c.write("event: bye\ndata: end\n\n"); } catch (e) {} } stopServer(); }, WEB_LIFETIME_MS); resolve(token); }); }); } // ================= কমান্ড ================= module.exports = { config: { name: "sysinfo", aliases: ["system", "sys"], version: "2.0", author: "Zihad", countDown: 10, role: 0, description: { en: "Live CPU / RAM / disk monitor (live-edit message or real-time web dashboard)", bn: "লাইভ CPU / RAM / ডিস্ক মনিটর (লাইভ মেসেজ বা রিয়েল-টাইম ওয়েব ড্যাশবোর্ড)" }, category: "system", guide: { en: "{pn} → live-updating message\n{pn} web → real-time web dashboard link (bot admin only)\n{pn} stop → stop web dashboard (bot admin only)" } }, onStart: async function ({ message, api, event, args }) { const mode = (args[0] || "").toLowerCase(); const admins = (global.GoatBot && global.GoatBot.config && global.GoatBot.config.adminBot) || []; const isAdmin = admins.includes(String(event.senderID)); try { if (mode === "web") { if (!isAdmin) return message.reply("⛔ ওয়েব ড্যাশবোর্ড শুধু বট অ্যাডমিন চালাতে পারবে।"); const token = await startServer(); const link = `${getLinkBase()}/sysinfo/${token}`; return message.reply( `🌐 লাইভ ড্যাশবোর্ড চালু!\n${link}\n\n` + `⏳ ${Math.round(WEB_LIFETIME_MS / 60000)} মিনিট পর নিজে বন্ধ হবে।\n` + `বন্ধ করতে: sysinfo stop` ); } if (mode === "stop") { if (!isAdmin) return message.reply("⛔ শুধু বট অ্যাডমিন।"); if (!server) return message.reply("ওয়েব ড্যাশবোর্ড চালু নেই।"); stopServer(); return message.reply("🛑 ওয়েব ড্যাশবোর্ড বন্ধ করা হয়েছে।"); } return await runLiveEdit({ message, api }); } catch (err) { console.error("[sysinfo] error:", err); if (err && err.code === "EADDRINUSE") { return message.reply(`❌ পোর্ট ${WEB_PORT} ব্যস্ত। অন্য পোর্ট দিন: SYSINFO_PORT=পোর্ট`); } return message.reply("❌ সমস্যা হয়েছে: " + (err.message || err)); } } };