resetbutton dashboard + agent

This commit is contained in:
Thomas Ciesla
2026-01-09 15:32:42 +01:00
parent a435ba5c8c
commit 1dce17fe76
2 changed files with 106 additions and 1 deletions

View File

@@ -1277,6 +1277,72 @@ async def get_shop_history_api(domain: str, request: Request):
return {"domain": domain, **data}
@app.post("/api/reset-stats")
async def reset_stats(request: Request):
"""Setzt alle In-Memory Statistiken zurück (Dashboard + alle Agents)."""
user = await get_current_user(request)
if not user:
raise HTTPException(401)
# 1. Reset-Command an alle verbundenen Agents senden
agent_count = 0
command_id = f"reset_{int(time.time())}"
for agent_id in list(manager.agent_connections.keys()):
await manager.send_to_agent(agent_id, {
'type': 'command.reset_stats',
'data': {'command_id': command_id}
})
agent_count += 1
# 2. Dashboard Shops zurücksetzen (Statistiken, History)
for shop in store.shops.values():
shop.log_entries = 0
shop.bot_bans = 0
shop.country_bans = 0
shop.active_bot_bans = 0
shop.active_country_bans = 0
shop.banned_bots = []
shop.banned_countries = []
shop.req_per_min = 0.0
shop.unique_ips = 0
shop.unique_bots = 0
shop.unique_countries = 0
shop.top_bots = {}
shop.top_ips = []
shop.top_countries = {}
shop.top_requests = {}
shop.human_requests = 0
shop.bot_requests = 0
shop.human_rpm = 0.0
shop.bot_rpm = 0.0
shop.history.clear()
shop.bot_history.clear()
shop.country_history.clear()
# 3. Agents zurücksetzen (nicht löschen, nur Stats)
for agent in store.agents.values():
agent.load_1m = 0.0
agent.load_5m = 0.0
agent.memory_percent = 0.0
# 4. Broadcast an alle Browser um UI zu aktualisieren
await manager.broadcast_to_browsers({
'type': 'refresh',
'data': {
'agents': store.get_all_agents(),
'shops': store.get_all_shops(),
'stats': {
'agents_online': len([a for a in store.agents.values() if a.status == 'online']),
'shops_active': len([s for s in store.shops.values() if s.status == 'active']),
'total_bans': 0,
'total_rpm': 0
}
}
})
return {"success": True, "message": f"Dashboard + {agent_count} Agent(s) zurückgesetzt"}
@app.post("/api/update-dashboard")
async def update_dashboard(request: Request):
"""Dashboard selbst updaten."""
@@ -1629,7 +1695,7 @@ def get_dashboard_html() -> str:
<div class="clock" id="clock">--:--:--</div>
<div class="connection-status"><div class="status-dot" id="wsStatus"></div><span id="wsStatusText">Verbinde...</span></div>
<div style="display:flex;align-items:center;gap:8px"><span style="font-size:12px;color:var(--text-secondary)">Update:</span><select id="updateInterval" onchange="setUpdateInterval(this.value)" style="padding:4px 8px;border-radius:4px;border:1px solid var(--border);background:var(--card-bg);color:var(--text);font-size:12px"><option value="2000">2s</option><option value="5000">5s</option><option value="10000" selected>10s</option><option value="15000">15s</option></select></div><div style="display:flex;align-items:center;gap:6px;padding:4px 8px;border-radius:4px;border:1px solid var(--border);background:var(--card-bg)"><label style="display:flex;align-items:center;gap:6px;cursor:pointer;font-size:12px;color:var(--text-secondary)" title="OPcache nach Aktivierung/Deaktivierung leeren"><input type="checkbox" id="autoFpmRestart" checked style="margin:0"><span>FPM-Restart</span></label></div>
<div class="update-dropdown" style="position:relative"><button class="btn-header" onclick="toggleUpdateDropdown()" id="updateDropdownBtn">🔄 v3.1</button><div id="updateDropdownMenu" style="display:none;position:absolute;right:0;top:100%;margin-top:4px;background:var(--card-bg);border:1px solid var(--border);border-radius:8px;padding:8px 0;min-width:200px;z-index:1000;box-shadow:0 4px 12px rgba(0,0,0,0.3)"><button onclick="updateDashboard()" style="display:block;width:100%;text-align:left;padding:8px 16px;border:none;background:none;color:var(--text);cursor:pointer;font-size:13px" onmouseover="this.style.background='var(--bg)'" onmouseout="this.style.background='none'">📊 Dashboard updaten</button><button onclick="updateAgents()" style="display:block;width:100%;text-align:left;padding:8px 16px;border:none;background:none;color:var(--text);cursor:pointer;font-size:13px" onmouseover="this.style.background='var(--bg)'" onmouseout="this.style.background='none'">🖥️ Alle Agents updaten (<span id="agentCountDropdown">0</span>)</button></div></div>
<button class="btn-header" onclick="resetStats()" title="Alle Statistiken zurücksetzen">🗑️ Reset</button><div class="update-dropdown" style="position:relative"><button class="btn-header" onclick="toggleUpdateDropdown()" id="updateDropdownBtn">🔄 v3.1</button><div id="updateDropdownMenu" style="display:none;position:absolute;right:0;top:100%;margin-top:4px;background:var(--card-bg);border:1px solid var(--border);border-radius:8px;padding:8px 0;min-width:200px;z-index:1000;box-shadow:0 4px 12px rgba(0,0,0,0.3)"><button onclick="updateDashboard()" style="display:block;width:100%;text-align:left;padding:8px 16px;border:none;background:none;color:var(--text);cursor:pointer;font-size:13px" onmouseover="this.style.background='var(--bg)'" onmouseout="this.style.background='none'">📊 Dashboard updaten</button><button onclick="updateAgents()" style="display:block;width:100%;text-align:left;padding:8px 16px;border:none;background:none;color:var(--text);cursor:pointer;font-size:13px" onmouseover="this.style.background='var(--bg)'" onmouseout="this.style.background='none'">🖥️ Alle Agents updaten (<span id="agentCountDropdown">0</span>)</button></div></div>
<div class="notification-dropdown" style="position:relative"><button class="btn-header" onclick="toggleNotificationDropdown()" id="notificationBtn" title="Benachrichtigungen">🔔<span class="notification-badge" id="notificationBadge" style="display:none">0</span></button><div id="notificationDropdown" style="display:none;position:absolute;right:0;top:100%;margin-top:4px;background:#1a1a2e;border:1px solid rgba(255,255,255,0.15);border-radius:8px;min-width:350px;max-width:450px;z-index:1000;box-shadow:0 4px 20px rgba(0,0,0,0.5)"><div style="display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid rgba(255,255,255,0.1);background:#1e1e32"><span style="font-weight:600;font-size:14px">📜 Benachrichtigungen</span><button onclick="clearNotifications()" style="background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:12px" title="Alle löschen">🗑️ Leeren</button></div><div id="notificationList" style="max-height:400px;overflow-y:auto;background:#1a1a2e"></div><div id="notificationEmpty" style="padding:24px;text-align:center;color:var(--text-secondary);font-size:13px;background:#1a1a2e">Keine Benachrichtigungen</div></div></div>
<div style="display:flex;gap:8px"><button class="btn-header" onclick="openPasswordModal()">🔑</button><a href="/logout" class="btn-header">Abmelden</a></div>
</div>
@@ -1805,6 +1871,7 @@ def get_dashboard_html() -> str:
document.addEventListener('click',e=>{const dd=document.querySelector('.update-dropdown');if(dd&&!dd.contains(e.target)){document.getElementById('updateDropdownMenu').style.display='none';}});
async function updateDashboard(){document.getElementById('updateDropdownMenu').style.display='none';if(!confirm('Dashboard aktualisieren? Das Dashboard wird nach dem Update neu gestartet.'))return;toast('Dashboard wird aktualisiert...','info');try{const r=await fetch('/api/update-dashboard',{method:'POST'});const d=await r.json();if(d.success){toast(d.message,'success');setTimeout(()=>location.reload(),3000);}else{toast(d.error,'error');}}catch(e){toast('Update fehlgeschlagen: '+e,'error');}}
async function updateAgents(){document.getElementById('updateDropdownMenu').style.display='none';const cnt=Object.values(agents).filter(a=>a.status==='online').length;if(cnt===0){toast('Keine Agents online','warning');return;}if(!confirm(cnt+' Agent(s) aktualisieren? Die Agents werden nach dem Update neu gestartet.'))return;toast('Agents werden aktualisiert...','info');try{const r=await fetch('/api/update-agents',{method:'POST'});const d=await r.json();if(d.success){toast(d.message,'success');}else{toast(d.error,'error');}}catch(e){toast('Update fehlgeschlagen: '+e,'error');}}
async function resetStats(){if(!confirm('Alle Statistiken zurücksetzen?\\n\\nDas löscht:\\n- Alle Shop-Statistiken\\n- Alle History-Graphen\\n- Alle Top-Listen\\n\\nDie Bans und Whitelists bleiben erhalten.'))return;toast('Statistiken werden zurückgesetzt...','info');try{const r=await fetch('/api/reset-stats',{method:'POST'});const d=await r.json();if(d.success){toast(d.message,'success');}else{toast(d.error||'Fehler','error');}}catch(e){toast('Reset fehlgeschlagen: '+e,'error');}}
// Server Detail Modal Functions
function openServerDetailModal(agentId){currentDetailServer=agentId;const a=agents[agentId];if(!a)return;renderServerDetail();document.getElementById('serverDetailModal').classList.add('open');startServerHistoryUpdate();}
function getServerShops(agentId){return Object.values(shops).filter(s=>s.agent_id===agentId);}