Spaces:
Sleeping
Sleeping
| <html lang="id"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>API Dashboard | 𝐂𝐑𝐄𝐀𝐓𝐄 𝐁𝐘 𝐒𝐈𝐆𝐈𝐓</title> | |
| <style> | |
| body { | |
| background-color: #000000; | |
| color: #ffffff; | |
| font-family: 'Courier New', Courier, monospace; | |
| margin: 0; | |
| padding: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| .header { | |
| text-align: center; | |
| margin-bottom: 30px; | |
| border-bottom: 1px solid #333333; | |
| padding-bottom: 20px; | |
| width: 100%; | |
| max-width: 700px; | |
| } | |
| .header h1 { margin: 0 0 5px 0; font-size: 26px; letter-spacing: 2px; } | |
| .header p { margin: 0; color: #888888; font-size: 14px; } | |
| .container { | |
| width: 100%; | |
| max-width: 700px; | |
| } | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 15px; | |
| margin-bottom: 30px; | |
| } | |
| @media (max-width: 600px) { .stats-grid { grid-template-columns: repeat(2, 1fr); } } | |
| .stat-box { | |
| border: 1px solid #333333; | |
| padding: 15px; | |
| text-align: center; | |
| background-color: #0a0a0a; | |
| } | |
| .stat-box .label { font-size: 12px; color: #888888; text-transform: uppercase; margin-bottom: 8px; } | |
| .stat-box .value { font-size: 22px; font-weight: bold; } | |
| .color-green { color: #00ff00; } | |
| .color-red { color: #ff0000; } | |
| .server-status { | |
| display: inline-block; | |
| padding: 5px 12px; | |
| font-size: 12px; | |
| font-weight: bold; | |
| margin-top: 15px; | |
| letter-spacing: 1px; | |
| } | |
| .status-on { color: #00ff00; border: 1px solid #00ff00; background-color: rgba(0, 255, 0, 0.05); } | |
| .status-off { color: #ff0000; border: 1px solid #ff0000; background-color: rgba(255, 0, 0, 0.05); } | |
| .features-section, .history-section { | |
| border: 1px solid #333333; | |
| padding: 20px; | |
| background-color: #0a0a0a; | |
| margin-bottom: 30px; | |
| } | |
| .features-section h2, .history-section h2 { | |
| margin-top: 0; | |
| font-size: 16px; | |
| border-bottom: 1px solid #333333; | |
| padding-bottom: 15px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .feature-list { list-style: none; padding: 0; margin: 0; } | |
| .feature-item { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 15px 0; | |
| border-bottom: 1px dashed #222222; | |
| } | |
| .feature-item:last-child { border-bottom: none; } | |
| .feature-info strong { color: #ffffff; font-size: 16px; display: block; margin-bottom: 5px; } | |
| .feature-info span { color: #888888; font-size: 12px; } | |
| .badge-aktif { font-size: 10px; padding: 4px 8px; color: #00ff00; border: 1px solid #00ff00; } | |
| /* Terminal History Style */ | |
| .terminal-box { | |
| background-color: #000000; | |
| border: 1px solid #222222; | |
| padding: 10px; | |
| height: 250px; | |
| overflow-y: auto; | |
| font-family: 'Courier New', Courier, monospace; | |
| font-size: 12px; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .log-entry { margin-bottom: 5px; } | |
| .log-time { color: #888888; margin-right: 10px; } | |
| .log-cmd { color: #ffffff; margin-right: 10px; } | |
| /* Custom Scrollbar untuk Terminal */ | |
| .terminal-box::-webkit-scrollbar { width: 5px; } | |
| .terminal-box::-webkit-scrollbar-track { background: #0a0a0a; } | |
| .terminal-box::-webkit-scrollbar-thumb { background: #333333; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <h1>QUANTUM API</h1> | |
| <p>System Maintained by 𝐂𝐑𝐄𝐀𝐓𝐄 𝐁𝐘 𝐒𝐈𝐆𝐈𝐓</p> | |
| <div id="mainStatus" class="server-status status-on">SERVER ONLINE</div> | |
| </div> | |
| <div class="container"> | |
| <!-- Dashboard Tracking --> | |
| <div class="stats-grid"> | |
| <div class="stat-box"> | |
| <div class="label">Total Req</div> | |
| <div class="value" id="reqTotal">0</div> | |
| </div> | |
| <div class="stat-box"> | |
| <div class="label">Success</div> | |
| <div class="value color-green" id="reqSuccess">0</div> | |
| </div> | |
| <div class="stat-box"> | |
| <div class="label">Total Error</div> | |
| <div class="value color-red" id="reqFailed">0</div> | |
| </div> | |
| <div class="stat-box"> | |
| <div class="label">Uptime</div> | |
| <div class="value" id="uptime">0s</div> | |
| </div> | |
| </div> | |
| <!-- History Terminal --> | |
| <div class="history-section"> | |
| <h2> | |
| <span>LIVE SYSTEM LOGS</span> | |
| <span style="color: #888888; font-size: 12px;">Real-time</span> | |
| </h2> | |
| <div class="terminal-box" id="terminalLog"> | |
| <div style="color: #888888; font-style: italic;">Menunggu request masuk...</div> | |
| </div> | |
| </div> | |
| <!-- Daftar Fitur Otomatis --> | |
| <div class="features-section"> | |
| <h2> | |
| <span>DAFTAR FITUR API</span> | |
| <span id="totalFitur" style="color: #00ff00;">0 Endpoint</span> | |
| </h2> | |
| <ul class="feature-list" id="featureList"> | |
| <li style="text-align: center; color: #888; padding: 20px;">Memindai folder fitur...</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <script> | |
| let lastHistoryLength = 0; | |
| const evtSource = new EventSource("/api/stats"); | |
| evtSource.onmessage = function(event) { | |
| const data = JSON.parse(event.data); | |
| document.getElementById('reqTotal').innerText = data.totalRequests.toLocaleString('id-ID'); | |
| document.getElementById('reqSuccess').innerText = data.success.toLocaleString('id-ID'); | |
| document.getElementById('reqFailed').innerText = data.failed.toLocaleString('id-ID'); | |
| const u = data.uptime; | |
| const h = Math.floor(u / 3600); | |
| const m = Math.floor((u % 3600) / 60); | |
| const s = u % 60; | |
| let uptimeStr = ''; | |
| if (h > 0) uptimeStr += `${h}h `; | |
| if (m > 0 || h > 0) uptimeStr += `${m}m `; | |
| uptimeStr += `${s}s`; | |
| document.getElementById('uptime').innerText = uptimeStr; | |
| const statusEl = document.getElementById('mainStatus'); | |
| statusEl.innerText = 'SERVER ONLINE'; | |
| statusEl.className = 'server-status status-on'; | |
| // Update Log Terminal jika ada history baru | |
| if (data.history && data.history.length > 0) { | |
| if (data.history.length !== lastHistoryLength || data.history.length === 50) { | |
| const terminal = document.getElementById('terminalLog'); | |
| let logHTML = ''; | |
| data.history.forEach(log => { | |
| const statusColor = log.status === 'SUCCESS' ? '#00ff00' : '#ff0000'; | |
| logHTML += ` | |
| <div class="log-entry"> | |
| <span class="log-time">[${log.time}]</span> | |
| <span class="log-cmd">EXEC /${log.cmd}</span> | |
| <span style="color: ${statusColor};">[ ${log.status} ]</span> | |
| </div> | |
| `; | |
| }); | |
| terminal.innerHTML = logHTML; | |
| // Auto-scroll ke paling bawah (log terbaru) | |
| terminal.scrollTop = terminal.scrollHeight; | |
| lastHistoryLength = data.history.length; | |
| } | |
| } | |
| }; | |
| evtSource.onerror = function() { | |
| const statusEl = document.getElementById('mainStatus'); | |
| statusEl.innerText = 'SERVER OFFLINE / ERROR'; | |
| statusEl.className = 'server-status status-off'; | |
| }; | |
| async function muatDaftarFitur() { | |
| try { | |
| const response = await fetch('/api/menu'); | |
| const result = await response.json(); | |
| if (result.status) { | |
| const listContainer = document.getElementById('featureList'); | |
| listContainer.innerHTML = ''; | |
| const semuaFitur = [ | |
| { cmd: 'brat', desc: 'Generate gambar teks ala album Brat' }, | |
| ...result.data | |
| ]; | |
| document.getElementById('totalFitur').innerText = `${semuaFitur.length} Endpoint`; | |
| semuaFitur.forEach(fitur => { | |
| const li = document.createElement('li'); | |
| li.className = 'feature-item'; | |
| li.innerHTML = ` | |
| <div class="feature-info"> | |
| <strong>/${fitur.cmd}</strong> | |
| <span>${fitur.desc}</span> | |
| </div> | |
| <div class="badge-aktif">AKTIF</div> | |
| `; | |
| listContainer.appendChild(li); | |
| }); | |
| } | |
| } catch (error) { | |
| const listContainer = document.getElementById('featureList'); | |
| listContainer.innerHTML = ` | |
| <li style="text-align: center; color: #ff0000; padding: 20px;"> | |
| [ ERROR ] Gagal memuat daftar fitur. | |
| </li> | |
| `; | |
| } | |
| } | |
| window.onload = muatDaftarFitur; | |
| </script> | |
| </body> | |
| </html> |