← back to browse
goat command

uptime

Check system uptime and status with image

0
views
0
likes
0
installs

Aliases: runtime, up

raw source
const os = require("os");
const path = require("path");
const fs = require("fs");
const { createCanvas } = require("canvas");

process.stderr.clearLine = process.stderr.clearLine || function () {};
process.stdout.clearLine = process.stdout.clearLine || function () {};

module.exports = {
  config: {
    name: "uptime",
    aliases: ["runtime", "up"],
    version: "1.10",
    author: "NZ R",
    countDown: 5,
    role: 0,
    shortDescription: { en: "Check system uptime and status with image" },
    longDescription: { en: "Displays the system uptime, RAM usage, CPU load, and other server details on an image." },
    category: "SYSTEM",
    guide: { en: "{pn}" }
  },

  onStart: async function ({ api, event }) {
    const { threadID, messageID } = event;
    const cacheFolderPath = path.join(__dirname, "cache");
    if (!fs.existsSync(cacheFolderPath)) fs.mkdirSync(cacheFolderPath, { recursive: true });
    const imagePath = path.join(cacheFolderPath, `uptime_${Date.now()}.png`);

    try {
      api.setMessageReaction("๐Ÿ“ก", event.messageID, () => {}, true);

      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 seconds = Math.floor(uptime % 60);
      const uptimeString = `${days}d ${hours}h ${minutes}m ${seconds}s`;

      const totalMem = os.totalmem();
      const freeMem = os.freemem();
      const usedMem = totalMem - freeMem;
      const usedGB = (usedMem / 1024 / 1024 / 1024).toFixed(2);
      const totalGB = (totalMem / 1024 / 1024 / 1024).toFixed(2);

      const cpus = os.cpus();
      let totalIdle = 0, totalTick = 0;
      cpus.forEach(cpu => {
        for (const type in cpu.times) totalTick += cpu.times[type];
        totalIdle += cpu.times.idle;
      });
      const avgCpuLoad = ((1 - totalIdle / totalTick) * 100).toFixed(2);

      const ping = Date.now() - event.timestamp;
      const platform = `${os.platform()} (${os.arch()})`;
      const nodeVersion = process.version;
      const hostname = os.hostname();

      const info = [
        { label: "Uptime", value: uptimeString },
        { label: "Ping", value: `${ping} ms` },
        { label: "RAM Usage", value: `${usedGB} GB / ${totalGB} GB` },
        { label: "CPU Load", value: `${avgCpuLoad}%` },
        { label: "Platform", value: platform },
        { label: "Node.js", value: nodeVersion },
        { label: "Hostname", value: hostname }
      ];

      const width = 1400;
      const height = 800;
      const canvas = createCanvas(width, height);
      const ctx = canvas.getContext('2d');

      const gradient = ctx.createLinearGradient(0, 0, width, height);
      gradient.addColorStop(0, '#181825');
      gradient.addColorStop(1, '#0a0a10');
      
      const rx = 60, ry = 60;
      ctx.fillStyle = gradient;
      ctx.beginPath();
      ctx.moveTo(rx, 0);
      ctx.lineTo(width - rx, 0);
      ctx.quadraticCurveTo(width, 0, width, ry);
      ctx.lineTo(width, height - ry);
      ctx.quadraticCurveTo(width, height, width - rx, height);
      ctx.lineTo(rx, height);
      ctx.quadraticCurveTo(0, height, 0, height - ry);
      ctx.lineTo(0, ry);
      ctx.quadraticCurveTo(0, 0, rx, 0);
      ctx.closePath();
      ctx.fill();

      const infoBoxWidth = 1260;
      const infoBoxHeight = 610;
      const infoBoxX = (width - infoBoxWidth) / 2;
      const infoBoxY = (height - infoBoxHeight) / 2;
      const infoBoxRx = 70, infoBoxRy = 70;

      ctx.shadowColor = 'rgba(44, 39, 66, 0.8)';
      ctx.shadowBlur = 8;
      ctx.shadowOffsetX = 0;
      ctx.shadowOffsetY = 5;

      ctx.fillStyle = 'rgba(21, 21, 32, 0.98)';
      ctx.beginPath();
      ctx.moveTo(infoBoxX + infoBoxRx, infoBoxY);
      ctx.lineTo(infoBoxX + infoBoxWidth - infoBoxRx, infoBoxY);
      ctx.quadraticCurveTo(infoBoxX + infoBoxWidth, infoBoxY, infoBoxX + infoBoxWidth, infoBoxY + infoBoxRy);
      ctx.lineTo(infoBoxX + infoBoxWidth, infoBoxY + infoBoxHeight - infoBoxRy);
      ctx.quadraticCurveTo(infoBoxX + infoBoxWidth, infoBoxY + infoBoxHeight, infoBoxX + infoBoxWidth - infoBoxRx, infoBoxY + infoBoxHeight);
      ctx.lineTo(infoBoxX + infoBoxRx, infoBoxY + infoBoxHeight);
      ctx.quadraticCurveTo(infoBoxX, infoBoxY + infoBoxHeight, infoBoxX, infoBoxY + infoBoxHeight - infoBoxRy);
      ctx.lineTo(infoBoxX, infoBoxY + infoBoxRy);
      ctx.quadraticCurveTo(infoBoxX, infoBoxY, infoBoxX + infoBoxRx, infoBoxY);
      ctx.closePath();
      ctx.fill();

      ctx.shadowColor = 'transparent';
      ctx.shadowBlur = 0;

      const centerX = width / 2;
      const centerY = height / 2;
      
      const radialGradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, 160);
      radialGradient.addColorStop(0, 'rgba(139, 92, 246, 0.4)');
      radialGradient.addColorStop(0.7, 'rgba(139, 92, 246, 0)');
      radialGradient.addColorStop(1, 'transparent'); 
      
      ctx.fillStyle = radialGradient;
      ctx.beginPath();
      ctx.arc(centerX, centerY, 160, 0, Math.PI * 2);
      ctx.fill();

      ctx.strokeStyle = 'rgba(139, 92, 246, 0.6)';
      ctx.lineWidth = 2.5;
      ctx.beginPath();
      ctx.arc(centerX, centerY, 130, 0, Math.PI * 2);
      ctx.stroke();

      ctx.strokeStyle = 'rgba(167, 139, 250, 0.4)';
      ctx.lineWidth = 1.8;
      ctx.beginPath();
      ctx.arc(centerX, centerY, 100, 0, Math.PI * 2);
      ctx.stroke();

      ctx.font = '500 40px sans-serif';
      
      const startY = infoBoxY + 120;

      info.forEach((item, i) => {
        const yPos = startY + i * 75;

        ctx.fillStyle = '#d1c4e9';
        ctx.textAlign = 'left';
        ctx.fillText(item.label, 160, yPos);

        ctx.fillStyle = '#e0e0f4';
        ctx.fillText(item.value, 600, yPos);

        ctx.strokeStyle = 'rgba(139, 92, 246, 0.15)';
        ctx.lineWidth = 1.2;
        ctx.beginPath();
        ctx.moveTo(160, yPos + 28);
        ctx.lineTo(1240, yPos + 28);
        ctx.stroke();
      });

      const out = fs.createWriteStream(imagePath);
      const stream = canvas.createPNGStream();
      stream.pipe(out);

      out.on('finish', () => {
        api.setMessageReaction("โœ…", event.messageID, () => {}, true);
        api.sendMessage({ attachment: fs.createReadStream(imagePath) }, threadID, (err) => {
          if (!err) fs.unlink(imagePath, () => {});
          else {
            if (fs.existsSync(imagePath)) fs.unlink(imagePath, () => {});
          }
        }, messageID);
      });

    } catch (error) {
      api.setMessageReaction("โŒ", event.messageID, () => {}, true);
      if (fs.existsSync(imagePath)) fs.unlink(imagePath, () => {});
    }
  }
};

View raw file