From 9459f2bc77007bdb4da0eea4aa289e1d34c65cb9 Mon Sep 17 00:00:00 2001 From: Medicopter117 Date: Sun, 22 Mar 2026 14:15:46 +0100 Subject: [PATCH 1/2] feat: Introduce user settings API and dashboard page for managing preferences and viewing stats, and add a new UI standards file. --- src/api/dashboard/user_routes.py | 70 +++++++++++++- src/web/dashboard/UserSettingsPage.tsx | 123 ++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 4 deletions(-) diff --git a/src/api/dashboard/user_routes.py b/src/api/dashboard/user_routes.py index fb7db00..fc4d9f6 100644 --- a/src/api/dashboard/user_routes.py +++ b/src/api/dashboard/user_routes.py @@ -2,6 +2,15 @@ from src.api.dashboard.auth_routes import get_current_user from mx_devtools import SettingsDB, StatsDB import discord +import sqlite3 +import os +from pathlib import Path + +# Paths to databases +BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent +DATA_DIR = BASE_DIR / "data" +MOD_DIR = BASE_DIR / "src" / "bot" / "cogs" / "moderation" + router = APIRouter( prefix="/user", @@ -23,13 +32,72 @@ async def get_user_settings(user: dict = Depends(get_current_user)): stats_db = StatsDB() global_info = await stats_db.get_global_user_info(user_id) + # 1. Moderation Stats (Global Warnings) + warns_count = 0 + warns_db_path = MOD_DIR / "Datenbanken" / "warns.db" + if warns_db_path.exists(): + try: + conn = sqlite3.connect(warns_db_path) + cursor = conn.cursor() + cursor.execute("SELECT COUNT(*) FROM warns WHERE user_id = ?", (user_id,)) + warns_count = cursor.fetchone()[0] + conn.close() + except Exception: + pass + + # 2. Global Chat Stats + global_chat_messages = 0 + gc_db_path = DATA_DIR / "globalchat.db" + if gc_db_path.exists(): + try: + conn = sqlite3.connect(gc_db_path) + cursor = conn.cursor() + cursor.execute("SELECT COUNT(*) FROM message_log WHERE user_id = ?", (user_id,)) + global_chat_messages = cursor.fetchone()[0] + conn.close() + except Exception: + pass + + # 3. Top Servers (from LevelSystem) + top_servers = [] + ls_db_path = DATA_DIR / "levelsystem.db" + if ls_db_path.exists(): + try: + conn = sqlite3.connect(ls_db_path) + cursor = conn.cursor() + # Get top 3 guilds by XP for this user + cursor.execute(""" + SELECT guild_id, level, xp + FROM user_levels + WHERE user_id = ? + ORDER BY xp DESC + LIMIT 3 + """, (user_id,)) + rows = cursor.fetchall() + for row in rows: + top_servers.append({ + "guild_id": str(row[0]), + "level": row[1], + "xp": row[2] + }) + conn.close() + except Exception: + pass + return { "success": True, "data": { "user_id": str(user_id), "language": language, "username": user.get("username", "Unknown"), - "global_stats": global_info + "global_stats": global_info, + "moderation": { + "total_warnings": warns_count + }, + "global_chat": { + "total_messages": global_chat_messages + }, + "top_servers": top_servers } } except Exception as e: diff --git a/src/web/dashboard/UserSettingsPage.tsx b/src/web/dashboard/UserSettingsPage.tsx index 71bb9b4..6eba8c6 100644 --- a/src/web/dashboard/UserSettingsPage.tsx +++ b/src/web/dashboard/UserSettingsPage.tsx @@ -22,7 +22,11 @@ import { Trophy, Mic, Server, - Flame + Flame, + Calendar, + Award, + Activity, + History } from "lucide-react"; import { useAuth } from "../components/AuthProvider"; import { Button } from "../components/ui/button"; @@ -42,7 +46,10 @@ export default function UserSettingsPage() { const [settings, setSettings] = useState({ username: "", language: "de", - globalStats: null as any + globalStats: null as any, + moderation: null as any, + globalChat: null as any, + topServers: [] as any[] }); useEffect(() => { @@ -61,7 +68,10 @@ export default function UserSettingsPage() { setSettings({ username: data.data.username || "", language: data.data.language || "de", - globalStats: data.data.global_stats + globalStats: data.data.global_stats, + moderation: data.data.moderation, + globalChat: data.data.global_chat, + topServers: data.data.top_servers || [] }); } } @@ -261,6 +271,31 @@ export default function UserSettingsPage() { + {/* Advanced Global Stats */} +
+
+
+ +
+
+

Mitglied seit

+

+ {settings.globalStats.first_seen ? new Date(settings.globalStats.first_seen).toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' }) : 'Unbekannt'} +

+
+
+
+
+ +
+
+

Beste Streak

+

{settings.globalStats.best_streak || settings.globalStats.daily_streak} Tage

+
+
+
+ + {/* Achievements Preview */} {settings.globalStats.achievements && settings.globalStats.achievements.length > 0 && (
@@ -282,6 +317,88 @@ export default function UserSettingsPage() { )} + {/* Moderation & Community */} +
+ {/* Moderation Card */} + + +
+
+ +
+
+ Moderation + Deine globale History. +
+
+
+ +
+
+

Gesamt Verwarnungen

+

0 ? "text-red-500" : "text-green-500")}> + {settings.moderation?.total_warnings || 0} +

+
+
+ {(settings.moderation?.total_warnings || 0) === 0 ? "Clean Record ✓" : "Achtung"} +
+
+ +
+
+ +
+
+

Global-Chat Nachrichten

+

{settings.globalChat?.total_messages?.toLocaleString() || 0}

+
+
+
+
+ + {/* Top Servers Card */} + + +
+
+ +
+
+ Top Server + Deine aktivsten Communities. +
+
+
+ + {settings.topServers && settings.topServers.length > 0 ? ( + settings.topServers.map((srv: any, i: number) => ( +
+
+
+ #{i + 1} +
+
+

Server ID: {srv.guild_id}

+

Level {srv.level}

+
+
+
+

{srv.xp.toLocaleString()} XP

+
+
+ )) + ) : ( +
+ +

Noch keine Level-Daten

+
+ )} +
+
+
+ + {/* Preferences */} From 3c849ffd09d4b84710c38e17d731cd529df4c6dc Mon Sep 17 00:00:00 2001 From: Medicopter117 Date: Sun, 22 Mar 2026 14:17:36 +0100 Subject: [PATCH 2/2] feat: Introduce standards module for bot configuration and text constants. --- src/bot/ui/standards.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/bot/ui/standards.py diff --git a/src/bot/ui/standards.py b/src/bot/ui/standards.py new file mode 100644 index 0000000..6ff74c9 --- /dev/null +++ b/src/bot/ui/standards.py @@ -0,0 +1,9 @@ +class config: + version = "2.0.0-beta" + topgg = "https://top.gg/bot/1368201272624287754" + website = "https://managerx-bot.de" + github = "https://github.com/ManagerX-Development/ManagerX" + +class texts: + footer = "Powered by ManagerX" + author = "ManagerX Development" \ No newline at end of file