fix
This commit is contained in:
208
index.html
208
index.html
@@ -360,100 +360,146 @@ function getFiltered() {
|
|||||||
.sort((a, b) => (b.points||0) - (a.points||0));
|
.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;
|
if (!list.length) {
|
||||||
document.getElementById('s-online').textContent = online;
|
tb.innerHTML = '<tr><td colspan="10" style="padding:28px;text-align:center;color:var(--muted)">No servers found.</td></tr>';
|
||||||
document.getElementById('s-total').textContent = allServers.length;
|
|
||||||
const top = getFiltered()[0];
|
|
||||||
document.getElementById('s-block').textContent = top ? fmt(top.last_block) : '—';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchData() {
|
list.forEach((d, i) => {
|
||||||
const chain = getChain();
|
const rank = i + 1;
|
||||||
const params = new URLSearchParams({ page: 0, limit: 100 });
|
const st = d.status === "online" || d.status === "OK"
|
||||||
if (!withTor) params.append("onion", "no");
|
? '<span class="status online"><span class="dot"></span>Online</span>'
|
||||||
try {
|
: '<span class="status offline"><span class="dot"></span>Offline</span>';
|
||||||
const response = await fetch(`/data/${chain}?${params}`);
|
const weLink = `/weinfo/${d.chain||getChain()}/${d.id}`;
|
||||||
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('onion').addEventListener('change', e => {
|
tb.insertAdjacentHTML('beforeend', `
|
||||||
withTor = e.target.checked;
|
<tr>
|
||||||
fetchData();
|
<td class="num"><span class="rank ${rank<=3?'top':''}">${rank}</span></td>
|
||||||
|
<td class="url"><a href="${weLink}">${DOMPurify.sanitize(d.url)}</a></td>
|
||||||
|
<td class="info">${DOMPurify.sanitize(d.info||'—')}</td>
|
||||||
|
<td class="num">${fmt(d.base_fee)}</td>
|
||||||
|
<td class="mono">${DOMPurify.sanitize(d.version||'—')}</td>
|
||||||
|
<td class="num">${fmt(d.balance)}</td>
|
||||||
|
<td>${st}</td>
|
||||||
|
<td class="num">${fmt(d.last_block)}</td>
|
||||||
|
<td class="num">${d.count_win != null ? d.count_win : '—'}</td>
|
||||||
|
<td class="num"><span class="score">${fmt(d.points)}</span></td>
|
||||||
|
</tr>`);
|
||||||
|
|
||||||
|
ml.insertAdjacentHTML('beforeend', `
|
||||||
|
<div class="srv">
|
||||||
|
<div class="top">
|
||||||
|
<div><div class="rk">#${rank}</div><a href="${weLink}" style="color:var(--ink);font-weight:600;text-decoration:none;font-size:14px">${DOMPurify.sanitize(d.url)}</a></div>
|
||||||
|
${st}
|
||||||
|
</div>
|
||||||
|
<div class="grid">
|
||||||
|
<div><span>Score</span><b>${fmt(d.points)}</b></div>
|
||||||
|
<div><span>Wins</span><b>${d.count_win != null ? d.count_win : '—'}</b></div>
|
||||||
|
<div><span>Fee</span><b>${fmt(d.base_fee)} sat</b></div>
|
||||||
|
<div><span>Balance</span><b>${fmt(d.balance)}</b></div>
|
||||||
|
<div><span>Version</span><b>${DOMPurify.sanitize(d.version||'—')}</b></div>
|
||||||
|
<div><span>Height</span><b>${fmt(d.last_block)}</b></div>
|
||||||
|
</div>
|
||||||
|
</div>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('filter').addEventListener('input', e => {
|
const online = allServers.filter(d => d.status === "online" || d.status === "OK").length;
|
||||||
q = e.target.value;
|
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();
|
render();
|
||||||
});
|
} catch (err) {
|
||||||
|
console.error('Fetch error:', err);
|
||||||
|
allServers = [];
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('chainSeg').addEventListener('click', e => {
|
document.getElementById('onion').addEventListener('change', e => {
|
||||||
const b = e.target.closest('button');
|
withTor = e.target.checked;
|
||||||
if (!b) return;
|
fetchData();
|
||||||
[...e.currentTarget.children].forEach(x => x.setAttribute('aria-pressed', 'false'));
|
});
|
||||||
b.setAttribute('aria-pressed', 'true');
|
|
||||||
fetchData();
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('submit').addEventListener('click', async () => {
|
document.getElementById('filter').addEventListener('input', e => {
|
||||||
const urlInput = document.getElementById('url');
|
q = e.target.value;
|
||||||
let url = urlInput.value.trim();
|
render();
|
||||||
if (!url) return;
|
});
|
||||||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
|
||||||
url = 'https://' + url;
|
document.getElementById('chainSeg').addEventListener('click', e => {
|
||||||
urlInput.value = url;
|
const b = e.target.closest('button');
|
||||||
}
|
if (!b) return;
|
||||||
const chain = getChain();
|
[...e.currentTarget.children].forEach(x => x.setAttribute('aria-pressed', 'false'));
|
||||||
try {
|
b.setAttribute('aria-pressed', 'true');
|
||||||
const response = await fetch('/data', {
|
fetchData();
|
||||||
method: 'POST',
|
});
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ url, chain })
|
document.getElementById('submit').addEventListener('click', async () => {
|
||||||
});
|
const urlInput = document.getElementById('url');
|
||||||
const result = await response.json();
|
let url = urlInput.value.trim();
|
||||||
const inv = document.getElementById('invoice');
|
if (!url) return;
|
||||||
if (!response.ok) {
|
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||||||
document.getElementById('iv-status').className = 'err-line';
|
url = 'https://' + url;
|
||||||
document.getElementById('iv-status').textContent = 'Error: ' + (result.message || result.error || JSON.stringify(result));
|
urlInput.value = url;
|
||||||
inv.classList.add('show');
|
}
|
||||||
document.getElementById('qrcode').innerHTML = '';
|
const chain = getChain();
|
||||||
return;
|
try {
|
||||||
}
|
const response = await fetch('/data', {
|
||||||
document.getElementById('iv-status').className = 'ok-line';
|
method: 'POST',
|
||||||
document.getElementById('iv-status').textContent = '✓ Server added. Pay the invoice to complete.';
|
headers: { 'Content-Type': 'application/json' },
|
||||||
document.getElementById('iv-min').textContent = (result.min_amount || '50,000') + ' sats';
|
body: JSON.stringify({ url, chain })
|
||||||
document.getElementById('iv-chain').textContent = result.chain || chain;
|
});
|
||||||
document.getElementById('iv-addr').textContent = result.address || '—';
|
const result = await response.json();
|
||||||
document.getElementById('iv-balance').textContent = result.balance != null ? fmt(result.balance) : '—';
|
const inv = document.getElementById('invoice');
|
||||||
document.getElementById('iv-status2').textContent = result.status || '—';
|
if (!response.ok) {
|
||||||
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').className = 'err-line';
|
||||||
document.getElementById('iv-status').textContent = 'Network error. Please try again.';
|
document.getElementById('iv-status').textContent = 'Error: ' + (result.message || result.error || JSON.stringify(result));
|
||||||
document.getElementById('invoice').classList.add('show');
|
inv.classList.add('show');
|
||||||
document.getElementById('qrcode').innerHTML = '';
|
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() {
|
(function init() {
|
||||||
const blob = new Blob([JSON.stringify(allServers, null, 2)], { type: 'application/json' });
|
const blob = new Blob([JSON.stringify(allServers, null, 2)], { type: 'application/json' });
|
||||||
document.getElementById('download').href = URL.createObjectURL(blob);
|
document.getElementById('download').href = URL.createObjectURL(blob);
|
||||||
fetchData();
|
fetchData();
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user