← back to browse
goat command

up

No description

1
views
0
likes
1
installs

Aliases: uptime

raw source
module.exports.config = {
  name: "up",
  version: "1.0.0",
  author: "Mohammad Maruf",
  aliases: ["uptime"],
  role: 0,
  category: "system"
};

const { createCanvas } = require("canvas");
const fs = require("fs-extra");
const path = require("path");
const os = require("os");

module.exports.onStart = async function ({ api, event }) {
  const started = Date.now();

  try {
    const formatUptime = (seconds) => {
      seconds = Math.floor(seconds);

      const days = Math.floor(seconds / 86400);
      seconds %= 86400;

      const hours = Math.floor(seconds / 3600);
      seconds %= 3600;

      const minutes = Math.floor(seconds / 60);
      const secs = seconds % 60;

      const parts = [];

      if (days > 0) parts.push(`${days}d`);
      if (hours > 0) parts.push(`${hours}h`);
      if (minutes > 0) parts.push(`${minutes}m`);
      parts.push(`${secs}s`);

      return parts.join(" ");
    };

    const getCPU = () => {
      try {
        const cpus = os.cpus();

        if (!cpus.length) return 0;

        let idle = 0;
        let total = 0;

        for (const cpu of cpus) {
          idle += cpu.times.idle;
          total +=
            cpu.times.user +
            cpu.times.nice +
            cpu.times.sys +
            cpu.times.idle +
            cpu.times.irq;
        }

        const usage = 100 - (idle / total) * 100;

        return Math.max(0, Math.min(100, usage));
      } catch (_) {
        return 0;
      }
    };

    const getDisk = () => {
      try {
        if (typeof fs.statfsSync !== "function") {
          return { used: 0, total: 0, percent: 0 };
        }

        const stat = fs.statfsSync("/");

        const total = Number(stat.blocks) * Number(stat.bsize);
        const free = Number(stat.bfree) * Number(stat.bsize);
        const used = total - free;

        return {
          used,
          total,
          percent: total > 0 ? (used / total) * 100 : 0
        };
      } catch (_) {
        return { used: 0, total: 0, percent: 0 };
      }
    };

    const roundRect = (ctx, x, y, w, h, r) => {
      ctx.beginPath();
      ctx.moveTo(x + r, y);
      ctx.lineTo(x + w - r, y);
      ctx.quadraticCurveTo(x + w, y, x + w, y + r);
      ctx.lineTo(x + w, y + h - r);
      ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
      ctx.lineTo(x + r, y + h);
      ctx.quadraticCurveTo(x, y + h, x, y + h - r);
      ctx.lineTo(x, y + r);
      ctx.quadraticCurveTo(x, y, x + r, y);
      ctx.closePath();
    };

    const bubble = (ctx, x, y, r, color, alpha = 1) => {
      ctx.save();
      ctx.globalAlpha = alpha;
      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.arc(x, y, r, 0, Math.PI * 2);
      ctx.fill();
      ctx.restore();
    };

    const cloud = (ctx, x, y, scale = 1) => {
      ctx.save();

      ctx.fillStyle = "#FFFFFF";
      ctx.globalAlpha = 0.72;

      ctx.beginPath();
      ctx.arc(x, y + 22 * scale, 30 * scale, 0, Math.PI * 2);
      ctx.arc(x + 34 * scale, y, 39 * scale, 0, Math.PI * 2);
      ctx.arc(x + 75 * scale, y + 20 * scale, 31 * scale, 0, Math.PI * 2);

      ctx.moveTo(x - 30 * scale, y + 22 * scale);
      ctx.quadraticCurveTo(
        x + 38 * scale,
        y + 58 * scale,
        x + 104 * scale,
        y + 23 * scale
      );

      ctx.lineTo(x + 104 * scale, y + 43 * scale);
      ctx.lineTo(x - 30 * scale, y + 43 * scale);
      ctx.closePath();

      ctx.fill();
      ctx.restore();
    };

    const drawSparkle = (ctx, x, y, size, color) => {
      ctx.save();
      ctx.fillStyle = color;

      ctx.beginPath();
      ctx.moveTo(x, y - size);
      ctx.lineTo(x + size * 0.28, y - size * 0.28);
      ctx.lineTo(x + size, y);
      ctx.lineTo(x + size * 0.28, y + size * 0.28);
      ctx.lineTo(x, y + size);
      ctx.lineTo(x - size * 0.28, y + size * 0.28);
      ctx.lineTo(x - size, y);
      ctx.lineTo(x - size * 0.28, y - size * 0.28);
      ctx.closePath();
      ctx.fill();

      ctx.restore();
    };

    const width = 1280;
    const height = 760;

    const canvas = createCanvas(width, height);
    const ctx = canvas.getContext("2d");

    const background = ctx.createLinearGradient(0, 0, width, height);
    background.addColorStop(0, "#E9F6FF");
    background.addColorStop(0.45, "#F0EBFF");
    background.addColorStop(1, "#FFF0F5");

    ctx.fillStyle = background;
    ctx.fillRect(0, 0, width, height);

    cloud(ctx, 75, 70, 1);
    cloud(ctx, 1010, 75, 1.25);
    cloud(ctx, 1110, 280, 0.55);

    bubble(ctx, 115, 300, 55, "#DCCFFF", 0.25);
    bubble(ctx, 1180, 500, 75, "#B9DFF7", 0.25);
    bubble(ctx, 1010, 580, 42, "#F5C9D9", 0.3);

    drawSparkle(ctx, 1050, 180, 10, "#C6B7F4");
    drawSparkle(ctx, 180, 180, 7, "#A8D5F0");
    drawSparkle(ctx, 1125, 330, 6, "#E6AFC5");

    ctx.save();

    ctx.shadowColor = "rgba(93, 77, 130, 0.16)";
    ctx.shadowBlur = 45;
    ctx.shadowOffsetY = 18;

    roundRect(ctx, 65, 55, 1150, 650, 48);

    const panel = ctx.createLinearGradient(65, 55, 1215, 705);
    panel.addColorStop(0, "rgba(255,255,255,0.94)");
    panel.addColorStop(1, "rgba(255,249,253,0.90)");

    ctx.fillStyle = panel;
    ctx.fill();

    ctx.restore();

    ctx.fillStyle = "#443A5B";
    ctx.font = "700 42px Sans";
    ctx.fillText("MARUF'S BOT", 115, 125);

    ctx.fillStyle = "#9389A6";
    ctx.font = "500 17px Sans";
    ctx.fillText("Live information", 118, 153);

    bubble(ctx, 1080, 115, 9, "#B8A8E7");

    ctx.fillStyle = "#8A80A0";
    ctx.font = "600 13px Sans";
    ctx.fillText("ONLINE", 1100, 120);

    const heroX = 115;
    const heroY = 185;
    const heroW = 1050;
    const heroH = 165;

    ctx.save();

    ctx.shadowColor = "rgba(114, 96, 155, 0.12)";
    ctx.shadowBlur = 25;
    ctx.shadowOffsetY = 10;

    roundRect(ctx, heroX, heroY, heroW, heroH, 38);

    const hero = ctx.createLinearGradient(
      heroX,
      heroY,
      heroX + heroW,
      heroY + heroH
    );

    hero.addColorStop(0, "#DDF2FF");
    hero.addColorStop(0.5, "#EDE5FF");
    hero.addColorStop(1, "#FFE7F0");

    ctx.fillStyle = hero;
    ctx.fill();

    ctx.restore();

    ctx.fillStyle = "#817596";
    ctx.font = "600 15px Sans";
    ctx.fillText("RUNNING FOR", 155, 228);

    ctx.fillStyle = "#403652";
    ctx.font = "700 48px Sans";
    ctx.fillText(
      formatUptime(process.uptime()),
      155,
      282
    );

    ctx.fillStyle = "#9489A7";
    ctx.font = "500 16px Sans";
    ctx.fillText("process uptime", 158, 313);

    bubble(ctx, 1030, 260, 50, "#FFFFFF", 0.55);
    bubble(ctx, 1080, 285, 32, "#FFFFFF", 0.42);
    bubble(ctx, 990, 290, 25, "#FFFFFF", 0.35);

    drawSparkle(ctx, 1075, 230, 9, "#B39DEB");

    const response = Date.now() - started;
    const cpu = getCPU();

    const totalMemory = os.totalmem();
    const freeMemory = os.freemem();
    const usedMemory = totalMemory - freeMemory;

    const ramPercent =
      totalMemory > 0
        ? (usedMemory / totalMemory) * 100
        : 0;

    const disk = getDisk();

    const cards = [
      {
        x: 115,
        title: "RESPONSE",
        value: `${response} ms`,
        bg: "#FFF0E5",
        dot: "#E8AE80"
      },
      {
        x: 380,
        title: "CPU",
        value: `${cpu.toFixed(1)}%`,
        bg: "#EAE5FF",
        dot: "#9E8BD7"
      },
      {
        x: 645,
        title: "RAM",
        value: `${ramPercent.toFixed(1)}%`,
        bg: "#E4F3FF",
        dot: "#82B8D8"
      },
      {
        x: 910,
        title: "DISK",
        value: `${disk.percent.toFixed(1)}%`,
        bg: "#FFE8F0",
        dot: "#D89AB4"
      }
    ];

    cards.forEach((card) => {
      ctx.save();

      ctx.shadowColor = "rgba(105, 88, 130, 0.09)";
      ctx.shadowBlur = 18;
      ctx.shadowOffsetY = 9;

      roundRect(ctx, card.x, 385, 235, 120, 30);

      ctx.fillStyle = card.bg;
      ctx.fill();

      ctx.restore();

      bubble(ctx, card.x + 28, 415, 6, card.dot);

      ctx.fillStyle = "#827791";
      ctx.font = "600 12px Sans";
      ctx.fillText(card.title, card.x + 43, 420);

      ctx.fillStyle = "#463B58";
      ctx.font = "700 27px Sans";
      ctx.fillText(card.value, card.x + 25, 463);

      ctx.fillStyle = "#A39AAD";
      ctx.font = "500 12px Sans";

      if (card.title === "RAM") {
        ctx.fillText(
          `${Math.round(usedMemory / 1024 / 1024)} MB used`,
          card.x + 25,
          486
        );
      } else if (card.title === "DISK") {
        ctx.fillText(
          `${Math.round(disk.used / 1024 / 1024 / 1024)} GB used`,
          card.x + 25,
          486
        );
      } else {
        ctx.fillText("current value", card.x + 25, 486);
      }
    });

    const details = [
      ["PLATFORM", process.platform],
      ["NODE", process.version],
      ["CORES", String(os.cpus().length)],
      ["LOAD", (os.loadavg()[0] || 0).toFixed(2)]
    ];

    details.forEach((item, index) => {
      const x = 115 + index * 265;

      ctx.fillStyle = "#978CA9";
      ctx.font = "600 11px Sans";
      ctx.fillText(item[0], x, 548);

      ctx.fillStyle = "#554967";
      ctx.font = "600 17px Sans";
      ctx.fillText(item[1], x, 578);
    });

    ctx.save();

    ctx.globalAlpha = 0.8;

    ctx.fillStyle = "#D9CEFA";
    ctx.beginPath();
    ctx.ellipse(135, 650, 70, 25, -0.15, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#C9E7FA";
    ctx.beginPath();
    ctx.ellipse(235, 660, 100, 27, 0.12, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#F4D4E0";
    ctx.beginPath();
    ctx.ellipse(1090, 650, 95, 26, -0.1, 0, Math.PI * 2);
    ctx.fill();

    ctx.restore();

    drawSparkle(ctx, 320, 630, 6, "#B5A3E9");
    drawSparkle(ctx, 930, 625, 8, "#D9A8BE");

    const now = new Date();

    const dateText = now.toLocaleDateString("en-GB", {
      day: "2-digit",
      month: "short",
      year: "numeric"
    });

    const timeText = now.toLocaleTimeString("en-US", {
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit"
    });

    ctx.fillStyle = "#A097A9";
    ctx.font = "500 12px Sans";
    ctx.fillText(
      `${dateText}  •  ${timeText}`,
      115,
      670
    );

    const filePath = path.join(
      __dirname,
      `uptime_${Date.now()}.png`
    );

    fs.writeFileSync(
      filePath,
      canvas.toBuffer("image/png")
    );

    await api.sendMessage(
      {
        attachment: fs.createReadStream(filePath)
      },
      event.threadID,
      () => {
        try {
          fs.unlinkSync(filePath);
        } catch (_) {}
      },
      event.messageID
    );
  } catch (_) {}
};

View raw file