First commit

This commit is contained in:
2025-09-23 01:38:39 -04:00
parent 33cc11c568
commit a1cfe5ca9c
55 changed files with 2252 additions and 195 deletions

66
services/aprelay.js Normal file
View File

@@ -0,0 +1,66 @@
/* @licstart Copyleft (🄯) 2025 James Osborne — AGPLv3+ @licend */
'use strict';
/* ===== Copy-to-clipboard handler ===== */
document.addEventListener('click', (e) => {
const el = e.target.closest('.copyable');
if (!el) return;
const text = el.dataset.copy ?? '';
const copyPromise =
(navigator.clipboard && window.isSecureContext)
? navigator.clipboard.writeText(text)
: (async () => {
const ta = document.createElement('textarea');
ta.value = text;
ta.style.position = 'fixed';
ta.style.opacity = '0';
ta.style.left = '-9999px';
document.body.appendChild(ta);
ta.select();
try { document.execCommand('copy'); } catch {}
ta.remove();
})();
Promise.resolve(copyPromise).then(() => {
el.dataset._orig ??= el.textContent || '';
el.textContent = `${el.dataset._orig} (copied!)`;
setTimeout(() => { el.textContent = el.dataset._orig; }, 1500);
});
});
/* ===== Stats loader ===== */
async function loadStats() {
const endpoints = [
'/relay-stats.json', // same-origin first (no CORS)
'https://relay-us-east.circlewithadot.net/relay-stats.json',
];
for (const url of endpoints) {
try {
const r = await fetch(url, { cache: 'no-store' });
if (!r.ok) continue;
const d = await r.json();
const set = (id, val) => {
const el = document.getElementById(id);
if (el) el.textContent = val;
};
set('instances', d.instances ?? '');
// accept either jobs_5min (new) or jobs_per_min (old)
set('jobs', (d.jobs_5min ?? d.jobs_per_min ?? ''));
set('updated', d.updated ? new Date(d.updated).toLocaleString() : '');
return;
} catch (e) {
console.warn('[relay stats] fetch failed:', e);
}
}
const box = document.getElementById('relay-stats');
if (box) box.textContent = 'Stats unavailable';
}
loadStats();
setInterval(loadStats, 300000);