Files
2026-08-22 17:10:27 +02:00

48 lines
2.0 KiB
TypeScript

// Converts a Steam2 id ("STEAM_0:1:12345678", as stored by the plugin) into
// a Steam64 id, which is what profile URLs and avatar lookups need.
const STEAM64_BASE = 76561197960265728n;
export function steam2ToSteam64(steamId2: string): string | null {
const match = /^STEAM_[0-5]:([01]):(\d+)$/.exec(steamId2.trim());
if (!match) return null;
const y = BigInt(match[1]);
const z = BigInt(match[2]);
return (STEAM64_BASE + y + z * 2n).toString();
}
export function steamProfileUrl(steamId2: string): string | null {
const id64 = steam2ToSteam64(steamId2);
return id64 ? `https://steamcommunity.com/profiles/${id64}` : null;
}
// Formats total minutes as "123h 45m" for display. Negative values (which
// shouldn't be possible, but have shown up from anomalous underlying data —
// e.g. a player_time counter that decreased between two session snapshots)
// are shown as "—" rather than a nonsensical negative duration.
export function formatMinutes(totalMinutes: number | null): string {
if (totalMinutes == null || Number.isNaN(totalMinutes) || totalMinutes < 0) return '—';
const h = Math.floor(totalMinutes / 60);
const m = totalMinutes % 60;
return `${h}h ${m}m`;
}
// ISO 3166-1 alpha-2 -> flag emoji, e.g. "DE" -> "🇩🇪". No external assets needed.
export function countryCodeToFlag(code: string | null): string {
if (!code || code.length !== 2) return '🏳️';
const codePoints = [...code.toUpperCase()].map((c) => 0x1f1a5 + c.charCodeAt(0));
return String.fromCodePoint(...codePoints);
}
// ISO 3166-1 alpha-2 -> English display name, e.g. "DE" -> "Germany".
// Uses the built-in Intl.DisplayNames (Node 14+ / all modern browsers) —
// no extra dependency or lookup table needed.
const regionNames = new Intl.DisplayNames(['en'], { type: 'region' });
export function countryCodeToName(code: string | null): string {
if (!code || code.length !== 2) return 'Unknown';
try {
return regionNames.of(code.toUpperCase()) ?? code;
} catch {
return code;
}
}