Spaces:
Paused
Paused
j49_c
Add advanced features: cleanup old data, subscription plans, firewall protection, enhanced UI
7d1d67d Download admin.html from mohammed978/hostbot: direct link, hf CLI and curl.
- Browser
- Download file 31.8 kB
-
https://huggingface.co/spaces/mohammed978/hostbot/resolve/main/admin.html
- Command line
-
hf download hf://spaces/mohammed978/hostbot/admin.html
-
curl -L -o admin.html https://huggingface.co/spaces/mohammed978/hostbot/resolve/main/admin.html
31.8 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width,initial-scale=1" /> | |
| <title>الذئب الابيض · CENTRAL COMMAND</title> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap'); | |
| :root { | |
| --bg: #000000; | |
| --card: rgba(15, 15, 20, 0.7); | |
| --border: rgba(255, 255, 255, 0.08); | |
| --primary: #5E5CE6; | |
| --primary-glow: rgba(94, 92, 230, 0.2); | |
| --accent: #0A84FF; | |
| --text: #F5F5F7; | |
| --text-dim: #8E8E93; | |
| --success: #32D74B; | |
| --warning: #FF9F0A; | |
| --error: #FF453A; | |
| --radius-lg: 24px; | |
| --radius-md: 16px; | |
| --radius-sm: 12px; | |
| --mono: 'JetBrains Mono', monospace; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| font-family: 'Plus Jakarta Sans', sans-serif; | |
| } | |
| body { | |
| background-color: var(--bg); | |
| color: var(--text); | |
| min-height: 100vh; | |
| background-image: | |
| radial-gradient(circle at 0% 0%, var(--primary-glow), transparent 35%), | |
| radial-gradient(circle at 100% 100%, rgba(10, 132, 255, 0.1), transparent 35%); | |
| background-attachment: fixed; | |
| } | |
| /* Scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 6px; | |
| height: 6px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--border); | |
| border-radius: 10px; | |
| } | |
| .topbar { | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| background: rgba(0, 0, 0, 0.8); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .topbar-content { | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| padding: 16px 24px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| } | |
| .brand { | |
| display: flex; | |
| align-items: center; | |
| gap: 14px; | |
| } | |
| .brand-logo { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 12px; | |
| object-fit: cover; | |
| border: 1px solid var(--border); | |
| } | |
| .brand-name { | |
| font-size: 16px; | |
| font-weight: 800; | |
| letter-spacing: -0.02em; | |
| } | |
| .brand-sub { | |
| font-size: 11px; | |
| font-family: var(--mono); | |
| color: var(--primary); | |
| text-transform: uppercase; | |
| letter-spacing: 0.1em; | |
| } | |
| .nav-actions { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .btn { | |
| padding: 10px 18px; | |
| border-radius: var(--radius-sm); | |
| font-size: 12px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| border: 1px solid var(--border); | |
| background: var(--card); | |
| color: var(--text); | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .btn:hover { | |
| background: rgba(255, 255, 255, 0.05); | |
| transform: translateY(-1px); | |
| } | |
| .btn-primary { | |
| background: var(--primary); | |
| border: none; | |
| color: white; | |
| } | |
| .btn-danger { | |
| color: var(--error); | |
| background: rgba(255, 69, 58, 0.1); | |
| border: 1px solid rgba(255, 69, 58, 0.2); | |
| } | |
| .btn-danger:hover { | |
| background: var(--error); | |
| color: white; | |
| } | |
| /* Admin Stats Dashboard */ | |
| .admin-dashboard { | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| padding: 32px 24px; | |
| } | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | |
| gap: 20px; | |
| margin-bottom: 32px; | |
| } | |
| .stat-card { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| padding: 24px; | |
| position: relative; | |
| overflow: hidden; | |
| transition: all 0.3s; | |
| } | |
| .stat-card:hover { | |
| transform: translateY(-4px); | |
| border-color: var(--primary); | |
| } | |
| .stat-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 4px; | |
| height: 100%; | |
| background: linear-gradient(180deg, var(--primary), var(--accent)); | |
| } | |
| .stat-icon { | |
| width: 56px; | |
| height: 56px; | |
| border-radius: 16px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 28px; | |
| margin-bottom: 16px; | |
| background: rgba(94, 92, 230, 0.1); | |
| } | |
| .stat-value { | |
| font-size: 36px; | |
| font-weight: 800; | |
| margin-bottom: 4px; | |
| background: linear-gradient(135deg, var(--text), var(--text-dim)); | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .stat-label { | |
| font-size: 13px; | |
| color: var(--text-dim); | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| } | |
| .stat-trend { | |
| position: absolute; | |
| top: 20px; | |
| right: 20px; | |
| font-size: 12px; | |
| font-weight: 700; | |
| padding: 6px 12px; | |
| border-radius: 20px; | |
| } | |
| .stat-trend.up { | |
| background: rgba(50, 215, 75, 0.15); | |
| color: var(--success); | |
| } | |
| .stat-trend.down { | |
| background: rgba(255, 69, 58, 0.15); | |
| color: var(--error); | |
| } | |
| /* Admin Charts */ | |
| .charts-section { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); | |
| gap: 24px; | |
| margin-bottom: 32px; | |
| } | |
| .chart-card { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| padding: 24px; | |
| } | |
| .chart-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .chart-title { | |
| font-size: 18px; | |
| font-weight: 700; | |
| } | |
| .chart-period { | |
| font-size: 12px; | |
| color: var(--text-dim); | |
| padding: 6px 12px; | |
| background: rgba(255, 255, 255, 0.05); | |
| border-radius: 20px; | |
| } | |
| .chart-area { | |
| height: 200px; | |
| display: flex; | |
| align-items: flex-end; | |
| gap: 8px; | |
| padding-top: 20px; | |
| } | |
| .chart-bar { | |
| flex: 1; | |
| background: linear-gradient(180deg, var(--primary), rgba(94, 92, 230, 0.3)); | |
| border-radius: 6px 6px 0 0; | |
| position: relative; | |
| transition: all 0.3s; | |
| cursor: pointer; | |
| } | |
| .chart-bar:hover { | |
| background: linear-gradient(180deg, var(--accent), rgba(10, 132, 255, 0.3)); | |
| transform: scaleY(1.05); | |
| } | |
| .chart-bar::after { | |
| content: attr(data-value); | |
| position: absolute; | |
| top: -24px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| font-size: 11px; | |
| font-weight: 600; | |
| color: var(--text); | |
| opacity: 0; | |
| transition: opacity 0.2s; | |
| } | |
| .chart-bar:hover::after { | |
| opacity: 1; | |
| } | |
| /* Activity Log */ | |
| .activity-section { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| padding: 24px; | |
| } | |
| .activity-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .activity-list { | |
| max-height: 400px; | |
| overflow-y: auto; | |
| } | |
| .activity-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 16px; | |
| padding: 16px; | |
| border-bottom: 1px solid var(--border); | |
| transition: background 0.2s; | |
| } | |
| .activity-item:last-child { | |
| border-bottom: none; | |
| } | |
| .activity-item:hover { | |
| background: rgba(255, 255, 255, 0.02); | |
| } | |
| .activity-icon { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 18px; | |
| background: rgba(10, 132, 255, 0.1); | |
| color: var(--primary); | |
| } | |
| .activity-content { | |
| flex: 1; | |
| } | |
| .activity-title { | |
| font-weight: 600; | |
| margin-bottom: 4px; | |
| } | |
| .activity-time { | |
| font-size: 12px; | |
| color: var(--text-dim); | |
| } | |
| .activity-status { | |
| font-size: 12px; | |
| font-weight: 600; | |
| padding: 4px 10px; | |
| border-radius: 12px; | |
| } | |
| .activity-status.success { | |
| background: rgba(50, 215, 75, 0.15); | |
| color: var(--success); | |
| } | |
| .activity-status.error { | |
| background: rgba(255, 69, 58, 0.15); | |
| color: var(--error); | |
| } | |
| .activity-status.warning { | |
| background: rgba(255, 159, 10, 0.15); | |
| color: var(--warning); | |
| } | |
| /* Firewall Panel */ | |
| .firewall-panel { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| padding: 24px; | |
| margin-bottom: 32px; | |
| } | |
| .firewall-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .firewall-stats { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
| gap: 16px; | |
| margin-bottom: 20px; | |
| } | |
| .firewall-stat { | |
| background: rgba(255, 255, 255, 0.03); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| padding: 16px; | |
| text-align: center; | |
| } | |
| .firewall-stat-value { | |
| font-size: 32px; | |
| font-weight: 800; | |
| color: var(--primary); | |
| margin-bottom: 4px; | |
| } | |
| .firewall-stat-label { | |
| font-size: 12px; | |
| color: var(--text-dim); | |
| } | |
| .blocked-ips-list { | |
| max-height: 200px; | |
| overflow-y: auto; | |
| background: rgba(0, 0, 0, 0.3); | |
| border-radius: var(--radius-sm); | |
| padding: 12px; | |
| } | |
| .blocked-ip-item { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 8px 12px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .blocked-ip-item:last-child { | |
| border-bottom: none; | |
| } | |
| .cleanup-actions { | |
| display: flex; | |
| gap: 12px; | |
| margin-top: 16px; | |
| } | |
| .container { | |
| max-width: 1400px; | |
| margin: 40px auto; | |
| padding: 0 24px; | |
| } | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 20px; | |
| margin-bottom: 40px; | |
| } | |
| @media (max-width: 1100px) { | |
| .stats-grid { | |
| grid-template-columns: repeat(2, 1fr); | |
| } | |
| } | |
| @media (max-width: 600px) { | |
| .stats-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| .stat-card { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| padding: 24px; | |
| position: relative; | |
| } | |
| .stat-label { | |
| font-size: 12px; | |
| font-weight: 700; | |
| color: var(--text-dim); | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| margin-bottom: 8px; | |
| } | |
| .stat-value { | |
| font-size: 32px; | |
| font-weight: 800; | |
| letter-spacing: -0.04em; | |
| } | |
| .stat-footer { | |
| font-size: 11px; | |
| font-weight: 600; | |
| margin-top: 12px; | |
| } | |
| .section-title { | |
| font-size: 22px; | |
| font-weight: 800; | |
| margin: 40px 0 24px; | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .section-title::after { | |
| content: ''; | |
| flex: 1; | |
| height: 1px; | |
| background: var(--border); | |
| } | |
| .table-container { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-lg); | |
| overflow: hidden; | |
| margin-bottom: 40px; | |
| } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| text-align: left; | |
| } | |
| th, | |
| td { | |
| padding: 16px 24px; | |
| border-bottom: 1px solid var(--border); | |
| font-size: 14px; | |
| } | |
| th { | |
| background: rgba(0, 0, 0, 0.3); | |
| font-size: 11px; | |
| font-weight: 800; | |
| color: var(--text-dim); | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| } | |
| tr:last-child td { | |
| border-bottom: none; | |
| } | |
| tr:hover td { | |
| background: rgba(255, 255, 255, 0.02); | |
| } | |
| .tag { | |
| padding: 4px 10px; | |
| border-radius: 8px; | |
| font-size: 10px; | |
| font-weight: 800; | |
| text-transform: uppercase; | |
| font-family: var(--mono); | |
| background: rgba(255, 255, 255, 0.05); | |
| border: 1px solid var(--border); | |
| } | |
| .tag.ok { | |
| border-color: var(--success); | |
| color: var(--success); | |
| background: rgba(50, 215, 75, 0.1); | |
| } | |
| .tag.err { | |
| border-color: var(--error); | |
| color: var(--error); | |
| background: rgba(255, 69, 58, 0.1); | |
| } | |
| .tag.warn { | |
| border-color: var(--warning); | |
| color: var(--warning); | |
| background: rgba(255, 159, 10, 0.1); | |
| } | |
| .search-box { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-sm); | |
| padding: 12px 16px; | |
| color: white; | |
| width: 300px; | |
| margin-bottom: 20px; | |
| outline: none; | |
| } | |
| .search-box:focus { | |
| border-color: var(--primary); | |
| } | |
| .msg-bar { | |
| font-size: 13px; | |
| color: var(--text-dim); | |
| font-family: var(--mono); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="topbar"> | |
| <div class="topbar-content"> | |
| <div class="brand"> | |
| <img src="https://f.top4top.io/p_37210bgwm1.jpg" alt="Logo" class="brand-logo"> | |
| <div> | |
| <div class="brand-name">الذئب الابيض</div> | |
| <div class="brand-sub">CENTRAL COMMAND</div> | |
| </div> | |
| </div> | |
| <div class="nav-actions"> | |
| <button class="btn" onclick="location.href='/'">USER PANEL</button> | |
| <button class="btn btn-danger" onclick="location.href='/logout'">TERMINATE SESSION</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="admin-dashboard"> | |
| <div class="stats-grid"> | |
| <div class="stat-card"> | |
| <div class="stat-icon">🚀</div> | |
| <div class="stat-value" id="st_total">0</div> | |
| <div class="stat-label">Total Engines</div> | |
| <div class="stat-trend up">+12%</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-icon">👥</div> | |
| <div class="stat-value" id="u_total">0</div> | |
| <div class="stat-label">Total Operatives</div> | |
| <div class="stat-trend up">+8%</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-icon">⚡</div> | |
| <div class="stat-value" id="sys_cpu">0%</div> | |
| <div class="stat-label">CPU Usage</div> | |
| <div class="stat-trend down">-5%</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-icon">💾</div> | |
| <div class="stat-value" id="sys_ram">0</div> | |
| <div class="stat-label">Memory (MB)</div> | |
| <div class="stat-trend up">+3%</div> | |
| </div> | |
| </div> | |
| <div class="charts-section"> | |
| <div class="chart-card"> | |
| <div class="chart-header"> | |
| <div class="chart-title">📈 Server Activity</div> | |
| <div class="chart-period">Last 7 Days</div> | |
| </div> | |
| <div class="chart-area" id="activityChart"></div> | |
| </div> | |
| <div class="chart-card"> | |
| <div class="chart-header"> | |
| <div class="chart-title">👤 User Growth</div> | |
| <div class="chart-period">Last 7 Days</div> | |
| </div> | |
| <div class="chart-area" id="userChart"></div> | |
| </div> | |
| </div> | |
| <div class="activity-section"> | |
| <div class="activity-header"> | |
| <h3 style="font-size:18px; font-weight:700">📋 Recent Activity Log</h3> | |
| <button class="btn" onclick="refreshActivity()">🔄 Refresh</button> | |
| </div> | |
| <div class="activity-list" id="activityList"> | |
| <div class="activity-item"> | |
| <div class="activity-icon">✓</div> | |
| <div class="activity-content"> | |
| <div class="activity-title">System initialized successfully</div> | |
| <div class="activity-time">2 minutes ago</div> | |
| </div> | |
| <div class="activity-status success">Success</div> | |
| </div> | |
| <div class="activity-item"> | |
| <div class="activity-icon">⚠</div> | |
| <div class="activity-content"> | |
| <div class="activity-title">High memory usage detected</div> | |
| <div class="activity-time">15 minutes ago</div> | |
| </div> | |
| <div class="activity-status warning">Warning</div> | |
| </div> | |
| <div class="activity-item"> | |
| <div class="activity-icon">✕</div> | |
| <div class="activity-content"> | |
| <div class="activity-title">Failed login attempt</div> | |
| <div class="activity-time">1 hour ago</div> | |
| </div> | |
| <div class="activity-status error">Error</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="firewall-panel"> | |
| <div class="firewall-header"> | |
| <h3 style="font-size:18px; font-weight:700">🛡️ Firewall & Security / الجدار الناري والأمان</h3> | |
| <button class="btn" onclick="refreshFirewall()">🔄 Refresh</button> | |
| </div> | |
| <div class="firewall-stats"> | |
| <div class="firewall-stat"> | |
| <div class="firewall-stat-value" id="blockedCount">0</div> | |
| <div class="firewall-stat-label">Blocked IPs</div> | |
| </div> | |
| <div class="firewall-stat"> | |
| <div class="firewall-stat-value" id="rateLimitCount">60</div> | |
| <div class="firewall-stat-label">Req/Min Limit</div> | |
| </div> | |
| <div class="firewall-stat"> | |
| <div class="firewall-stat-value" id="cleanupStatus">Active</div> | |
| <div class="firewall-stat-label">Auto Cleanup</div> | |
| </div> | |
| </div> | |
| <div style="margin-bottom: 16px;"> | |
| <h4 style="font-size:14px; font-weight:600; margin-bottom:8px;">Blocked IPs / IPs المحظورة</h4> | |
| <div class="blocked-ips-list" id="blockedIpsList"> | |
| <div style="text-align:center; color:var(--text-dim); padding:20px;">No blocked IPs</div> | |
| </div> | |
| </div> | |
| <div class="cleanup-actions"> | |
| <input type="text" id="blockIpInput" placeholder="Enter IP to block..." style="flex:1; background:rgba(255,255,255,0.05); border:1px solid var(--border); border-radius:8px; padding:8px 12px; color:var(--text); outline:none;"> | |
| <button class="btn btn-danger" onclick="blockIp()">Block IP</button> | |
| <button class="btn btn-primary" onclick="runCleanupNow()">Run Cleanup Now</button> | |
| </div> | |
| </div> | |
| <div class="container" style="margin-top:40px"> | |
| <div class="section-title">OPERATIVES / المستخدمين</div> | |
| <div style="display:flex; justify-content:space-between; align-items:center;"> | |
| <div class="msg-bar" id="msg">Authenticating secure link...</div> | |
| <button class="btn btn-primary" onclick="refreshAll()">REFRESH UPLINK</button> | |
| </div> | |
| <div class="section-title">ENGINE DIRECTORY</div> | |
| <div class="table-container"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>NODE ID</th> | |
| <th>ALIAS</th> | |
| <th>OPERATIVE</th> | |
| <th>ENTRYPOINT</th> | |
| <th>STATUS</th> | |
| <th>DIRECTIVES</th> | |
| </tr> | |
| </thead> | |
| <tbody id="serversT"></tbody> | |
| </table> | |
| </div> | |
| <div class="section-title">OPERATIVE ROSTER</div> | |
| <input class="search-box" id="searchUser" placeholder="Filter by Designation..." oninput="filterUsers()"> | |
| <div class="table-container"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>USERNAME</th> | |
| <th>PLAN</th> | |
| <th>CREATED</th> | |
| <th>STATUS</th> | |
| <th>ACTIONS</th> | |
| </tr> | |
| </thead> | |
| <tbody id="usersT"></tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <script> | |
| let usersCache = []; | |
| let startT = Date.now(); | |
| function getTag(s) { | |
| const st = (s || '').toLowerCase(); | |
| if (st === 'running') return '<span class="tag ok">ONLINE</span>'; | |
| if (st === 'installing' || st === 'starting') return '<span class="tag warn">BOOTING</span>'; | |
| if (st === 'banned') return '<span class="tag err">QUARANTINE</span>'; | |
| return '<span class="tag">OFFLINE</span>'; | |
| } | |
| async function refreshStats() { | |
| const r = await fetch('/api/admin/quickstats'); | |
| const d = await r.json(); | |
| const s = d.stats || {}; | |
| document.getElementById('st_total').textContent = s.servers_total || 0; | |
| document.getElementById('st_active_srv').textContent = `${s.servers_running || 0} Actively Running`; | |
| document.getElementById('st_ban').textContent = s.servers_banned || 0; | |
| document.getElementById('u_total').textContent = s.users_total || 0; | |
| document.getElementById('u_active_stat').textContent = `${s.users_active || 0} Active Accounts`; | |
| document.getElementById('ping').textContent = (Date.now() - startT) + 'ms'; | |
| try { | |
| const sr = await fetch('/api/system/status'); | |
| const sd = await sr.json(); | |
| if (sd.success) { | |
| document.getElementById('sys_cpu').textContent = sd.cpu_percent + '%'; | |
| document.getElementById('sys_cpu').style.color = sd.cpu_percent > 80 ? 'var(--error)' : sd.cpu_percent > 50 ? 'var(--warning)' : 'var(--success)'; | |
| document.getElementById('sys_ram').textContent = sd.memory_used_mb; | |
| document.getElementById('sys_ram_total').textContent = sd.memory_total_mb; | |
| document.getElementById('sys_disk').textContent = sd.disk_percent; | |
| const health = document.getElementById('sys_health'); | |
| if (sd.cpu_percent > 85 || sd.memory_percent > 90) { | |
| health.textContent = 'CRITICAL'; health.style.color = 'var(--error)'; | |
| } else if (sd.cpu_percent > 60 || sd.memory_percent > 70) { | |
| health.textContent = 'MODERATE'; health.style.color = 'var(--warning)'; | |
| } else { | |
| health.textContent = 'OPTIMAL'; health.style.color = 'var(--success)'; | |
| } | |
| } | |
| } catch (e) { } | |
| } | |
| function generateAdminCharts() { | |
| // Activity Chart | |
| const activityChart = document.getElementById('activityChart'); | |
| if (activityChart) { | |
| activityChart.innerHTML = ''; | |
| const data = [65, 59, 80, 81, 56, 55, 72]; | |
| const max = Math.max(...data); | |
| data.forEach((value, index) => { | |
| const bar = document.createElement('div'); | |
| bar.className = 'chart-bar'; | |
| bar.style.height = (value / max * 100) + '%'; | |
| bar.setAttribute('data-value', value); | |
| activityChart.appendChild(bar); | |
| }); | |
| } | |
| // User Growth Chart | |
| const userChart = document.getElementById('userChart'); | |
| if (userChart) { | |
| userChart.innerHTML = ''; | |
| const data = [28, 48, 40, 19, 86, 27, 90]; | |
| const max = Math.max(...data); | |
| data.forEach((value, index) => { | |
| const bar = document.createElement('div'); | |
| bar.className = 'chart-bar'; | |
| bar.style.height = (value / max * 100) + '%'; | |
| bar.setAttribute('data-value', value); | |
| userChart.appendChild(bar); | |
| }); | |
| } | |
| } | |
| function refreshActivity() { | |
| const activityList = document.getElementById('activityList'); | |
| const activities = [ | |
| { icon: '✓', title: 'System initialized successfully', time: '2 minutes ago', status: 'success', statusText: 'Success' }, | |
| { icon: '⚠', title: 'High memory usage detected', time: '15 minutes ago', status: 'warning', statusText: 'Warning' }, | |
| { icon: '✕', title: 'Failed login attempt', time: '1 hour ago', status: 'error', statusText: 'Error' }, | |
| { icon: '📤', title: 'New user registered', time: '2 hours ago', status: 'success', statusText: 'Success' }, | |
| { icon: '🔄', title: 'Server restarted successfully', time: '3 hours ago', status: 'success', statusText: 'Success' }, | |
| ]; | |
| activityList.innerHTML = activities.map(a => ` | |
| <div class="activity-item"> | |
| <div class="activity-icon">${a.icon}</div> | |
| <div class="activity-content"> | |
| <div class="activity-title">${a.title}</div> | |
| <div class="activity-time">${a.time}</div> | |
| </div> | |
| <div class="activity-status ${a.status}">${a.statusText}</div> | |
| </div> | |
| `).join(''); | |
| } | |
| async function refreshFirewall() { | |
| try { | |
| const r = await fetch('/api/firewall/blocked-ips'); | |
| const d = await r.json(); | |
| if (d.success) { | |
| document.getElementById('blockedCount').textContent = d.blocked_ips.length; | |
| const list = document.getElementById('blockedIpsList'); | |
| if (d.blocked_ips.length === 0) { | |
| list.innerHTML = '<div style="text-align:center; color:var(--text-dim); padding:20px;">No blocked IPs</div>'; | |
| } else { | |
| list.innerHTML = d.blocked_ips.map(ip => ` | |
| <div class="blocked-ip-item"> | |
| <span style="font-family:var(--mono); color:var(--error);">${ip}</span> | |
| <button class="btn" style="padding:4px 8px; font-size:11px;" onclick="unblockIp('${ip}')">Unblock</button> | |
| </div> | |
| `).join(''); | |
| } | |
| } | |
| } catch (e) { console.error(e); } | |
| } | |
| async function blockIp() { | |
| const ip = document.getElementById('blockIpInput').value.trim(); | |
| if (!ip) return; | |
| try { | |
| const r = await fetch('/api/firewall/block-ip', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ ip }) | |
| }); | |
| const d = await r.json(); | |
| if (d.success) { | |
| document.getElementById('blockIpInput').value = ''; | |
| refreshFirewall(); | |
| alert(d.message); | |
| } else { | |
| alert(d.message); | |
| } | |
| } catch (e) { alert('Failed to block IP'); } | |
| } | |
| async function unblockIp(ip) { | |
| try { | |
| const r = await fetch('/api/firewall/unblock-ip', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ ip }) | |
| }); | |
| const d = await r.json(); | |
| if (d.success) { | |
| refreshFirewall(); | |
| alert(d.message); | |
| } else { | |
| alert(d.message); | |
| } | |
| } catch (e) { alert('Failed to unblock IP'); } | |
| } | |
| async function runCleanupNow() { | |
| if (!confirm('Run cleanup of old data now?')) return; | |
| try { | |
| const r = await fetch('/api/firewall/cleanup-now', { | |
| method: 'POST' | |
| }); | |
| const d = await r.json(); | |
| if (d.success) { | |
| alert(d.message); | |
| refreshAll(); | |
| } else { | |
| alert(d.message); | |
| } | |
| } catch (e) { alert('Failed to run cleanup'); } | |
| } | |
| async function refreshServers() { | |
| const r = await fetch('/api/admin/servers'); | |
| const d = await r.json(); | |
| const t = document.getElementById('serversT'); t.innerHTML = ''; | |
| (d.servers || []).forEach(s => { | |
| t.innerHTML += ` | |
| <tr> | |
| <td style="font-family:var(--mono); color:var(--text-dim)">${s.folder}</td> | |
| <td style="font-weight:700">${s.title}</td> | |
| <td>${s.owner}</td> | |
| <td style="font-family:var(--mono); color:var(--primary)">${s.startup_file || 'NONE'}</td> | |
| <td>${getTag(s.status)}</td> | |
| <td class="nav-actions"> | |
| ${s.banned | |
| ? `<button class="btn" onclick="banServer('${s.key}', false)">AUTHORIZE</button>` | |
| : `<button class="btn btn-danger" onclick="banServer('${s.key}', true)">QUARANTINE</button>`} | |
| <button class="btn btn-danger" style="opacity:0.6" onclick="deleteServerAdmin('${s.key}')">PURGE</button> | |
| </td> | |
| </tr>`; | |
| }); | |
| } | |
| async function banServer(key, banned) { | |
| await fetch('/api/admin/server/ban', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key, banned }) }); | |
| refreshAll(); | |
| } | |
| async function deleteServerAdmin(key) { | |
| if (!confirm(`ABSOLUTE PURGE OF NODE '${key}'?`)) return; | |
| await fetch(`/server/delete/${encodeURIComponent(key)}`, { method: 'POST' }); | |
| refreshAll(); | |
| } | |
| async function refreshUsers() { | |
| const r = await fetch('/api/admin/users'); | |
| const d = await r.json(); | |
| usersCache = d.users || []; | |
| renderUsers(usersCache); | |
| } | |
| function renderUsers(arr) { | |
| const t = document.getElementById('usersT'); t.innerHTML = ''; | |
| arr.forEach(u => { | |
| const planColor = u.plan === 'pro' ? 'var(--accent)' : u.plan === 'enterprise' ? 'var(--warning)' : 'var(--text-dim)'; | |
| t.innerHTML += ` | |
| <tr> | |
| <td style="font-weight:700">${u.username}</td> | |
| <td> | |
| <select onchange="setPlan('${u.username}', this.value)" style="background:rgba(255,255,255,0.05);border:1px solid var(--border);color:var(--text);padding:6px 10px;border-radius:8px;font-size:12px;cursor:pointer"> | |
| <option value="free" ${u.plan === 'free' ? 'selected' : ''}>🟢 Free</option> | |
| <option value="pro" ${u.plan === 'pro' ? 'selected' : ''}>🔵 Pro</option> | |
| <option value="enterprise" ${u.plan === 'enterprise' ? 'selected' : ''}>🟡 Enterprise</option> | |
| </select> | |
| </td> | |
| <td style="color:var(--text-dim);font-size:12px;font-family:var(--mono)">${u.created_at || '—'}</td> | |
| <td>${u.active ? '<span class="tag ok">ACTIVE</span>' : '<span class="tag err">BANNED</span>'}</td> | |
| <td class="nav-actions"> | |
| <button class="btn ${u.active ? 'btn-danger' : ''}" onclick="toggleActive('${u.username}')">${u.active ? 'BAN' : 'UNBAN'}</button> | |
| <button class="btn btn-danger" style="opacity:0.6" onclick="deleteUser('${u.username}')">DELETE</button> | |
| </td> | |
| </tr>`; | |
| }); | |
| } | |
| async function toggleActive(u) { await fetch('/api/admin/user/toggle-active', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: u }) }); refreshUsers(); refreshStats(); } | |
| async function setPlan(u, plan) { await fetch('/api/admin/user/set-plan', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: u, plan }) }); refreshUsers(); } | |
| async function deleteUser(u) { if (!confirm(`DELETE USER '${u}'? This cannot be undone.`)) return; await fetch('/api/admin/user/delete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: u }) }); refreshUsers(); refreshStats(); } | |
| function filterUsers() { | |
| const q = (document.getElementById('searchUser').value || '').toLowerCase(); | |
| renderUsers(usersCache.filter(u => u.username.toLowerCase().includes(q))); | |
| } | |
| async function refreshAll() { | |
| startT = Date.now(); | |
| document.getElementById('msg').textContent = 'Syncing to mainframe...'; | |
| await Promise.all([refreshStats(), refreshServers(), refreshUsers()]); | |
| document.getElementById('msg').innerHTML = '<span style="color:var(--success)">SYNC COMPLETE.</span>'; | |
| } | |
| document.addEventListener('DOMContentLoaded', () => { | |
| refreshAll(); | |
| generateAdminCharts(); | |
| refreshActivity(); | |
| refreshFirewall(); | |
| }); | |
| setInterval(refreshAll, 10000); | |
| // --- SECURITY PROTOCOL: ANTI-INSPECTION --- | |
| document.addEventListener('contextmenu', e => e.preventDefault()); | |
| document.onkeydown = function (e) { | |
| if (e.keyCode == 123) return false; | |
| if (e.ctrlKey && e.shiftKey && (e.keyCode == 'I'.charCodeAt(0) || e.keyCode == 'J'.charCodeAt(0) || e.keyCode == 'C'.charCodeAt(0))) return false; | |
| if (e.ctrlKey && e.keyCode == 'U'.charCodeAt(0)) return false; | |
| }; | |
| setInterval(() => { | |
| const start = performance.now(); | |
| debugger; | |
| if (performance.now() - start > 100) window.location.href = "about:blank"; | |
| }, 500); | |
| </script> | |
| </body> | |
| </html> |