From 0a95746d040d39845e8806b6e4d220a2b0977095 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Fri, 8 Aug 2025 20:50:11 +0200 Subject: [PATCH] =?UTF-8?q?feat(stats):=20totalPlays=20Z=C3=A4hler=20persi?= =?UTF-8?q?stent;=20Health-Endpoint=20liefert=20totalPlays;=20UI=20zeigt?= =?UTF-8?q?=20Gesamtzahl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/index.ts | 9 +++++---- web/src/App.tsx | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/server/src/index.ts b/server/src/index.ts index 44139c0..b745376 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -45,7 +45,7 @@ if (!DISCORD_TOKEN) { fs.mkdirSync(SOUNDS_DIR, { recursive: true }); // Persistente Lautstärke pro Guild speichern -type PersistedState = { volumes: Record; plays: Record }; +type PersistedState = { volumes: Record; plays: Record; totalPlays: number }; const STATE_FILE = path.join(path.resolve(SOUNDS_DIR, '..'), 'state.json'); function readPersistedState(): PersistedState { @@ -53,10 +53,10 @@ function readPersistedState(): PersistedState { if (fs.existsSync(STATE_FILE)) { const raw = fs.readFileSync(STATE_FILE, 'utf8'); const parsed = JSON.parse(raw); - return { volumes: parsed.volumes ?? {}, plays: parsed.plays ?? {} } as PersistedState; + return { volumes: parsed.volumes ?? {}, plays: parsed.plays ?? {}, totalPlays: parsed.totalPlays ?? 0 } as PersistedState; } } catch {} - return { volumes: {}, plays: {} }; + return { volumes: {}, plays: {}, totalPlays: 0 }; } function writePersistedState(state: PersistedState): void { @@ -77,6 +77,7 @@ function incrementPlaysFor(relativePath: string) { try { const key = relativePath.replace(/\\/g, '/'); persistedState.plays[key] = (persistedState.plays[key] ?? 0) + 1; + persistedState.totalPlays = (persistedState.totalPlays ?? 0) + 1; writePersistedState(persistedState); } catch {} } @@ -315,7 +316,7 @@ app.use(express.json()); app.use(cors()); app.get('/api/health', (_req: Request, res: Response) => { - res.json({ ok: true }); + res.json({ ok: true, totalPlays: persistedState.totalPlays ?? 0 }); }); // --- Admin Auth --- diff --git a/web/src/App.tsx b/web/src/App.tsx index fd1383b..ccaed85 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -24,6 +24,7 @@ export default function App() { const [selectedSet, setSelectedSet] = useState>({}); const selectedCount = useMemo(() => Object.values(selectedSet).filter(Boolean).length, [selectedSet]); const [clock, setClock] = useState(() => new Intl.DateTimeFormat('de-DE', { hour: '2-digit', minute: '2-digit', hour12: false, timeZone: 'Europe/Berlin' }).format(new Date())); + const [totalPlays, setTotalPlays] = useState(0); const [mediaUrl, setMediaUrl] = useState(''); useEffect(() => { @@ -41,6 +42,10 @@ export default function App() { setError(e?.message || 'Fehler beim Laden der Channels'); } try { setIsAdmin(await adminStatus()); } catch {} + try { + const h = await fetch('/api/health').then(r => r.json()).catch(() => null); + if (h && typeof h.totalPlays === 'number') setTotalPlays(h.totalPlays); + } catch {} })(); }, []); @@ -140,6 +145,7 @@ export default function App() {
Geladene Sounds: {total}
+
Gesamt abgespielt: {totalPlays}