goat
command
cpanel
Display hosting information with beautiful circular visual interface
0
views
0
likes
0
installs
Aliases: hosting, server, hostinfo, panel
raw source
const { createCanvas, loadImage, registerFont } = require('canvas');
const fs = require('fs-extra');
const path = require('path');
const os = require('os');
const fontDir = path.join(__dirname, 'assets', 'font');
const cacheDir = path.join(__dirname, 'cache');
registerFont(path.join(fontDir, 'BeVietnamPro-Bold.ttf'), { family: 'BeVietnamPro', weight: 'bold' });
registerFont(path.join(fontDir, 'BeVietnamPro-SemiBold.ttf'), { family: 'BeVietnamPro', weight: '600' });
registerFont(path.join(fontDir, 'BeVietnamPro-Regular.ttf'), { family: 'BeVietnamPro', weight: 'normal' });
registerFont(path.join(fontDir, 'NotoSans-Bold.ttf'), { family: 'NotoSans', weight: 'bold' });
registerFont(path.join(fontDir, 'NotoSans-SemiBold.ttf'), { family: 'NotoSans', weight: '600' });
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 B';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
function formatUptime(seconds) {
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${days}d ${hours}h ${minutes}m`;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function drawGlowCircle(ctx, x, y, radius, colors, glowColor, glowSize = 30) {
ctx.save();
for (let i = glowSize; i > 0; i--) {
const alpha = (1 - i / glowSize) * 0.15;
ctx.beginPath();
ctx.arc(x, y, radius + i, 0, Math.PI * 2);
ctx.fillStyle = glowColor.replace(')', `, ${alpha})`).replace('rgb', 'rgba');
ctx.fill();
}
const gradient = ctx.createRadialGradient(x - radius * 0.3, y - radius * 0.3, 0, x, y, radius);
gradient.addColorStop(0, colors[0]);
gradient.addColorStop(0.7, colors[1]);
gradient.addColorStop(1, colors[2] || colors[1]);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = gradient;
ctx.fill();
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
ctx.lineWidth = 2;
ctx.stroke();
ctx.beginPath();
ctx.arc(x, y, radius - 5, -Math.PI * 0.7, -Math.PI * 0.3);
const shineGradient = ctx.createLinearGradient(x - radius, y - radius, x, y);
shineGradient.addColorStop(0, 'rgba(255,255,255,0.4)');
shineGradient.addColorStop(1, 'rgba(255,255,255,0)');
ctx.strokeStyle = shineGradient;
ctx.lineWidth = 3;
ctx.stroke();
ctx.restore();
}
function drawProgressArc(ctx, x, y, radius, progress, bgColor, fillColor, lineWidth = 8) {
ctx.save();
ctx.beginPath();
ctx.arc(x, y, radius, -Math.PI * 0.75, Math.PI * 0.75);
ctx.strokeStyle = bgColor;
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
ctx.stroke();
if (progress > 0) {
const sweepAngle = (Math.PI * 1.5) * (progress / 100);
ctx.beginPath();
ctx.arc(x, y, radius, -Math.PI * 0.75, -Math.PI * 0.75 + sweepAngle);
ctx.strokeStyle = fillColor;
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
ctx.stroke();
}
ctx.restore();
}
function drawConnectingLine(ctx, x1, y1, x2, y2, color) {
ctx.save();
const gradient = ctx.createLinearGradient(x1, y1, x2, y2);
gradient.addColorStop(0, 'rgba(255,255,255,0.05)');
gradient.addColorStop(0.5, color);
gradient.addColorStop(1, 'rgba(255,255,255,0.05)');
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.strokeStyle = gradient;
ctx.lineWidth = 2;
ctx.stroke();
const dotX = x1 + (x2 - x1) * 0.3;
const dotY = y1 + (y2 - y1) * 0.3;
ctx.beginPath();
ctx.arc(dotX, dotY, 4, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
ctx.restore();
}
function drawIcon(ctx, x, y, size, type, color = 'rgba(255,255,255,0.9)') {
ctx.save();
ctx.fillStyle = color;
ctx.strokeStyle = color;
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
const scale = size / 24;
ctx.translate(x - 12 * scale, y - 12 * scale);
ctx.scale(scale, scale);
switch(type) {
case 'server':
ctx.beginPath();
ctx.roundRect(4, 3, 16, 5, 2);
ctx.roundRect(4, 10, 16, 5, 2);
ctx.roundRect(4, 17, 16, 4, 2);
ctx.stroke();
ctx.beginPath();
ctx.arc(7, 5.5, 1, 0, Math.PI * 2);
ctx.arc(7, 12.5, 1, 0, Math.PI * 2);
ctx.fill();
break;
case 'cpu':
ctx.strokeRect(6, 6, 12, 12);
ctx.beginPath();
const pins = [[9,3,9,6], [12,3,12,6], [15,3,15,6], [9,18,9,21], [12,18,12,21], [15,18,15,21],
[3,9,6,9], [3,12,6,12], [3,15,6,15], [18,9,21,9], [18,12,21,12], [18,15,21,15]];
pins.forEach(([a,b,c,d]) => { ctx.moveTo(a, b); ctx.lineTo(c, d); });
ctx.stroke();
ctx.fillRect(9, 9, 6, 6);
break;
case 'ram':
ctx.strokeRect(2, 7, 20, 10);
ctx.fillRect(5, 10, 3, 4);
ctx.fillRect(10, 10, 3, 4);
ctx.fillRect(16, 10, 3, 4);
break;
case 'storage':
ctx.beginPath();
ctx.ellipse(12, 7, 8, 4, 0, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(4, 7); ctx.lineTo(4, 17);
ctx.moveTo(20, 7); ctx.lineTo(20, 17);
ctx.stroke();
ctx.beginPath();
ctx.ellipse(12, 17, 8, 4, 0, 0, Math.PI * 2);
ctx.stroke();
break;
case 'bandwidth':
ctx.beginPath();
ctx.moveTo(3, 17); ctx.lineTo(8, 11); ctx.lineTo(12, 14); ctx.lineTo(16, 7); ctx.lineTo(21, 10);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(16, 7); ctx.lineTo(21, 7); ctx.lineTo(21, 12);
ctx.stroke();
break;
case 'domain':
ctx.beginPath();
ctx.arc(12, 12, 9, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.ellipse(12, 12, 4, 9, 0, 0, Math.PI * 2);
ctx.stroke();
ctx.moveTo(3, 12); ctx.lineTo(21, 12);
ctx.moveTo(12, 3); ctx.lineTo(12, 21);
ctx.stroke();
break;
case 'ssl':
ctx.strokeRect(5, 11, 14, 9);
ctx.beginPath();
ctx.moveTo(8, 11); ctx.lineTo(8, 8);
ctx.arc(12, 8, 4, Math.PI, 0);
ctx.lineTo(16, 11);
ctx.stroke();
ctx.beginPath();
ctx.arc(12, 15, 2, 0, Math.PI * 2);
ctx.fill();
break;
case 'email':
ctx.strokeRect(2, 5, 20, 14);
ctx.beginPath();
ctx.moveTo(2, 5); ctx.lineTo(12, 12); ctx.lineTo(22, 5);
ctx.stroke();
break;
case 'ftp':
ctx.beginPath();
ctx.moveTo(12, 4); ctx.lineTo(12, 16);
ctx.moveTo(7, 9); ctx.lineTo(12, 4); ctx.lineTo(17, 9);
ctx.stroke();
ctx.strokeRect(4, 16, 16, 4);
break;
case 'database':
ctx.beginPath();
ctx.ellipse(12, 6, 7, 3, 0, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(5, 6); ctx.lineTo(5, 18);
ctx.moveTo(19, 6); ctx.lineTo(19, 18);
ctx.stroke();
ctx.beginPath();
ctx.ellipse(12, 12, 7, 3, 0, Math.PI, 0, true);
ctx.ellipse(12, 18, 7, 3, 0, 0, Math.PI * 2);
ctx.stroke();
break;
case 'uptime':
ctx.beginPath();
ctx.arc(12, 12, 9, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(12, 6); ctx.lineTo(12, 12); ctx.lineTo(17, 15);
ctx.stroke();
ctx.beginPath();
ctx.arc(12, 12, 2, 0, Math.PI * 2);
ctx.fill();
break;
case 'visitors':
ctx.beginPath();
ctx.arc(9, 8, 4, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(2, 21); ctx.quadraticCurveTo(9, 14, 16, 21);
ctx.stroke();
ctx.beginPath();
ctx.arc(17, 6, 3, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(12, 18); ctx.quadraticCurveTo(17, 12, 22, 18);
ctx.stroke();
break;
case 'php':
ctx.font = 'bold 14px BeVietnamPro';
ctx.textAlign = 'center';
ctx.fillText('{ }', 12, 16);
break;
}
ctx.restore();
}
async function generateCpanelCard(botName = "GOAT BOT") {
const width = 1600;
const height = 1200;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d');
const centerX = width / 2;
const centerY = height / 2;
const bgGradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, height);
bgGradient.addColorStop(0, '#1a1a3e');
bgGradient.addColorStop(0.4, '#0f1628');
bgGradient.addColorStop(0.7, '#0a0f1a');
bgGradient.addColorStop(1, '#050810');
ctx.fillStyle = bgGradient;
ctx.fillRect(0, 0, width, height);
ctx.save();
for (let i = 0; i < 200; i++) {
const x = Math.random() * width;
const y = Math.random() * height;
const size = Math.random() * 2 + 0.5;
const opacity = Math.random() * 0.6 + 0.2;
ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`;
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
ctx.save();
ctx.strokeStyle = 'rgba(100, 150, 255, 0.03)';
ctx.lineWidth = 1;
for (let r = 100; r < Math.max(width, height); r += 80) {
ctx.beginPath();
ctx.arc(centerX, centerY, r, 0, Math.PI * 2);
ctx.stroke();
}
ctx.restore();
const cpuUsage = getRandomInt(15, 45);
const ramUsage = getRandomInt(30, 65);
const storageUsed = getRandomInt(20, 70);
const bandwidthUsed = getRandomInt(40, 85);
const uptime = os.uptime();
const totalMem = os.totalmem();
const freeMem = os.freemem();
const usedMem = totalMem - freeMem;
const hostingData = {
serverStatus: 'Online',
serverLocation: 'US-East',
cpuUsage: cpuUsage,
cpuCores: os.cpus().length,
ramUsage: ramUsage,
ramUsed: formatBytes(usedMem),
storageUsed: storageUsed,
storageTotal: '50 GB',
bandwidthUsed: bandwidthUsed,
domains: getRandomInt(1, 5),
sslStatus: 'Active',
emailAccounts: getRandomInt(1, 20),
ftpAccounts: getRandomInt(1, 5),
databases: getRandomInt(1, 10),
uptime: formatUptime(uptime),
visitors: getRandomInt(100, 5000),
phpVersion: '8.2'
};
const infoCircles = [
{ title: 'SERVER', icon: 'server', value: hostingData.serverStatus, sub: hostingData.serverLocation, colors: ['#34d399', '#10b981', '#059669'], glow: 'rgb(16, 185, 129)' },
{ title: 'CPU', icon: 'cpu', value: `${hostingData.cpuUsage}%`, sub: `${hostingData.cpuCores} Cores`, colors: ['#818cf8', '#6366f1', '#4f46e5'], glow: 'rgb(99, 102, 241)', progress: hostingData.cpuUsage },
{ title: 'RAM', icon: 'ram', value: `${hostingData.ramUsage}%`, sub: hostingData.ramUsed, colors: ['#fbbf24', '#f59e0b', '#d97706'], glow: 'rgb(245, 158, 11)', progress: hostingData.ramUsage },
{ title: 'STORAGE', icon: 'storage', value: `${hostingData.storageUsed}%`, sub: hostingData.storageTotal, colors: ['#f472b6', '#ec4899', '#db2777'], glow: 'rgb(236, 72, 153)', progress: hostingData.storageUsed },
{ title: 'BANDWIDTH', icon: 'bandwidth', value: `${hostingData.bandwidthUsed}%`, sub: '1 TB/mo', colors: ['#2dd4bf', '#14b8a6', '#0d9488'], glow: 'rgb(20, 184, 166)', progress: hostingData.bandwidthUsed },
{ title: 'DOMAINS', icon: 'domain', value: hostingData.domains, sub: 'Active', colors: ['#a78bfa', '#8b5cf6', '#7c3aed'], glow: 'rgb(139, 92, 246)' },
{ title: 'SSL', icon: 'ssl', value: hostingData.sslStatus, sub: 'Secured', colors: ['#4ade80', '#22c55e', '#16a34a'], glow: 'rgb(34, 197, 94)' },
{ title: 'EMAIL', icon: 'email', value: hostingData.emailAccounts, sub: 'Accounts', colors: ['#60a5fa', '#3b82f6', '#2563eb'], glow: 'rgb(59, 130, 246)' },
{ title: 'FTP', icon: 'ftp', value: hostingData.ftpAccounts, sub: 'Accounts', colors: ['#fb7185', '#f43f5e', '#e11d48'], glow: 'rgb(244, 63, 94)' },
{ title: 'DATABASE', icon: 'database', value: hostingData.databases, sub: 'MySQL', colors: ['#38bdf8', '#0ea5e9', '#0284c7'], glow: 'rgb(14, 165, 233)' },
{ title: 'UPTIME', icon: 'uptime', value: hostingData.uptime, sub: '99.9% SLA', colors: ['#a3e635', '#84cc16', '#65a30d'], glow: 'rgb(132, 204, 22)' },
{ title: 'VISITORS', icon: 'visitors', value: hostingData.visitors.toLocaleString(), sub: 'This Month', colors: ['#c084fc', '#a855f7', '#9333ea'], glow: 'rgb(168, 85, 247)' },
];
const outerRadius = 420;
const circleRadius = 95;
infoCircles.forEach((circle, index) => {
const angle = (Math.PI * 2 / 12) * index - Math.PI / 2;
const x = centerX + Math.cos(angle) * outerRadius;
const y = centerY + Math.sin(angle) * outerRadius;
const innerEdgeX = centerX + Math.cos(angle) * 160;
const innerEdgeY = centerY + Math.sin(angle) * 160;
const outerEdgeX = centerX + Math.cos(angle) * (outerRadius - circleRadius - 10);
const outerEdgeY = centerY + Math.sin(angle) * (outerRadius - circleRadius - 10);
drawConnectingLine(ctx, innerEdgeX, innerEdgeY, outerEdgeX, outerEdgeY, circle.glow.replace('rgb', 'rgba').replace(')', ', 0.4)'));
});
const centerRadius = 150;
ctx.save();
for (let i = 50; i > 0; i--) {
const alpha = (1 - i / 50) * 0.2;
ctx.beginPath();
ctx.arc(centerX, centerY, centerRadius + i, 0, Math.PI * 2);
ctx.fillStyle = `rgba(99, 102, 241, ${alpha})`;
ctx.fill();
}
ctx.restore();
const centerGradient = ctx.createRadialGradient(centerX - 40, centerY - 40, 0, centerX, centerY, centerRadius);
centerGradient.addColorStop(0, '#4f46e5');
centerGradient.addColorStop(0.5, '#3730a3');
centerGradient.addColorStop(1, '#1e1b4b');
ctx.beginPath();
ctx.arc(centerX, centerY, centerRadius, 0, Math.PI * 2);
ctx.fillStyle = centerGradient;
ctx.fill();
ctx.beginPath();
ctx.arc(centerX, centerY, centerRadius, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
ctx.lineWidth = 3;
ctx.stroke();
ctx.beginPath();
ctx.arc(centerX, centerY, centerRadius + 10, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(99, 102, 241, 0.5)';
ctx.lineWidth = 2;
ctx.setLineDash([10, 10]);
ctx.stroke();
ctx.setLineDash([]);
ctx.save();
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 36px BeVietnamPro';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('∆', centerX, centerY - 45);
ctx.font = 'bold 32px BeVietnamPro';
ctx.fillText('NeoKEX AI', centerX, centerY);
ctx.font = '600 16px BeVietnamPro';
ctx.fillStyle = 'rgba(255,255,255,0.8)';
ctx.fillText('CONTROL PANEL', centerX, centerY + 35);
ctx.font = '600 14px BeVietnamPro';
ctx.fillStyle = 'rgba(255,255,255,0.6)';
ctx.fillText('Hosting Dashboard', centerX, centerY + 60);
ctx.restore();
infoCircles.forEach((circle, index) => {
const angle = (Math.PI * 2 / 12) * index - Math.PI / 2;
const x = centerX + Math.cos(angle) * outerRadius;
const y = centerY + Math.sin(angle) * outerRadius;
drawGlowCircle(ctx, x, y, circleRadius, circle.colors, circle.glow, 25);
if (circle.progress !== undefined) {
drawProgressArc(ctx, x, y, circleRadius + 12, circle.progress, 'rgba(0,0,0,0.3)', '#ffffff', 6);
}
drawIcon(ctx, x, y - 30, 28, circle.icon);
ctx.save();
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 11px BeVietnamPro';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(circle.title, x, y - 5);
ctx.font = 'bold 24px BeVietnamPro';
ctx.fillText(String(circle.value), x, y + 22);
ctx.font = '600 12px BeVietnamPro';
ctx.fillStyle = 'rgba(255,255,255,0.8)';
ctx.fillText(circle.sub, x, y + 45);
ctx.restore();
});
ctx.save();
ctx.fillStyle = 'rgba(255,255,255,0.4)';
ctx.font = '600 14px BeVietnamPro';
ctx.textAlign = 'center';
ctx.fillText(`Last Updated: ${new Date().toLocaleString()}`, centerX, height - 40);
ctx.font = '600 12px BeVietnamPro';
ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.fillText('Real-time Monitoring System', centerX, height - 20);
ctx.restore();
return canvas.toBuffer('image/png');
}
module.exports = {
config: {
name: "cpanel",
aliases: ["hosting", "server", "hostinfo", "panel"],
version: "2.0.0",
author: "Neoaz ゐ",
countDown: 10,
role: 0,
description: "Display hosting information with beautiful circular visual interface",
category: "utility",
guide: "{pn}"
},
onStart: async function({ message, event }) {
try {
message.reaction("⏳", event.messageID);
if (!fs.existsSync(cacheDir)) {
fs.mkdirpSync(cacheDir);
}
const botName = global.GoatBot?.config?.nickNameBot || "GOAT BOT";
const buffer = await generateCpanelCard(botName);
const imagePath = path.join(cacheDir, `cpanel_${Date.now()}.png`);
fs.writeFileSync(imagePath, buffer);
await message.reply({
body: "📊 𝗛𝗢𝗦𝗧𝗜𝗡𝗚 𝗖𝗢𝗡𝗧𝗥𝗢𝗟 𝗣𝗔𝗡𝗘𝗟",
attachment: fs.createReadStream(imagePath)
});
message.reaction("✅", event.messageID);
setTimeout(() => {
if (fs.existsSync(imagePath)) {
fs.unlinkSync(imagePath);
}
}, 5000);
} catch (error) {
console.error("CPanel Command Error:", error);
message.reaction("❌", event.messageID);
return message.reply("❌ An error occurred while generating the hosting panel. Please try again.");
}
}
};