-
-
-**ManagerX** ist ein hochmoderner, leistungsstarker Discord-Bot, der speziell fรผr professionelles Community-Management entwickelt wurde. Mit modernster Architektur und einer Vielzahl an Features bietet ManagerX alles, was anspruchsvolle Discord-Server benรถtigen.
+**ManagerX ist ein Discord Bot**, der als hochmoderne und leistungsstarke Lรถsung fรผr das professionelle Community-Management konzipiert wurde. Durch die Verbindung einer robusten Python-Architektur mit einem Echtzeit-Web-Interface bietet ManagerX alles, was anspruchsvolle Server fรผr Skalierung, Sicherheit und Engagement benรถtigen.
-### ๐ Warum ManagerX?
+### ๐ Kernvorteile
-| โก |
-Blazing Fast Optimierte SQLite-Architektur fรผr maximale Performance |
-
-
-| ๐ก๏ธ |
-Enterprise Security Anti-Spam, Moderation-Logs und umfassende Sicherheitsfeatures |
-
-
-| ๐จ |
-Hochgradig Anpassbar Jedes Modul vollstรคndig konfigurierbar fรผr deine Bedรผrfnisse |
-
-
-| ๐ |
-Global Connected Verbinde deine Community mit Servern weltweit via Globalchat |
-
-
-| ๐ |
-Aktive Entwicklung Regelmรครige Updates mit neuen Features und Verbesserungen |
+
+
+**โก Performance & Speed**
+
+Optimierte SQLite-Architektur & Caching fรผr blitzschnelle Reaktionen, selbst bei tausenden Events.
+
+ |
+
+
+**๐ก๏ธ Enterprise Security**
+
+Umfassendes Anti-Spam, Moderations-Logs und granulare Sicherheits-Features fรผr deine Community.
+
+ |
-| ๐ |
-100% Open Source Transparent, community-driven und kostenlos verfรผgbar |
-
-
+ |
+
+**๐จ Vollstรคndige Anpassbarkeit**
+
+Jedes Modul kann รผber das Dashboard oder Command-Interface individuell konfiguriert werden.
|
-
-
-```yaml
-โ๏ธ Technical Specifications
-โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-Status: Production Ready โ
-Current: v2.0.0
-Next Release: v2.1.0 (Q1 2025)
-
-๐ง Technology Stack
-โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-Language: Python 3.10+
-Framework: py-cord + ezcord
-Database: SQLite3
-API: Discord API v10
-Architecture: Modular Cogs System
-
-๐ Deployment
-โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-Platforms: Linux, Windows, macOS
-Hosting: Cloud-Ready
-Requirements: 512MB RAM (1GB+ rec.)
-Uptime: 99.9%+ Verfรผgbarkeit
-
-๐ฆ Active Modules
-โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-โ Advanced Moderation System
-โ Dynamic Leveling & XP Engine
-โ Smart Welcome Automation
-โ Temporary Voice Channels
-โ Global Cross-Server Chat
-โ Real-Time Weather Data
-โ Wikipedia Integration
-โ Comprehensive Statistics
-โ Custom Command Framework
-```
+ |
+
+**๐ Globales Netzwerk**
+
+Verbinde deine Community mit Servern weltweit รผber unser integriertes Globalchat-System.
|
@@ -215,178 +131,64 @@ Uptime: 99.9%+ Verfรผgbarkeit
-## โจ Feature-รbersicht
+## โจ Feature-Deep-Dive
-*Entdecke die leistungsstarken Module von ManagerX*
+*Entdecke die mรคchtigen Werkzeuge von ManagerX*
-
-|
-
### ๐ก๏ธ Moderation & Sicherheit
+*Sicherheit auf Enterprise-Niveau fรผr deinen Server.*
-
-
-**๐ Advanced Moderation Toolkit**
+- **Vollstรคndiges Toolkit**: `/ban`, `/kick`, `/mute`, `/warn`, `/timeout`, `/purge`.
+- **Intelligentes Anti-Spam**: Duplicate Detection, Mention Protection & Link-Filter.
+- **Action-History**: Lรผckenlose Protokollierung aller Moderations-Ereignisse.
+- **Evidence Collection**: Automatisierte Beweissicherung fรผr Moderations-Fรคlle.
-
+### ๐ Community & Engagement
+*Baue eine aktive und loyale Community auf.*
-```yaml
-Moderation Commands:
- /ban - Permanenter Server-Ausschluss
- /kick - User vom Server entfernen
- /mute - Temporรคres Timeout verhรคngen
- /warn - Verwarnungen aussprechen
- /timeout - Zeitlich begrenzte Stummschaltung
- /purge - Massen-Nachrichtenlรถschung
-
-Anti-Spam Engine:
- โ Intelligente Spam-Erkennung
- โ Duplicate Message Detection
- โ Mention Spam Protection
- โ Link & URL Filter
- โ Custom Regex Patterns
- โ Configurable Thresholds
-
-Moderation Logs:
- โ Vollstรคndige Action History
- โ Reason Tracking
- โ Moderator Attribution
- โ Automatic Evidence Collection
- โ Appeal System Ready
-```
+- **Smart Leveling**: Dynamisches XP-System fรผr Voice & Text mit Multiplikatoren.
+- **Auto-Rewards**: Automatische Rollenvergabe bei Stufenaufstiegen.
+- **Interaktive Leaderboards**: Lokale und globale Rankings fรผr maximalen Wettbewerb.
+- **Welcome 2.0**: Hochwertige Embed-Designs und automatisierte Onboarding-Prozesse.
-
+### ๏ฟฝ๏ธ Voice & Automatisierung
+*Dynamische Kanรคle fรผr moderne Kommunikation.*
-### ๐ Community Engagement
-
-
-
-**๐ฎ Gamification & Engagement**
-
-
-
-```yaml
-Levelsystem Features:
- XP System:
- - Vollstรคndig anpassbare XP-Raten
- - Text & Voice Channel XP
- - XP-Multiplier & Boosts
- - Daily/Weekly Bonuses
-
- Rewards:
- - Automatische Rollenbelohnungen
- - Custom Level-Up Messages
- - Achievement System
- - Milestone Rewards
-
- Leaderboards:
- - Server Top Rankings
- - Global Leaderboards
- - Category-Specific Rankings
- - Historical Statistics
-
-Welcome System:
- โ Benutzerdefinierte Embed-Designs
- โ Auto-Role Assignment
- โ Regel- & Info-Nachrichten
- โ User Counter Integration
- โ Custom Welcome Images
- โ Join/Leave Logging
-```
-
- |
-
-
-### ๐ Social & Communication
-
-
-
-**๐ฌ Cross-Server Communication**
-
-
-
-```yaml
-Globalchat System:
- Core Features:
- - Echtzeit Cross-Server Chat
- - Moderierte Kommunikation
- - Server-รผbergreifende Community
- - Report & Block Funktionen
- - User Reputation System
-
- Safety Features:
- โ Content-Filterung
- โ Blacklist System
- โ Admin-Kontrolle
- โ Spam Prevention
- โ Moderation Queue
- โ Appeal Process
-
-Information Tools:
- Wikipedia Integration:
- - Direkte Artikelsuche
- - Formatierte Previews
- - Multi-Language Support
- - Related Articles
- - Quick Summaries
-
- Weather System:
- - Live-Wetterdaten
- - 5-Tage Vorhersage
- - Detaillierte Metriken
- - Location Auto-Detection
- - Weather Alerts
-```
+- **Temporary Voice**: User-gesteuerte Sprachkanรคle mit voller Permission-Control.
+- **Auto-Cleanup**: Intelligente Lรถschung inaktiver Kanรคle spart Ressourcen.
+- **Live-Stats**: Echtzeit-Analysen รผber Voice-Aktivitรคt und User-Engagement.
+- **Toolbox**: Integrationen wie Google-Search, Wetterdaten und Wikipedia.
-### ๐ฎ Interaktive Features
+---
-**๐๏ธ Dynamic Voice & Analytics**
+## โ๏ธ Technischer Stack
-```yaml
-Temporary Voice Channels:
- User Control:
- โ Eigene Voice-Channel erstellen
- โ Custom Namen & Beschreibung
- โ User-Limit Management
- โ Permission Control
- โ Channel Transfer
-
- Automation:
- - Auto-Delete bei Inaktivitรคt
- - Category Organization
- - Template System
- - VIP Channel Options
-
-Stats & Analytics:
- Real-Time Metrics:
- - Server Activity Tracking
- - User Engagement Stats
- - Command Usage Analytics
- - Voice Channel Statistics
- - Growth Metrics
-
- Reports:
- โ Daily/Weekly Summaries
- โ Performance Dashboards
- โ Member Insights
- โ Trend Analysis
-```
-
- |
+
+
+| Kern |
+Python 3.10+, Pycord, Ezcord |
-
-
+
+| Interface |
+FastAPI, React (Vite), TailwindCSS, Lucide Icons |
+
+
+| Daten |
+SQLite3 (lokal), JSON-Analytics |
+
+
+| Deployment |
+Docker-ready, Linux/Windows/macOS Unterstรผtzung |
---
@@ -395,56 +197,31 @@ Stats & Analytics:
## ๐ Installation & Setup
-*Starte ManagerX in wenigen Minuten*
+*Starte dein Community-Management in wenigen Minuten*
-### ๐ Systemanforderungen
+### ๐ Voraussetzungen
|
-**Minimum Requirements**
-
-```yaml
-Operating System:
- - Linux (Ubuntu 20.04+)
- - Windows 10/11
- - macOS 11+
-
-Software:
- - Python 3.10 oder hรถher
- - pip (Python Package Manager)
- - Git 2.0+
-
-Resources:
- - RAM: 512 MB minimum
- - Storage: 200 MB freier Speicher
- - Network: Stabile Internetverbindung
-```
+**System-Anforderungen**
+- Python 3.10 oder hรถher
+- Git 2.0+
+- RAM: 512 MB minimum (1 GB empfohlen)
+- OS: Linux (Ubuntu rec.), Windows, macOS
|
-**Empfohlene Konfiguration**
-
-```yaml
-Production Environment:
- - Linux Server (Ubuntu 22.04 LTS)
- - Python 3.11+
- - 1 GB+ RAM
- - SSD Storage
- - 24/7 Uptime Hosting
-
-Optional Services:
- - Discord Bot Token (Required)
- - Weather API Key (Optional)
- - Custom Domain (Optional)
- - SSL Certificate (Optional)
-```
+**Zusรคtzliche Dienste**
+- Discord Bot Token ([Developer Portal](https://discord.com/developers/applications))
+- Weather API Key ([OpenWeatherMap](https://openweathermap.org/api)) - *Optional*
+- Eigene Domain & SSL - *Optional fรผr Dashboard*
|
@@ -452,194 +229,65 @@ Optional Services:
-### โก Installation Guide
+### โก Schritt-fรผr-Schritt Anleitung
-๐ง Linux / macOS Installation (Click to expand)
-
-
+๐ง Linux / ๐ macOS Setup (Klicken zum Aufklappen)
```bash
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 1: Repository klonen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 1. Repository klonen
git clone https://github.com/Oppro-net-Development/ManagerX.git
cd ManagerX
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 2: Virtual Environment erstellen (empfohlen)
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 2. Virtual Environment & Dependencies
python3 -m venv venv
source venv/bin/activate
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 3: Dependencies installieren
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-pip install --upgrade pip
pip install -r requirements.txt
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 4: Konfiguration erstellen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 3. Konfiguration erstellen
cp .env.example .env
-nano .env # Passe TOKEN und andere Einstellungen an
+nano .env # Token und Einstellungen anpassen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 5: Erste Datenbankinitialisierung
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 4. Datenbank initialisieren & Start
python -c "from utils.database import init_db; init_db()"
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 6: Bot starten
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
python main.py
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Optional: Systemd Service erstellen (fรผr 24/7 Betrieb)
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-sudo nano /etc/systemd/system/managerx.service
-# Fรผge Service-Konfiguration hinzu (siehe Dokumentation)
-sudo systemctl enable managerx
-sudo systemctl start managerx
```
-๐ช Windows Installation (Click to expand)
-
-
+๐ช Windows Setup (Klicken zum Aufklappen)
```powershell
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 1: Repository klonen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 1. Repository klonen
git clone https://github.com/Oppro-net-Development/ManagerX.git
cd ManagerX
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 2: Virtual Environment erstellen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 2. Virtual Environment & Dependencies
python -m venv venv
venv\Scripts\activate
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 3: Dependencies installieren
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-python -m pip install --upgrade pip
pip install -r req.txt
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 4: Konfiguration erstellen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 3. Konfiguration erstellen
copy .env.example .env
-notepad .env # TOKEN und Einstellungen anpassen
+notepad .env # Token und Einstellungen anpassen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 5: Datenbank initialisieren
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+# 4. Datenbank initialisieren & Start
python -c "from utils.database import init_db; init_db()"
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Step 6: Bot starten
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
python main.py
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Optional: Als Windows Service einrichten
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Siehe Dokumentation fรผr NSSM Setup
```
-### ๐ง Konfiguration
-
-
-
-|
-
-**Environment Variables (.env)**
-
-```bash
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Discord Bot Configuration
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-DISCORD_TOKEN=your_bot_token_here
-DISCORD_CLIENT_ID=your_client_id
-DISCORD_CLIENT_SECRET=your_client_secret
-DISCORD_REDIRECT_URI=http://localhost:8080/callback
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Optional API Keys
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-WEATHER_API=your_openweathermap_api_key
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Bot Settings
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-BOT_PREFIX=!
-DEBUG_MODE=false
-LOG_LEVEL=INFO
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Database Configuration
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-DATABASE_PATH=./data/managerx.db
-BACKUP_ENABLED=true
-BACKUP_INTERVAL=24h
-```
-
- |
-
-
-**๐ Token erstellen**
-
-1. Besuche [Discord Developer Portal](https://discord.com/developers/applications)
-2. Klicke auf "New Application"
-3. Gehe zu "Bot" โ "Add Bot"
-4. Kopiere den Token
-5. Fรผge ihn in `.env` ein
-
-**๐ Wichtige Berechtigungen**
-
-```yaml
-Required Intents:
- โ Server Members Intent
- โ Message Content Intent
- โ Presence Intent
-
-Bot Permissions:
- โ Manage Roles
- โ Manage Channels
- โ Kick Members
- โ Ban Members
- โ Send Messages
- โ Embed Links
- โ Attach Files
- โ Manage Messages
- โ Read Message History
-```
-
-**๐ฆ๏ธ Weather API**
-
-Kostenloser API-Key: [OpenWeatherMap](https://openweathermap.org/api)
-
- |
-
-
-
-
-
---
-## ๐ Version History & Roadmap
+## ๐ Roadmap & History
-*Entwicklungsgeschichte und zukรผnftige Features*
+*Unsere Vision fรผr die Zukunft von ManagerX*
@@ -649,169 +297,45 @@ Kostenloser API-Key: [OpenWeatherMap](https://openweathermap.org/api)
```mermaid
gantt
- title ManagerX Development Timeline
+ title ManagerX Entwicklungs-Timeline
dateFormat YYYY-MM-DD
- section Releases
- v1.0.0 Initial Release :done, 2023-01-01, 30d
- v1.5.0 Welcome System :done, 2023-05-01, 45d
- v1.6.0 Levelsystem :done, 2023-08-01, 60d
- v1.7.0 TempVC System :done, 2023-11-01, 45d
+ section Release-Zyklen
v2.0.0 Major Refactor :done, 2024-06-01, 90d
v2.1.0 Enhancements :active, 2025-01-01, 60d
v2.5.0 Advanced Features :2025-04-01, 90d
+ v3.0.0 Web-only Dash :2025-10-01, 120d
```
-
-
-| Version |
-Status |
-Datum |
-Key Features |
-
-
-| v2.1.0 |
-๐ In Dev |
-Q1 2025 |
-
-โข Performance Optimierungen
-โข Bug Fixes & Stability
-โข Enhanced Error Handling
-โข UI/UX Improvements
- |
-
-
-| v2.0.0 |
-โ
Current |
-2024-12 |
-
-โข Komplettes Code Refactoring
-โข Globalchat v2 Launch
-โข Enhanced Statistics Module
-โข Improved Database Architecture
- |
-
-
-| v1.7.1 |
-๐ฆ Stable |
-2024-08 |
-
-โข Feature Enhancements
-โข Critical Bug Fixes
-โข Security Updates
- |
-
-
-| v1.7.0 |
-๐ฆ Archived |
-2024-05 |
-
-โข TempVC System Implementation
-โข Dynamic Voice Channel Management
-โข User Control Features
- |
-
-
-| v1.6.0 |
-๐ฆ Archived |
-2024-02 |
-
-โข Advanced Levelsystem
-โข XP & Rewards Engine
-โข Leaderboard System
- |
-
-
-| v1.5.0 |
-๐ฆ Archived |
-2023-11 |
-
-โข Welcome System Launch
-โข Auto-Role Assignment
-โข Custom Embeds
- |
-
-
-
-
+### ๐บ๏ธ Meilensteine
-### ๐บ๏ธ Roadmap
+- [x] **v2.0.0**: Kompletter Code-Rewrite, Globalchat v2 & neues API-Backend.
+- [/] **v2.1.0**: Performance-Optimierungen, Enhanced Error Recovery & UI/UX Politur.
+- [ ] **v2.2.0**: Ticket-System, Fortgeschrittene Umfragen, Musik-Modul 2.0.
+- [ ] **v2.5.0**: Plugin-System fรผr Third-Party Module, Deep Learning Moderation.
-
-
-
+
-**๐ฏ v2.1.0 - Q1 2025**
+---
-```yaml
-Focus: Stability & Polish
+
-Features:
- - Performance Tuning
- - Memory Optimization
- - Enhanced Logging
- - Bug Fixes
+## ๐ค Mitwirken & Entwicklung
-Improvements:
- - Error Recovery
- - Database Indexing
- - Command Response Time
- - Resource Management
-```
+Werde Teil unserer Open-Source Community!
- |
-
-
-**๐ v2.2.0 - Q2 2025**
-
-```yaml
-Focus: New Features
-
-Planned Features:
- - Ticket System
- - Advanced Polls
- - Music Module
- - Custom Commands 2.0
-
-Enhancements:
- - AI Integration
- - Multi-Language Support
- - Enhanced Analytics
- - API Webhooks
-```
-
- |
-
-
-**๐ซ v2.3.0 - Q4 2025**
-
-```yaml
-Focus: Major Upgrade
-
-Revolutionary Features:
- - Web Dashboard
- - Mobile App Support
- - Plugin System
- - Advanced AI Features
-
-Architecture:
- - Microservices
- - Cloud-Native
- - Horizontal Scaling
- - GraphQL API
-```
+
- |
+
+
+**๐ Bugs** [Melden โ](https://github.com/Oppro-net-Development/ManagerX/issues) |
+**โจ Features** [Vorschlagen โ](https://github.com/Oppro-net-Development/ManagerX/issues) |
+**๐ป PRs** [Beitregen โ](https://github.com/Oppro-net-Development/ManagerX/pulls) |
+**๐ Docs** [Verbessern โ][def] |
-
-
-
-
-[๐ **Vollstรคndiges Changelog anzeigen** โ](CHANGELOG.md)
-
@@ -820,161 +344,23 @@ Architecture:
-## ๐ค Contributing & Development
-
-*Werde Teil unseres Open-Source Projekts!*
+## ๐ฌ Support & Community
-
+Brauchst du Hilfe? Tritt unserer Community bei!
-### ๐ก Wie kann ich beitragen?
-
-
-
-
-
-**๐ Bug Reports**
-
-Fehler gefunden?
-[Issue erstellen โ](https://github.com/Oppro-net-Development/ManagerX/issues/new?template=bug_report.md)
-
- |
-
-
-**โจ Feature Requests**
-
-Idee fรผr ein Feature?
-[Feature vorschlagen โ](https://github.com/Oppro-net-Development/ManagerX/issues/new?template=feature_request.md)
-
- |
-
-
-**๐ป Code Beitrรคge**
-
-Code beisteuern?
-[Pull Request โ](https://github.com/Oppro-net-Development/ManagerX/pulls)
-
- |
-
-
-**๐ Dokumentation**
-
-Docs verbessern?
-[Docs bearbeiten โ](https://github.com/Oppro-net-Development/ManagerX-Docs)
-
- |
-
-
+[](https://discord.gg/oppro)
+[](https://twitter.com/ManagerX)
+[](https://managerx-bot.de)
-### ๐ Commit-Konventionen
-
-Wir verwenden standardisierte Commit-Prefixes fรผr bessere Nachvollziehbarkeit:
-
-
-
-| Prรคfix |
-Verwendung |
-Beispiel |
-
-
-โจ FEATURE: |
-Neue Funktion hinzugefรผgt |
-โจ FEATURE: Add weather command integration |
-
-
-๐ UPDATE: |
-Bestehende Funktion verbessert |
-๐ UPDATE: Improve levelsystem performance by 40% |
-
-
-๐ BUGFIX: |
-Bug behoben (normal) |
-๐ BUGFIX: Fix welcome message formatting issue |
-
-
-๐ HOTFIX: |
-Kritischer Bug behoben |
-๐ HOTFIX: Resolve critical database connection error |
-
-
-๐ DOCS: |
-Dokumentation aktualisiert |
-๐ DOCS: Update installation guide with troubleshooting |
-
-
-๐๏ธ DELETE: |
-Code/Feature entfernt |
-๐๏ธ DELETE: Remove deprecated legacy commands |
-
-
-๐จ STYLE: |
-Code-Style รnderungen |
-๐จ STYLE: Refactor code to match PEP 8 standards |
-
-
-โป๏ธ REFACTOR: |
-Code-Umstrukturierung |
-โป๏ธ REFACTOR: Restructure database module architecture |
-
-
-โก PERF: |
-Performance-Verbesserung |
-โก PERF: Optimize query execution time |
-
-
-๐งช TEST: |
-Tests hinzugefรผgt/geรคndert |
-๐งช TEST: Add unit tests for moderation module |
-
-
-
+**ManagerX** wird mit โค๏ธ von [OPPRO.NET](https://oppro-network.de) entwickelt.
+*Copyright ยฉ 2026 ManagerX Development โข Lizenziert unter GPL-3.0*
-### ๐ Versionierungs-Schema
-
-Um maximale Transparenz und Aktualitรคt zu gewรคhrleisten, nutzen wir eine duale Strategie:
-
-* **GitHub (Source Code):** Nutzt das **Semantic Versioning** (Beispiel: `2.0.0`). Dies markiert groรe Meilensteine und strukturelle รnderungen im Code.
-* **PyPI (Distribution):** Nutzt **CalVer (Calendar Versioning)** (Beispiel: `2.2026.1.9.1`). Dies ermรถglicht es Entwicklern, sofort zu erkennen, wie aktuell das installierte Paket ist.
-
-| Plattform | Schema | Beispiel |
-| :--- | :--- | :--- |
-| **GitHub** | MAJOR.MINOR.PATCH | `2.0.0` |
-| **PyPI** | MAJOR.JJJJ.MM.TT | `2.2026.01.09.1` |
-
-### ๐ง Development Workflow
-
-```bash
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# 1. Repository forken & klonen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-git clone https://github.com/YOUR_USERNAME/ManagerX.git
-cd ManagerX
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# 2. Development Branch erstellen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-git checkout -b feature/amazing-feature
-# Oder fรผr Bugfixes:
-git checkout -b bugfix/fix-critical-issue
+
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# 3. Development Environment aufsetzen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-python -m venv venv
-source venv/bin/activate # Windows: venv\Scripts\activate
-pip install -r requirements-dev.txt
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# 4. รnderungen vornehmen und testen
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# Code schreiben...
-python main.py # Bot testen
-pytest tests/ # Unit Tests ausfรผhren
-
-# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-# 5. Code Style prรผfen
-#
+[def]: https://github.com/Oppro-net-Development/ManagerX-Docs
+```
\ No newline at end of file
diff --git a/config/example.env b/config/example.env
new file mode 100644
index 0000000..b2561c8
--- /dev/null
+++ b/config/example.env
@@ -0,0 +1,11 @@
+TOKEN=abc123
+WEATHER_API=abc123
+ERROR_WEBHOOK=https://discord.com/api/webhooks
+
+DISCORD_CLIENT_ID=12345678900
+DISCORD_CLIENT_SECRET=abc123
+DISCORD_REDIRECT_URI=https://
+
+URL=https://
+
+DASHBOARD_API_KEYS=abc123
\ No newline at end of file
diff --git a/examples/bot/cog.py b/examples/bot/cog.py
index 8657882..c7f6eed 100644
--- a/examples/bot/cog.py
+++ b/examples/bot/cog.py
@@ -1,9 +1,9 @@
import discord
import ezcord
-class Cog(ezcord.Cog): # Create a cog
+class ExampleCog(ezcord.Cog): # Create a cog
def __init__(self, bot): # Initialize the cog
self.bot = bot # Set the bot
def setup(bot):
- bot.add_cog(Cog(bot)) # Add the cog to the bot
\ No newline at end of file
+ bot.add_cog(ExampleCog(bot)) # Add the cog to the bot
\ No newline at end of file
diff --git a/examples/bot/embeds.py b/examples/bot/embeds.py
index ac19583..8d0fef0 100644
--- a/examples/bot/embeds.py
+++ b/examples/bot/embeds.py
@@ -4,7 +4,7 @@
from discord import slash_command
import ezcord
-class Embeds(ezcord.Cog):
+class ExampleEmbeds(ezcord.Cog):
def __init__(self, bot):
self.bot = bot
@@ -32,4 +32,4 @@ async def embed(self, ctx):
await ctx.respond(embed=embed)
def setup(bot):
- bot.add_cog(Embeds(bot)) # Add the Cog to the Bot
\ No newline at end of file
+ bot.add_cog(ExampleEmbeds(bot)) # Add the Cog to the Bot
\ No newline at end of file
diff --git a/examples/bot/slash_command.py b/examples/bot/slash_command.py
index bf8f46e..1151079 100644
--- a/examples/bot/slash_command.py
+++ b/examples/bot/slash_command.py
@@ -2,7 +2,7 @@
import ezcord
from discord import slash_command
-class SlashCommand(ezcord.Cog):
+class ExampleSlashCommand(ezcord.Cog):
def __init__(self, bot):
self.bot = bot
@@ -11,4 +11,4 @@ async def ping(self, ctx): # Define the slash command
await ctx.respond("Pong!") # Send a message
def setup(bot):
- bot.add_cog(SlashCommand(bot))
\ No newline at end of file
+ bot.add_cog(ExampleSlashCommand(bot))
\ No newline at end of file
diff --git a/examples/bot/views/buttons.py b/examples/bot/views/buttons.py
new file mode 100644
index 0000000..a1e8b55
--- /dev/null
+++ b/examples/bot/views/buttons.py
@@ -0,0 +1,29 @@
+import discord
+from discord import slash_command
+import ezcord
+
+class ExampleButtonsCog(ezcord.Cog):
+ def __init__(self, bot: ezcord.Bot):
+ self.bot = bot
+
+ @slash_command(description="Button Example")
+ async def buttons(self, ctx):
+ await ctx.respond("Click here:", view=ExampleButtonView()) # Send the button
+
+async def setup(bot):
+ bot.add_cog(ExampleButtonsCog(bot))
+
+
+class ExampleButtonView(discord.ui.View): # Create a view
+ def __init__(self):
+ super().__init__()
+
+ @discord.ui.button(label="Click Me", style=discord.ButtonStyle.primary) # Create a button
+ async def button_callback(self, button, interaction): # Define the button
+ await interaction.response.send_message("You clicked the button!") # Send a message
+
+ # Your can more Buttons adding in a View.
+
+ @discord.ui.button(label="Delete", style=discord.ButtonStyle.danger) # Create a button
+ async def delete_callback(self, button, interaction): # Define the button
+ await interaction.message.delete() # Delete the message
\ No newline at end of file
diff --git a/examples/bot/containers.py b/examples/bot/views/containers.py
similarity index 77%
rename from examples/bot/containers.py
rename to examples/bot/views/containers.py
index 264dfb8..f7e56f2 100644
--- a/examples/bot/containers.py
+++ b/examples/bot/views/containers.py
@@ -2,7 +2,7 @@
# First import the Modul
import discord
-from discord.ui import Container # Import the Container Modul
+from discord.ui import Container # Import the Container Class
import ezcord
class ContainerExample(ezcord.Cog):
@@ -11,15 +11,12 @@ def __init__(self, bot):
@discord.slash_command(name="container", description="Zeigt ein Container an")
async def container(self, ctx: discord.ApplicationContext):
- container = Container() # Define the Container
+ container = Container(color=discord.Color.blue()) # Define the Container with a color
container.add_text("## Hello World") # Add a Markdown Text to the Container
container.add_separator() # Add a Separator to the Container
container.add_text("Hello World") # Add a Text to the Container
view = discord.ui.DesignerView(container, timeout=0) # Define the View
- await ctx.respond(view=view)
+ await ctx.respond(view=view) # Send the View
def setup(bot):
bot.add_cog(ContainerExample(bot)) # Add the Cog to the Bot
-
-
-
\ No newline at end of file
diff --git a/main.py b/main.py
index 05a36d5..5cac787 100644
--- a/main.py
+++ b/main.py
@@ -35,6 +35,7 @@
# API Routes fรผr Dashboard
from src.api.dashboard.routes import set_bot_instance, router as dashboard_router
+from mx_handler import TranslationHandler
# =============================================================================
# SETUP
@@ -43,6 +44,15 @@
load_dotenv(dotenv_path=BASEDIR / 'config' / '.env')
colorama_init(autoreset=True)
+TranslationHandler.settings(
+ path="translation/messages",
+ default_lang="de",
+ fallback_langs=("en", "de"),
+ logging=False,
+ colored=False,
+ log_level="DEBUG"
+)
+
# Sys-Path
if str(BASEDIR) not in sys.path:
sys.path.append(str(BASEDIR))
@@ -111,17 +121,16 @@ async def start_webserver():
dashboard = DashboardTask(bot, BASEDIR)
dashboard.register()
- # Event Handler
@bot.event
async def on_ready():
logger.success("BOT", f"Logged in as {bot.user.name}")
# --- NEU: Status API & Webserver starten ---
bot.loop.create_task(start_webserver())
-
+
# Dashboard starten
dashboard.start()
-
+
# Bot-Status
if config['features'].get('bot_status', True):
await bot.change_presence(
@@ -130,11 +139,20 @@ async def on_ready():
name=f"ManagerX v{BotConfig.VERSION}"
)
)
-
+
# 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)
+ root_slots = [c for c in all_cmds if isinstance(c, discord.SlashCommand)]
+
+ logger.info("LIMITS", f"EzCord zรคhlt (alle Funktionen): {len(bot.commands)}")
+ logger.info("LIMITS", f"Discord-API Slots belegt: {len(root_slots)} / 100")
+ # --- LIMIT CHECK ENDE ---
+
# Minimaler KeepAlive Cog
class KeepAlive(discord.ext.commands.Cog):
def __init__(self, bot):
@@ -156,7 +174,6 @@ async def on_ready(self):
"src/bot/cogs",
subdirectories=True,
ignored_cogs=ignored,
- log=CogLog.sum
)
logger.success("BOT", "Cogs geladen")
diff --git a/.github/renovate.json b/renovate.json
similarity index 100%
rename from .github/renovate.json
rename to renovate.json
diff --git a/src/bot/cogs/bot/about.py b/src/bot/cogs/bot/about.py
index c3c07e8..758f20f 100644
--- a/src/bot/cogs/bot/about.py
+++ b/src/bot/cogs/bot/about.py
@@ -2,6 +2,7 @@
import platform
import discord
from discord.ext import commands
+import psutil
import ezcord
from mx_handler import TranslationHandler
@@ -33,7 +34,7 @@ async def about(self, ctx: discord.ApplicationContext):
member_count = sum(g.member_count for g in self.bot.guilds)
# Create Container
- container = discord.ui.Container()
+ container = discord.ui.Container(color=discord.Color.red())
# Header
title = await TranslationHandler.get_for_user(self.bot, ctx.author.id, "cog_about.messages.title")
@@ -76,6 +77,39 @@ async def about(self, ctx: discord.ApplicationContext):
container.add_text(tech_info)
container.add_separator()
+ # System
+ system_header = await TranslationHandler.get_for_user(self.bot, ctx.author.id, "cog_about.messages.system_header")
+
+ # Gather System Info
+ os_info = f"{platform.system()} {platform.release()}"
+
+ memory = psutil.virtual_memory()
+ ram_info = f"{memory.used / (1024 ** 3):.2f} GB / {memory.total / (1024 ** 3):.2f} GB"
+
+ # CPU can be 0 on first call without interval, but blocking is bad.
+ # We'll stick to non-blocking.
+ cpu_usage = f"{psutil.cpu_percent()}%"
+
+ try:
+ if platform.system() == "Windows":
+ storage_info = "N/A"
+ else:
+ disk = psutil.disk_usage("/")
+ storage_info = f"{disk.used / (1024 ** 3):.2f} GB / {disk.total / (1024 ** 3):.2f} GB"
+ except Exception:
+ storage_info = "N/A"
+
+ system_info = await TranslationHandler.get_for_user(self.bot, ctx.author.id, "cog_about.messages.system_info",
+ os=os_info,
+ ram=ram_info,
+ cpu=cpu_usage,
+ storage=storage_info
+ )
+
+ container.add_text(system_header)
+ container.add_text(system_info)
+ container.add_separator()
+
# Footer
footer = await TranslationHandler.get_for_user(self.bot, ctx.author.id, "cog_about.messages.footer",
year=datetime.now().year,
diff --git a/src/bot/cogs/bot/admin.py b/src/bot/cogs/bot/admin.py
new file mode 100644
index 0000000..be68a64
--- /dev/null
+++ b/src/bot/cogs/bot/admin.py
@@ -0,0 +1,620 @@
+import discord
+from discord import SlashCommandGroup
+import ezcord
+from discord.ui import Container, View, Button
+import sys
+import os
+import psutil
+import platform
+from datetime import datetime
+import asyncio
+from pathlib import Path
+import math
+import subprocess
+
+ALLOWED_IDS = [1427994077332373554]
+
+class ServerListView(View):
+ def __init__(self, guilds, page=0, per_page=20):
+ super().__init__(timeout=180) # 3 Minuten Timeout
+ self.guilds = guilds
+ self.page = page
+ self.per_page = per_page
+ self.max_pages = math.ceil(len(guilds) / per_page)
+
+ self.update_buttons()
+
+ def update_buttons(self):
+ # Entferne alle Buttons
+ self.clear_items()
+
+ # Erste Seite Button
+ first_button = Button(
+ label="โฎ๏ธ",
+ style=discord.ButtonStyle.gray,
+ disabled=(self.page == 0)
+ )
+ first_button.callback = self.first_page
+ self.add_item(first_button)
+
+ # Vorherige Seite Button
+ prev_button = Button(
+ label="โ๏ธ",
+ style=discord.ButtonStyle.primary,
+ disabled=(self.page == 0)
+ )
+ prev_button.callback = self.previous_page
+ self.add_item(prev_button)
+
+ # Seiten-Anzeige (deaktivierter Button)
+ page_button = Button(
+ label=f"Seite {self.page + 1}/{self.max_pages}",
+ style=discord.ButtonStyle.gray,
+ disabled=True
+ )
+ self.add_item(page_button)
+
+ # Nรคchste Seite Button
+ next_button = Button(
+ label="โถ๏ธ",
+ style=discord.ButtonStyle.primary,
+ disabled=(self.page >= self.max_pages - 1)
+ )
+ next_button.callback = self.next_page
+ self.add_item(next_button)
+
+ # Letzte Seite Button
+ last_button = Button(
+ label="โญ๏ธ",
+ style=discord.ButtonStyle.gray,
+ disabled=(self.page >= self.max_pages - 1)
+ )
+ last_button.callback = self.last_page
+ self.add_item(last_button)
+
+ def get_page_container(self):
+ start = self.page * self.per_page
+ end = start + self.per_page
+ page_guilds = self.guilds[start:end]
+
+ guilds_text = "\n".join([
+ f"**{i + start + 1}.** {guild.name}\n`ID: {guild.id}` โข {guild.member_count:,} Mitglieder"
+ for i, guild in enumerate(page_guilds)
+ ])
+
+ container = Container(color=discord.Color.blue())
+ container.add_text(f"# ๐ Server-Liste (Seite {self.page + 1}/{self.max_pages})")
+ container.add_separator()
+ container.add_text(guilds_text if guilds_text else "*Keine Server auf dieser Seite*")
+ container.add_separator()
+ container.add_text(f"**Gesamt:** {len(self.guilds):,} Server โข **Zeige:** {start + 1}-{min(end, len(self.guilds))}")
+
+ return container
+
+ async def first_page(self, interaction: discord.Interaction):
+ self.page = 0
+ self.update_buttons()
+ await interaction.response.edit_message(
+ view=discord.ui.DesignerView(self.get_page_container(), view=self, timeout=180)
+ )
+
+ async def previous_page(self, interaction: discord.Interaction):
+ self.page = max(0, self.page - 1)
+ self.update_buttons()
+ await interaction.response.edit_message(
+ view=discord.ui.DesignerView(self.get_page_container(), view=self, timeout=180)
+ )
+
+ async def next_page(self, interaction: discord.Interaction):
+ self.page = min(self.max_pages - 1, self.page + 1)
+ self.update_buttons()
+ await interaction.response.edit_message(
+ view=discord.ui.DesignerView(self.get_page_container(), view=self, timeout=180)
+ )
+
+ async def last_page(self, interaction: discord.Interaction):
+ self.page = self.max_pages - 1
+ self.update_buttons()
+ await interaction.response.edit_message(
+ view=discord.ui.DesignerView(self.get_page_container(), view=self, timeout=180)
+ )
+
+ async def on_timeout(self):
+ # Deaktiviere alle Buttons nach Timeout
+ for item in self.children:
+ item.disabled = True
+
+class admin(ezcord.Cog, hidden=True):
+ def __init__(self, bot):
+ self.bot = bot
+ self.start_time = datetime.now()
+ self.cogs_path = Path("src/bot/cogs")
+
+ admin = SlashCommandGroup("admin", "Admin commands")
+ bot = admin.create_subgroup("bot", "Bot commands")
+ system = admin.create_subgroup("system", "System commands")
+ server = admin.create_subgroup("server", "Server management commands")
+
+ async def cog_check(self, ctx):
+ if ctx.author.id not in ALLOWED_IDS:
+ await ctx.respond("Zugriff verweigert: Deine ID ist nicht autorisiert.", ephemeral=True)
+ return False
+ return True
+
+ def get_all_cogs(self):
+ """Scannt das Cogs-Verzeichnis und gibt alle verfรผgbaren Cogs zurรผck"""
+ cogs = []
+ if not self.cogs_path.exists():
+ return cogs
+
+ for category_dir in self.cogs_path.iterdir():
+ if category_dir.is_dir() and not category_dir.name.startswith('_'):
+ for cog_file in category_dir.glob('*.py'):
+ if not cog_file.name.startswith('_'):
+ # Format: category.cogname
+ cog_path = f"{category_dir.name}.{cog_file.stem}"
+ cogs.append(cog_path)
+
+ return sorted(cogs)
+
+ def format_cog_path(self, cog_input: str):
+ """Formatiert den Cog-Pfad korrekt"""
+ # Wenn bereits im Format "category.cog", direkt verwenden
+ if '.' in cog_input:
+ category, cog_name = cog_input.split('.', 1)
+ return f"src.bot.cogs.{category}.{cog_name}"
+
+ # Ansonsten nach dem Cog in allen Kategorien suchen
+ for category_dir in self.cogs_path.iterdir():
+ if category_dir.is_dir() and not category_dir.name.startswith('_'):
+ cog_file = category_dir / f"{cog_input}.py"
+ if cog_file.exists():
+ return f"src.bot.cogs.{category_dir.name}.{cog_input}"
+
+ # Fallback
+ return f"src.bot.cogs.{cog_input}"
+
+ # ===== SYSTEM COMMANDS =====
+
+ @system.command(name="shutdown", description="Stoppt den Bot-Prozess")
+ async def shutdown(self, ctx: discord.ApplicationContext):
+ container = Container(color=discord.Color.red())
+ container.add_text("# โ ๏ธ ManagerX wird heruntergefahren...")
+ container.add_separator()
+ container.add_text("Dies kann ein paar Sekunden dauern.")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ await self.bot.close()
+ sys.exit()
+
+ @system.command(name="restart", description="Startet den Bot neu")
+ async def restart(self, ctx: discord.ApplicationContext):
+ container = Container(color=discord.Color.orange())
+ container.add_text("# ๐ ManagerX wird neugestartet...")
+ container.add_separator()
+ container.add_text("Der Bot sollte in wenigen Sekunden wieder online sein.")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ await self.bot.close()
+ os.execv(sys.executable, ['python'] + sys.argv)
+
+ @system.command(name="info", description="Zeigt System-Informationen an")
+ async def system_info(self, ctx: discord.ApplicationContext):
+ # CPU Informationen
+ cpu_percent = psutil.cpu_percent(interval=1)
+ cpu_count_physical = psutil.cpu_count(logical=False) or "N/A"
+ cpu_count_logical = psutil.cpu_count(logical=True) or "N/A"
+ cpu_freq = psutil.cpu_freq()
+
+ # RAM Informationen
+ ram = psutil.virtual_memory()
+ ram_used = ram.used / (1024 ** 3)
+ ram_total = ram.total / (1024 ** 3)
+ ram_percent = ram.percent
+ ram_available = ram.available / (1024 ** 3)
+
+ # Disk Informationen - Dynamisch fรผr Windows und Linux
+ # Nutze os.path.abspath(os.sep) fรผr das System-Laufwerk
+ disk_path = os.path.abspath(os.sep)
+ try:
+ disk = psutil.disk_usage(disk_path)
+ disk_used_str = f"{disk.used / (1024 ** 3):.2f} GB"
+ disk_total_str = f"{disk.total / (1024 ** 3):.2f} GB"
+ disk_percent = disk.percent
+ disk_free_str = f"{disk.free / (1024 ** 3):.2f} GB"
+ except Exception:
+ disk_used_str = "N/A"
+ disk_total_str = "N/A"
+ disk_percent = 0
+ disk_free_str = "N/A"
+
+ # Pfad fรผr die Anzeige formatieren (Forward Slashes verhindern Markdown-Escaping auf Windows)
+ display_path = disk_path.replace("\\", "/")
+
+ # Uptime berechnen
+ uptime = datetime.now() - self.start_time
+ days = uptime.days
+ hours, remainder = divmod(uptime.seconds, 3600)
+ minutes, seconds = divmod(remainder, 60)
+
+ # CPU Frequenz formatieren
+ cpu_freq_current = f"{cpu_freq.current:.0f} MHz" if cpu_freq else "N/A"
+ cpu_freq_max = f"{cpu_freq.max:.0f} MHz" if cpu_freq and cpu_freq.max > 0 else "N/A"
+
+ container = Container(color=discord.Color.blue())
+ container.add_text("# ๐ฅ๏ธ System-Informationen")
+ container.add_separator()
+
+ # Betriebssystem
+ container.add_text("## ๐ป Betriebssystem")
+ container.add_text(f"**OS:** {platform.system()} ({platform.release()})")
+ container.add_text(f"**Version:** {platform.version()}")
+ container.add_text(f"**Architektur:** {platform.machine()}")
+ container.add_text(f"**Python:** {platform.python_version()}")
+ container.add_text(f"**Py-cord:** {discord.__version__}")
+
+ # CPU Modell ermitteln (speziell fรผr Linux/vServer)
+ def get_cpu_model():
+ try:
+ cmd = "cat /proc/cpuinfo | grep 'model name' | head -n 1 | cut -d ':' -f 2"
+ model = subprocess.check_output(cmd, shell=True).decode().strip()
+ return model if model else platform.processor()
+ except:
+ # Fallback fรผr Windows oder wenn cat/grep fehlt
+ if platform.system() == "Windows":
+ return platform.processor()
+ return "AMD Ryzen 9 7900" # User-Wunsch Fallback
+
+ cpu_model = get_cpu_model()
+
+ # CPU Informationen
+ container.add_text("## โ๏ธ CPU")
+ container.add_text(f"**Prozessor:** {cpu_model or 'Unbekannt'}")
+ container.add_text(f"**Kerne:** {cpu_count_physical} Physisch, {cpu_count_logical} Logisch")
+ container.add_text(f"**Frequenz:** {cpu_freq_current} (Max: {cpu_freq_max})")
+
+ # CPU Auslastungs-Balken
+ cpu_bar = "โ" * int(cpu_percent / 10) + "โ" * (10 - int(cpu_percent / 10))
+ container.add_text(f"**Auslastung:** `{cpu_bar}` {cpu_percent}%")
+
+ container.add_separator()
+
+ # RAM Informationen
+ container.add_text("## ๐ง Arbeitsspeicher (RAM)")
+ container.add_text(f"**Gesamt:** {ram_total:.2f} GB")
+ container.add_text(f"**Verwendet:** {ram_used:.2f} GB ({ram_percent}%)")
+ container.add_text(f"**Verfรผgbar:** {ram_available:.2f} GB")
+
+ # RAM Auslastungs-Balken
+ ram_bar = "โ" * int(ram_percent / 10) + "โ" * (10 - int(ram_percent / 10))
+ container.add_text(f"`{ram_bar}` {ram_percent}%")
+
+ container.add_separator()
+
+ # Disk Informationen
+ container.add_text("## ๐พ Festplatte")
+ container.add_text(f"**Pfad:** `{display_path}`")
+ container.add_text(f"**Gesamt:** {disk_total_str}")
+ container.add_text(f"**Verwendet:** {disk_used_str} ({disk_percent}%)")
+ container.add_text(f"**Frei:** {disk_free_str}")
+
+ # Disk Auslastungs-Balken
+ disk_bar = "โ" * int(disk_percent / 10) + "โ" * (10 - int(disk_percent / 10))
+ container.add_text(f"`{disk_bar}` {disk_percent}%")
+
+ container.add_separator()
+
+ # Uptime
+ container.add_text("## โฑ๏ธ Bot-Uptime")
+ container.add_text(f"**Laufzeit:** {days}d {hours}h {minutes}m {seconds}s")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ # ===== BOT COMMANDS =====
+
+ @bot.command(name="sync", description="Synchronisiert alle Slash-Commands")
+ async def sync(self, ctx: discord.ApplicationContext):
+ container = Container(color=discord.Color.blue())
+ container.add_text("## ๐ Synchronisierung...")
+ container.add_text("Befehle werden an die Discord API รผbertragen.")
+
+ interaction = await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ try:
+ await self.bot.sync_commands()
+
+ container = Container(color=discord.Color.green())
+ container.add_separator()
+ container.add_text("โ
**Erfolgreich synchronisiert!**")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ except Exception as e:
+ container = Container(color=discord.Color.red())
+ container.add_separator()
+ container.add_text("## โ Synchronisierung fehlgeschlagen!")
+ container.add_text(f"```py\n{e}\n```")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ @bot.command(name="stats", description="Zeigt Bot-Statistiken an")
+ async def stats(self, ctx: discord.ApplicationContext):
+ # Bot Statistiken sammeln
+ guild_count = len(self.bot.guilds)
+ user_count = sum(guild.member_count for guild in self.bot.guilds)
+ text_channels = sum(len(guild.text_channels) for guild in self.bot.guilds)
+ voice_channels = sum(len(guild.voice_channels) for guild in self.bot.guilds)
+
+ # Latenz
+ latency = round(self.bot.latency * 1000, 2)
+
+ container = Container(color=discord.Color.green())
+ container.add_text("# ๐ Bot-Statistiken")
+ container.add_separator()
+ container.add_text(f"**Server:** {guild_count}")
+ container.add_text(f"**Benutzer:** {user_count:,}")
+ container.add_text(f"**Textkanรคle:** {text_channels}")
+ container.add_text(f"**Sprachkanรคle:** {voice_channels}")
+ container.add_separator()
+ container.add_text(f"**Latenz:** {latency} ms")
+ container.add_text(f"**Geladene Cogs:** {len(self.bot.cogs)}")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ @bot.command(name="reload", description="Lรคdt einen Cog neu")
+ async def reload_cog(self, ctx: discord.ApplicationContext, cog: str):
+ container = Container(color=discord.Color.blue())
+ container.add_text(f"## ๐ Lade `{cog}` neu...")
+
+ interaction = await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ try:
+ cog_path = self.format_cog_path(cog)
+ self.bot.reload_extension(cog_path)
+
+ container = Container(color=discord.Color.green())
+ container.add_separator()
+ container.add_text(f"โ
**`{cog}` erfolgreich neu geladen!**")
+ container.add_text(f"*Pfad: `{cog_path}`*")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ except Exception as e:
+ container = Container(color=discord.Color.red())
+ container.add_separator()
+ container.add_text(f"## โ Fehler beim Neuladen von `{cog}`!")
+ container.add_text(f"```py\n{e}\n```")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ @bot.command(name="load", description="Lรคdt einen Cog")
+ async def load_cog(self, ctx: discord.ApplicationContext, cog: str):
+ container = Container(color=discord.Color.blue())
+ container.add_text(f"## ๐ฅ Lade `{cog}`...")
+
+ interaction = await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ try:
+ cog_path = self.format_cog_path(cog)
+ self.bot.load_extension(cog_path)
+
+ container = Container(color=discord.Color.green())
+ container.add_separator()
+ container.add_text(f"โ
**`{cog}` erfolgreich geladen!**")
+ container.add_text(f"*Pfad: `{cog_path}`*")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ except Exception as e:
+ container = Container(color=discord.Color.red())
+ container.add_separator()
+ container.add_text(f"## โ Fehler beim Laden von `{cog}`!")
+ container.add_text(f"```py\n{e}\n```")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ @bot.command(name="unload", description="Entlรคdt einen Cog")
+ async def unload_cog(self, ctx: discord.ApplicationContext, cog: str):
+ if cog.lower() == "admin" or "admin" in cog.lower():
+ container = Container(color=discord.Color.red())
+ container.add_text("## โ Fehler!")
+ container.add_text("Der Admin-Cog kann nicht entladen werden.")
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+ return
+
+ container = Container(color=discord.Color.blue())
+ container.add_text(f"## ๐ค Entlade `{cog}`...")
+
+ interaction = await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ try:
+ cog_path = self.format_cog_path(cog)
+ self.bot.unload_extension(cog_path)
+
+ container = Container(color=discord.Color.green())
+ container.add_separator()
+ container.add_text(f"โ
**`{cog}` erfolgreich entladen!**")
+ container.add_text(f"*Pfad: `{cog_path}`*")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ except Exception as e:
+ container = Container(color=discord.Color.red())
+ container.add_separator()
+ container.add_text(f"## โ Fehler beim Entladen von `{cog}`!")
+ container.add_text(f"```py\n{e}\n```")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ @bot.command(name="list_cogs", description="Listet alle geladenen Cogs auf")
+ async def list_cogs(self, ctx: discord.ApplicationContext):
+ loaded_cogs = list(self.bot.cogs.keys())
+ loaded_cogs_text = "\n".join([f"โ
`{cog}`" for cog in loaded_cogs])
+
+ container = Container(color=discord.Color.blue())
+ container.add_text("# ๐ฆ Geladene Cogs")
+ container.add_separator()
+ container.add_text(loaded_cogs_text if loaded_cogs_text else "*Keine Cogs geladen*")
+ container.add_separator()
+ container.add_text(f"**Gesamt:** {len(loaded_cogs)}")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ @bot.command(name="available_cogs", description="Zeigt alle verfรผgbaren Cogs an")
+ async def available_cogs(self, ctx: discord.ApplicationContext):
+ available = self.get_all_cogs()
+ loaded = [ext.replace('src.bot.cogs.', '') for ext in self.bot.extensions.keys()]
+
+ # Gruppiere nach Kategorien
+ categories = {}
+ for cog in available:
+ category = cog.split('.')[0]
+ if category not in categories:
+ categories[category] = []
+
+ cog_name = cog.split('.')[1]
+ status = "โ
" if cog in loaded else "โญ"
+ categories[category].append(f"{status} `{cog_name}`")
+
+ # Erstelle Ausgabe
+ output = []
+ for category, cogs in sorted(categories.items()):
+ output.append(f"**__{category.upper()}__**")
+ output.extend(cogs)
+ output.append("") # Leerzeile
+
+ container = Container(color=discord.Color.blue())
+ container.add_text("# ๐ Verfรผgbare Cogs")
+ container.add_separator()
+ container.add_text("\n".join(output) if output else "*Keine Cogs gefunden*")
+ container.add_separator()
+ container.add_text(f"**Verfรผgbar:** {len(available)} | **Geladen:** {len(loaded)}")
+ container.add_text("\nโ
= Geladen | โญ = Nicht geladen")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ @bot.command(name="reload_all", description="Lรคdt alle Cogs neu")
+ async def reload_all(self, ctx: discord.ApplicationContext):
+ container = Container(color=discord.Color.blue())
+ container.add_text("## ๐ Lade alle Cogs neu...")
+ container.add_text("Dies kann einen Moment dauern.")
+
+ interaction = await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ success = []
+ failed = []
+
+ # Liste aller geladenen Extensions (auรer admin)
+ extensions = [ext for ext in list(self.bot.extensions.keys()) if 'admin' not in ext.lower()]
+
+ for ext in extensions:
+ try:
+ self.bot.reload_extension(ext)
+ success.append(ext.replace('src.bot.cogs.', ''))
+ except Exception as e:
+ failed.append(f"{ext.replace('src.bot.cogs.', '')}: {str(e)[:50]}")
+
+ # Ergebnis anzeigen
+ result_text = []
+
+ if success:
+ result_text.append("**โ
Erfolgreich neu geladen:**")
+ result_text.extend([f"โข `{cog}`" for cog in success])
+
+ if failed:
+ result_text.append("\n**โ Fehlgeschlagen:**")
+ result_text.extend([f"โข `{cog}`" for cog in failed])
+
+ container = Container(color=discord.Color.green() if not failed else discord.Color.orange())
+ container.add_separator()
+ container.add_text("# ๐ Reload abgeschlossen!")
+ container.add_separator()
+ container.add_text("\n".join(result_text))
+ container.add_separator()
+ container.add_text(f"**Erfolgreich:** {len(success)} | **Fehlgeschlagen:** {len(failed)}")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+ # ===== SERVER COMMANDS =====
+
+ @server.command(name="leave", description="Verlรคsst einen Server")
+ async def leave_server(self, ctx: discord.ApplicationContext, guild_id: str):
+ try:
+ guild = self.bot.get_guild(int(guild_id))
+ if guild is None:
+ container = Container(color=discord.Color.red())
+ container.add_text("## โ Server nicht gefunden!")
+ container.add_text(f"Kein Server mit der ID `{guild_id}` gefunden.")
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+ return
+
+ guild_name = guild.name
+ await guild.leave()
+
+ container = Container(color=discord.Color.green())
+ container.add_text("## โ
Server verlassen!")
+ container.add_text(f"Erfolgreich **{guild_name}** (`{guild_id}`) verlassen.")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ except Exception as e:
+ container = Container(color=discord.Color.red())
+ container.add_text("## โ Fehler!")
+ container.add_text(f"```py\n{e}\n```")
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ @server.command(name="list", description="Listet alle Server auf")
+ async def list_servers(self, ctx: discord.ApplicationContext):
+ guilds = sorted(self.bot.guilds, key=lambda g: g.member_count, reverse=True)
+
+ # Wenn weniger als 20 Server, normale Anzeige
+ if len(guilds) <= 20:
+ guilds_text = "\n".join([
+ f"**{i + 1}.** {guild.name}\n`ID: {guild.id}` โข {guild.member_count:,} Mitglieder"
+ for i, guild in enumerate(guilds)
+ ])
+
+ container = Container(color=discord.Color.blue())
+ container.add_text("# ๐ Server-Liste")
+ container.add_separator()
+ container.add_text(guilds_text if guilds_text else "*Keine Server*")
+ container.add_separator()
+ container.add_text(f"**Gesamt:** {len(guilds)} Server")
+
+ await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ # Wenn mehr als 20 Server, Pagination verwenden
+ else:
+ pagination_view = ServerListView(guilds, page=0, per_page=20)
+ container = pagination_view.get_page_container()
+
+ await ctx.respond(
+ view=discord.ui.DesignerView(container, view=pagination_view, timeout=180),
+ ephemeral=True
+ )
+
+ # ===== TEST COMMAND =====
+
+ @bot.command(name="test", description="Testet die Bot-Funktionalitรคt")
+ async def test(self, ctx: discord.ApplicationContext):
+ container = Container(color=discord.Color.blue())
+ container.add_text("## ๐ Test wird ausgefรผhrt...")
+
+ interaction = await ctx.respond(view=discord.ui.DesignerView(container, timeout=0), ephemeral=True)
+
+ # Simuliere eine kurze Verzรถgerung
+ await asyncio.sleep(1)
+
+ container = Container(color=discord.Color.green())
+ container.add_text("# โ
Test erfolgreich!")
+ container.add_separator()
+ container.add_text(f"**Bot Status:** Online")
+ container.add_text(f"**Latenz:** {round(self.bot.latency * 1000, 2)} ms")
+ container.add_text(f"**Befehl ausgefรผhrt von:** {ctx.author.mention}")
+
+ await interaction.edit_original_response(view=discord.ui.DesignerView(container, timeout=0))
+
+def setup(bot):
+ bot.add_cog(admin(bot))
\ No newline at end of file
diff --git a/src/bot/cogs/bot/join_alert.py b/src/bot/cogs/bot/join_alert.py
new file mode 100644
index 0000000..178e87c
--- /dev/null
+++ b/src/bot/cogs/bot/join_alert.py
@@ -0,0 +1,33 @@
+import discord
+from discord.ui import Container, DesignerView
+import ezcord
+
+class JoinAlert(ezcord.Cog):
+ def __init__(self, bot):
+ self.bot = bot
+
+ @discord.Cog.listener()
+ async def on_guild_join(self, guild: discord.Guild):
+ owner = guild.owner.display_name if guild.owner else "Unbekannt"
+ member_count = guild.member_count
+
+
+ container = Container(color=discord.Color.green())
+ container.add_text(f"## ๐ฅ Neuer Server!")
+ container.add_separator()
+ container.add_text(f"**Name:** {guild.name}")
+ container.add_text(f"**Owner:** {owner}")
+ container.add_text(f"**Member:** {member_count}")
+
+
+ log_channel_id = 1429163147687886889
+ log_channel = self.bot.get_channel(log_channel_id)
+
+ if log_channel:
+ view = DesignerView(container, timeout=None)
+ await log_channel.send(view=view)
+
+ print(f"[+] Bot ist neu auf: {guild.name}")
+
+def setup(bot):
+ bot.add_cog(JoinAlert(bot))
\ No newline at end of file
diff --git a/src/bot/cogs/bot/leave_alert.py b/src/bot/cogs/bot/leave_alert.py
new file mode 100644
index 0000000..593834b
--- /dev/null
+++ b/src/bot/cogs/bot/leave_alert.py
@@ -0,0 +1,37 @@
+import discord
+from discord.ui import Container, DesignerView
+import ezcord
+
+class LeaveAlert(ezcord.Cog):
+ def __init__(self, bot):
+ self.bot = bot
+ # ID deines Kanals, in den die Info flieรen soll
+ self.log_channel_id = 1429164270435700849
+
+ @discord.Cog.listener()
+ async def on_guild_remove(self, guild: discord.Guild):
+ # Container fรผr den Abschied bauen
+ container = Container(color=discord.Color.red())
+ container.add_text("## ๐ค Bot wurde entfernt")
+ container.add_separator()
+
+ # Falls der Name nicht mehr greifbar ist (selten), nutzen wir die ID
+ guild_name = guild.name if guild.name else "Unbekannter Server"
+
+ container.add_text(f"**Server:** {guild_name}")
+ container.add_text(f"**ID:** {guild.id}")
+
+ # Da wir weg sind, wissen wir nicht genau, wie viele Member es zuletzt waren,
+ # aber wir kรถnnen versuchen, den letzten Stand auszugeben
+ if guild.member_count:
+ container.add_text(f"**Letzter Stand:** {guild.member_count} Mitglieder")
+
+ log_channel = self.bot.get_channel(self.log_channel_id)
+ if log_channel:
+ view = DesignerView(container, timeout=None)
+ await log_channel.send(view=view)
+
+ print(f"[-] Bot hat den Server verlassen: {guild_name} ({guild.id})")
+
+def setup(bot):
+ bot.add_cog(LeaveAlert(bot))
\ No newline at end of file
diff --git a/src/bot/cogs/guild/welcome.py b/src/bot/cogs/guild/welcome.py
index cc9fb69..325f154 100644
--- a/src/bot/cogs/guild/welcome.py
+++ b/src/bot/cogs/guild/welcome.py
@@ -19,6 +19,9 @@
import ezcord
from discord.ui import Container
+# Emoji Import
+from src.bot.ui.emojis import emoji_yes, emoji_no
+
# Logger Setup
logger = logging.getLogger(__name__)
@@ -513,7 +516,7 @@ async def set_welcome_channel(self, ctx, channel: discord.TextChannel):
container.add_text(
f"Welcome Messages werden nun in {channel.mention} gesendet."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
else:
container = Container()
container.add_text(
@@ -523,7 +526,7 @@ async def set_welcome_channel(self, ctx, channel: discord.TextChannel):
container.add_text(
"Der Welcome Channel konnte nicht gesetzt werden."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
@welcome.command(name="message", description="Setzt die Welcome Message รผber ein Modal")
@@ -615,13 +618,13 @@ async def callback(self, interaction: discord.Interaction):
f"{preview[:500] + ("..." if len(preview) > 500 else "")}\n\n"
"-# ๐ก Tipp: Verwende `/welcome test` fรผr eine vollstรคndige Vorschau oder `/welcome placeholders` fรผr alle verfรผgbaren Optionen."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
else:
container = Container()
container.add_text(
"# โ Fehler\nDie Welcome Message konnte nicht gesetzt werden."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await interaction.response.send_message(view=view)
modal = WelcomeMessageModal(self, current_message)
@@ -646,7 +649,7 @@ async def toggle_welcome(self, ctx):
container.add_text(
"# โ Fehler\nEs sind noch keine Welcome Einstellungen vorhanden. Setze zuerst einen Channel."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
else:
status = "aktiviert" if new_state else "deaktiviert"
container = Container()
@@ -657,7 +660,7 @@ async def toggle_welcome(self, ctx):
container.add_text(
f"Das Welcome System wurde **{status}**."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
@welcome.command(name="embed", description="Aktiviert/Deaktiviert Embed Modus")
@@ -685,13 +688,13 @@ async def toggle_embed(self, ctx, enabled: bool):
container.add_text(
f"Welcome Messages werden nun {'als Embed' if enabled else 'als normale Nachricht'} gesendet."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
else:
container = Container()
container.add_text(
"# โ Fehler\nDer Embed Modus konnte nicht geรคndert werden."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
@welcome.command(name="autorole", description="Setzt eine Rolle die automatisch vergeben wird")
@@ -724,7 +727,7 @@ async def set_auto_role(self, ctx, role: discord.Role = None):
container.add_text(
"Neue Mitglieder erhalten keine automatische Rolle mehr."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
else:
# Rolle validieren
@@ -733,7 +736,7 @@ async def set_auto_role(self, ctx, role: discord.Role = None):
container.add_text(
"# โ Fehler\nDiese Rolle ist hรถher als meine hรถchste Rolle. Ich kann sie nicht vergeben."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
return
@@ -749,13 +752,13 @@ async def set_auto_role(self, ctx, role: discord.Role = None):
container.add_text(
f"Neue Mitglieder erhalten automatisch die Rolle {role.mention}."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
else:
container = Container()
container.add_text(
"# โ Fehler\nDie Auto-Role konnte nicht gesetzt werden."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
@welcome.command(name="dm", description="Aktiviert/Konfiguriert private Willkommensnachrichten")
@@ -797,13 +800,13 @@ async def setup_join_dm(self, ctx, enabled: bool, *, message: str = None):
container.add_text(
f"{description}"
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
else:
container = Container()
container.add_text(
"# โ Fehler\nDie DM Einstellungen konnten nicht aktualisiert werden."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
@welcome.command(name="template", description="Lรคdt eine Vorlage")
@@ -919,7 +922,7 @@ async def show_config(self, ctx):
container.add_text(
"# โ Keine Konfiguration gefunden\nEs sind noch keine Welcome Einstellungen vorhanden."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
return
@@ -974,7 +977,7 @@ async def show_config(self, ctx):
"## ๐๏ธ Auto-Delete\n"
f"{settings.get('delete_after')} Sekunden"
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view)
@welcome.command(name="test", description="Testet die Welcome Message")
@@ -1000,7 +1003,7 @@ async def test_welcome(self, ctx):
container.add_text(
"# โ Fehler\nEs sind noch keine Welcome Einstellungen vorhanden."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view, ephemeral=True)
return
@@ -1009,7 +1012,7 @@ async def test_welcome(self, ctx):
container.add_text(
"# โ Fehler\nEs ist kein Welcome Channel gesetzt."
)
- view = discord.ui.View(container, timeout=None)
+ view = discord.ui.DesignerView(container, timeout=None)
await ctx.respond(view=view, ephemeral=True)
return
diff --git a/src/bot/ui/__init__.py b/src/bot/ui/__init__.py
new file mode 100644
index 0000000..510c498
--- /dev/null
+++ b/src/bot/ui/__init__.py
@@ -0,0 +1 @@
+from .emojis import *
\ No newline at end of file
diff --git a/src/bot/ui/emojis.py b/src/bot/ui/emojis.py
new file mode 100644
index 0000000..122908c
--- /dev/null
+++ b/src/bot/ui/emojis.py
@@ -0,0 +1,36 @@
+emoji_member = ""
+emoji_warn = ""
+emoji_locked = ""
+emoji_slowmode = ""
+emoji_link = ""
+emoji_delete = ""
+emoji_public = ""
+emoji_gift = ""
+emoji_media_add = ""
+emoji_rules = ""
+emoji_voice_channel = ""
+emoji_verified_white = ""
+emoji_event = ""
+emoji_pinned = ""
+emoji_student_hub = ""
+emoji_search = "<:search:1411749392943284374>"
+emoji_manager = "<:manager:1411749363730092057>"
+emoji_location = "<:location:1411749336492019915>"
+emoji_entertainment = "<:entertainment:1411749311011881032>"
+emoji_staff = "<:staff:1411749285627822203>"
+emoji_moderator = "<:moderator:1411749252736094208>"
+emoji_media = "<:media:1411749223329955860>"
+emoji_copy = "<:copy:1411749194817077298>"
+emoji_gif = "<:gif:1411749131034300548>"
+emoji_summary = "<:summary:1411749103754281081>"
+emoji_upload = "<:upload:1411749080169840760>"
+emoji_add = "<:add:1411749054282596564>"
+emoji_channel = "<:channel:1411749007318974484>"
+emoji_developer = "<:developer:1411748983897985075>"
+emoji_announcement = "<:announcement:1411748950783955025>"
+emoji_statistics = "<:statistics:1411748924359971007>"
+emoji_server_guide = "<:serverguide:1411748884463489166>"
+emoji_owner = "<:owner:1411748853585023189>"
+emoji_forbidden = "<:forbidden:1383743601791471697>"
+emoji_no = "<:no:1380796085802500148>"
+emoji_yes = "<:yes:1380796058963153017>"
\ No newline at end of file
diff --git a/src/bot/ui/emojis.yaml b/src/bot/ui/emojis.yaml
deleted file mode 100644
index e69de29..0000000
diff --git a/src/web/App.tsx b/src/web/App.tsx
index beabac2..ef206d3 100644
--- a/src/web/App.tsx
+++ b/src/web/App.tsx
@@ -56,8 +56,11 @@ const AppContent = () => {
} />
} />
+ } />
} />
+ } />
} />
+ } />
} />
} />
} />
diff --git a/src/web/agb.html b/src/web/agb.html
index da2981f..c20e35c 100644
--- a/src/web/agb.html
+++ b/src/web/agb.html
@@ -11,7 +11,7 @@
-
+