async function jget(u){const r=await fetch(u);return r.json();}
async function post(u){const r=await fetch(u,{method:'POST'});return r.json();}
async function refresh(){
try{
const s=await jget('/api/stats');
el('m-total').textContent=s.total.toLocaleString('ru');
el('m-today').textContent=s.today.toLocaleString('ru');
const alive=Object.values(s.engines).filter(e=>e.alive).length;
el('m-eng').textContent=alive+' / '+Object.keys(s.engines).length;
el('m-ts').textContent=s.ts;
// движки
const box=el('eng');box.innerHTML='';
for(const [id,e] of Object.entries(s.engines)){
const c=document.createElement('div');c.className='card';
c.innerHTML=`
${id}${e.desc}${e.auto?' · auto':''}
`;
const btn=document.createElement('button');
btn.textContent=e.alive?'стоп':'старт';
if(e.alive)btn.className='stop';
btn.onclick=async()=>{e.alive?await post('/api/engine/'+id+'/stop'):await post('/api/engine/'+id+'/start');refresh();};
c.appendChild(btn);box.appendChild(c);
}
// статусы
const st=el('t-status');st.innerHTML='';
const mx=Math.max(...s.by_status.map(x=>x.n),1);
for(const r of s.by_status){
const tr=document.createElement('tr');
tr.innerHTML=`${r.status} | ${r.n.toLocaleString('ru')} |
| `;
st.appendChild(tr);
}
// провайдеры
const pv=el('t-prov');pv.innerHTML='';
for(const r of s.by_prov){
const tr=document.createElement('tr');
tr.innerHTML=`${r.prov} | ${r.n.toLocaleString('ru')} | `;
tr.style.cursor='pointer';
tr.onclick=()=>{el('f-prov').value=r.prov;loadKeys();};
pv.appendChild(tr);
}
loadKeys();
loadLog();
}catch(e){console.error(e);}
}
async function loadKeys(){
const st=el('f-status').value,pv=el('f-prov').value,lim=el('f-limit').value||50;
const d=await jget(`/api/keys?status=${st}&prov=${pv}&limit=${lim}`);
const t=el('t-keys');t.innerHTML='';
for(const r of d.rows){
const tr=document.createElement('tr');
tr.innerHTML=`${r.status} | ${r.prov} |
${r.val} | ${r.repo||''} | ${r.found||''} | `;
t.appendChild(tr);
}
el('k-count').textContent=d.rows.length+' показано';
}
async function loadLog(){
const r=await fetch('/api/log?engine='+el('f-log').value);
el('log').textContent=await r.text();
el('log').scrollTop=el('log').scrollHeight;
}
function el(id){return document.getElementById(id);}
function exportKeys(){const st=el('f-status').value,pv=el('f-prov').value;
window.open(`/api/export?status=${st}&prov=${pv}`,'_blank');}
refresh();
setInterval(refresh,5000);