feat: add bot action controls and real-time vital statistics to the web dashboard

This commit is contained in:
syntaxbullet
2026-01-07 14:26:37 +01:00
parent 9804456257
commit 8047bce755
7 changed files with 588 additions and 582 deletions

View File

@@ -12,72 +12,115 @@ export function dashboardRoute(): Response {
const ping = AuroraClient.ws.ping;
// Real system metrics
const memoryUsage = (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2);
const memUsage = process.memoryUsage();
const memoryUsage = (memUsage.heapUsed / 1024 / 1024).toFixed(2);
const memoryTotal = (memUsage.rss / 1024 / 1024).toFixed(1);
const uptimeSeconds = process.uptime();
const uptime = new Date(uptimeSeconds * 1000).toISOString().substr(11, 8); // HH:MM:SS
const startTimestamp = Date.now() - (uptimeSeconds * 1000);
// Real activity logs
const activityLogs = getRecentLogs();
const memPercent = Math.min(100, (memUsage.heapUsed / memUsage.rss) * 100).toFixed(1);
// Get top guilds
const topGuilds = AuroraClient.guilds.cache
.sort((a, b) => b.memberCount - a.memberCount)
.first(5);
const content = `
<div class="dashboard-grid">
<!-- Top Stats Row -->
<div class="stat-card">
<h3>Servers</h3>
<div class="stat-value">${guildCount}</div>
<div class="stat-header">
<h3>Members</h3>
<i data-lucide="users" style="width: 14px; height: 14px; color: var(--accents-5)"></i>
</div>
<div id="stat-users" class="stat-value">${userCount.toLocaleString()}</div>
<div class="stat-trend">
<span>Total user reach</span>
</div>
</div>
<div class="stat-card">
<h3>Users</h3>
<div class="stat-value">${userCount}</div>
<div class="stat-header">
<h3>Guilds</h3>
<i data-lucide="server" style="width: 14px; height: 14px; color: var(--accents-5)"></i>
</div>
<div id="stat-servers" class="stat-value">${guildCount}</div>
<div class="stat-trend">
<span>Active connections</span>
</div>
</div>
<div class="stat-card">
<h3>Commands</h3>
<div class="stat-value">${commandCount}</div>
</div>
<div class="stat-card">
<h3>Ping</h3>
<div class="stat-value">${ping < 0 ? "?" : ping}ms</div>
<div class="stat-header">
<h3>Latency</h3>
<i data-lucide="activity" style="width: 14px; height: 14px; color: var(--accents-5)"></i>
</div>
<div id="stat-ping" class="stat-value">${ping < 0 ? "?" : ping}ms</div>
<div id="stat-ping-trend" class="stat-trend ${ping < 100 ? "up" : "down"}">
<i data-lucide="${ping < 100 ? "check-circle" : "alert-circle"}" style="width: 12px; height: 12px"></i>
<span>${ping < 100 ? "Stable" : "High"}</span>
</div>
</div>
<!-- Main Content Area -->
<div class="dashboard-main">
<div class="panel activity-panel">
<div class="panel-header">
<h2>Live Activity</h2>
<span class="badge live">LIVE</span>
<div class="panel-header" style="display: flex; justify-content: space-between; align-items: center;">
<h2>Activity Flow</h2>
<span class="badge live">Live</span>
</div>
<ul class="activity-feed">
${activityLogs.length > 0 ? activityLogs.map(log => `
<li class="activity-item ${log.type}">
<li class="activity-item">
<span class="time">${log.time}</span>
<span class="message">${log.message}</span>
</li>
`).join('') : `
<li class="activity-item info"><span class="time">--:--:--</span> <span class="message">No recent activity.</span></li>
<li class="activity-item">
<span class="message" style="color: var(--accents-5)">Listening for activity...</span>
</li>
`}
</ul>
</div>
<div class="panel metrics-panel">
<div class="panel-header">
<h2>System Health</h2>
<div class="panel" style="display: flex; flex-direction: column; gap: 24px;">
<div>
<div class="panel-header">
<h2>Health</h2>
</div>
<div class="metrics-grid">
<div class="metric-card">
<div class="metric-header">
<span class="metric-label">Memory</span>
<span id="stat-memory" class="metric-value">${memoryUsage} MB</span>
</div>
<div class="progress-bar-bg">
<div id="stat-memory-bar" class="progress-bar-fill" style="width: ${memPercent}%"></div>
</div>
</div>
<div class="metric-card">
<div class="metric-header">
<span class="metric-label">Uptime</span>
<span id="stat-uptime" class="metric-value uptime-display" data-start-timestamp="${Math.floor(startTimestamp)}">${uptime}</span>
</div>
</div>
</div>
</div>
<div class="metrics-grid">
<div class="metric-item">
<span class="metric-label">Uptime</span>
<span class="metric-value">${uptime}</span>
<div>
<div class="panel-header">
<h2>Top Guilds</h2>
</div>
<div class="metric-item">
<span class="metric-label">Memory (Heap)</span>
<span class="metric-value">${memoryUsage} MB</span>
</div>
<div class="metric-item">
<span class="metric-label">Node Version</span>
<span class="metric-value">${process.version}</span>
</div>
<div class="metric-item">
<span class="metric-label">Platform</span>
<span class="metric-value">${process.platform}</span>
<div class="guild-list" style="display: flex; flex-direction: column; gap: 12px;">
${topGuilds.map(g => `
<div style="display: flex; justify-content: space-between; align-items: center; font-size: 0.875rem;">
<span style="font-weight: 500;">${g.name}</span>
<span style="color: var(--accents-5); font-family: var(--font-mono);">${g.memberCount} members</span>
</div>
`).join('')}
</div>
</div>
</div>
@@ -89,9 +132,15 @@ export function dashboardRoute(): Response {
<h2>Quick Actions</h2>
</div>
<div class="action-buttons">
<button class="btn btn-secondary" disabled>Clear Cache</button>
<button class="btn btn-secondary" disabled>Reload Commands</button>
<button class="btn btn-danger" disabled>Restart Bot</button>
<button class="btn" data-action="clear_cache">
Clear Cache
</button>
<button class="btn" data-action="reload_commands">
Reload Commands
</button>
<button class="btn btn-danger" data-action="restart_bot">
Restart Bot
</button>
</div>
</div>
</div>