| <!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; |
| |
| const online=d.online||0,total=d.bots?.length||1; |
| score+=Math.round((online/total)*30); |
| |
| const tps=d.performance?.tps; |
| if(tps!=null) score+=Math.min(30,Math.round(tps*1.5)); |
| |
| const memPct=d.performance?.rss?(d.performance.rss/(d.performance.memLimit||450)*100):50; |
| score+=memPct<70?20:memPct<85?10:0; |
| |
| 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; |
| |
| |
| 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+' متصل'; |
| |
| |
| 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'; |
| |
| |
| 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> |
|
|