diff --git a/public/admin.js b/public/admin.js index afe6033..32b0082 100644 --- a/public/admin.js +++ b/public/admin.js @@ -52,7 +52,7 @@ document.getElementById('loginForm').addEventListener('submit',async e=>{e.preve document.getElementById('logoutBtn').addEventListener('click',async()=>{await api('/api/admin/logout',{method:'POST'});location.reload()}); document.getElementById('addSponsorForm').addEventListener('submit',async e=>{e.preventDefault();const form=e.currentTarget,obj=Object.fromEntries(new FormData(form));try{const d=await api('/api/admin/sponsors',{method:'POST',body:JSON.stringify(obj)});state.sponsors=d.sponsors;form.reset();render();showToast('Member added')}catch(x){showToast(x.message)}}); document.getElementById('configForm').addEventListener('submit',async e=>{e.preventDefault();const f=e.currentTarget,obj=Object.fromEntries(new FormData(f));obj.showSponsorName=f.elements.showSponsorName.checked;obj.showQueueProgress=f.elements.showQueueProgress.checked;obj.announceEnabled=!!(f.elements.announceEnabled&&f.elements.announceEnabled.checked);obj.premiumEntryPol=Number(obj.premiumEntryPol);try{const d=await api('/api/admin/config',{method:'PATCH',body:JSON.stringify(obj)});state.config=d.config;render();showToast('Settings saved')}catch(x){showToast(x.message)}}); -rows.addEventListener('click',async e=>{const b=e.target.closest('button[data-action]');if(!b)return;const id=b.dataset.id,a=b.dataset.action;try{let d;if(a==='rename'){const cur=(state.sponsors.find(s=>s.id===id)||{}).name||'';const nm=prompt(`Name for sponsor ID ${id}:`,cur);if(nm===null||!nm.trim())return;d=await api(`/api/admin/sponsors/${id}`,{method:'PATCH',body:JSON.stringify({name:nm.trim()})});}else if(a==='email'){const cur=(state.sponsors.find(s=>s.id===id)||{}).email||'';const em=prompt(`Contact email for sponsor ID ${id} (leave empty to clear):`,cur);if(em===null)return;d=await api(`/api/admin/sponsors/${id}`,{method:'PATCH',body:JSON.stringify({email:em.trim()})});}else if(a==='delete'){if(!confirm(`Delete sponsor ID ${id}?`))return;d=await api(`/api/admin/sponsors/${id}`,{method:'DELETE'})}else if(a==='inc')d=await api(`/api/admin/sponsors/${id}/increment`,{method:'POST'});else if(a==='qualify')d=await api(`/api/admin/sponsors/${id}/qualify`,{method:'POST'});else if(a==='activate')d=await api(`/api/admin/sponsors/${id}/activate`,{method:'POST'});else if(a==='reset')d=await api(`/api/admin/sponsors/${id}/reset`,{method:'POST'});else if(a==='up'||a==='down')d=await api(`/api/admin/sponsors/${id}/move`,{method:'POST',body:JSON.stringify({direction:a})});if(d&&d.sponsors){state.sponsors=d.sponsors;render();showToast('Updated')}}catch(x){showToast(x.message)}}); +rows.addEventListener('click',async e=>{const b=e.target.closest('button[data-action]');if(!b)return;const id=b.dataset.id,a=b.dataset.action;try{let d;if(a==='rename'){const cur=(state.sponsors.find(s=>s.id===id)||{}).name||'';const nm=prompt(`Name for sponsor ID ${id}:`,cur);if(nm===null||!nm.trim())return;d=await api(`/api/admin/sponsors/${id}`,{method:'PATCH',body:JSON.stringify({name:nm.trim()})});}else if(a==='email'){const cur=(state.sponsors.find(s=>s.id===id)||{}).email||'';const em=prompt(`Contact email for sponsor ID ${id} (leave empty to clear):`,cur);if(em===null)return;d=await api(`/api/admin/sponsors/${id}`,{method:'PATCH',body:JSON.stringify({email:em.trim()})});}else if(a==='delete'){if(!confirm(`Delete sponsor ID ${id}?`))return;d=await api(`/api/admin/sponsors/${id}`,{method:'DELETE'})}else if(a==='up'||a==='down')d=await api(`/api/admin/sponsors/${id}/move`,{method:'POST',body:JSON.stringify({direction:a})});if(d&&d.sponsors){state.sponsors=d.sponsors;render();showToast('Updated')}}catch(x){showToast(x.message)}}); document.getElementById('aiKeyForm').addEventListener('submit',async e=>{e.preventDefault();const inp=e.currentTarget.elements.key,key=inp.value.trim();if(!key){showToast('Paste a key first');return}try{const d=await api('/api/admin/openrouter-key',{method:'POST',body:JSON.stringify({key})});state.aiChat={...(state.aiChat||{}),configured:d.configured};inp.value='';render();showToast('AI chat enabled')}catch(x){showToast(x.message)}}); document.getElementById('aiKeyClear').addEventListener('click',async()=>{if(!confirm('Turn off AI chat and go back to built-in answers?'))return;try{const d=await api('/api/admin/openrouter-key',{method:'POST',body:JSON.stringify({key:''})});state.aiChat={...(state.aiChat||{}),configured:d.configured};render();showToast('AI chat disabled')}catch(x){showToast(x.message)}}); rows.addEventListener('change',async e=>{const sel=e.target.closest('select[data-action="level"]');if(!sel)return;try{const d=await api(`/api/admin/sponsors/${sel.dataset.id}`,{method:'PATCH',body:JSON.stringify({level:sel.value})});state.sponsors=d.sponsors;render();showToast('Level updated')}catch(x){showToast(x.message);render()}}); diff --git a/server.js b/server.js index c6ac120..f1cc27d 100644 --- a/server.js +++ b/server.js @@ -1592,7 +1592,7 @@ async function handleApi(req,res,pathname){ const b=await bodyJson(req).catch(()=>({}));recordEvent('click',b.source); const clickid=typeof b.clickid==='string'?b.clickid.trim().slice(0,80).replace(/[^A-Za-z0-9._-]/g,''):''; firePostback(clickid,`join-${clickid}`,b.source); - let sponsors=getSponsors();const a=activeSponsor(sponsors);if(a){sponsors=sponsors.map(s=>s.id===a.id?{...s,clicks:(s.clicks||0)+1}:s);saveSponsors(sponsors)}return json(res,200,{ok:true}); + return json(res,200,{ok:true}); } if(req.method==='POST'&&pathname==='/api/public/translate')return await handleTranslate(req,res); if(req.method==='POST'&&pathname==='/api/public/chat')return await handleChat(req,res);