goat
command
0up
See bot uptime and most used commands in a large neon System Overview HUD (no-prefix: just type 0up)
0
views
0
likes
0
installs
raw source
const os = require('os');
const { createCanvas } = require('canvas');
const fs = require('fs-extra');
const path = require('path');
let si = null;
try {
si = require('systeminformation');
} catch (e) {
si = null;
}
const C = {
bg: '#02060d',
grid: '#0a1830',
panel: '#050f20',
panelAlt: 'rgba(255,255,255,0.03)',
border: '#1c6fe0',
glow: 'rgba(45,150,255,0.6)',
cyan: '#38ecff',
green: '#39ffb8',
blue: '#4a90ff',
purple: '#c07bff',
dim: '#82aee0',
white: '#f5faff',
};
const statsPath = path.join(__dirname, 'cache', 'command_stats_0up.json');
function readCommandStats() {
try {
return fs.readJsonSync(statsPath);
} catch (e) {
return {};
}
}
function writeCommandStats(data) {
try {
fs.ensureDirSync(path.dirname(statsPath));
fs.writeJsonSync(statsPath, data);
} catch (e) {}
}
module.exports = {
config: {
name: "0up",
version: "4.0",
author: "JABED",
countDown: 5,
role: 0,
description: "See bot uptime and most used commands in a large neon System Overview HUD (no-prefix: just type 0up)",
category: "system"
},
// No-prefix trigger: this fires on EVERY message. We check if the
// message text is exactly "0up" (case-insensitive) and run the HUD.
onChat: async function ({ api, event }) {
const body = (event.body || '').trim();
if (!body) return;
// Only trigger on an exact "0up" message (ignoring case/extra spaces)
if (body.toLowerCase() !== '0up') return;
const { threadID, messageID, timestamp } = event;
const uptime = process.uptime();
const days = Math.floor(uptime / 86400);
const hours = Math.floor((uptime % 86400) / 3600);
const minutes = Math.floor((uptime % 3600) / 60);
const secs = Math.floor(uptime % 60);
const uptimeStr = `${days}d ${hours}h ${minutes}m ${secs}s`;
const ping = Date.now() - timestamp;
const nodeVer = process.version;
const platform = `${os.platform()} (${os.arch()})`;
const totalMem = os.totalmem();
const freeMem = os.freemem();
const usedMem = totalMem - freeMem;
const usedMemStr = (usedMem / 1024 / 1024 / 1024).toFixed(2) + ' GB';
const totalMemStr = (totalMem / 1024 / 1024 / 1024).toFixed(2) + ' GB';
const bodyMsg =
`✧━━━━━━━━━━━━━━━━━━━━✧
𝗦𝗬𝗦𝗧𝗘𝗠 𝗢𝗩𝗘𝗥𝗩𝗜𝗘𝗪
✧━━━━━━━━━━━━━━━━━━━━✧
⏱ Uptime : ${uptimeStr}
🏓 Ping : ${ping} ms
📦 Node : ${nodeVer}
🖥 Platform: ${platform}
💾 Memory : ${usedMemStr} / ${totalMemStr}
✧━━━━━━━━━━━━━━━━━━━━✧
⚡ Powered by JABED`;
try {
const cachePath = path.join(__dirname, 'cache', `zeroup_hud.png`);
fs.ensureDirSync(path.join(__dirname, 'cache'));
const buffer = await generateHUD({ timestamp });
fs.writeFileSync(cachePath, buffer);
return api.sendMessage(
{
body: bodyMsg,
attachment: fs.createReadStream(cachePath)
},
threadID,
() => fs.unlinkSync(cachePath),
messageID
);
} catch (e) {
api.sendMessage(`Error: ${e.message}`, threadID);
}
},
// Keeping onStart too, in case the bot loader requires it and/or
// someone still calls it with the prefix (prefix + 0up).
onStart: async function ({ api, event }) {
const { threadID, messageID, timestamp } = event;
const uptime = process.uptime();
const days = Math.floor(uptime / 86400);
const hours = Math.floor((uptime % 86400) / 3600);
const minutes = Math.floor((uptime % 3600) / 60);
const secs = Math.floor(uptime % 60);
const uptimeStr = `${days}d ${hours}h ${minutes}m ${secs}s`;
const ping = Date.now() - timestamp;
const nodeVer = process.version;
const platform = `${os.platform()} (${os.arch()})`;
const totalMem = os.totalmem();
const freeMem = os.freemem();
const usedMem = totalMem - freeMem;
const usedMemStr = (usedMem / 1024 / 1024 / 1024).toFixed(2) + ' GB';
const totalMemStr = (totalMem / 1024 / 1024 / 1024).toFixed(2) + ' GB';
const bodyMsg =
`✧━━━━━━━━━━━━━━━━━━━━✧
𝗦𝗬𝗦𝗧𝗘𝗠 𝗢𝗩𝗘𝗥𝗩𝗜𝗘𝗪
✧━━━━━━━━━━━━━━━━━━━━✧
⏱ Uptime : ${uptimeStr}
🏓 Ping : ${ping} ms
📦 Node : ${nodeVer}
🖥 Platform: ${platform}
💾 Memory : ${usedMemStr} / ${totalMemStr}
✧━━━━━━━━━━━━━━━━━━━━✧
⚡ Powered by JABED`;
try {
const cachePath = path.join(__dirname, 'cache', `zeroup_hud.png`);
fs.ensureDirSync(path.join(__dirname, 'cache'));
const buffer = await generateHUD({ timestamp });
fs.writeFileSync(cachePath, buffer);
return api.sendMessage(
{
body: bodyMsg,
attachment: fs.createReadStream(cachePath)
},
threadID,
() => fs.unlinkSync(cachePath),
messageID
);
} catch (e) {
api.sendMessage(`Error: ${e.message}`, threadID);
}
}
};
async function generateHUD({ timestamp }) {
const totalMem = os.totalmem();
const freeMem = os.freemem();
const usedMem = totalMem - freeMem;
const ramPct = (usedMem / totalMem) * 100;
const cpuPct = Math.min(100, (os.loadavg()[0] / os.cpus().length) * 100);
const ping = Date.now() - timestamp;
let cpuHistory = [];
for (let i = 0; i < 30; i++) cpuHistory.push(Math.max(3, cpuPct + (Math.random() * 16 - 8)));
let storage = [];
let processes = [];
if (si) {
const [fsSize, procs] = await Promise.all([
si.fsSize().catch(() => []),
si.processes().catch(() => null),
]);
storage = fsSize.slice(0, 3).map(d => ({ name: d.mount, used: d.used, size: d.size, pct: d.use }));
if (procs && procs.list) {
processes = procs.list.sort((a, b) => b.cpu - a.cpu).slice(0, 5)
.map(p => ({ name: p.name, cpu: p.cpu.toFixed(2) + '%', mem: (p.memRss / 1024).toFixed(1) + ' MB' }));
}
}
const rawStats = readCommandStats();
const topCommands = Object.entries(rawStats)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([name, count]) => ({ name, count }));
const maxCount = topCommands.length ? topCommands[0].count : 1;
const s = {
botUptime: fmtUptime(process.uptime()),
ping: `${ping} ms`,
ramUsed: fmtBytes(usedMem),
ramTotal: fmtBytes(totalMem),
ramPct,
cpuPct,
cpuHistory,
platform: `${os.platform()} (${os.arch()})`,
nodeVersion: process.version,
hostname: os.hostname(),
storage,
processes,
topCommands,
maxCount,
};
const W = 3400, H = 2000;
const canvas = createCanvas(W, H);
const ctx = canvas.getContext('2d');
const bgGrad = ctx.createRadialGradient(W / 2, H / 2, 120, W / 2, H / 2, W * 0.75);
bgGrad.addColorStop(0, '#071228');
bgGrad.addColorStop(0.55, '#03080f');
bgGrad.addColorStop(1, '#000103');
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, W, H);
ctx.strokeStyle = C.grid;
ctx.lineWidth = 1;
for (let gx = 0; gx < W; gx += 60) { ctx.beginPath(); ctx.moveTo(gx, 0); ctx.lineTo(gx, H); ctx.stroke(); }
for (let gy = 0; gy < H; gy += 60) { ctx.beginPath(); ctx.moveTo(0, gy); ctx.lineTo(W, gy); ctx.stroke(); }
drawPanel(ctx, 30, 30, W - 60, H - 60, 34);
ctx.fillStyle = C.cyan;
ctx.font = 'bold 78px Sans';
ctx.textAlign = 'left';
spacedText(ctx, '● SYSTEM OVERVIEW', 110, 150, 2);
ctx.font = '600 34px Sans';
ctx.fillStyle = C.dim;
spacedText(ctx, 'REAL-TIME MONITORING', 1230, 140, 5);
const now = new Date();
ctx.textAlign = 'right';
ctx.fillStyle = C.white;
ctx.font = 'bold 48px Sans';
ctx.fillText(now.toLocaleTimeString('en-GB'), W - 110, 140);
ctx.font = '32px Sans';
ctx.fillStyle = C.dim;
ctx.fillText(now.toDateString(), W - 110, 92);
ctx.textAlign = 'left';
const leftX = 110, leftY = 230, leftW = 1900, leftH = 1050;
drawPanel(ctx, leftX, leftY, leftW, leftH);
const rows = [
['BOT UPTIME', s.botUptime],
['PING', s.ping],
['RAM', `${s.ramUsed} / ${s.ramTotal}`],
['CPU LOAD', `${s.cpuPct.toFixed(2)}%`],
['PLATFORM', s.platform],
['NODE.JS', s.nodeVersion],
['HOSTNAME', s.hostname],
];
let ry = leftY + 120;
const rowH = 140;
rows.forEach(([label, value], i) => {
if (i % 2 === 0) {
ctx.fillStyle = C.panelAlt;
ctx.fillRect(leftX + 30, ry - 70, leftW - 60, rowH - 16);
}
ctx.fillStyle = C.green;
ctx.beginPath();
ctx.arc(leftX + 68, ry - 12, 9, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = C.green;
ctx.font = 'bold 40px monospace';
ctx.fillText(label, leftX + 100, ry);
ctx.fillStyle = C.white;
ctx.font = '40px monospace';
ctx.fillText(': ' + value, leftX + 580, ry);
if (label === 'RAM') {
drawProgressBar(ctx, leftX + 580, ry + 30, 950, 30, s.ramPct, C.cyan);
ctx.fillStyle = C.white;
ctx.font = 'bold 34px monospace';
ctx.fillText(s.ramPct.toFixed(0) + '%', leftX + 1560, ry + 55);
}
if (label === 'CPU LOAD') {
drawSparkline(ctx, leftX + 580, ry - 45, 750, 65, s.cpuHistory, C.green);
}
if (i < rows.length - 1) {
ctx.strokeStyle = '#123057';
ctx.setLineDash([7, 7]);
ctx.beginPath();
ctx.moveTo(leftX + 80, ry + 42);
ctx.lineTo(leftX + leftW - 80, ry + 42);
ctx.stroke();
ctx.setLineDash([]);
}
ry += rowH;
});
const rightX = 2060, rightW = 1230;
drawPanel(ctx, rightX, leftY, rightW, 500);
ctx.fillStyle = C.cyan;
ctx.font = 'bold 36px Sans';
ctx.fillText('● CPU USAGE', rightX + 45, leftY + 60);
drawGauge(ctx, rightX + 230, leftY + 260, 145, s.cpuPct, C.blue, 50);
drawSparkline(ctx, rightX + 420, leftY + 90, 760, 270, s.cpuHistory, C.blue);
const ramY = leftY + 500 + 50;
drawPanel(ctx, rightX, ramY, rightW, 500);
ctx.fillStyle = C.cyan;
ctx.font = 'bold 36px Sans';
ctx.fillText('● RAM USAGE', rightX + 45, ramY + 60);
drawGauge(ctx, rightX + 230, ramY + 260, 145, s.ramPct, C.green, 50);
ctx.fillStyle = C.green;
ctx.font = 'bold 34px monospace';
ctx.fillText(`USED ${s.ramUsed}`, rightX + 470, ramY + 200);
ctx.fillStyle = C.white;
ctx.font = '34px monospace';
ctx.fillText(`TOTAL ${s.ramTotal}`, rightX + 470, ramY + 250);
drawProgressBar(ctx, rightX + 470, ramY + 285, 700, 30, s.ramPct, C.green);
const botY = leftY + leftH + 50, botH = 500, colW = 1026, gap = 50;
const col1 = 110, col2 = col1 + colW + gap, col3 = col2 + colW + gap;
drawPanel(ctx, col1, botY, colW, botH);
ctx.fillStyle = C.cyan;
ctx.font = 'bold 36px Sans';
ctx.fillText('☰ STORAGE', col1 + 45, botY + 65);
let sy = botY + 150;
const storageData = s.storage.length ? s.storage : [{ name: '/', used: 0, size: 1, pct: 0 }];
storageData.forEach(d => {
ctx.fillStyle = C.white;
ctx.font = 'bold 30px monospace';
ctx.fillText(d.name, col1 + 45, sy);
drawProgressBar(ctx, col1 + 300, sy - 26, 380, 22, d.pct, C.blue);
ctx.fillStyle = C.cyan;
ctx.font = 'bold 27px monospace';
ctx.fillText(`${d.pct.toFixed(0)}%`, col1 + 720, sy);
ctx.font = '23px monospace';
ctx.fillStyle = C.dim;
ctx.fillText(`${fmtBytes(d.used)} / ${fmtBytes(d.size)}`, col1 + 300, sy + 32);
sy += 115;
});
drawPanel(ctx, col2, botY, colW, botH);
ctx.fillStyle = C.cyan;
ctx.font = 'bold 36px Sans';
ctx.fillText('★ TOP COMMANDS', col2 + 45, botY + 65);
let cy = botY + 155;
const cmdData = s.topCommands.length ? s.topCommands : [{ name: 'N/A', count: 0 }];
const cmdColors = [C.green, C.cyan, C.blue, C.purple, C.dim];
cmdData.forEach((c, i) => {
ctx.fillStyle = cmdColors[i % cmdColors.length];
ctx.font = 'bold 30px monospace';
ctx.fillText(`${i + 1}.`, col2 + 45, cy);
ctx.fillStyle = C.white;
ctx.font = 'bold 30px monospace';
ctx.fillText(c.name, col2 + 100, cy);
drawProgressBar(ctx, col2 + 45, cy + 18, colW - 200, 18, (c.count / s.maxCount) * 100, cmdColors[i % cmdColors.length]);
ctx.fillStyle = C.dim;
ctx.font = '24px monospace';
ctx.textAlign = 'right';
ctx.fillText(`${c.count}x`, col2 + colW - 45, cy);
ctx.textAlign = 'left';
cy += 82;
});
drawPanel(ctx, col3, botY, colW, botH);
ctx.fillStyle = C.cyan;
ctx.font = 'bold 36px Sans';
ctx.fillText('☰ TOP PROCESSES', col3 + 45, botY + 65);
ctx.font = 'bold 24px monospace';
ctx.fillStyle = C.dim;
ctx.fillText('CPU', col3 + 680, botY + 65);
ctx.fillText('MEM', col3 + 830, botY + 65);
const procData = s.processes.length ? s.processes : [{ name: 'node', cpu: '—', mem: '—' }];
let py = botY + 145;
const dots = [C.green, C.green, C.blue, C.purple, C.purple];
procData.forEach((p, i) => {
if (i % 2 === 0) {
ctx.fillStyle = C.panelAlt;
ctx.fillRect(col3 + 30, py - 38, colW - 60, 58);
}
ctx.fillStyle = dots[i % dots.length];
ctx.beginPath();
ctx.arc(col3 + 68, py - 10, 9, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = C.white;
ctx.font = 'bold 30px monospace';
ctx.fillText(p.name, col3 + 100, py);
ctx.font = '27px monospace';
ctx.fillStyle = C.cyan;
ctx.fillText(p.cpu, col3 + 670, py);
ctx.fillStyle = C.white;
ctx.fillText(p.mem, col3 + 810, py);
py += 72;
});
const footY = H - 160, footW = W - 220;
drawPanel(ctx, 110, footY, footW, 110);
ctx.fillStyle = C.green;
ctx.beginPath();
ctx.arc(170, footY + 55, 11, 0, Math.PI * 2);
ctx.fill();
ctx.font = 'bold 30px monospace';
ctx.fillStyle = C.dim;
ctx.fillText('STATUS:', 200, footY + 66);
ctx.fillStyle = C.white;
ctx.fillText('ONLINE', 380, footY + 66);
ctx.fillStyle = C.dim;
ctx.fillText('LOAD AVG:', 680, footY + 66);
ctx.fillStyle = C.white;
ctx.fillText(os.loadavg().map(n => n.toFixed(2)).join(', '), 940, footY + 66);
ctx.fillStyle = C.dim;
ctx.fillText('COMMANDS TRACKED:', 1650, footY + 66);
ctx.fillStyle = C.white;
ctx.fillText(String(Object.keys(rawStats).length), 2020, footY + 66);
ctx.fillStyle = C.green;
ctx.font = 'bold 30px monospace';
ctx.textAlign = 'right';
ctx.fillText('🔒 SECURE', W - 160, footY + 66);
ctx.textAlign = 'left';
return canvas.toBuffer('image/png');
}
function roundRect(ctx, x, y, w, h, r) {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
}
function drawPanel(ctx, x, y, w, h, r = 20) {
ctx.save();
ctx.shadowColor = C.glow;
ctx.shadowBlur = 18;
roundRect(ctx, x, y, w, h, r);
ctx.fillStyle = C.panel;
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = C.border;
ctx.stroke();
ctx.restore();
}
function spacedText(ctx, text, x, y, spacing = 2) {
let cx = x;
for (const ch of text) {
ctx.fillText(ch, cx, y);
cx += ctx.measureText(ch).width + spacing;
}
}
function drawProgressBar(ctx, x, y, w, h, pct, color) {
roundRect(ctx, x, y, w, h, h / 2);
ctx.fillStyle = '#0b1b33';
ctx.fill();
const fillW = Math.max(h, (w * Math.min(pct, 100)) / 100);
roundRect(ctx, x, y, fillW, h, h / 2);
ctx.fillStyle = color;
ctx.shadowColor = color;
ctx.shadowBlur = 14;
ctx.fill();
ctx.shadowBlur = 0;
}
function drawGauge(ctx, cx, cy, radius, pct, color, fontSize = 30) {
const start = -Math.PI / 2;
const end = start + (Math.PI * 2 * Math.min(pct, 100)) / 100;
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.strokeStyle = '#0b1b33';
ctx.lineWidth = 26;
ctx.stroke();
ctx.beginPath();
ctx.arc(cx, cy, radius, start, end);
ctx.strokeStyle = color;
ctx.lineWidth = 26;
ctx.lineCap = 'round';
ctx.shadowColor = color;
ctx.shadowBlur = 20;
ctx.stroke();
ctx.shadowBlur = 0;
ctx.fillStyle = C.white;
ctx.font = `bold ${fontSize}px Sans`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(`${pct.toFixed(2)}%`, cx, cy);
ctx.textAlign = 'left';
ctx.textBaseline = 'alphabetic';
}
function drawSparkline(ctx, x, y, w, h, data, color) {
if (!data || data.length < 2) return;
const max = Math.max(...data, 1);
const step = w / (data.length - 1);
ctx.beginPath();
data.forEach((v, i) => {
const px = x + i * step;
const py = y + h - (v / max) * h;
if (i === 0) ctx.moveTo(px, py);
else ctx.lineTo(px, py);
});
ctx.strokeStyle = color;
ctx.lineWidth = 4;
ctx.shadowColor = color;
ctx.shadowBlur = 10;
ctx.stroke();
ctx.shadowBlur = 0;
ctx.lineTo(x + w, y + h);
ctx.lineTo(x, y + h);
ctx.closePath();
const grad = ctx.createLinearGradient(0, y, 0, y + h);
grad.addColorStop(0, color + '55');
grad.addColorStop(1, color + '00');
ctx.fillStyle = grad;
ctx.fill();
}
function fmtBytes(bytes) {
return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB';
}
function fmtUptime(seconds) {
const d = Math.floor(seconds / 86400);
const h = Math.floor((seconds % 86400) / 3600);
const m = Math.floor((seconds % 3600) / 60);
const sec = Math.floor(seconds % 60);
return `${d}d ${h}h ${m}m ${sec}s`;
}