feat(stats): totalPlays Zähler persistent; Health-Endpoint liefert totalPlays; UI zeigt Gesamtzahl
This commit is contained in:
parent
7f4b60c0bd
commit
0a95746d04
2 changed files with 11 additions and 4 deletions
|
|
@ -45,7 +45,7 @@ if (!DISCORD_TOKEN) {
|
|||
fs.mkdirSync(SOUNDS_DIR, { recursive: true });
|
||||
|
||||
// Persistente Lautstärke pro Guild speichern
|
||||
type PersistedState = { volumes: Record<string, number>; plays: Record<string, number> };
|
||||
type PersistedState = { volumes: Record<string, number>; plays: Record<string, number>; 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 ---
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export default function App() {
|
|||
const [selectedSet, setSelectedSet] = useState<Record<string, boolean>>({});
|
||||
const selectedCount = useMemo(() => Object.values(selectedSet).filter(Boolean).length, [selectedSet]);
|
||||
const [clock, setClock] = useState<string>(() => new Intl.DateTimeFormat('de-DE', { hour: '2-digit', minute: '2-digit', hour12: false, timeZone: 'Europe/Berlin' }).format(new Date()));
|
||||
const [totalPlays, setTotalPlays] = useState<number>(0);
|
||||
const [mediaUrl, setMediaUrl] = useState<string>('');
|
||||
|
||||
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() {
|
|||
</div>
|
||||
<div style={{ display:'flex', gap:12, alignItems:'center' }}>
|
||||
<div className="badge">Geladene Sounds: {total}</div>
|
||||
<div className="badge">Gesamt abgespielt: {totalPlays}</div>
|
||||
<button type="button" className="tab" style={{ background:'#b91c1c', borderColor:'transparent', color:'#fff' }} onClick={async () => {
|
||||
if (!selected) return;
|
||||
const [guildId] = selected.split(':');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue