diff --git a/index.html b/index.html index c95f425..478ade4 100644 --- a/index.html +++ b/index.html @@ -360,100 +360,146 @@ function getFiltered() { .sort((a, b) => (b.points||0) - (a.points||0)); } - }); +function render() { + const list = getFiltered(); + const tb = document.getElementById('tbody'); + const ml = document.getElementById('mlist'); + tb.innerHTML = ""; ml.innerHTML = ""; - const online = allServers.filter(d => d.status === "online" || d.status === "OK").length; - document.getElementById('s-online').textContent = online; - document.getElementById('s-total').textContent = allServers.length; - const top = getFiltered()[0]; - document.getElementById('s-block').textContent = top ? fmt(top.last_block) : '—'; + if (!list.length) { + tb.innerHTML = 'No servers found.'; } - async function fetchData() { - const chain = getChain(); - const params = new URLSearchParams({ page: 0, limit: 100 }); - if (!withTor) params.append("onion", "no"); - try { - const response = await fetch(`/data/${chain}?${params}`); - if (!response.ok) throw new Error(`HTTP ${response.status}`); - const obj = await response.json(); - allServers = Object.entries(obj).map(([key, s]) => ({ id: key, ...s })); - render(); - } catch (err) { - console.error('Fetch error:', err); - allServers = []; - render(); - } - } + list.forEach((d, i) => { + const rank = i + 1; + const st = d.status === "online" || d.status === "OK" + ? 'Online' + : 'Offline'; + const weLink = `/weinfo/${d.chain||getChain()}/${d.id}`; - document.getElementById('onion').addEventListener('change', e => { - withTor = e.target.checked; - fetchData(); + tb.insertAdjacentHTML('beforeend', ` + + ${rank} + ${DOMPurify.sanitize(d.url)} + ${DOMPurify.sanitize(d.info||'—')} + ${fmt(d.base_fee)} + ${DOMPurify.sanitize(d.version||'—')} + ${fmt(d.balance)} + ${st} + ${fmt(d.last_block)} + ${d.count_win != null ? d.count_win : '—'} + ${fmt(d.points)} + `); + + ml.insertAdjacentHTML('beforeend', ` +
+
+
#${rank}
${DOMPurify.sanitize(d.url)}
+ ${st} +
+
+
Score${fmt(d.points)}
+
Wins${d.count_win != null ? d.count_win : '—'}
+
Fee${fmt(d.base_fee)} sat
+
Balance${fmt(d.balance)}
+
Version${DOMPurify.sanitize(d.version||'—')}
+
Height${fmt(d.last_block)}
+
+
`); }); - document.getElementById('filter').addEventListener('input', e => { - q = e.target.value; + const online = allServers.filter(d => d.status === "online" || d.status === "OK").length; + document.getElementById('s-online').textContent = online; + document.getElementById('s-total').textContent = allServers.length; + const top = getFiltered()[0]; + document.getElementById('s-block').textContent = top ? fmt(top.last_block) : '—'; +} + +async function fetchData() { + const chain = getChain(); + const params = new URLSearchParams({ page: 0, limit: 100 }); + if (!withTor) params.append("onion", "no"); + try { + const response = await fetch(`/data/${chain}?${params}`); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + const obj = await response.json(); + allServers = Object.entries(obj).map(([key, s]) => ({ id: key, ...s })); render(); - }); + } catch (err) { + console.error('Fetch error:', err); + allServers = []; + render(); + } +} - document.getElementById('chainSeg').addEventListener('click', e => { - const b = e.target.closest('button'); - if (!b) return; - [...e.currentTarget.children].forEach(x => x.setAttribute('aria-pressed', 'false')); - b.setAttribute('aria-pressed', 'true'); - fetchData(); - }); +document.getElementById('onion').addEventListener('change', e => { + withTor = e.target.checked; + fetchData(); +}); - document.getElementById('submit').addEventListener('click', async () => { - const urlInput = document.getElementById('url'); - let url = urlInput.value.trim(); - if (!url) return; - if (!url.startsWith('http://') && !url.startsWith('https://')) { - url = 'https://' + url; - urlInput.value = url; - } - const chain = getChain(); - try { - const response = await fetch('/data', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url, chain }) - }); - const result = await response.json(); - const inv = document.getElementById('invoice'); - if (!response.ok) { - document.getElementById('iv-status').className = 'err-line'; - document.getElementById('iv-status').textContent = 'Error: ' + (result.message || result.error || JSON.stringify(result)); - inv.classList.add('show'); - document.getElementById('qrcode').innerHTML = ''; - return; - } - document.getElementById('iv-status').className = 'ok-line'; - document.getElementById('iv-status').textContent = '✓ Server added. Pay the invoice to complete.'; - document.getElementById('iv-min').textContent = (result.min_amount || '50,000') + ' sats'; - document.getElementById('iv-chain').textContent = result.chain || chain; - document.getElementById('iv-addr').textContent = result.address || '—'; - document.getElementById('iv-balance').textContent = result.balance != null ? fmt(result.balance) : '—'; - document.getElementById('iv-status2').textContent = result.status || '—'; - const invoiceuri = `bitcoin:${result.address}?label=BAL&message=Order+For+url+%26+${encodeURIComponent(url)}`; - const qrEl = document.getElementById('qrcode'); - qrEl.innerHTML = ''; - new QRCode(qrEl, invoiceuri); - inv.classList.add('show'); - inv.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - } catch (err) { +document.getElementById('filter').addEventListener('input', e => { + q = e.target.value; + render(); +}); + +document.getElementById('chainSeg').addEventListener('click', e => { + const b = e.target.closest('button'); + if (!b) return; + [...e.currentTarget.children].forEach(x => x.setAttribute('aria-pressed', 'false')); + b.setAttribute('aria-pressed', 'true'); + fetchData(); +}); + +document.getElementById('submit').addEventListener('click', async () => { + const urlInput = document.getElementById('url'); + let url = urlInput.value.trim(); + if (!url) return; + if (!url.startsWith('http://') && !url.startsWith('https://')) { + url = 'https://' + url; + urlInput.value = url; + } + const chain = getChain(); + try { + const response = await fetch('/data', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ url, chain }) + }); + const result = await response.json(); + const inv = document.getElementById('invoice'); + if (!response.ok) { document.getElementById('iv-status').className = 'err-line'; - document.getElementById('iv-status').textContent = 'Network error. Please try again.'; - document.getElementById('invoice').classList.add('show'); + document.getElementById('iv-status').textContent = 'Error: ' + (result.message || result.error || JSON.stringify(result)); + inv.classList.add('show'); document.getElementById('qrcode').innerHTML = ''; + return; } - }); + document.getElementById('iv-status').className = 'ok-line'; + document.getElementById('iv-status').textContent = '✓ Server added. Pay the invoice to complete.'; + document.getElementById('iv-min').textContent = (result.min_amount || '50,000') + ' sats'; + document.getElementById('iv-chain').textContent = result.chain || chain; + document.getElementById('iv-addr').textContent = result.address || '—'; + document.getElementById('iv-balance').textContent = result.balance != null ? fmt(result.balance) : '—'; + document.getElementById('iv-status2').textContent = result.status || '—'; + const invoiceuri = `bitcoin:${result.address}?label=BAL&message=Order+For+url+%26+${encodeURIComponent(url)}`; + const qrEl = document.getElementById('qrcode'); + qrEl.innerHTML = ''; + new QRCode(qrEl, invoiceuri); + inv.classList.add('show'); + inv.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + } catch (err) { + document.getElementById('iv-status').className = 'err-line'; + document.getElementById('iv-status').textContent = 'Network error. Please try again.'; + document.getElementById('invoice').classList.add('show'); + document.getElementById('qrcode').innerHTML = ''; + } +}); - (function init() { - const blob = new Blob([JSON.stringify(allServers, null, 2)], { type: 'application/json' }); - document.getElementById('download').href = URL.createObjectURL(blob); - fetchData(); - })(); +(function init() { + const blob = new Blob([JSON.stringify(allServers, null, 2)], { type: 'application/json' }); + document.getElementById('download').href = URL.createObjectURL(blob); + fetchData(); +})();