länder vollständig
This commit is contained in:
@@ -1682,6 +1682,8 @@ def get_dashboard_html() -> str:
|
|||||||
let notifications=[],maxNotifications=50,unreadCount=0;
|
let notifications=[],maxNotifications=50,unreadCount=0;
|
||||||
let serverBotChart=null,serverCountryChart=null,serverBotHistory={},serverCountryHistory={};
|
let serverBotChart=null,serverCountryChart=null,serverBotHistory={},serverCountryHistory={};
|
||||||
const BOT_COLORS=['#4a9eff','#00d26a','#ff4757','#ffc107','#9b59b6','#1abc9c','#e74c3c','#3498db','#f39c12','#2ecc71'];
|
const BOT_COLORS=['#4a9eff','#00d26a','#ff4757','#ffc107','#9b59b6','#1abc9c','#e74c3c','#3498db','#f39c12','#2ecc71'];
|
||||||
|
const COUNTRY_NAMES={AF:'Afghanistan',AL:'Albanien',DZ:'Algerien',AD:'Andorra',AO:'Angola',AG:'Antigua und Barbuda',AR:'Argentinien',AM:'Armenien',AU:'Australien',AT:'Österreich',AZ:'Aserbaidschan',BS:'Bahamas',BH:'Bahrain',BD:'Bangladesch',BB:'Barbados',BY:'Belarus',BE:'Belgien',BZ:'Belize',BJ:'Benin',BT:'Bhutan',BO:'Bolivien',BA:'Bosnien und Herzegowina',BW:'Botswana',BR:'Brasilien',BN:'Brunei',BG:'Bulgarien',BF:'Burkina Faso',BI:'Burundi',KH:'Kambodscha',CM:'Kamerun',CA:'Kanada',CV:'Kap Verde',CF:'Zentralafrikanische Republik',TD:'Tschad',CL:'Chile',CN:'China',CO:'Kolumbien',KM:'Komoren',CG:'Kongo',CD:'DR Kongo',CR:'Costa Rica',CI:'Elfenbeinküste',HR:'Kroatien',CU:'Kuba',CY:'Zypern',CZ:'Tschechien',DK:'Dänemark',DJ:'Dschibuti',DM:'Dominica',DO:'Dominikanische Republik',EC:'Ecuador',EG:'Ägypten',SV:'El Salvador',GQ:'Äquatorialguinea',ER:'Eritrea',EE:'Estland',SZ:'Eswatini',ET:'Äthiopien',FJ:'Fidschi',FI:'Finnland',FR:'Frankreich',GA:'Gabun',GM:'Gambia',GE:'Georgien',DE:'Deutschland',GH:'Ghana',GR:'Griechenland',GD:'Grenada',GT:'Guatemala',GN:'Guinea',GW:'Guinea-Bissau',GY:'Guyana',HT:'Haiti',HN:'Honduras',HU:'Ungarn',IS:'Island',IN:'Indien',ID:'Indonesien',IR:'Iran',IQ:'Irak',IE:'Irland',IL:'Israel',IT:'Italien',JM:'Jamaika',JP:'Japan',JO:'Jordanien',KZ:'Kasachstan',KE:'Kenia',KI:'Kiribati',KP:'Nordkorea',KR:'Südkorea',KW:'Kuwait',KG:'Kirgisistan',LA:'Laos',LV:'Lettland',LB:'Libanon',LS:'Lesotho',LR:'Liberia',LY:'Libyen',LI:'Liechtenstein',LT:'Litauen',LU:'Luxemburg',MG:'Madagaskar',MW:'Malawi',MY:'Malaysia',MV:'Malediven',ML:'Mali',MT:'Malta',MH:'Marshallinseln',MR:'Mauretanien',MU:'Mauritius',MX:'Mexiko',FM:'Mikronesien',MD:'Moldawien',MC:'Monaco',MN:'Mongolei',ME:'Montenegro',MA:'Marokko',MZ:'Mosambik',MM:'Myanmar',NA:'Namibia',NR:'Nauru',NP:'Nepal',NL:'Niederlande',NZ:'Neuseeland',NI:'Nicaragua',NE:'Niger',NG:'Nigeria',MK:'Nordmazedonien',NO:'Norwegen',OM:'Oman',PK:'Pakistan',PW:'Palau',PA:'Panama',PG:'Papua-Neuguinea',PY:'Paraguay',PE:'Peru',PH:'Philippinen',PL:'Polen',PT:'Portugal',QA:'Katar',RO:'Rumänien',RU:'Russland',RW:'Ruanda',KN:'St. Kitts und Nevis',LC:'St. Lucia',VC:'St. Vincent',WS:'Samoa',SM:'San Marino',ST:'São Tomé und Príncipe',SA:'Saudi-Arabien',SN:'Senegal',RS:'Serbien',SC:'Seychellen',SL:'Sierra Leone',SG:'Singapur',SK:'Slowakei',SI:'Slowenien',SB:'Salomonen',SO:'Somalia',ZA:'Südafrika',SS:'Südsudan',ES:'Spanien',LK:'Sri Lanka',SD:'Sudan',SR:'Suriname',SE:'Schweden',CH:'Schweiz',SY:'Syrien',TW:'Taiwan',TJ:'Tadschikistan',TZ:'Tansania',TH:'Thailand',TL:'Osttimor',TG:'Togo',TO:'Tonga',TT:'Trinidad und Tobago',TN:'Tunesien',TR:'Türkei',TM:'Turkmenistan',TV:'Tuvalu',UG:'Uganda',UA:'Ukraine',AE:'Vereinigte Arabische Emirate',GB:'Großbritannien',US:'USA',UY:'Uruguay',UZ:'Usbekistan',VU:'Vanuatu',VA:'Vatikanstadt',VE:'Venezuela',VN:'Vietnam',YE:'Jemen',ZM:'Sambia',ZW:'Simbabwe',HK:'Hongkong',MO:'Macau',PS:'Palästina',XK:'Kosovo',PR:'Puerto Rico',GU:'Guam',VI:'Amerikanische Jungferninseln',AS:'Amerikanisch-Samoa',MP:'Nördliche Marianen',RE:'Réunion',GP:'Guadeloupe',MQ:'Martinique',GF:'Französisch-Guayana',YT:'Mayotte',NC:'Neukaledonien',PF:'Französisch-Polynesien',AW:'Aruba',CW:'Curaçao',SX:'Sint Maarten',BQ:'Karibische Niederlande',FO:'Färöer',GL:'Grönland',GI:'Gibraltar',IM:'Isle of Man',JE:'Jersey',GG:'Guernsey',AX:'Åland',BM:'Bermuda',KY:'Kaimaninseln',VG:'Britische Jungferninseln',TC:'Turks- und Caicosinseln',MS:'Montserrat',AI:'Anguilla',SH:'St. Helena',FK:'Falklandinseln',PN:'Pitcairninseln',IO:'Brit. Territorium im Ind. Ozean',GS:'Südgeorgien'};
|
||||||
|
function getCountryName(code){const c=(code||'').toUpperCase();return COUNTRY_NAMES[c]||c;}
|
||||||
function setUpdateInterval(ms){updateInterval=parseInt(ms);if(renderTimer)clearInterval(renderTimer);renderTimer=setInterval(()=>{if(pendingRender){renderAgents();renderShops();renderTopShops();refreshStats();pendingRender=false;}},updateInterval);}
|
function setUpdateInterval(ms){updateInterval=parseInt(ms);if(renderTimer)clearInterval(renderTimer);renderTimer=setInterval(()=>{if(pendingRender){renderAgents();renderShops();renderTopShops();refreshStats();pendingRender=false;}},updateInterval);}
|
||||||
function scheduleRender(){pendingRender=true;}
|
function scheduleRender(){pendingRender=true;}
|
||||||
// Sort state für jede Tabelle
|
// Sort state für jede Tabelle
|
||||||
@@ -1725,17 +1727,17 @@ def get_dashboard_html() -> str:
|
|||||||
function openAllShopsModal(){document.getElementById('allShopsModal').classList.add('open');sortAllShops('req_per_min');}
|
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 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 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.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 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=>getCountryName(c)).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>'+getCountryName(n)+'</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 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>';});}
|
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>'+getCountryName(country)+'</span></div>';});}
|
||||||
let currentStatsWindow='5m',liveStatsInterval=null;
|
let currentStatsWindow='5m',liveStatsInterval=null;
|
||||||
function openLogs(d){currentLogsShop=d;document.getElementById('logsShop').textContent=d;document.getElementById('logsContent').innerHTML='<div style="color:#666">Warte auf Logs...</div>';document.getElementById('topIpsList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('suspiciousIpsList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('topRequestsList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('topBlockedList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('logsPanel').classList.add('open');if(ws&&ws.readyState===1){ws.send(JSON.stringify({type:'log.subscribe',data:{shop:d}}));requestLiveStats();}if(liveStatsInterval)clearInterval(liveStatsInterval);liveStatsInterval=setInterval(requestLiveStats,5000);}
|
function openLogs(d){currentLogsShop=d;document.getElementById('logsShop').textContent=d;document.getElementById('logsContent').innerHTML='<div style="color:#666">Warte auf Logs...</div>';document.getElementById('topIpsList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('suspiciousIpsList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('topRequestsList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('topBlockedList').innerHTML='<div style="color:#666;padding:8px">Lade...</div>';document.getElementById('logsPanel').classList.add('open');if(ws&&ws.readyState===1){ws.send(JSON.stringify({type:'log.subscribe',data:{shop:d}}));requestLiveStats();}if(liveStatsInterval)clearInterval(liveStatsInterval);liveStatsInterval=setInterval(requestLiveStats,5000);}
|
||||||
function closeLogs(){if(currentLogsShop&&ws&&ws.readyState===1)ws.send(JSON.stringify({type:'log.unsubscribe',data:{shop:currentLogsShop}}));currentLogsShop=null;document.getElementById('logsPanel').classList.remove('open');if(liveStatsInterval){clearInterval(liveStatsInterval);liveStatsInterval=null;}}
|
function closeLogs(){if(currentLogsShop&&ws&&ws.readyState===1)ws.send(JSON.stringify({type:'log.unsubscribe',data:{shop:currentLogsShop}}));currentLogsShop=null;document.getElementById('logsPanel').classList.remove('open');if(liveStatsInterval){clearInterval(liveStatsInterval);liveStatsInterval=null;}}
|
||||||
function changeStatsWindow(w){currentStatsWindow=w;requestLiveStats();}
|
function changeStatsWindow(w){currentStatsWindow=w;requestLiveStats();}
|
||||||
function requestLiveStats(){if(!currentLogsShop||!ws||ws.readyState!==1)return;ws.send(JSON.stringify({type:'command.livestats',data:{shop:currentLogsShop,window:currentStatsWindow}}));}
|
function requestLiveStats(){if(!currentLogsShop||!ws||ws.readyState!==1)return;ws.send(JSON.stringify({type:'command.livestats',data:{shop:currentLogsShop,window:currentStatsWindow}}));}
|
||||||
function renderLiveStats(data){if(!data.success||!data.stats)return;const st=data.stats;document.getElementById('topIpsList').innerHTML=renderTopIps(st.top_ips||[]);document.getElementById('suspiciousIpsList').innerHTML=renderSuspiciousIps(st.suspicious_ips||[]);document.getElementById('topRequestsList').innerHTML=renderRequests(st.top_requests||[]);document.getElementById('topBlockedList').innerHTML=renderRequests(st.top_blocked||[],'blocked');}
|
function renderLiveStats(data){if(!data.success||!data.stats)return;const st=data.stats;document.getElementById('topIpsList').innerHTML=renderTopIps(st.top_ips||[]);document.getElementById('suspiciousIpsList').innerHTML=renderSuspiciousIps(st.suspicious_ips||[]);document.getElementById('topRequestsList').innerHTML=renderRequests(st.top_requests||[]);document.getElementById('topBlockedList').innerHTML=renderRequests(st.top_blocked||[],'blocked');}
|
||||||
function renderTopIps(ips){if(!ips.length)return '<div style="color:#666;padding:8px">Keine Daten</div>';return ips.slice(0,10).map(ip=>'<div class="ip-item"><div class="ip-info"><span class="ip-addr">'+ip.ip+'</span><span class="ip-meta">'+ip.country+' | '+(ip.org||ip.asn||'-')+'</span></div><span class="ip-count">'+ip.count+'x</span><div class="ip-actions"><button class="btn-ban" onclick="quickBan(\\''+ip.ip+'\\')">🚫</button><button class="btn-whitelist" onclick="quickWhitelist(\\''+ip.ip+'\\')">✓</button></div></div>').join('');}
|
function renderTopIps(ips){if(!ips.length)return '<div style="color:#666;padding:8px">Keine Daten</div>';return ips.slice(0,10).map(ip=>'<div class="ip-item"><div class="ip-info"><span class="ip-addr">'+ip.ip+'</span><span class="ip-meta">'+getCountryName(ip.country)+' | '+(ip.org||ip.asn||'-')+'</span></div><span class="ip-count">'+ip.count+'x</span><div class="ip-actions"><button class="btn-ban" onclick="quickBan(\\''+ip.ip+'\\')">🚫</button><button class="btn-whitelist" onclick="quickWhitelist(\\''+ip.ip+'\\')">✓</button></div></div>').join('');}
|
||||||
function renderSuspiciousIps(ips){if(!ips.length)return '<div style="color:#666;padding:8px">Keine verdächtigen IPs</div>';return ips.slice(0,5).map(ip=>'<div class="ip-item suspicious-item"><div class="ip-info"><span class="ip-addr">'+ip.ip+'</span><span class="ip-meta">'+ip.country+' | '+ip.reason+(ip.errors?' | '+ip.errors+' Errors':'')+'</span></div><span class="ip-count">'+ip.count+'x</span><div class="ip-actions"><button class="btn-ban" onclick="quickBan(\\''+ip.ip+'\\')">🚫</button></div></div>').join('');}
|
function renderSuspiciousIps(ips){if(!ips.length)return '<div style="color:#666;padding:8px">Keine verdächtigen IPs</div>';return ips.slice(0,5).map(ip=>'<div class="ip-item suspicious-item"><div class="ip-info"><span class="ip-addr">'+ip.ip+'</span><span class="ip-meta">'+getCountryName(ip.country)+' | '+ip.reason+(ip.errors?' | '+ip.errors+' Errors':'')+'</span></div><span class="ip-count">'+ip.count+'x</span><div class="ip-actions"><button class="btn-ban" onclick="quickBan(\\''+ip.ip+'\\')">🚫</button></div></div>').join('');}
|
||||||
function renderRequests(reqs,type){if(!reqs.length)return '<div style="color:#666;padding:8px">Keine Daten</div>';return reqs.slice(0,10).map(r=>'<div class="request-item'+(type==='blocked'?' blocked':'')+'"><span class="request-path" title="'+r.path+'">'+r.path+'</span><span class="request-count">'+r.count+'x</span></div>').join('');}
|
function renderRequests(reqs,type){if(!reqs.length)return '<div style="color:#666;padding:8px">Keine Daten</div>';return reqs.slice(0,10).map(r=>'<div class="request-item'+(type==='blocked'?' blocked':'')+'"><span class="request-path" title="'+r.path+'">'+r.path+'</span><span class="request-count">'+r.count+'x</span></div>').join('');}
|
||||||
function quickBan(ip){if(!currentLogsShop)return;const duration=prompt('Ban-Dauer auswählen:\\n\\n900 = 15 Minuten\\n3600 = 1 Stunde\\n21600 = 6 Stunden\\n86400 = 24 Stunden\\n604800 = 7 Tage\\n-1 = Permanent','3600');if(duration===null)return;ws.send(JSON.stringify({type:'command.ban',data:{shop:currentLogsShop,ip:ip,duration:parseInt(duration),reason:'Manual ban from dashboard'}}));toast('IP '+ip+' wird gebannt...','success');}
|
function quickBan(ip){if(!currentLogsShop)return;const duration=prompt('Ban-Dauer auswählen:\\n\\n900 = 15 Minuten\\n3600 = 1 Stunde\\n21600 = 6 Stunden\\n86400 = 24 Stunden\\n604800 = 7 Tage\\n-1 = Permanent','3600');if(duration===null)return;ws.send(JSON.stringify({type:'command.ban',data:{shop:currentLogsShop,ip:ip,duration:parseInt(duration),reason:'Manual ban from dashboard'}}));toast('IP '+ip+' wird gebannt...','success');}
|
||||||
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 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');}
|
||||||
@@ -1762,10 +1764,10 @@ def get_dashboard_html() -> str:
|
|||||||
function openServerDetailModal(agentId){currentDetailServer=agentId;const a=agents[agentId];if(!a)return;renderServerDetail();document.getElementById('serverDetailModal').classList.add('open');startServerHistoryUpdate();}
|
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);}
|
function getServerShops(agentId){return Object.values(shops).filter(s=>s.agent_id===agentId);}
|
||||||
function aggregateServerStats(serverShops){const stats={total:serverShops.length,active:0,botMode:0,countryMode:0,monitorMode:0,humanRpm:0,botRpm:0,activeBans:0,totalBans:0,link11:0,direct:0,topBots:{},topCountries:{},bannedItems:[]};serverShops.forEach(s=>{if(s.status==='active')stats.active++;if(s.bot_mode&&!s.monitor_only)stats.botMode++;if(s.country_mode&&!s.monitor_only)stats.countryMode++;if(s.monitor_only)stats.monitorMode++;if(s.link11)stats.link11++;else stats.direct++;const st=s.stats||{};stats.humanRpm+=(st.human_rpm||0);stats.botRpm+=(st.bot_rpm||0);stats.activeBans+=(st.active_bot_bans||0)+(st.active_country_bans||0);stats.totalBans+=(st.bot_bans||0)+(st.country_bans||0);Object.entries(st.top_bots||{}).forEach(([bot,cnt])=>{stats.topBots[bot]=(stats.topBots[bot]||0)+cnt;});Object.entries(st.top_countries||{}).forEach(([country,cnt])=>{stats.topCountries[country]=(stats.topCountries[country]||0)+cnt;});(st.banned_bots||[]).forEach(b=>{if(!stats.bannedItems.includes(b))stats.bannedItems.push(b);});(st.banned_countries||[]).forEach(c=>{if(!stats.bannedItems.includes(c))stats.bannedItems.push(c);});});return stats;}
|
function aggregateServerStats(serverShops){const stats={total:serverShops.length,active:0,botMode:0,countryMode:0,monitorMode:0,humanRpm:0,botRpm:0,activeBans:0,totalBans:0,link11:0,direct:0,topBots:{},topCountries:{},bannedItems:[]};serverShops.forEach(s=>{if(s.status==='active')stats.active++;if(s.bot_mode&&!s.monitor_only)stats.botMode++;if(s.country_mode&&!s.monitor_only)stats.countryMode++;if(s.monitor_only)stats.monitorMode++;if(s.link11)stats.link11++;else stats.direct++;const st=s.stats||{};stats.humanRpm+=(st.human_rpm||0);stats.botRpm+=(st.bot_rpm||0);stats.activeBans+=(st.active_bot_bans||0)+(st.active_country_bans||0);stats.totalBans+=(st.bot_bans||0)+(st.country_bans||0);Object.entries(st.top_bots||{}).forEach(([bot,cnt])=>{stats.topBots[bot]=(stats.topBots[bot]||0)+cnt;});Object.entries(st.top_countries||{}).forEach(([country,cnt])=>{stats.topCountries[country]=(stats.topCountries[country]||0)+cnt;});(st.banned_bots||[]).forEach(b=>{if(!stats.bannedItems.includes(b))stats.bannedItems.push(b);});(st.banned_countries||[]).forEach(c=>{if(!stats.bannedItems.includes(c))stats.bannedItems.push(c);});});return stats;}
|
||||||
function renderServerDetail(){if(!currentDetailServer)return;const a=agents[currentDetailServer];if(!a)return;const serverShops=getServerShops(currentDetailServer);const stats=aggregateServerStats(serverShops);document.getElementById('serverDetailHostname').textContent=a.hostname;document.getElementById('serverDetailStatus').innerHTML=a.status==='online'?'<span style="color:var(--success)">🟢 Online</span>':'<span style="color:var(--danger)">🔴 Offline</span>';document.getElementById('serverDetailLoad').textContent=a.load_1m!=null?a.load_1m.toFixed(2):'-';document.getElementById('serverDetailMemory').textContent=a.memory_percent!=null?a.memory_percent.toFixed(1)+'%':'-';document.getElementById('serverDetailShops').textContent=stats.active+'/'+stats.total;document.getElementById('serverDetailBotMode').textContent=stats.botMode;document.getElementById('serverDetailCountryMode').textContent=stats.countryMode;document.getElementById('serverDetailMonitor').textContent=stats.monitorMode;document.getElementById('serverDetailHumanRpm').textContent=stats.humanRpm.toFixed(1);document.getElementById('serverDetailBotRpm').textContent=stats.botRpm.toFixed(1);document.getElementById('serverDetailActiveBans').textContent=stats.activeBans;document.getElementById('serverDetailTotalBans').textContent=stats.totalBans;document.getElementById('serverDetailLink11').textContent=stats.link11;document.getElementById('serverDetailDirect').textContent=stats.direct;document.getElementById('serverDetailTopBots').innerHTML=Object.entries(stats.topBots).sort((a,b)=>b[1]-a[1]).slice(0,15).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('serverDetailTopCountries').innerHTML=Object.entries(stats.topCountries).sort((a,b)=>b[1]-a[1]).slice(0,15).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>';document.getElementById('serverDetailBannedBots').innerHTML=stats.bannedItems.length>0?stats.bannedItems.map(n=>'<div class="bot-item"><span>🚫 '+n+'</span></div>').join(''):'<div style="color:var(--text-secondary);padding:8px">Keine aktiven Bans</div>';document.getElementById('serverShopsTable').innerHTML=serverShops.sort((a,b)=>(b.stats?.req_per_min||0)-(a.stats?.req_per_min||0)).map(s=>{const modeStr=s.monitor_only?'🔍':((s.bot_mode?'🤖':'')+(s.country_mode?'🌍':''))||'-';const bans=(s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0);return '<tr style="cursor:pointer" onclick="closeModal(\\'serverDetailModal\\');openDetailModal(\\''+s.domain+'\\')"><td><span class="status-badge status-'+(s.status||'inactive')+'">'+(s.status==='active'?'✅':'⭕')+'</span></td><td>'+s.domain+'</td><td>'+modeStr+'</td><td>'+(s.stats?.req_per_min||0).toFixed(1)+'</td><td>'+bans+'</td></tr>';}).join('')||'<tr><td colspan="5" style="color:var(--text-secondary);text-align:center;padding:16px">Keine Shops</td></tr>';updateServerCharts(serverShops);}
|
function renderServerDetail(){if(!currentDetailServer)return;const a=agents[currentDetailServer];if(!a)return;const serverShops=getServerShops(currentDetailServer);const stats=aggregateServerStats(serverShops);document.getElementById('serverDetailHostname').textContent=a.hostname;document.getElementById('serverDetailStatus').innerHTML=a.status==='online'?'<span style="color:var(--success)">🟢 Online</span>':'<span style="color:var(--danger)">🔴 Offline</span>';document.getElementById('serverDetailLoad').textContent=a.load_1m!=null?a.load_1m.toFixed(2):'-';document.getElementById('serverDetailMemory').textContent=a.memory_percent!=null?a.memory_percent.toFixed(1)+'%':'-';document.getElementById('serverDetailShops').textContent=stats.active+'/'+stats.total;document.getElementById('serverDetailBotMode').textContent=stats.botMode;document.getElementById('serverDetailCountryMode').textContent=stats.countryMode;document.getElementById('serverDetailMonitor').textContent=stats.monitorMode;document.getElementById('serverDetailHumanRpm').textContent=stats.humanRpm.toFixed(1);document.getElementById('serverDetailBotRpm').textContent=stats.botRpm.toFixed(1);document.getElementById('serverDetailActiveBans').textContent=stats.activeBans;document.getElementById('serverDetailTotalBans').textContent=stats.totalBans;document.getElementById('serverDetailLink11').textContent=stats.link11;document.getElementById('serverDetailDirect').textContent=stats.direct;document.getElementById('serverDetailTopBots').innerHTML=Object.entries(stats.topBots).sort((a,b)=>b[1]-a[1]).slice(0,15).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('serverDetailTopCountries').innerHTML=Object.entries(stats.topCountries).sort((a,b)=>b[1]-a[1]).slice(0,15).map(([n,c])=>'<div class="bot-item"><span>'+getCountryName(n)+'</span><span>'+c+'</span></div>').join('')||'<div style="color:var(--text-secondary);padding:8px">Keine Daten</div>';document.getElementById('serverDetailBannedBots').innerHTML=stats.bannedItems.length>0?stats.bannedItems.map(n=>'<div class="bot-item"><span>🚫 '+n+'</span></div>').join(''):'<div style="color:var(--text-secondary);padding:8px">Keine aktiven Bans</div>';document.getElementById('serverShopsTable').innerHTML=serverShops.sort((a,b)=>(b.stats?.req_per_min||0)-(a.stats?.req_per_min||0)).map(s=>{const modeStr=s.monitor_only?'🔍':((s.bot_mode?'🤖':'')+(s.country_mode?'🌍':''))||'-';const bans=(s.stats?.active_bot_bans||0)+(s.stats?.active_country_bans||0);return '<tr style="cursor:pointer" onclick="closeModal(\\'serverDetailModal\\');openDetailModal(\\''+s.domain+'\\')"><td><span class="status-badge status-'+(s.status||'inactive')+'">'+(s.status==='active'?'✅':'⭕')+'</span></td><td>'+s.domain+'</td><td>'+modeStr+'</td><td>'+(s.stats?.req_per_min||0).toFixed(1)+'</td><td>'+bans+'</td></tr>';}).join('')||'<tr><td colspan="5" style="color:var(--text-secondary);text-align:center;padding:16px">Keine Shops</td></tr>';updateServerCharts(serverShops);}
|
||||||
function updateServerCharts(serverShops){const botData={},countryData={};serverShops.forEach(s=>{const st=s.stats||{};Object.entries(st.top_bots||{}).forEach(([bot,cnt])=>{botData[bot]=(botData[bot]||0)+cnt;});Object.entries(st.top_countries||{}).forEach(([country,cnt])=>{countryData[country]=(countryData[country]||0)+cnt;});});const now=new Date().toISOString().substring(0,19).replace('T',' ');Object.entries(botData).forEach(([bot,cnt])=>{if(!serverBotHistory[bot])serverBotHistory[bot]=[];serverBotHistory[bot].push({timestamp:now,count:cnt});if(serverBotHistory[bot].length>60)serverBotHistory[bot].shift();});Object.entries(countryData).forEach(([country,cnt])=>{if(!serverCountryHistory[country])serverCountryHistory[country]=[];serverCountryHistory[country].push({timestamp:now,count:cnt});if(serverCountryHistory[country].length>60)serverCountryHistory[country].shift();});renderServerBotChart();renderServerCountryChart();}
|
function updateServerCharts(serverShops){const botData={},countryData={};serverShops.forEach(s=>{const st=s.stats||{};Object.entries(st.top_bots||{}).forEach(([bot,cnt])=>{botData[bot]=(botData[bot]||0)+cnt;});Object.entries(st.top_countries||{}).forEach(([country,cnt])=>{countryData[country]=(countryData[country]||0)+cnt;});});const now=new Date().toISOString().substring(0,19).replace('T',' ');Object.entries(botData).forEach(([bot,cnt])=>{if(!serverBotHistory[bot])serverBotHistory[bot]=[];serverBotHistory[bot].push({timestamp:now,count:cnt});if(serverBotHistory[bot].length>60)serverBotHistory[bot].shift();});Object.entries(countryData).forEach(([country,cnt])=>{if(!serverCountryHistory[country])serverCountryHistory[country]=[];serverCountryHistory[country].push({timestamp:now,count:cnt});if(serverCountryHistory[country].length>60)serverCountryHistory[country].shift();});renderServerBotChart();renderServerCountryChart();}
|
||||||
function renderServerBotChart(){const cv=document.getElementById('serverRequestChart'),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 bn=Object.keys(serverBotHistory).sort((a,b)=>(serverBotHistory[b][serverBotHistory[b].length-1]?.count||0)-(serverBotHistory[a][serverBotHistory[a].length-1]?.count||0)).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=>serverBotHistory[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=>serverBotHistory[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('serverChartLegend');lg.innerHTML='';bn.forEach((bot,idx)=>{const c=BOT_COLORS[idx%BOT_COLORS.length],pts=serverBotHistory[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 renderServerBotChart(){const cv=document.getElementById('serverRequestChart'),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 bn=Object.keys(serverBotHistory).sort((a,b)=>(serverBotHistory[b][serverBotHistory[b].length-1]?.count||0)-(serverBotHistory[a][serverBotHistory[a].length-1]?.count||0)).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=>serverBotHistory[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=>serverBotHistory[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('serverChartLegend');lg.innerHTML='';bn.forEach((bot,idx)=>{const c=BOT_COLORS[idx%BOT_COLORS.length],pts=serverBotHistory[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 renderServerCountryChart(){const cv=document.getElementById('serverCountryChart'),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 cn=Object.keys(serverCountryHistory).sort((a,b)=>(serverCountryHistory[b][serverCountryHistory[b].length-1]?.count||0)-(serverCountryHistory[a][serverCountryHistory[a].length-1]?.count||0)).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=>serverCountryHistory[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=>serverCountryHistory[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('serverCountryChartLegend');lg.innerHTML='';cn.forEach((country,idx)=>{const clr=BOT_COLORS[idx%BOT_COLORS.length],pts=serverCountryHistory[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>';});}
|
function renderServerCountryChart(){const cv=document.getElementById('serverCountryChart'),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 cn=Object.keys(serverCountryHistory).sort((a,b)=>(serverCountryHistory[b][serverCountryHistory[b].length-1]?.count||0)-(serverCountryHistory[a][serverCountryHistory[a].length-1]?.count||0)).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=>serverCountryHistory[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=>serverCountryHistory[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('serverCountryChartLegend');lg.innerHTML='';cn.forEach((country,idx)=>{const clr=BOT_COLORS[idx%BOT_COLORS.length],pts=serverCountryHistory[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>'+getCountryName(country)+'</span></div>';});}
|
||||||
let serverUpdateInterval=null;
|
let serverUpdateInterval=null;
|
||||||
function startServerHistoryUpdate(){if(serverUpdateInterval)clearInterval(serverUpdateInterval);serverBotHistory={};serverCountryHistory={};serverUpdateInterval=setInterval(()=>{if(!currentDetailServer||!document.getElementById('serverDetailModal').classList.contains('open')){clearInterval(serverUpdateInterval);serverUpdateInterval=null;return;}renderServerDetail();},updateInterval);}
|
function startServerHistoryUpdate(){if(serverUpdateInterval)clearInterval(serverUpdateInterval);serverBotHistory={};serverCountryHistory={};serverUpdateInterval=setInterval(()=>{if(!currentDetailServer||!document.getElementById('serverDetailModal').classList.contains('open')){clearInterval(serverUpdateInterval);serverUpdateInterval=null;return;}renderServerDetail();},updateInterval);}
|
||||||
async function serverActivateAll(){if(!currentDetailServer)return;const serverShops=getServerShops(currentDetailServer);const inactiveShops=serverShops.filter(s=>s.status!=='active');if(inactiveShops.length===0){toast('Alle Shops sind bereits aktiv','info');return;}if(!confirm(inactiveShops.length+' inaktive Shops auf diesem Server mit Bot-Mode aktivieren?'))return;toast('Aktiviere '+inactiveShops.length+' Shops...','info');const restartFpm=document.getElementById('autoFpmRestart').checked?'true':'false';for(const s of inactiveShops){const fd=new FormData();fd.append('domain',s.domain);fd.append('bot_mode','true');fd.append('bot_rate_limit','30');fd.append('bot_ban_duration','300');fd.append('country_mode','false');fd.append('monitor_only','false');fd.append('restart_fpm',restartFpm);await fetch('/api/shops/activate',{method:'POST',body:fd});await new Promise(r=>setTimeout(r,200));}toast('Alle Shops aktiviert','success');}
|
async function serverActivateAll(){if(!currentDetailServer)return;const serverShops=getServerShops(currentDetailServer);const inactiveShops=serverShops.filter(s=>s.status!=='active');if(inactiveShops.length===0){toast('Alle Shops sind bereits aktiv','info');return;}if(!confirm(inactiveShops.length+' inaktive Shops auf diesem Server mit Bot-Mode aktivieren?'))return;toast('Aktiviere '+inactiveShops.length+' Shops...','info');const restartFpm=document.getElementById('autoFpmRestart').checked?'true':'false';for(const s of inactiveShops){const fd=new FormData();fd.append('domain',s.domain);fd.append('bot_mode','true');fd.append('bot_rate_limit','30');fd.append('bot_ban_duration','300');fd.append('country_mode','false');fd.append('monitor_only','false');fd.append('restart_fpm',restartFpm);await fetch('/api/shops/activate',{method:'POST',body:fd});await new Promise(r=>setTimeout(r,200));}toast('Alle Shops aktiviert','success');}
|
||||||
|
|||||||
Reference in New Issue
Block a user