SAwww / dashboard.html
SAyyeedd's picture
Upload 30 files
309ec79 verified
Raw
History Blame Contribute Delete
42.9 kB
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Sayed Bot Team v26 — Quantum Dashboard</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
:root{--bg:#0d1117;--surface:rgba(22,27,34,.72);--surface2:rgba(30,39,50,.75);--surface3:rgba(40,50,65,.8);--border:rgba(255,255,255,.06);--border2:rgba(255,255,255,.03);--text:#e6edf3;--text2:#8b949e;--text3:#6e7681;--green:#3fb950;--green2:#56d364;--green-bg:rgba(63,185,80,.1);--blue:#58a6ff;--blue2:#79c0ff;--blue-bg:rgba(88,166,255,.1);--purple:#bc8cff;--purple2:#d2a8ff;--purple-bg:rgba(188,140,255,.1);--amber:#d29922;--amber2:#e3b341;--amber-bg:rgba(210,153,34,.1);--red:#f85149;--red2:#ff7b72;--red-bg:rgba(248,81,73,.1);--cyan:#39d0d8;--cyan2:#56d4dd;--cyan-bg:rgba(57,208,216,.1);--radius:12px;--radius-sm:8px;--radius-xs:6px;--shadow:0 8px 32px rgba(0,0,0,.35);--font:system-ui,'Segoe UI',Roboto,sans-serif;--mono:Consolas,'Courier New',monospace;--glass:rgba(22,27,34,.65);--glass-blur:20px}
html,body{min-height:100vh}
body{background:var(--bg);background-image:radial-gradient(ellipse 80% 50% at 20% 0%,rgba(63,185,80,.06) 0%,transparent 50%),radial-gradient(ellipse 60% 40% at 80% 100%,rgba(88,166,255,.04) 0%,transparent 50%);color:var(--text);font-family:var(--font);font-size:14px;direction:rtl;line-height:1.6}
::-webkit-scrollbar{width:5px}::-webkit-scrollbar-track{transparent}::-webkit-scrollbar-thumb{background:rgba(63,185,80,.25);border-radius:10px}
::selection{background:rgba(63,185,80,.3);color:#fff}
@keyframes fadeInUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
@keyframes dotPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.7)}}
@keyframes toastIn{from{opacity:0;transform:translateX(-50%) translateY(12px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}
@keyframes slideIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.layout{display:flex;min-height:100vh}
.sidebar{width:220px;flex-shrink:0;position:fixed;right:0;top:0;bottom:0;background:var(--glass);backdrop-filter:blur(var(--glass-blur));border-left:1px solid rgba(255,255,255,.08);display:flex;flex-direction:column;z-index:100}
@media(max-width:900px){.sidebar{display:none}}
.hamburger{display:none;position:fixed;top:16px;right:16px;z-index:200;width:42px;height:42px;border-radius:10px;background:var(--glass);backdrop-filter:blur(20px);border:1px solid var(--border);color:var(--text);font-size:20px;cursor:pointer;align-items:center;justify-content:center}
.hamburger:hover{background:var(--green-bg);border-color:rgba(63,185,80,.3)}
@media(max-width:900px){.hamburger{display:flex}}
.sidebar-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:99;backdrop-filter:blur(4px)}
.sidebar-overlay.show{display:block}
.sidebar{transition:transform .3s cubic-bezier(.4,0,.2,1)}
@media(max-width:900px){.sidebar.active{display:flex;transform:translateX(0)}.sidebar:not(.active){transform:translateX(220px)}}
.sidebar-header{padding:20px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:12px}
.sidebar-logo{width:40px;height:40px;border-radius:10px;background:linear-gradient(135deg,var(--green),var(--blue));display:flex;align-items:center;justify-content:center;font-size:20px}
.sidebar-brand{flex:1}.sidebar-title{font-size:14px;font-weight:800;color:var(--text)}.sidebar-ver{font-size:10px;color:var(--green);font-weight:700}
.sidebar-nav{flex:1;padding:12px;overflow-y:auto}
.nav-section{font-size:10px;color:var(--text3);font-weight:700;text-transform:uppercase;letter-spacing:1px;padding:10px 12px 4px}
.nav-item{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:var(--radius-sm);cursor:pointer;color:var(--text2);font-size:13px;font-weight:600;margin-bottom:2px;border:1px solid transparent;text-decoration:none;transition:all .2s}
.nav-item:hover{background:var(--green-bg);color:var(--green);border-color:rgba(63,185,80,.1)}
.nav-item.active{background:var(--green-bg);color:var(--green);border-color:rgba(63,185,80,.2)}
.nav-icon{font-size:15px;width:20px;text-align:center}
.sidebar-footer{padding:16px;border-top:1px solid var(--border)}
.live-badge{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:var(--radius-sm);background:var(--green-bg);border:1px solid rgba(63,185,80,.15);font-size:12px;font-weight:700;color:var(--green)}
.live-dot{width:8px;height:8px;border-radius:50%;background:var(--green);animation:dotPulse 2s ease-in-out infinite}
.main{flex:1;margin-right:220px;padding:20px 24px;min-width:0;max-width:1200px}
@media(max-width:900px){.main{margin-right:0;padding:16px}}
.main-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;flex-wrap:wrap;gap:10px;padding-bottom:14px;border-bottom:1px solid var(--border)}
.main-title{font-size:18px;font-weight:900;display:flex;align-items:center;gap:8px}
.main-actions{display:flex;gap:6px;flex-wrap:wrap}
.btn{display:inline-flex;align-items:center;gap:5px;padding:7px 14px;border-radius:var(--radius-sm);font-size:12px;font-weight:700;cursor:pointer;border:1px solid rgba(255,255,255,.08);background:var(--glass);backdrop-filter:blur(10px);color:var(--text2);transition:all .25s;white-space:nowrap;text-decoration:none}
.btn:hover{transform:translateY(-1px);box-shadow:0 4px 14px rgba(0,0,0,.25)}
.btn-green{border-color:rgba(63,185,80,.25);color:var(--green);background:var(--green-bg)}.btn-green:hover{background:rgba(63,185,80,.18);border-color:rgba(63,185,80,.45)}
.btn-red{border-color:rgba(248,81,73,.25);color:var(--red);background:var(--red-bg)}.btn-red:hover{background:rgba(248,81,73,.18);border-color:rgba(248,81,73,.45)}
.btn-amber{border-color:rgba(210,153,34,.25);color:var(--amber);background:var(--amber-bg)}.btn-amber:hover{background:rgba(210,153,34,.18);border-color:rgba(210,153,34,.45)}
.btn-purple{border-color:rgba(188,140,255,.25);color:var(--purple);background:var(--purple-bg)}.btn-purple:hover{background:rgba(188,140,255,.18);border-color:rgba(188,140,255,.45)}
.btn-blue{border-color:rgba(88,166,255,.25);color:var(--blue);background:var(--blue-bg)}.btn-blue:hover{background:rgba(88,166,255,.18);border-color:rgba(88,166,255,.45)}
.health-score{display:flex;align-items:center;gap:16px;background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);padding:16px 20px;margin-bottom:16px}
.health-ring{width:60px;height:60px;border-radius:50%;position:relative;flex-shrink:0}
.health-ring svg{transform:rotate(-90deg)}.health-ring .bg{fill:none;stroke:rgba(255,255,255,.06);stroke-width:5}.health-ring .fg{fill:none;stroke-width:5;stroke-linecap:round;transition:stroke-dashoffset .6s ease,stroke .3s}.health-ring .center{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:900;font-family:var(--mono)}
.health-info{flex:1}.health-label{font-size:11px;color:var(--text3);font-weight:600;text-transform:uppercase;letter-spacing:.5px}.health-value{font-size:28px;font-weight:900;line-height:1.1}.health-desc{font-size:11px;color:var(--text2)}
.stats-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:16px}
@media(max-width:900px){.stats-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:500px){.stats-grid{grid-template-columns:repeat(2,1fr)}}
.stat-card{background:var(--glass);backdrop-filter:blur(var(--glass-blur));border:1px solid rgba(255,255,255,.08);border-radius:var(--radius);padding:14px 12px;position:relative;overflow:hidden;transition:all .25s}
.stat-card::before{content:'';position:absolute;top:0;right:0;width:3px;height:100%;border-radius:0 var(--radius) var(--radius) 0}
.stat-card:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
.stat-card.green::before{background:var(--green)}.stat-card.blue::before{background:var(--blue)}.stat-card.purple::before{background:var(--purple)}.stat-card.amber::before{background:var(--amber)}.stat-card.red::before{background:var(--red)}
.stat-icon{font-size:20px;margin-bottom:6px}
.stat-value{font-size:22px;font-weight:900;font-family:var(--mono);line-height:1;margin-bottom:3px}
.stat-label{font-size:9px;color:var(--text3);font-weight:600;text-transform:uppercase;letter-spacing:.5px}
.server-bar{display:grid;grid-template-columns:repeat(5,1fr);background:var(--glass);backdrop-filter:blur(var(--glass-blur));border:1px solid rgba(255,255,255,.08);border-radius:var(--radius);overflow:hidden;margin-bottom:16px}
.server-bar-item{padding:12px 14px;border-left:1px solid var(--border)}
.server-bar-item:last-child{border-left:none}
.server-bar-label{font-size:9px;color:var(--text3);font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px}
.server-bar-value{font-size:12px;font-weight:700;font-family:var(--mono)}
.tps-panel{background:var(--glass);backdrop-filter:blur(var(--glass-blur));border:1px solid rgba(255,255,255,.08);border-radius:var(--radius);padding:14px 16px;margin-bottom:16px}
.tps-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.tps-title{font-size:13px;font-weight:700;display:flex;align-items:center;gap:6px}
.tps-legend{display:flex;align-items:center;gap:14px;font-size:10px;color:var(--text3)}
.section{margin-bottom:16px;padding:14px 16px;background:var(--glass);backdrop-filter:blur(var(--glass-blur));border:1px solid rgba(255,255,255,.08);border-radius:var(--radius)}
.section-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border2)}
.section-title{font-size:14px;font-weight:800;display:flex;align-items:center;gap:6px}
.section-sub{font-size:10px;color:var(--text3);font-weight:500}
.bots-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}
.bot-card{background:var(--surface2);border:1px solid var(--border);border-radius:var(--radius);padding:14px;transition:all .25s;position:relative;overflow:hidden}
.bot-card.online{border-color:rgba(16,185,129,.12)}.bot-card.sleeping{border-color:rgba(139,92,246,.12)}.bot-card.offline{border-color:rgba(239,68,68,.08)}
.bot-header{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.bot-avatar{width:38px;height:38px;border-radius:8px;background:var(--surface3);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:20px}
.bot-info{flex:1;min-width:0}.bot-name{font-size:13px;font-weight:800}.bot-role{font-size:10px;color:var(--text3)}
.bot-status-badge{font-size:9px;font-weight:700;padding:2px 7px;border-radius:10px;white-space:nowrap}
.bot-tags{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:8px}
.tag{font-size:9px;padding:2px 6px;border-radius:var(--radius-xs);font-weight:700;border:1px solid var(--border);color:var(--text2)}
.bot-stats{display:grid;grid-template-columns:1fr 1fr;gap:5px;margin-bottom:8px}
.bot-stat{background:rgba(255,255,255,.03);border-radius:var(--radius-xs);padding:6px 8px;border:1px solid var(--border2)}
.bot-stat-lbl{font-size:8px;color:var(--text3);font-weight:600;display:block;margin-bottom:1px}
.bot-stat-val{font-size:11px;font-weight:700;font-family:var(--mono)}
.bot-pos{display:flex;align-items:center;gap:5px;background:var(--cyan-bg);border:1px solid rgba(6,182,212,.1);border-radius:var(--radius-xs);padding:5px 8px;margin-bottom:6px;font-size:10px;color:var(--cyan);font-family:var(--mono);font-weight:600}
.bot-btns{display:flex;gap:4px}
.bot-btn{flex:1;padding:6px;border-radius:var(--radius-xs);font-size:11px;cursor:pointer;border:1px solid var(--border);background:var(--surface3);color:var(--text3);text-align:center;font-family:var(--font);font-weight:600;transition:all .2s}
.bot-btn.red:hover{border-color:rgba(248,81,73,.4);color:var(--red);background:var(--red-bg)}
.bot-btn.green:hover{border-color:rgba(63,185,80,.4);color:var(--green);background:var(--green-bg)}
.bot-btn.gold:hover{border-color:rgba(210,153,34,.4);color:var(--amber);background:var(--amber-bg)}
.bot-btn.purple:hover{border-color:rgba(188,140,255,.4);color:var(--purple);background:var(--purple-bg)}
.table-wrap{background:rgba(0,0,0,.15);border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden}
.table-wrap table{width:100%;border-collapse:collapse}
.table-wrap th{text-align:right;padding:8px 12px;font-size:9px;text-transform:uppercase;letter-spacing:.5px;color:var(--text3);font-weight:700;background:rgba(255,255,255,.03);border-bottom:1px solid var(--border)}
.table-wrap td{padding:8px 12px;border-bottom:1px solid var(--border2);font-size:12px}
.table-wrap tr:last-child td{border-bottom:none}
.cat-badge{font-size:9px;padding:2px 6px;border-radius:var(--radius-xs);font-weight:700;display:inline-block}
.events-panel{background:rgba(0,0,0,.15);border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px;max-height:240px;overflow-y:auto}
.ev-row{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:var(--radius-xs);font-size:11px;animation:slideIn .2s both}
.ev-time{font-size:9px;color:var(--text3);font-family:var(--mono);white-space:nowrap;margin-right:auto}
.chat-box{background:rgba(0,0,0,.15);border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px 14px}
.chat-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.chat-select,.chat-input{background:rgba(255,255,255,.04);border:1px solid var(--border);color:var(--text);border-radius:var(--radius-xs);padding:8px 10px;font-family:var(--font);font-size:12px;outline:none}
.chat-input{flex:1;min-width:160px}
.chat-input:focus,.chat-select:focus{border-color:var(--green);box-shadow:0 0 0 2px rgba(63,185,80,.1)}
.chat-send{background:var(--green-bg);border:1px solid rgba(63,185,80,.25);color:var(--green);border-radius:var(--radius-xs);padding:8px 18px;font-size:12px;font-weight:700;cursor:pointer}
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(16px);background:var(--glass);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius);padding:12px 24px;font-size:13px;font-weight:700;opacity:0;transition:all .3s;pointer-events:none;z-index:9999;box-shadow:0 10px 36px rgba(0,0,0,.4)}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0);animation:toastIn .3s both}
.toast.ok{border-color:rgba(63,185,80,.4);color:var(--green)}
.toast.err{border-color:rgba(248,81,73,.4);color:var(--red)}
.empty-state{text-align:center;color:var(--text3);padding:28px;font-size:13px}
.chart-canvas{width:100%;height:120px;border-radius:var(--radius-xs);display:block;margin-top:8px}
.mem-bar{height:8px;border-radius:4px;background:rgba(255,255,255,.06);overflow:hidden;margin-top:6px}
.mem-fill{height:100%;border-radius:4px;transition:width .5s ease}
.chart-sm{width:100%;height:36px;border-radius:3px;display:block;margin-top:4px}
.streamer-mode .bot-name,.streamer-mode .bot-role,.streamer-mode .bot-stat-val{filter:blur(4px);user-select:none}
.streamer-mode .bot-pos{filter:blur(3px)}
.streamer-mode .sidebar-ver{filter:blur(2px)}
.mode-badge{font-size:9px;padding:2px 8px;border-radius:10px;font-weight:700}
.notif-dot{width:10px;height:10px;border-radius:50%;display:inline-block;animation:pulse 1.5s infinite;margin-left:6px}
.notif-dot.red{background:var(--red);box-shadow:0 0 6px var(--red)}
.notif-dot.green{background:var(--green);box-shadow:0 0 6px var(--green)}
.csv-btn{font-size:10px;padding:3px 10px;border-radius:var(--radius-xs);cursor:pointer;border:1px solid var(--border);background:var(--surface3);color:var(--text2);margin-right:8px}
.csv-btn:hover{background:var(--blue-bg);color:var(--blue);border-color:rgba(88,166,255,.3)}
.footer{text-align:center;color:var(--text3);font-size:11px;padding:20px 0 8px;opacity:.4}
</style>
</head>
<body>
<div class="layout">
<button class="hamburger" id="hamburger" onclick="toggleSidebar()" aria-label="فتح القائمة"></button>
<div class="sidebar-overlay" id="sidebarOverlay" onclick="toggleSidebar()"></div>
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="sidebar-logo">🔥</div>
<div class="sidebar-brand">
<div class="sidebar-title">Sayed Bot</div>
<div class="sidebar-ver">v26.0 PHOENIX</div>
</div>
</div>
<nav class="sidebar-nav">
<div class="nav-section">الرئيسية</div>
<a class="nav-item active" href="#sec-top"><span class="nav-icon">📊</span>لوحة التحكم</a>
<a class="nav-item" href="#sec-bots"><span class="nav-icon">🤖</span>البوتات</a>
<a class="nav-item" href="#sec-plugins"><span class="nav-icon">🔌</span>البلاجن</a>
<a class="nav-item" href="#sec-players"><span class="nav-icon">👥</span>اللاعبين</a>
<a class="nav-item" href="#sec-events"><span class="nav-icon">📋</span>الأحداث</a>
<div class="nav-section">الإدارة</div>
<a class="nav-item" href="/setup"><span class="nav-icon">⚙️</span>الإعداد</a>
<a class="nav-item" href="/logs"><span class="nav-icon">📋</span>السجل</a>
<a class="nav-item" href="/features"><span class="nav-icon">🎯</span>الميزات</a>
</nav>
<div class="sidebar-footer">
<div class="live-badge">
<span class="live-dot" id="liveDot"></span>
<span id="navSt">جاري التحميل...</span>
</div>
</div>
</aside>
<main class="main" id="mainContent">
<div class="main-header">
<h1 class="main-title">🔥 لوحة التحكم</h1>
<div class="main-actions">
<button class="btn btn-green" onclick="location.reload()">🔄 تحديث</button>
<button class="btn btn-blue" id="streamerBtn" onclick="toggleStreamerMode()">🎥 Streamer</button>
<button class="btn btn-purple" onclick="screenshotReady()">📸 Screenshot</button>
<button class="btn btn-amber" onclick="ctrlAll('restart')">⚡ إعادة الكل</button>
<button class="btn btn-red" onclick="ctrlAll('stop')">⏹ إيقاف</button>
<button class="btn btn-purple" onclick="forceScan()">🔍 فحص</button>
</div>
</div>
<div id="ecoBanner" style="display:none"></div>
<div class="health-score" id="healthScore">
<div class="health-ring">
<svg width="60" height="60" viewBox="0 0 60 60">
<circle class="bg" cx="30" cy="30" r="24"/>
<circle class="fg" id="healthRing" cx="30" cy="30" r="24" stroke="#3fb950" stroke-dasharray="150.8" stroke-dashoffset="0"/>
</svg>
<div class="center" id="healthNum">--</div>
</div>
<div class="health-info">
<div class="health-label">SERVER HEALTH SCORE</div>
<div class="health-value" id="healthVal">--</div>
<div class="health-desc" id="healthDesc">جاري التحميل...</div>
</div>
</div>
<div class="stats-grid" id="statsGrid"></div>
<div id="serverStatusBar"></div>
<div class="server-bar" id="serverBar"></div>
<div id="modelBar" style="display:flex;align-items:center;gap:10px;padding:10px 16px;border-radius:12px;background:rgba(188,140,255,.08);border:1px solid rgba(188,140,255,.15);margin-bottom:16px">
<span id="modelIcon" style="font-size:16px"></span>
<span id="modelText" style="font-size:12px;font-weight:600;color:#a78bfa">جاري تحميل النموذج...</span>
<span id="modelStats" style="font-size:11px;color:#8b949e;margin-right:auto"></span>
<span id="modelRight" style="font-size:10px;color:#6e7681"></span>
</div>
<div id="datasetBar" style="display:flex;align-items:center;gap:10px;padding:10px 16px;border-radius:12px;background:rgba(88,166,255,.06);border:1px solid rgba(88,166,255,.15);margin-bottom:16px">
<span id="dsIcon" style="font-size:16px"></span>
<span id="dsText" style="font-size:12px;font-weight:600;color:#8b949e">جاري الاتصال بـ Dataset...</span>
<span id="dsFiles" style="font-size:11px;color:#6e7681;margin-right:auto"></span>
<span id="dsTime" style="font-size:10px;color:#6e7681"></span>
</div>
<div class="tps-panel">
<div class="tps-header">
<div class="tps-title">📈 TPS — آخر 120 ثانية</div>
<div class="tps-legend" id="tpsLegend"><span style="color:#3fb950">● TPS</span> <span style="color:#f59e0b">— الهدف (20)</span></div>
</div>
<canvas id="tpsChart" class="chart-canvas"></canvas>
</div>
<div class="tps-panel">
<div class="tps-header">
<div class="tps-title">💾 الذاكرة — <span id="memLabel">0</span>MB / 450MB</div>
<div class="tps-legend" id="memLegend"><span style="color:#3fb950">● مستخدم</span> <span style="color:#8b949e">● حر</span></div>
</div>
<div class="mem-bar"><div class="mem-fill" id="memFill" style="width:0%;background:linear-gradient(90deg,#3fb950,#58a6ff)"></div></div>
<div style="display:flex;justify-content:space-between;font-size:10px;color:var(--text3);margin-top:4px">
<span>RSS: <span id="memRss">0</span>MB</span>
<span>Heap: <span id="memHeap">0</span>MB / <span id="memTotal">450</span>MB</span>
</div>
</div>
<div class="section" id="sec-bots">
<div class="section-header"><h2 class="section-title">🤖 البوتات</h2><span class="section-sub">تحديث كل 15 ثانية</span></div>
<div class="bots-grid" id="botsGrid"></div>
</div>
<div class="section" id="sec-plugins">
<div class="section-header"><h2 class="section-title">🔌 البلاجن المكتشفة</h2></div>
<div class="table-wrap"><table><thead><tr><th>الاسم</th><th>التصنيف</th><th>الوصف</th></tr></thead><tbody id="pluginsBody"></tbody></table></div>
</div>
<div class="section" id="sec-players">
<div class="section-header"><h2 class="section-title">👥 سجل اللاعبين</h2></div>
<div class="table-wrap"><table><thead><tr><th>اللاعب</th><th>أول ظهور</th><th>آخر ظهور</th><th>الزيارات</th><th>الحالة</th></tr></thead><tbody id="playersBody"></tbody></table></div>
</div>
<div class="section" id="sec-events">
<div class="section-header">
<h2 class="section-title">📋 سجل الأحداث</h2>
<button class="csv-btn" onclick="exportCSV()">📥 تصدير CSV</button>
</div>
<div class="events-panel" id="evbox"></div>
</div>
<div class="section" id="sec-chat">
<div class="section-header"><h2 class="section-title">💬 إرسال رسالة</h2></div>
<div class="chat-box"><div class="chat-row">
<select id="chatBotId" class="chat-select"></select>
<input id="chatMsg" class="chat-input" type="text" placeholder="اكتب رسالة..." dir="auto" onkeydown="if(event.key==='Enter')sendChatMsg()">
<button class="chat-send" onclick="sendChatMsg()">📤 إرسال</button>
</div></div>
</div>
<div class="footer">🔥 Sayed Bot Team v26.0 "Phoenix Rising" — PacketShaper · PhantomReconnect · GC Scheduler · Soul Memory · Neural Chat · Quantum Dashboard</div>
</main>
</div>
<div class="toast" id="toast"></div>
<script>
let _streamerMode = false;
let _liveTimer = null;
const TZ = {connect:'#34d399',disconnect:'#5a7fa8',kick:'#f87171',plugin:'#a78bfa',perf:'#fbbf24',op:'#fbbf24',chat:'#22d3ee',sleep:'#a78bfa',info:'#93c5fd',session:'#7f9cc0'};
const CC = {performance:'#10b981',protection:'#3b82f6',utility:'#8b5cf6',security:'#f59e0b',admin:'#ec4899',economy:'#06b6d4',afk:'#10b981',misc:'#64748b'};
const tpsHistory = new Array(120).fill(20);
const pingHistory = {};
function toggleSidebar(){
const s=document.getElementById('sidebar'),o=document.getElementById('sidebarOverlay'),h=document.getElementById('hamburger');
s.classList.toggle('active');o.classList.toggle('show');
h.textContent=s.classList.contains('active')?'✕':'☰';
}
document.addEventListener('click',function(e){
const nav=e.target.closest('.nav-item');
if(nav && window.innerWidth<=900){const s=document.getElementById('sidebar');s.classList.remove('active');document.getElementById('sidebarOverlay').classList.remove('show');document.getElementById('hamburger').textContent='☰';}
});
function toggleStreamerMode(){
_streamerMode=!_streamerMode;
document.getElementById('mainContent').classList.toggle('streamer-mode',_streamerMode);
document.getElementById('streamerBtn').textContent=_streamerMode?'🎥 Streamer ON':'🎥 Streamer';
showToast(_streamerMode?'🎥 Streamer Mode مفعل — أسماء البوتات مخفية':'🎥 Streamer Mode منتهي','ok');
}
function screenshotReady(){
document.getElementById('healthScore').style.background='rgba(63,185,80,.15)';
document.getElementById('healthScore').style.border='2px solid #3fb950';
showToast('📸 اللوحة جاهزة للتصوير!','ok');
setTimeout(()=>{
document.getElementById('healthScore').style.background='';
document.getElementById('healthScore').style.border='';
},5000);
}
function exportCSV(){
const rows=[['الوقت','النوع','الرسالة']];
document.querySelectorAll('#evbox .ev-row').forEach(row=>{
const spans=row.querySelectorAll('span');
const time=spans[1]?.textContent||'';
const msg=spans[0]?.textContent||'';
rows.push([time,'event',msg]);
});
const csv=rows.map(r=>r.map(c=>'"'+c.replace(/"/g,'""')+'"').join(',')).join('\n');
const blob=new Blob([csv],{type:'text/csv'});
const a=document.createElement('a');
a.href=URL.createObjectURL(blob);
a.download='sayed-bot-events-'+new Date().toISOString().slice(0,10)+'.csv';
a.click();
URL.revokeObjectURL(a.href);
showToast('📥 تم تصدير CSV','ok');
}
function calcHealthScore(d){
let score=0;
// Online bots ratio
const online=d.online||0,total=d.bots?.length||1;
score+=Math.round((online/total)*30);
// TPS
const tps=d.performance?.tps;
if(tps!=null) score+=Math.min(30,Math.round(tps*1.5));
// Memory
const memPct=d.performance?.rss?(d.performance.rss/(d.performance.memLimit||450)*100):50;
score+=memPct<70?20:memPct<85?10:0;
// Uptime
const upt=d.uptime||0;
score+=Math.min(20,Math.round(upt/3600));
return Math.min(100,Math.max(0,score));
}
function drawChart(canvas, data, color, bgColor) {
if (!canvas || !data.length) return;
const ctx = canvas.getContext('2d'), W = canvas.width = canvas.clientWidth * 2, H = canvas.height = canvas.clientHeight * 2;
ctx.clearRect(0, 0, W, H);
const min = 0, max = 25, pad = 12, w = W - pad * 2, h = H - pad * 2;
ctx.strokeStyle = 'rgba(255,255,255,.04)'; ctx.lineWidth = 1;
for (let i = 0; i <= 5; i++) { const y = pad + h * (1 - i / 5); ctx.beginPath(); ctx.moveTo(pad, y); ctx.lineTo(W - pad, y); ctx.stroke(); }
ctx.beginPath(); ctx.moveTo(pad, H - pad);
data.forEach((v, i) => { const x = pad + w * i / (data.length - 1 || 1), y = pad + h * (1 - (v - min) / (max - min)); if (i === 0) ctx.lineTo(x, y); else ctx.lineTo(x, y); });
ctx.lineTo(W - pad, H - pad); ctx.closePath();
const g = ctx.createLinearGradient(0, pad, 0, H - pad); g.addColorStop(0, bgColor || 'rgba(63,185,80,.15)'); g.addColorStop(1, 'rgba(63,185,80,.01)');
ctx.fillStyle = g; ctx.fill();
ctx.beginPath(); ctx.strokeStyle = color || '#3fb950'; ctx.lineWidth = 2.5; ctx.lineJoin = 'round';
data.forEach((v, i) => { const x = pad + w * i / (data.length - 1 || 1), y = pad + h * (1 - (v - min) / (max - min)); if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); });
ctx.stroke();
ctx.strokeStyle = 'rgba(245,158,11,.25)'; ctx.lineWidth = 1; ctx.setLineDash([4, 4]);
const tY = pad + h * (1 - 20 / (max - min)); ctx.beginPath(); ctx.moveTo(pad, tY); ctx.lineTo(W - pad, tY); ctx.stroke(); ctx.setLineDash([]);
}
async function loadModelStatus(){
try{
const r = await fetch('/api/model-status');
if(!r.ok)return;
const m = await r.json();
const icon = document.getElementById('modelIcon');
const text = document.getElementById('modelText');
const stats = document.getElementById('modelStats');
const right = document.getElementById('modelRight');
if(m.loaded){
icon.textContent = '🧠';
text.textContent = 'النموذج جاهز ✓';
text.style.color = '#3fb950';
stats.textContent = '🔮 ' + m.predictions + ' توقع | ⏱️ ' + m.avgTime + 'ms';
right.textContent = '📐 ' + m.contextLen + '/' + m.botsWithModel + ' بوتات';
} else {
icon.textContent = '⚠️';
text.textContent = 'النموذج غير محمّل';
text.style.color = '#f59e0b';
stats.textContent = m.fallbacks > 0 ? '⚠️ ' + m.fallbacks + ' fallback' : '';
right.textContent = '📐 سياق: ' + m.contextLen;
}
}catch(_){}
}
async function loadDashboard(){
try{
const [r, dsR, mr] = await Promise.all([
fetch('/api/status'),
fetch('/api/dataset-status').catch(() => null),
loadModelStatus(),
]);
if(!r.ok)return;
const d=await r.json();
const ds = dsR && dsR.ok ? await dsR.json() : null;
// Dataset status bar
const dsBar = document.getElementById('datasetBar');
if (dsBar && ds) {
const icon = document.getElementById('dsIcon');
const text = document.getElementById('dsText');
const files = document.getElementById('dsFiles');
const time = document.getElementById('dsTime');
if (ds.connected && !ds.local) {
icon.textContent = '☁️';
text.textContent = 'Dataset متصل';
text.style.color = '#3fb950';
const fList = ds.files?.length ? ds.files.join(', ') : '—';
files.textContent = '📁 ' + fList;
const lt = ds.lastWrite ? new Date(ds.lastWrite).toLocaleTimeString('ar-EG') : '';
time.textContent = lt ? '🕐 آخر حفظ: ' + lt : '';
dsBar.style.background = 'rgba(63,185,80,.06)';
dsBar.style.borderColor = 'rgba(63,185,80,.15)';
} else if (!ds.hasToken) {
icon.textContent = '⚠️';
text.textContent = 'HF_TOKEN غير مضبوط — استخدم المحلي';
text.style.color = '#f59e0b';
files.textContent = '📁 محلي فقط';
time.textContent = '';
dsBar.style.background = 'rgba(245,158,11,.08)';
dsBar.style.borderColor = 'rgba(245,158,11,.2)';
} else if (ds.local) {
icon.textContent = '💾';
text.textContent = 'وضع محلي — Dataset غير متصل';
text.style.color = '#f85149';
files.textContent = '📁 محلي (يضيع عند rebuild)';
time.textContent = 'ضبط HF_TOKEN في Settings';
dsBar.style.background = 'rgba(248,81,73,.06)';
dsBar.style.borderColor = 'rgba(248,81,73,.15)';
} else {
icon.textContent = '⏳';
text.textContent = 'جاري التحميل...';
text.style.color = '#8b949e';
files.textContent = '';
time.textContent = '';
}
}
const online=d.online||0, total=d.bots?.length||0, bots=d.bots||[];
const ns=document.getElementById('navSt');
if(ns)ns.textContent=online+'/'+total+' متصل';
// Health Score
const score=calcHealthScore(d);
const hNum=document.getElementById('healthNum');
const hVal=document.getElementById('healthVal');
const hDesc=document.getElementById('healthDesc');
const hRing=document.getElementById('healthRing');
if(hNum)hNum.textContent=score;
if(hVal){
const c=score>=80?'#3fb950':score>=50?'#d29922':'#f85149';
hVal.style.color=c;
hVal.textContent=score+'/100 '+(score>=80?'🟢':score>=50?'🟡':'🔴');
}
if(hDesc)hDesc.textContent=score>=80?'أداء ممتاز!':score>=50?'أداء متوسط، يحتاج مراقبة':'أداء منخفض، يرجى التحقق';
if(hRing){
const circ=150.8;
hRing.style.strokeDashoffset=circ-(circ*score/100);
hRing.style.stroke=score>=80?'#3fb950':score>=50?'#d29922':'#f85149';
}
const tps=d.performance?.tps, tc=tps>=18?'#34d399':tps>=14?'#fbbf24':'#f87171', tl=tps!=null?tps.toFixed(1)+' TPS':'N/A';
const memPct=d.performance?.rss?(d.performance.rss/(d.performance.memLimit||450)*100).toFixed(0):'0';
const upt=d.uptime||0, uph=Math.floor(upt/3600), upm=Math.floor((upt%3600)/60);
document.getElementById('statsGrid').innerHTML=
'<div class="stat-card green"><div class="stat-icon">🤖</div><div class="stat-value" style="color:'+(online>0?'#34d399':'#f87151')+'">'+online+'/'+total+'</div><div class="stat-label">بوتات متصلة</div></div>'+
'<div class="stat-card blue"><div class="stat-icon">⚡</div><div class="stat-value" style="color:'+tc+'">'+tl+'</div><div class="stat-label">TPS السيرفر</div></div>'+
'<div class="stat-card purple"><div class="stat-icon">🔌</div><div class="stat-value" style="color:#a78bfa">'+(d.plugins||0)+'</div><div class="stat-label">بلاجن مكتشفة</div></div>'+
'<div class="stat-card amber"><div class="stat-icon">👥</div><div class="stat-value" style="color:#22d3ee">'+(d.players||0)+'</div><div class="stat-label">لاعبين</div></div>'+
'<div class="stat-card" style="border-color:'+(memPct>80?'rgba(248,81,73,.2)':'rgba(255,255,255,.08)')+'"><div class="stat-icon">💾</div><div class="stat-value" style="color:'+(memPct>80?'#f85149':'#3fb950')+'">'+memPct+'%</div><div class="stat-label">ذاكرة</div></div>'+
'<div class="stat-card" style="border-color:rgba(88,166,255,.1)"><div class="stat-icon">🕐</div><div class="stat-value" style="color:#58a6ff;font-size:18px">'+uph+'h '+upm+'m</div><div class="stat-label">مدة التشغيل</div></div>';
const sbar=document.getElementById('serverStatusBar');
if(sbar){
const c=online>0?'#3fb950':'#f85149', bg=online>0?'rgba(63,185,80,.08)':'rgba(248,81,73,.08)', bc=online>0?'rgba(63,185,80,.2)':'rgba(248,81,73,.2)';
sbar.style.cssText='display:flex;align-items:center;gap:10px;padding:12px 18px;border-radius:12px;background:'+bg+';border:1px solid '+bc+';margin-bottom:16px';
sbar.innerHTML='<span style="width:10px;height:10px;border-radius:50%;background:'+c+';box-shadow:0 0 8px '+c+';flex-shrink:0"></span><span style="font-size:13px;font-weight:600;color:'+c+'">'+(online>0?'🟢 السيرفر شغال':'🔴 السيرفر متوقف')+'</span>';
}
const ups2 = upt % 60;
document.getElementById('serverBar').innerHTML=
'<div class="server-bar-item"><div class="server-bar-label">🌐 العنوان</div><div class="server-bar-value">'+(d.server?.host||'—')+'</div></div>'+
'<div class="server-bar-item"><div class="server-bar-label">🔌 البورت</div><div class="server-bar-value">'+(d.server?.port||'—')+'</div></div>'+
'<div class="server-bar-item"><div class="server-bar-label">🎮 الإصدار</div><div class="server-bar-value">'+(d.server?.version||'auto')+'</div></div>'+
'<div class="server-bar-item"><div class="server-bar-label">⚡ TPS</div><div class="server-bar-value" style="color:'+tc+'">'+tl+'</div></div>'+
'<div class="server-bar-item"><div class="server-bar-label">🕐 تشغيل</div><div class="server-bar-value" style="color:#f59e0b">'+('0'+uph).slice(-2)+'h '+('0'+upm).slice(-2)+'m '+('0'+ups2).slice(-2)+'s</div></div>';
const eco=document.getElementById('ecoBanner');
if(d.performance?.ecoMode){
eco.style.display='flex'; eco.className='eco-banner';
eco.innerHTML='<span class="eco-icon">🌿</span><div class="eco-text"><div class="eco-title">ECO MODE مفعّل</div><div class="eco-desc">TPS منخفض — البوتات أوقفت المشي والحفر تلقائياً</div></div><div class="eco-value">'+tl+'</div>';
} else { eco.style.display='none'; }
document.getElementById('botsGrid').innerHTML=bots.map((s, idx)=>{
const h=Math.floor(s.uptime/3600), m=Math.floor((s.uptime%3600)/60), sc=s.uptime%60;
const pc=!s.avgPing?'#6e7681':s.avgPing<200?'#34d399':s.avgPing<500?'#fcd34d':'#f87171';
let st,stt,stc;
if(s.deepSleep){st='💤';stt='سبات عميق';stc='#c4b5fd'}
else if(s.connected){st='🟢';stt=h+'h '+m+'m '+sc+'s';stc='#34d399'}
else if(s.connecting){st='🟡';stt='جاري الاتصال...';stc='#fcd34d'}
else {st='🔴';stt='في الانتظار';stc='#6e7681'}
const sc2=s.connected?'online':s.deepSleep?'sleeping':'offline';
const env=s.env||{};
const chips=[];
if(env.hasOre)chips.push('<span style="color:#fbbf24;font-size:10px">⛏️ خام</span>');
if(env.hasWood)chips.push('<span style="color:#a78bfa;font-size:10px">🪵 أشجار</span>');
if(env.hasDanger)chips.push('<span style="color:#f87171;font-size:10px">⚠️ خطر</span>');
if(env.isNight)chips.push('<span style="color:#818cf8;font-size:10px">🌙 ليل</span>');
return '<div class="bot-card '+sc2+'"><div class="bot-header"><div class="bot-avatar">'+(s.emoji||'🤖')+'</div><div class="bot-info"><div class="bot-name">'+(s.username||'')+'</div><div class="bot-role">'+(s.label||'')+'</div></div><span class="bot-status-badge" style="background:'+stc+'18;color:'+stc+';border:1px solid '+stc+'40">'+st+' '+stt+'</span></div><div class="bot-stats"><div class="bot-stat"><span class="bot-stat-lbl">⏱️ الجلسة</span><span class="bot-stat-val">'+h+'h '+m+'m '+sc+'s</span></div><div class="bot-stat"><span class="bot-stat-lbl">📶 Ping</span><span class="bot-stat-val" style="color:'+pc+'">'+(s.avgPing!=null?s.avgPing+'ms':'N/A')+'</span></div></div><canvas id="pingChart'+idx+'" class="chart-sm" style="display:'+(s.connected?'block':'none')+'"></canvas><div class="bot-pos">📍 '+(s.position?s.position.x+', '+s.position.y+', '+s.position.z:'—')+'</div>'+(chips.length?'<div style="display:flex;gap:5px;flex-wrap:wrap;margin-bottom:6px">'+chips.join('')+'</div>':'')+'</div>';
}).join('');
const plugins=d.pluginsList||[];
document.getElementById('pluginsBody').innerHTML=plugins.slice(0,30).map(p=>{
const c=CC[p.cat]||'#64748b';
return '<tr><td><strong>'+(p.name||'')+'</strong></td><td><span class="cat-badge" style="background:'+c+'18;color:'+c+';border:1px solid '+c+'40">'+(p.cat||'')+'</span></td><td style="color:var(--text3);font-size:12px">'+(p.desc||'')+'</td></tr>';
}).join('')||'<tr><td colspan="3" style="text-align:center;color:#64748b;padding:20px">لم يُكتشف أي بلاجن بعد</td></tr>';
const players=d.playersList||[];
document.getElementById('playersBody').innerHTML=players.slice(0,25).map(p=>{
return '<tr><td><strong>'+(p.name||'')+'</strong></td><td style="color:var(--text3);font-size:12px">'+(p.firstSeen||'—')+'</td><td style="color:var(--text3);font-size:12px">'+(p.lastSeen||'—')+'</td><td style="color:var(--cyan);font-weight:700">'+(p.visits||0)+'</td><td>'+(p.online?'<span style="color:#34d399;font-weight:700">● متصل</span>':'<span style="color:var(--text3)">○ غير متصل</span>')+'</td></tr>';
}).join('')||'<tr><td colspan="5" style="text-align:center;color:#64748b;padding:20px">لم يُرصد أي لاعب بعد</td></tr>';
const events=d.events||[];
document.getElementById('evbox').innerHTML=events.slice(0,30).map(e=>'<div class="ev-row"><span style="color:'+(TZ[e.type]||'#7f9cc0')+'">'+(e.msg||'')+'</span><span class="ev-time">'+(e.time?e.time.slice(11,19):'')+'</span></div>').join('')||'<div class="ev-row" style="color:#6e7681">لا أحداث بعد...</div>';
const sel=document.getElementById('chatBotId');
if(sel&&bots.length){
sel.innerHTML=bots.map((s,i)=>'<option value="'+i+'">'+(s.emoji||'🤖')+' '+(s.username||'')+(s.connected?' ✅':' ❌')+'</option>').join('');
}
if (d.performance?.tps != null) {
tpsHistory.push(d.performance.tps); tpsHistory.shift();
drawChart(document.getElementById('tpsChart'), tpsHistory, '#3fb950', 'rgba(63,185,80,.12)');
}
const perf = d.performance || {};
if (perf.rss != null) {
const limit = perf.memLimit || 450, pct = Math.min(100, (perf.rss / limit * 100)).toFixed(1);
document.getElementById('memFill').style.width = pct + '%';
document.getElementById('memLabel').textContent = perf.rss;
document.getElementById('memRss').textContent = perf.rss;
document.getElementById('memHeap').textContent = perf.heapUsed || 0;
document.getElementById('memTotal').textContent = limit;
}
bots.forEach((s, idx) => {
if (s.avgPing != null) {
if (!pingHistory['b' + idx]) pingHistory['b' + idx] = new Array(30).fill(s.avgPing);
pingHistory['b' + idx].push(s.avgPing); pingHistory['b' + idx].shift();
}
});
setTimeout(() => {
bots.forEach((s, idx) => {
const c = document.getElementById('pingChart' + idx);
if (c && pingHistory['b' + idx]) drawChart(c, pingHistory['b' + idx], '#58a6ff', 'rgba(88,166,255,.1)');
});
}, 50);
const dot=document.getElementById('liveDot');
if(dot)dot.style.background=online>0?'#3fb950':'#f87171';
// Live notification for disconnected bots
const prevOnline=window._lastOnline||0;
if(prevOnline>0&&online<prevOnline){
showToast('⚠️ بوت انقطع — تحقق من اللوحة','err');
}
window._lastOnline=online;
}catch(e){}
}
async function ctrlAll(action){
try{
await fetch('/api/control',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action})});
showToast(action==='stop'?'⏹ تم إيقاف الكل':'🔄 جاري إعادة تشغيل الكل','ok');
}catch(e){showToast('❌ فشل','err')}
}
async function forceScan(){
try{
const r=await fetch('/api/force-scan',{method:'POST',headers:{'Content-Type':'application/json'},body:'{}'});
const d=await r.json();
showToast(d.ok?'🔍 '+(d.msg||'تم الفحص'):'❌ '+(d.error||'خطأ'),d.ok?'ok':'err');
}catch(e){showToast('❌ فشل','err')}
}
async function sendChatMsg(){
const botId=document.getElementById('chatBotId')?.value??0;
const msg=document.getElementById('chatMsg')?.value?.trim();
if(!msg){showToast('⚠️ الرسالة فارغة','err');return}
try{
const r=await fetch('/api/send-chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({botId:parseInt(botId),msg})});
const d=await r.json();
if(d.ok){showToast('✅ '+d.msg,'ok');document.getElementById('chatMsg').value='';}
else showToast('❌ '+(d.error||'خطأ'),'err');
}catch(e){showToast('❌ فشل','err')}
}
function showToast(msg,type='ok'){
const t=document.getElementById('toast');
if(!t)return;
t.textContent=msg; t.className='toast '+type+' show';
setTimeout(()=>{t.className='toast '+type;},3200);
}
loadDashboard();
_liveTimer=setInterval(loadDashboard, 15000);
</script>
</body>
</html>