Staff avatars from Steam, cached in memory

The public staff page, the staff panel's staff list and the signed-in badge show each member's
Steam avatar over their initial. The panel fetches it from the profile XML (no Web API key),
keeps it in memory for a day (failures for an hour, one shared fetch per player) and serves it
from /avatar/<steamid> with a day's browser caching, so the CSP stays img-src 'self' and
visitors never contact Steam. Only SimpleAdmin admins are served; anything else falls back to the
initial.
This commit is contained in:
Astra 2026-09-28 11:36:05 +01:00
parent 6324fc7f81
commit 861692c534
6 changed files with 196 additions and 21 deletions

View file

@ -82,6 +82,17 @@ function rankTag(rank) {
return `<span class="rank" style="--c:${esc(rank.color)}"><i></i>${esc(rank.label)}</span>`;
}
// A player's Steam avatar over their initial. /avatar only serves staff; for anyone else, or if
// Steam has none, the image fails and the initial shows (see the error listener below).
function avatar(sid, name, cls = "") {
return `<span class="avatar ${cls}">${initial(name)}<img src="/avatar/${encodeURIComponent(sid)}" alt="" loading="lazy"></span>`;
}
// Error events don't bubble, so catch them on the way down; the CSP rules out inline onerror.
document.addEventListener("error", (e) => {
if (e.target instanceof HTMLImageElement && e.target.parentElement?.classList.contains("avatar")) e.target.remove();
}, true);
function initial(name) { return esc(String(name || "").replace(/[^a-z0-9]/gi, "").charAt(0).toUpperCase() || "?"); }
// Time served against the full term: the bar under each length.