diff --git a/README.md b/README.md index 865ea74..be5a8c3 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ python main.py Brauchst du Hilfe oder möchtest du das Projekt unterstützen? -[![Discord](https://img.shields.io/badge/Discord-Join%20Now-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/oppro) +[![Discord](https://img.shields.io/badge/Discord-Join%20Now-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/9T28DWup3g) [![GitHub Issues](https://img.shields.io/github/issues/Oppro-net-Development/ManagerX?style=for-the-badge&logo=github&logoColor=white)](https://github.com/Oppro-net-Development/ManagerX/issues)
diff --git a/config/example.env b/config/example.env index b2561c8..e404e7d 100644 --- a/config/example.env +++ b/config/example.env @@ -6,6 +6,12 @@ DISCORD_CLIENT_ID=12345678900 DISCORD_CLIENT_SECRET=abc123 DISCORD_REDIRECT_URI=https:// -URL=https:// +URL=https://my-super-discord-bot.com -DASHBOARD_API_KEYS=abc123 \ No newline at end of file +DASHBOARD_API_KEYS=abc123 + +JWT_SECRET=abc123 +DASHBOARD_URL=https://my-super-discord-bot.com +VITE_API_URL=https://api.my-super-discord-bot.com + +TOPGG_TOKEN=abc123 \ No newline at end of file diff --git a/main.py b/main.py index a77f79e..46df1c9 100644 --- a/main.py +++ b/main.py @@ -142,10 +142,6 @@ async def on_ready(): ) ) - # Commands sync - await bot.sync_commands() - logger.success("COMMANDS", "Application Commands synchronisiert") - # --- LIMIT CHECK START --- all_cmds = bot.pending_application_commands # Wir zählen nur die echten Top-Level Slash Commands (Slots) @@ -155,6 +151,15 @@ async def on_ready(): logger.info("LIMITS", f"Discord-API Slots belegt: {len(root_slots)} / 100") # --- LIMIT CHECK ENDE --- + @bot.event + async def on_application_command_completion(ctx: discord.ApplicationContext): + """Track command usage across all guilds.""" + if ctx.guild and hasattr(bot, 'stats_db'): + try: + await bot.stats_db.log_command(ctx.guild.id, ctx.command.qualified_name) + except Exception as e: + logger.error("STATS", f"Fehler beim Loggen des Commands: {e}") + # Minimaler KeepAlive Cog class KeepAlive(discord.ext.commands.Cog): def __init__(self, bot): diff --git a/src/bot/cogs/bot/admin.py b/src/bot/cogs/bot/admin.py index 4c05b37..09b36cc 100644 --- a/src/bot/cogs/bot/admin.py +++ b/src/bot/cogs/bot/admin.py @@ -21,23 +21,7 @@ AUDIT_LOG_FILE = Path("data/admin_audit.json") BLACKLIST_FILE = Path("data/blacklist.json") -class ConfirmView(View): - """Bestätigungsdialog für kritische Aktionen""" - def __init__(self, timeout=30): - super().__init__(timeout=timeout) - self.value = None - @discord.ui.button(label="✅ Bestätigen", style=discord.ButtonStyle.danger) - async def confirm(self, button: discord.ui.Button, interaction: discord.Interaction): - self.value = True - self.stop() - await interaction.response.defer() - - @discord.ui.button(label="❌ Abbrechen", style=discord.ButtonStyle.secondary) - async def cancel(self, button: discord.ui.Button, interaction: discord.Interaction): - self.value = False - self.stop() - await interaction.response.defer() class ServerListView: @@ -322,6 +306,34 @@ async def cog_check(self, ctx): return True + async def request_confirmation(self, ctx: discord.ApplicationContext, container: Container, timeout: int = 30) -> bool: + """Helper to create a confirmation dialog with buttons and a designer container.""" + view = discord.ui.DesignerView(container, timeout=timeout) + view.value = None + + async def confirm_callback(interaction: discord.Interaction): + view.value = True + view.stop() + await interaction.response.defer() + + async def cancel_callback(interaction: discord.Interaction): + view.value = False + view.stop() + await interaction.response.defer() + + confirm_btn = Button(label="✅ Bestätigen", style=discord.ButtonStyle.danger) + confirm_btn.callback = confirm_callback + + cancel_btn = Button(label="❌ Abbrechen", style=discord.ButtonStyle.secondary) + cancel_btn.callback = cancel_callback + + view.add_item(confirm_btn) + view.add_item(cancel_btn) + + await ctx.respond(view=view, ephemeral=True) + await view.wait() + return view.value if view.value is not None else False + def log_command(self, ctx): """Loggt Admin-Commands""" AUDIT_LOG_FILE.parent.mkdir(parents=True, exist_ok=True) @@ -414,11 +426,7 @@ async def shutdown(self, ctx: discord.ApplicationContext): container.add_text("# ⚠️ Shutdown bestätigen") container.add_text("Bist du sicher, dass du den Bot herunterfahren möchtest?") - view = ConfirmView() - await ctx.respond(view=discord.ui.DesignerView(container, timeout=30), ephemeral=True) - await view.wait() - - if view.value: + if await self.request_confirmation(ctx, container): container = Container(color=discord.Color.red()) container.add_text("# ⚠️ ManagerX wird heruntergefahren...") container.add_separator() @@ -437,11 +445,7 @@ async def restart(self, ctx: discord.ApplicationContext): container.add_text("# ⚠️ Restart bestätigen") container.add_text("Bist du sicher, dass du den Bot neustarten möchtest?") - view = ConfirmView() - await ctx.respond(view=discord.ui.DesignerView(container, timeout=30), ephemeral=True) - await view.wait() - - if view.value: + if await self.request_confirmation(ctx, container): container = Container(color=discord.Color.orange()) container.add_text("# 🔄 ManagerX wird neugestartet...") container.add_separator() @@ -804,11 +808,7 @@ async def reload_all(self, ctx: discord.ApplicationContext): container.add_text("# ⚠️ Reload All bestätigen") container.add_text("Alle Cogs (außer Admin) werden neu geladen. Fortfahren?") - view = ConfirmView() - await ctx.respond(view=discord.ui.DesignerView(container, timeout=30), ephemeral=True) - await view.wait() - - if not view.value: + if not await self.request_confirmation(ctx, container): container = Container(color=discord.Color.green()) container.add_text("## ✅ Reload abgebrochen") await ctx.edit(view=discord.ui.DesignerView(container, timeout=0)) @@ -924,11 +924,7 @@ async def leave_server( container.add_text(f"**ID:** `{guild_id}`") container.add_text(f"**Mitglieder:** {guild.member_count:,}") - view = ConfirmView() - await ctx.respond(view=discord.ui.DesignerView(container, timeout=30), ephemeral=True) - await view.wait() - - if view.value: + if await self.request_confirmation(ctx, container): await guild.leave() container = Container(color=discord.Color.green()) @@ -1075,6 +1071,26 @@ async def server_info( container.add_text("## ✨ Features") container.add_text(features_text) + container.add_separator() + + # Befehls-Statistiken (NEU) + if hasattr(self.bot, "stats_db"): + guild_top = await self.bot.stats_db.get_top_commands(guild.id, 3) + global_top = await self.bot.stats_db.get_global_top_commands(3) + + container.add_text("## 📊 Top 3 Befehle") + + if guild_top: + gt_text = "\n".join([f"• `/{name}` ({count}x)" for name, count in guild_top]) + container.add_text(f"**Dieser Server:**\n{gt_text}") + else: + container.add_text("**Dieser Server:** Keine Daten") + + if global_top: + glob_text = "\n".join([f"• `/{name}` ({count}x)" for name, count in global_top]) + container.add_text(f"**Global:**\n{glob_text}") + else: + container.add_text("**Global:** Keine Daten") await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True) @@ -1374,11 +1390,7 @@ async def clear_logs(self, ctx: discord.ApplicationContext): container.add_text("# ⚠️ Logs löschen bestätigen") container.add_text("Alle Admin-Logs werden permanent gelöscht!") - view = ConfirmView() - await ctx.respond(view=discord.ui.DesignerView(container, timeout=30), ephemeral=True) - await view.wait() - - if view.value: + if await self.request_confirmation(ctx, container): if AUDIT_LOG_FILE.exists(): AUDIT_LOG_FILE.unlink() diff --git a/src/bot/cogs/user/stats.py b/src/bot/cogs/user/stats.py index 10f78a7..cef5649 100644 --- a/src/bot/cogs/user/stats.py +++ b/src/bot/cogs/user/stats.py @@ -21,8 +21,9 @@ class EnhancedStatsCog(ezcord.Cog): def __init__(self, bot: commands.Bot): self.bot = bot - self.db = StatsDB() - self.bot.stats_db = self.db + self.db = getattr(bot, "stats_db", None) or StatsDB() + if not hasattr(bot, "stats_db"): + bot.stats_db = self.db self.level_db = LevelDatabase() self.cleanup_task.start() self.monthly_reset_task.start() diff --git a/src/bot/core/bot_setup.py b/src/bot/core/bot_setup.py index 85df90a..bf96fff 100644 --- a/src/bot/core/bot_setup.py +++ b/src/bot/core/bot_setup.py @@ -65,7 +65,7 @@ def create_bot(self) -> ezcord.Bot: name="🔗 **Important Links**", value=( "🌐 [**Website**](https://managerx-bot.de) • " - "🚑 [**Support**](https://discord.gg/SrcE6zJZ) • " + "🚑 [**Support**](https://discord.gg/9T28DWup3g) • " "💻 [**GitHub**](https://github.com/ManagerX-Development/ManagerX)" ), inline=False diff --git a/src/bot/core/database.py b/src/bot/core/database.py index 6050f3c..eb86ef3 100644 --- a/src/bot/core/database.py +++ b/src/bot/core/database.py @@ -9,10 +9,11 @@ from logger import logger, Category try: - from mx_devtools import SettingsDB + from mx_devtools import SettingsDB, StatsDB except ImportError as e: - logger.critical(Category.DATABASE, f"SettingsDB Import fehlgeschlagen: {e}") + logger.critical(Category.DATABASE, f"Database Imports fehlgeschlagen: {e}") SettingsDB = None + StatsDB = None class DatabaseManager: """Verwaltet die Datenbank-Initialisierung""" @@ -38,6 +39,11 @@ def initialize(self, bot) -> bool: self.db = SettingsDB() bot.settings_db = self.db logger.success(Category.DATABASE, "Settings Database initialized ✓") + + if StatsDB: + bot.stats_db = StatsDB() + logger.success(Category.DATABASE, "Stats Database initialized ✓") + return True except Exception as e: diff --git a/scripts/fix_xp.py b/src/scripts/fix_xp.py similarity index 100% rename from scripts/fix_xp.py rename to src/scripts/fix_xp.py diff --git a/src/web/components/CTA.tsx b/src/web/components/CTA.tsx index d3880b7..364abd2 100644 --- a/src/web/components/CTA.tsx +++ b/src/web/components/CTA.tsx @@ -77,7 +77,7 @@ export const CTA = memo(function CTA() { Ressourcen Dokumentation - Support Server + Support Server GitHub Repository diff --git a/src/web/dashboard/LoginPage.tsx b/src/web/dashboard/LoginPage.tsx index 17564e7..60a4db7 100644 --- a/src/web/dashboard/LoginPage.tsx +++ b/src/web/dashboard/LoginPage.tsx @@ -197,7 +197,7 @@ export default function LoginPage() { > Datenschutz Nutzungsbedingungen - Hilfe erhalten + Hilfe erhalten diff --git a/src/web/pages/CommandsPage.tsx b/src/web/pages/CommandsPage.tsx index b78ffc6..d1856d3 100644 --- a/src/web/pages/CommandsPage.tsx +++ b/src/web/pages/CommandsPage.tsx @@ -224,7 +224,7 @@ export const CommandsPage = memo(function CommandsPage() {

ManagerX wird für euch entwickelt. Schlag uns neue Features auf unserem Support-Server vor!

-
+ Feedback geben diff --git a/translation/messages/de.yaml b/translation/messages/de.yaml index ad0f74b..0810a6e 100644 --- a/translation/messages/de.yaml +++ b/translation/messages/de.yaml @@ -131,7 +131,7 @@ cog_about: title: "# ℹ️ Über ManagerX" description: "Ein fortschrittlicher Management-Bot entwickelt für professionelle Communities.\nManagerX bietet umfangreiche Tools für Moderation, Statistiken und Server-Verwaltung." dev_header: "## 👨💻 Entwicklung" - dev_info: "Entwickelt von **ManagerX Development**\n❯ [🌐 Website](https://managerx-bot.de)\n❯ [💬 Support Server](https://discord.gg/uDDWzsZNzD)" + dev_info: "Entwickelt von **ManagerX Development**\n❯ [🌐 Website](https://managerx-bot.de)\n❯ [💬 Support Server](https://discord.gg/9T28DWup3g)" stats_header: "## 📊 Statistiken" stats_info: "❯ **Server:** `{server_count}`\n❯ **User:** `{member_count}`\n❯ **Ping:** {ping}\n❯ **Uptime:** {uptime}" tech_header: "## 🛠️ Technik & Versionen" diff --git a/translation/messages/en.yaml b/translation/messages/en.yaml index bb1f281..70bb887 100644 --- a/translation/messages/en.yaml +++ b/translation/messages/en.yaml @@ -131,7 +131,7 @@ cog_about: title: "# ℹ️ About ManagerX" description: "An advanced management bot developed for professional communities.\nManagerX offers comprehensive tools for moderation, statistics, and server management." dev_header: "## 👨💻 Development" - dev_info: "Developed by **ManagerX Development**\n❯ [🌐 Website](https://managerx-bot.de)\n❯ [💬 Support Server](https://discord.gg/uDDWzsZNzD)" + dev_info: "Developed by **ManagerX Development**\n❯ [🌐 Website](https://managerx-bot.de)\n❯ [💬 Support Server](https://discord.gg/9T28DWup3g)" stats_header: "## 📊 Statistics" stats_info: "❯ **Servers:** `{server_count}`\n❯ **Users:** `{member_count}`\n❯ **Ping:** {ping}\n❯ **Uptime:** {uptime}" tech_header: "## 🛠️ Technology & Versions"