activation time fix
This commit is contained in:
@@ -1686,7 +1686,7 @@ def get_dashboard_html() -> str:
|
||||
function sortAgents(col){const st=sortState.agents;if(st.col===col){st.asc=!st.asc;}else{st.col=col;st.asc=false;}renderAgents();updateSortIcons('agentsTable',col,st.asc);}
|
||||
function sortShops(type,col){const st=sortState[type];if(st.col===col){st.asc=!st.asc;}else{st.col=col;st.asc=false;}renderShops();const tableId=type==='link11'?'tableLink11':'tableDirect';updateSortIcons(tableId,col,st.asc);}
|
||||
function getSortedAgents(){const list=Object.values(agents);const st=sortState.agents;if(!st.col)return list;const dir=st.asc?1:-1;return list.sort((a,b)=>{let va,vb;switch(st.col){case'status':const order={online:3,pending:2,offline:1};va=order[a.status]||0;vb=order[b.status]||0;break;case'hostname':va=(a.hostname||'').toLowerCase();vb=(b.hostname||'').toLowerCase();return dir*(va<vb?-1:va>vb?1:0);case'shops':va=(a.shops_active||0);vb=(b.shops_active||0);break;case'human_rpm':const rpmA=getAgentRpm(a.id);va=rpmA.humanRpm;const rpmB_h=getAgentRpm(b.id);vb=rpmB_h.humanRpm;break;case'bot_rpm':const rpmA_b=getAgentRpm(a.id);va=rpmA_b.botRpm;const rpmB_b=getAgentRpm(b.id);vb=rpmB_b.botRpm;break;case'load':va=(a.load_1m||0);vb=(b.load_1m||0);break;case'memory':va=(a.memory_percent||0);vb=(b.memory_percent||0);break;case'last_seen':va=a.last_seen||'';vb=b.last_seen||'';return dir*(va<vb?-1:va>vb?1:0);default:return 0;}return dir*(va-vb);});}
|
||||
function getSortedShops(list,type){const st=sortState[type];if(!st.col)return list;const dir=st.asc?1:-1;return list.sort((a,b)=>{let va,vb;switch(st.col){case'status':va=a.status==='active'?1:0;vb=b.status==='active'?1:0;break;case'domain':va=(a.domain||'').toLowerCase();vb=(b.domain||'').toLowerCase();return dir*(va<vb?-1:va>vb?1:0);case'server':va=(a.agent_hostname||'').toLowerCase();vb=(b.agent_hostname||'').toLowerCase();return dir*(va<vb?-1:va>vb?1:0);case'modus':va=(a.mode||'').toLowerCase();vb=(b.mode||'').toLowerCase();return dir*(va<vb?-1:va>vb?1:0);case'req':va=(a.stats?.req_per_min||0);vb=(b.stats?.req_per_min||0);break;case'bans':va=((a.stats?.active_bot_bans||0)+(a.stats?.active_country_bans||0));vb=((b.stats?.active_bot_bans||0)+(b.stats?.active_country_bans||0));break;case'runtime':va=(a.runtime_minutes||0);vb=(b.runtime_minutes||0);break;default:return 0;}return dir*(va-vb);});}
|
||||
function getSortedShops(list,type){const st=sortState[type];if(!st.col)return list;const dir=st.asc?1:-1;return list.sort((a,b)=>{let va,vb;switch(st.col){case'status':va=a.status==='active'?1:0;vb=b.status==='active'?1:0;break;case'domain':va=(a.domain||'').toLowerCase();vb=(b.domain||'').toLowerCase();return dir*(va<vb?-1:va>vb?1:0);case'server':va=(a.agent_hostname||'').toLowerCase();vb=(b.agent_hostname||'').toLowerCase();return dir*(va<vb?-1:va>vb?1:0);case'modus':va=(a.mode||'').toLowerCase();vb=(b.mode||'').toLowerCase();return dir*(va<vb?-1:va>vb?1:0);case'req':va=(a.stats?.req_per_min||0);vb=(b.stats?.req_per_min||0);break;case'bans':va=((a.stats?.active_bot_bans||0)+(a.stats?.active_country_bans||0));vb=((b.stats?.active_bot_bans||0)+(b.stats?.active_country_bans||0));break;case'runtime':va=a.activated?new Date(a.activated).getTime():0;vb=b.activated?new Date(b.activated).getTime():0;break;default:return 0;}return dir*(va-vb);});}
|
||||
function updateClock(){document.getElementById('clock').textContent=new Date().toLocaleTimeString('de-DE');}
|
||||
setInterval(updateClock,1000);updateClock();
|
||||
function connect(){const p=location.protocol==='https:'?'wss:':'ws:';ws=new WebSocket(p+'//'+location.host+'/ws/dashboard');ws.onopen=()=>{document.getElementById('wsStatus').classList.add('connected');document.getElementById('wsStatusText').textContent='Verbunden';};ws.onclose=()=>{document.getElementById('wsStatus').classList.remove('connected');document.getElementById('wsStatusText').textContent='Getrennt';setTimeout(connect,3000);};ws.onmessage=e=>handleMessage(JSON.parse(e.data));}
|
||||
@@ -1694,7 +1694,7 @@ def get_dashboard_html() -> str:
|
||||
function getAgentRpm(agentId){const agentShops=Object.values(shops).filter(s=>s.agent_id===agentId);let humanRpm=0,botRpm=0;agentShops.forEach(s=>{const st=s.stats||{};humanRpm+=(st.human_rpm||0);botRpm+=(st.bot_rpm||0);});return {humanRpm,botRpm};}
|
||||
function renderAgents(){const t=document.getElementById('agentsTable'),l=getSortedAgents();document.getElementById('agentCount').textContent=l.length+' Agents';document.getElementById('agentCountDropdown').textContent=l.length;t.innerHTML=l.map(a=>{const rpm=getAgentRpm(a.id);return '<tr><td><span class="status-badge status-'+(a.status||'offline')+'">'+(a.status==='online'?'🟢':a.status==='pending'?'🟡':'🔴')+' '+(a.status==='pending'?'Warte':a.status==='online'?'Online':'Offline')+'</span></td><td><span class="domain-link" onclick="openServerDetailModal(\\''+a.id+'\\')"><strong>'+a.hostname+'</strong></span></td><td>'+(a.shops_active||0)+'/'+(a.shops_total||0)+'</td><td class="success">'+rpm.humanRpm.toFixed(1)+'</td><td class="warning">'+rpm.botRpm.toFixed(1)+'</td><td>'+(a.load_1m!=null?a.load_1m.toFixed(2):'-')+'</td><td>'+(a.memory_percent!=null?a.memory_percent.toFixed(1)+'%':'-')+'</td><td>'+(a.last_seen?formatTime(a.last_seen):'-')+'</td><td>'+(a.status==='pending'?'<button class="btn btn-primary" onclick="approveAgent(\\''+a.id+'\\')">✓</button>':'')+'</td></tr>';}).join('');}
|
||||
function renderShops(){const all=Object.values(shops);let l11=all.filter(s=>s.link11),dir=all.filter(s=>!s.link11);l11=getSortedShops(l11,'link11');dir=getSortedShops(dir,'direct');document.getElementById('link11Count').textContent=l11.length+' Shops';document.getElementById('directCount').textContent=dir.length+' Shops';document.getElementById('shopsLink11Table').innerHTML=renderShopRows(l11);document.getElementById('shopsDirectTable').innerHTML=renderShopRows(dir);}
|
||||
function renderShopRows(l){return l.map(s=>{const modeStr=s.monitor_only?'🔍 Monitor':((s.bot_mode?'🤖':'')+(s.country_mode?' 🌍':''))||'-';const bansStr=s.monitor_only?'-':((s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0));return '<tr><td><span class="status-badge status-'+(s.status||'inactive')+'">'+(s.status==='active'?'✅':'⭕')+'</span></td><td><span class="domain-link" onclick="openDetailModal(\\''+s.domain+'\\')">'+s.domain+'</span></td><td>'+(s.agent_hostname||'-')+'</td><td>'+modeStr+'</td><td>'+((s.stats?.req_per_min||0).toFixed(1))+'</td><td>'+bansStr+'</td><td>'+formatRuntime(s.runtime_minutes)+'</td><td class="actions"><a href="https://'+s.domain+'" target="_blank" class="btn-icon">🔗</a>'+(s.status==='active'?'<button class="btn-icon" onclick="openLogs(\\''+s.domain+'\\')">📜</button><button class="btn btn-danger" onclick="deactivateShop(\\''+s.domain+'\\')">Stop</button>':'<button class="btn btn-primary" onclick="openActivateModal(\\''+s.domain+'\\')">Start</button>')+'</td></tr>';}).join('');}
|
||||
function renderShopRows(l){return l.map(s=>{const modeStr=s.monitor_only?'🔍 Monitor':((s.bot_mode?'🤖':'')+(s.country_mode?' 🌍':''))||'-';const bansStr=s.monitor_only?'-':((s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0));return '<tr><td><span class="status-badge status-'+(s.status||'inactive')+'">'+(s.status==='active'?'✅':'⭕')+'</span></td><td><span class="domain-link" onclick="openDetailModal(\\''+s.domain+'\\')">'+s.domain+'</span></td><td>'+(s.agent_hostname||'-')+'</td><td>'+modeStr+'</td><td>'+((s.stats?.req_per_min||0).toFixed(1))+'</td><td>'+bansStr+'</td><td>'+formatRuntime(s.activated)+'</td><td class="actions"><a href="https://'+s.domain+'" target="_blank" class="btn-icon">🔗</a>'+(s.status==='active'?'<button class="btn-icon" onclick="openLogs(\\''+s.domain+'\\')">📜</button><button class="btn btn-danger" onclick="deactivateShop(\\''+s.domain+'\\')">Stop</button>':'<button class="btn btn-primary" onclick="openActivateModal(\\''+s.domain+'\\')">Start</button>')+'</td></tr>';}).join('');}
|
||||
function renderTopShops(){const l=Object.values(shops).filter(s=>s.status==='active').sort((a,b)=>(b.stats?.req_per_min||0)-(a.stats?.req_per_min||0)).slice(0,10);document.getElementById('topShopsList').innerHTML=l.map(s=>{const bans=(s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0);return '<div class="top-shop-item" onclick="openDetailModal(\\''+s.domain+'\\')"><div class="top-shop-domain">'+s.domain+'</div><div class="top-shop-stats"><span class="top-shop-req">'+((s.stats?.req_per_min||0).toFixed(1))+' req/m</span><span class="top-shop-bans">'+bans+' bans</span></div></div>';}).join('')||'<div style="color:var(--text-secondary)">Keine aktiven Shops</div>';}
|
||||
function updateStats(s){document.getElementById('statAgents').textContent=s.agents_online||0;document.getElementById('statShops').textContent=(s.shops_active||0)+'/'+(s.shops_total||0);document.getElementById('statLink11').textContent=s.shops_link11||0;document.getElementById('statDirect').textContent=s.shops_direct||0;document.getElementById('statBans').textContent=s.active_bans||0;document.getElementById('statHumanRpm').textContent=(s.human_rpm||0).toFixed(1);document.getElementById('statBotRpm').textContent=(s.bot_rpm||0).toFixed(1);}
|
||||
function refreshStats(){const l=Object.values(shops),a=l.filter(s=>s.status==='active');document.getElementById('statShops').textContent=a.length+'/'+l.length;document.getElementById('statLink11').textContent=l.filter(s=>s.link11).length;document.getElementById('statDirect').textContent=l.filter(s=>!s.link11).length;document.getElementById('statBans').textContent=l.reduce((sum,s)=>sum+(s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0),0);document.getElementById('statHumanRpm').textContent=a.reduce((sum,s)=>sum+(s.stats?.human_rpm||0),0).toFixed(1);document.getElementById('statBotRpm').textContent=a.reduce((sum,s)=>sum+(s.stats?.bot_rpm||0),0).toFixed(1);}
|
||||
@@ -1720,7 +1720,7 @@ def get_dashboard_html() -> str:
|
||||
function openAllShopsModal(){document.getElementById('allShopsModal').classList.add('open');sortAllShops('req_per_min');}
|
||||
function sortAllShops(by){currentSortBy=by;document.getElementById('sortByReq').className='btn'+(by==='req_per_min'?' btn-primary':' btn-secondary');document.getElementById('sortByBans').className='btn'+(by==='active_bans'?' btn-primary':' btn-secondary');if(ws&&ws.readyState===1)ws.send(JSON.stringify({type:'get_all_shops_sorted',data:{sort_by:by}}));}
|
||||
function renderAllShopsTable(l,by){document.getElementById('allShopsTable').innerHTML=l.map((s,i)=>{const bans=(s.active_bot_bans||0)+(s.active_country_bans||0);return '<tr onclick="openDetailModal(\\''+s.domain+'\\')" style="cursor:pointer"><td>'+(i+1)+'</td><td><strong>'+s.domain+'</strong></td><td>'+(s.agent_hostname||'-')+'</td><td><span class="status-badge status-'+(s.status||'inactive')+'">'+(s.status==='active'?'✅':'⭕')+'</span></td><td style="'+(by==='req_per_min'?'color:var(--accent);font-weight:600':'')+'">'+(s.req_per_min||0).toFixed(1)+'</td><td style="'+(by==='active_bans'?'color:var(--warning);font-weight:600':'')+'">'+bans+'</td><td>'+(s.link11?'🛡️':'⚡')+'</td></tr>';}).join('');}
|
||||
function openDetailModal(d){currentDetailShop=d;const s=shops[d];if(!s)return;document.getElementById('detailDomain').textContent=d;document.getElementById('detailDomainLink').href='https://'+d;document.getElementById('detailServer').textContent=s.agent_hostname||'-';document.getElementById('detailStatus').textContent=s.status==='active'?'✅ Aktiv':'⭕ Inaktiv';const modeStr=s.monitor_only?'🔍 Monitor':((s.bot_mode?'🤖 Bot':'')+(s.country_mode?' 🌍 Country':''))||'-';document.getElementById('detailMode').textContent=modeStr;const unlimitedStr=s.unlimited_countries&&s.unlimited_countries.length>0?s.unlimited_countries.map(c=>c.toUpperCase()).join(', '):(s.country_mode?'(keine)':'-');document.getElementById('detailRegion').textContent=unlimitedStr;const rlStr=s.monitor_only?'- (Monitor)':(s.bot_mode&&s.bot_rate_limit?'Bot:'+s.bot_rate_limit+'/min':'')+(s.country_mode&&s.country_rate_limit?(s.bot_mode?' | ':'')+'Country:'+s.country_rate_limit+'/min':'')||'-';document.getElementById('detailRateLimit').textContent=rlStr;const bdStr=s.monitor_only?'- (Monitor)':(s.bot_mode&&s.bot_ban_duration?'Bot:'+(s.bot_ban_duration>=60?Math.round(s.bot_ban_duration/60)+'m':s.bot_ban_duration+'s'):'')+(s.country_mode&&s.country_ban_duration?(s.bot_mode?' | ':'')+'Country:'+(s.country_ban_duration>=60?Math.round(s.country_ban_duration/60)+'m':s.country_ban_duration+'s'):'')||'-';document.getElementById('detailBanDuration').textContent=bdStr;document.getElementById('detailRuntime').textContent=formatRuntime(s.runtime_minutes);const st=s.stats||{};document.getElementById('detailHumanRpm').textContent=(st.human_rpm||0).toFixed(1);document.getElementById('detailBotRpm').textContent=(st.bot_rpm||0).toFixed(1);const activeBans=s.monitor_only?'-':((st.active_bot_bans||0)+(st.active_country_bans||0));document.getElementById('detailActiveBans').textContent=activeBans;const totalBans=s.monitor_only?'-':((st.bot_bans||0)+(st.country_bans||0));document.getElementById('detailTotalBans').textContent=totalBans;document.getElementById('detailTopBots').innerHTML=Object.entries(st.top_bots||{}).sort((a,b)=>b[1]-a[1]).map(([n,c])=>'<div class="bot-item"><span>'+n+'</span><span>'+c+'</span></div>').join('')||'<div style="color:var(--text-secondary);padding:8px">Keine Daten</div>';document.getElementById('detailTopCountries').innerHTML=Object.entries(st.top_countries||{}).sort((a,b)=>b[1]-a[1]).map(([n,c])=>'<div class="bot-item"><span>'+n.toUpperCase()+'</span><span>'+c+'</span></div>').join('')||'<div style="color:var(--text-secondary);padding:8px">Keine Daten</div>';const bannedList=(st.banned_bots||[]).concat(st.banned_countries||[]);document.getElementById('detailBannedBots').innerHTML=s.monitor_only?'<div style="color:var(--text-secondary);padding:8px">Monitor-Only (keine Bans)</div>':bannedList.map(n=>'<div class="bot-item"><span>🚫 '+n+'</span></div>').join('')||'<div style="color:var(--text-secondary);padding:8px">Keine Bans</div>';document.getElementById('detailBtnDeactivate').style.display=s.status==='active'?'inline-block':'none';document.getElementById('rateLimitFormArea').style.display='none';document.getElementById('detailRateLimitInput').value=s.bot_rate_limit||30;const bd=s.bot_ban_duration||300;document.getElementById('detailBanDurationInput').value=[60,300,600,1800,3600,86400].includes(bd)?bd:300;document.getElementById('chartLegend').innerHTML='';document.getElementById('countryChartLegend').innerHTML='';const cv=document.getElementById('requestChart');cv.getContext('2d').clearRect(0,0,cv.width,cv.height);const ccv=document.getElementById('countryChart');ccv.getContext('2d').clearRect(0,0,ccv.width,ccv.height);if(ws&&ws.readyState===1)ws.send(JSON.stringify({type:'get_shop_history',data:{domain:d}}));document.getElementById('detailModal').classList.add('open');}
|
||||
function openDetailModal(d){currentDetailShop=d;const s=shops[d];if(!s)return;document.getElementById('detailDomain').textContent=d;document.getElementById('detailDomainLink').href='https://'+d;document.getElementById('detailServer').textContent=s.agent_hostname||'-';document.getElementById('detailStatus').textContent=s.status==='active'?'✅ Aktiv':'⭕ Inaktiv';const modeStr=s.monitor_only?'🔍 Monitor':((s.bot_mode?'🤖 Bot':'')+(s.country_mode?' 🌍 Country':''))||'-';document.getElementById('detailMode').textContent=modeStr;const unlimitedStr=s.unlimited_countries&&s.unlimited_countries.length>0?s.unlimited_countries.map(c=>c.toUpperCase()).join(', '):(s.country_mode?'(keine)':'-');document.getElementById('detailRegion').textContent=unlimitedStr;const rlStr=s.monitor_only?'- (Monitor)':(s.bot_mode&&s.bot_rate_limit?'Bot:'+s.bot_rate_limit+'/min':'')+(s.country_mode&&s.country_rate_limit?(s.bot_mode?' | ':'')+'Country:'+s.country_rate_limit+'/min':'')||'-';document.getElementById('detailRateLimit').textContent=rlStr;const bdStr=s.monitor_only?'- (Monitor)':(s.bot_mode&&s.bot_ban_duration?'Bot:'+(s.bot_ban_duration>=60?Math.round(s.bot_ban_duration/60)+'m':s.bot_ban_duration+'s'):'')+(s.country_mode&&s.country_ban_duration?(s.bot_mode?' | ':'')+'Country:'+(s.country_ban_duration>=60?Math.round(s.country_ban_duration/60)+'m':s.country_ban_duration+'s'):'')||'-';document.getElementById('detailBanDuration').textContent=bdStr;document.getElementById('detailRuntime').textContent=formatRuntime(s.activated);const st=s.stats||{};document.getElementById('detailHumanRpm').textContent=(st.human_rpm||0).toFixed(1);document.getElementById('detailBotRpm').textContent=(st.bot_rpm||0).toFixed(1);const activeBans=s.monitor_only?'-':((st.active_bot_bans||0)+(st.active_country_bans||0));document.getElementById('detailActiveBans').textContent=activeBans;const totalBans=s.monitor_only?'-':((st.bot_bans||0)+(st.country_bans||0));document.getElementById('detailTotalBans').textContent=totalBans;document.getElementById('detailTopBots').innerHTML=Object.entries(st.top_bots||{}).sort((a,b)=>b[1]-a[1]).map(([n,c])=>'<div class="bot-item"><span>'+n+'</span><span>'+c+'</span></div>').join('')||'<div style="color:var(--text-secondary);padding:8px">Keine Daten</div>';document.getElementById('detailTopCountries').innerHTML=Object.entries(st.top_countries||{}).sort((a,b)=>b[1]-a[1]).map(([n,c])=>'<div class="bot-item"><span>'+n.toUpperCase()+'</span><span>'+c+'</span></div>').join('')||'<div style="color:var(--text-secondary);padding:8px">Keine Daten</div>';const bannedList=(st.banned_bots||[]).concat(st.banned_countries||[]);document.getElementById('detailBannedBots').innerHTML=s.monitor_only?'<div style="color:var(--text-secondary);padding:8px">Monitor-Only (keine Bans)</div>':bannedList.map(n=>'<div class="bot-item"><span>🚫 '+n+'</span></div>').join('')||'<div style="color:var(--text-secondary);padding:8px">Keine Bans</div>';document.getElementById('detailBtnDeactivate').style.display=s.status==='active'?'inline-block':'none';document.getElementById('rateLimitFormArea').style.display='none';document.getElementById('detailRateLimitInput').value=s.bot_rate_limit||30;const bd=s.bot_ban_duration||300;document.getElementById('detailBanDurationInput').value=[60,300,600,1800,3600,86400].includes(bd)?bd:300;document.getElementById('chartLegend').innerHTML='';document.getElementById('countryChartLegend').innerHTML='';const cv=document.getElementById('requestChart');cv.getContext('2d').clearRect(0,0,cv.width,cv.height);const ccv=document.getElementById('countryChart');ccv.getContext('2d').clearRect(0,0,ccv.width,ccv.height);if(ws&&ws.readyState===1)ws.send(JSON.stringify({type:'get_shop_history',data:{domain:d}}));document.getElementById('detailModal').classList.add('open');}
|
||||
function updateBotChart(data){const cv=document.getElementById('requestChart'),ctx=cv.getContext('2d'),ct=cv.parentElement,w=ct.clientWidth-32,h=230;cv.width=w;cv.height=h;ctx.clearRect(0,0,w,h);const bh=data.bot_history||{},bn=Object.keys(bh).slice(0,10);if(bn.length===0){ctx.fillStyle='#a0a0b0';ctx.font='14px sans-serif';ctx.fillText('Noch keine Bot-Daten',w/2-60,h/2);return;}let ts=new Set();bn.forEach(b=>bh[b].forEach(p=>ts.add(p.timestamp)));ts=[...ts].sort();if(ts.length<2){ctx.fillStyle='#a0a0b0';ctx.font='14px sans-serif';ctx.fillText('Warte auf Daten...',w/2-50,h/2);return;}let mx=1;bn.forEach(b=>bh[b].forEach(p=>{if(p.count>mx)mx=p.count;}));const pd={t:20,r:20,b:40,l:50},cW=w-pd.l-pd.r,cH=h-pd.t-pd.b;ctx.strokeStyle='rgba(255,255,255,0.1)';ctx.lineWidth=1;for(let i=0;i<=4;i++){const y=pd.t+(cH/4)*i;ctx.beginPath();ctx.moveTo(pd.l,y);ctx.lineTo(w-pd.r,y);ctx.stroke();ctx.fillStyle='#a0a0b0';ctx.font='10px sans-serif';ctx.fillText(Math.round(mx-(mx/4)*i),5,y+4);}const step=Math.max(1,Math.floor(ts.length/6));ctx.fillStyle='#a0a0b0';ctx.font='10px sans-serif';for(let i=0;i<ts.length;i+=step){const t=ts[i].split(' ')[1]?.substring(0,5)||ts[i],x=pd.l+(cW/(ts.length-1))*i;ctx.fillText(t,x-15,h-10);}const lg=document.getElementById('chartLegend');lg.innerHTML='';bn.forEach((bot,idx)=>{const c=BOT_COLORS[idx%BOT_COLORS.length],pts=bh[bot];ctx.strokeStyle=c;ctx.lineWidth=2;ctx.beginPath();pts.forEach((p,i)=>{const ti=ts.indexOf(p.timestamp),x=pd.l+(cW/(ts.length-1))*ti,y=pd.t+cH-(p.count/mx)*cH;i===0?ctx.moveTo(x,y):ctx.lineTo(x,y);});ctx.stroke();lg.innerHTML+='<div class="legend-item"><div class="legend-color" style="background:'+c+'"></div><span>'+bot+'</span></div>';});}
|
||||
function updateCountryChart(data){const cv=document.getElementById('countryChart'),ctx=cv.getContext('2d'),ct=cv.parentElement,w=ct.clientWidth-32,h=230;cv.width=w;cv.height=h;ctx.clearRect(0,0,w,h);const ch=data.country_history||{},cn=Object.keys(ch).slice(0,10);if(cn.length===0){ctx.fillStyle='#a0a0b0';ctx.font='14px sans-serif';ctx.fillText('Noch keine Country-Daten',w/2-70,h/2);return;}let ts=new Set();cn.forEach(c=>ch[c].forEach(p=>ts.add(p.timestamp)));ts=[...ts].sort();if(ts.length<2){ctx.fillStyle='#a0a0b0';ctx.font='14px sans-serif';ctx.fillText('Warte auf Daten...',w/2-50,h/2);return;}let mx=1;cn.forEach(c=>ch[c].forEach(p=>{if(p.count>mx)mx=p.count;}));const pd={t:20,r:20,b:40,l:50},cW=w-pd.l-pd.r,cH=h-pd.t-pd.b;ctx.strokeStyle='rgba(255,255,255,0.1)';ctx.lineWidth=1;for(let i=0;i<=4;i++){const y=pd.t+(cH/4)*i;ctx.beginPath();ctx.moveTo(pd.l,y);ctx.lineTo(w-pd.r,y);ctx.stroke();ctx.fillStyle='#a0a0b0';ctx.font='10px sans-serif';ctx.fillText(Math.round(mx-(mx/4)*i),5,y+4);}const step=Math.max(1,Math.floor(ts.length/6));ctx.fillStyle='#a0a0b0';ctx.font='10px sans-serif';for(let i=0;i<ts.length;i+=step){const t=ts[i].split(' ')[1]?.substring(0,5)||ts[i],x=pd.l+(cW/(ts.length-1))*i;ctx.fillText(t,x-15,h-10);}const lg=document.getElementById('countryChartLegend');lg.innerHTML='';cn.forEach((country,idx)=>{const clr=BOT_COLORS[idx%BOT_COLORS.length],pts=ch[country];ctx.strokeStyle=clr;ctx.lineWidth=2;ctx.beginPath();pts.forEach((p,i)=>{const ti=ts.indexOf(p.timestamp),x=pd.l+(cW/(ts.length-1))*ti,y=pd.t+cH-(p.count/mx)*cH;i===0?ctx.moveTo(x,y):ctx.lineTo(x,y);});ctx.stroke();lg.innerHTML+='<div class="legend-item"><div class="legend-color" style="background:'+clr+'"></div><span>'+country.toUpperCase()+'</span></div>';});}
|
||||
let currentStatsWindow='5m',liveStatsInterval=null;
|
||||
@@ -1736,7 +1736,7 @@ def get_dashboard_html() -> str:
|
||||
function quickWhitelist(ip){if(!currentLogsShop)return;const desc=prompt('Beschreibung (optional):','');if(desc===null)return;ws.send(JSON.stringify({type:'command.whitelist',data:{shop:currentLogsShop,ip:ip,description:desc}}));toast('IP '+ip+' wird gewhitelisted...','success');}
|
||||
function addLogEntry(line){const c=document.getElementById('logsContent');if(c.querySelector('div[style*="color:#666"]'))c.innerHTML='';const e=document.createElement('div');e.className='log-entry'+(line.includes('BANNED')?' banned':'');e.textContent=line;c.insertBefore(e,c.firstChild);while(c.children.length>100)c.removeChild(c.lastChild);}
|
||||
function formatTime(iso){return new Date(iso).toLocaleTimeString('de-DE');}
|
||||
function formatRuntime(m){if(!m||m<=0)return'-';if(m<60)return Math.round(m)+'m';const h=m/60;if(h<24)return Math.round(h)+'h';return Math.round(h/24)+'d';}
|
||||
function formatRuntime(activated){if(!activated)return'-';const start=new Date(activated);const now=new Date();const m=(now-start)/60000;if(m<=0)return'-';if(m<60)return Math.round(m)+'m';const h=m/60;if(h<24)return Math.round(h)+'h';return Math.round(h/24)+'d';}
|
||||
function toast(msg,type='info'){const c=document.getElementById('toastContainer'),t=document.createElement('div');t.className='toast '+type;t.innerHTML='<span>'+msg+'</span>';c.appendChild(t);setTimeout(()=>t.remove(),4000);addNotification(msg,type);}
|
||||
function addNotification(msg,type='info'){const icons={success:'✅',error:'❌',warning:'⚠️',info:'ℹ️'};const n={id:Date.now(),message:msg,type:type,icon:icons[type]||'ℹ️',time:new Date()};notifications.unshift(n);if(notifications.length>maxNotifications)notifications.pop();unreadCount++;updateNotificationBadge();renderNotifications();}
|
||||
function updateNotificationBadge(){const badge=document.getElementById('notificationBadge');if(unreadCount>0){badge.textContent=unreadCount>99?'99+':unreadCount;badge.style.display='flex';}else{badge.style.display='none';}}
|
||||
|
||||
Reference in New Issue
Block a user