feat: add admin stats page with token usage

This commit is contained in:
Alexej Wolff
2026-02-11 01:00:02 +01:00
parent 6616c2e9a7
commit c404b1e17c
6 changed files with 455 additions and 0 deletions
+60
View File
@@ -472,6 +472,66 @@ app.delete("/api/characters/:id", requireAuth, async (req, res) => {
}
});
// ============ ADMIN STATS ============
// Получить статистику по всем историям и токенам
app.get("/api/admin/stats", requireAuth, async (req, res) => {
try {
const stories = db.collection("stories");
const gameSessions = db.collection("game_sessions");
// Получаем все истории пользователя
const userStories = await stories
.find({ userId: req.session.userId })
.toArray();
// Получаем все сессии пользователя
const userSessions = await gameSessions
.find({ storyId: { $in: userStories.map((s) => s._id.toString()) } })
.toArray();
// Считаем статистику для каждой истории
const storyStats = userStories.map((story) => {
const session = userSessions.find(
(s) => s.storyId === story._id.toString()
);
const messages = session?.messages || [];
const messageCount = messages.length;
// Примерный подсчёт токенов (1 токен ≈ 3 символа для русского)
const totalChars = messages.reduce(
(sum, msg) => sum + (msg.content?.length || 0),
0
);
const tokens = Math.round(totalChars / 3);
return {
id: story._id.toString(),
title: story.title,
messageCount,
tokens,
lastPlayed: session?.updatedAt || null,
};
});
// Сортируем по токенам (больше сверху)
storyStats.sort((a, b) => b.tokens - a.tokens);
// Общая статистика
const totalTokens = storyStats.reduce((sum, s) => sum + s.tokens, 0);
res.json({
totalStories: userStories.length,
totalSessions: userSessions.length,
totalTokens,
stories: storyStats,
});
} catch (error) {
console.error("Get admin stats error:", error);
res.status(500).json({ error: "Failed to get stats" });
}
});
// Запуск сервера
connectDB().then(() => {
app.listen(PORT, () => {