modified: app.py

modified:   bot.py
This commit is contained in:
SimolZimol
2025-08-24 01:21:39 +02:00
parent 3de4d6b455
commit a8770abd3a
3 changed files with 284 additions and 56 deletions

161
app.py
View File

@@ -8,6 +8,7 @@ import os
import subprocess
import psutil
import mysql.connector
import mysql.connector.pooling
from datetime import datetime, timedelta
from flask_session import Session
import logging
@@ -85,15 +86,68 @@ def stop_bot():
else:
print("Bot läuft nicht.")
# Database Connection Pool für bessere Verbindungsverwaltung
app_pool = mysql.connector.pooling.MySQLConnectionPool(
pool_name="app_pool",
pool_size=15, # Reduziert von 20 auf 15 (Bot: 30, App: 15 = max 45 statt 50+)
pool_reset_session=True,
host=DB_HOST,
port=DB_PORT,
user=DB_USER,
password=DB_PASS,
database=DB_NAME,
# Zusätzliche Pool-Optimierungen
use_pure=True, # Verwende Pure Python Connector für bessere Stabilität
connect_timeout=10, # Timeout für Verbindungsaufbau
autocommit=True, # Für bessere Pool-Performance
)
def get_db_connection():
"""Stellt eine Verbindung zur MySQL-Datenbank her."""
return mysql.connector.connect(
host=DB_HOST,
port=DB_PORT,
user=DB_USER,
password=DB_PASS,
database=DB_NAME
)
"""Stellt eine Verbindung zur MySQL-Datenbank über Connection Pool her."""
try:
connection = app_pool.get_connection()
return connection
except mysql.connector.PoolError as e:
print(f"Pool error in app.py: {e}")
# Fallback zu direkter Verbindung bei Pool-Problemen
return mysql.connector.connect(
host=DB_HOST,
port=DB_PORT,
user=DB_USER,
password=DB_PASS,
database=DB_NAME
)
from contextlib import contextmanager
@contextmanager
def get_db_cursor():
"""Context Manager für sichere Datenbankverbindungen mit automatischer Bereinigung."""
connection = None
cursor = None
try:
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
yield cursor, connection
except Exception as e:
if connection:
connection.rollback()
raise e
finally:
if cursor:
cursor.close()
if connection and connection.is_connected():
connection.close()
def get_pool_status():
"""Gibt Pool-Status zurück für Monitoring"""
try:
return {
"pool_size": app_pool.pool_size,
"connections_in_use": len(app_pool._cnx_queue._queue) if hasattr(app_pool, '_cnx_queue') else 'Unknown'
}
except Exception as e:
return {"error": str(e)}
def token_updater(token):
session['oauth_token'] = token
@@ -146,15 +200,14 @@ def is_bot_admin():
user_info = session["discord_user"]
user_id = user_info["id"]
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT global_permission FROM bot_data WHERE user_id = %s", (user_id,))
user_data = cursor.fetchone()
cursor.close()
connection.close()
return user_data and user_data["global_permission"] >= 8
try:
with get_db_cursor() as (cursor, connection):
cursor.execute("SELECT global_permission FROM bot_data WHERE user_id = %s", (user_id,))
user_data = cursor.fetchone()
return user_data and user_data["global_permission"] >= 8
except Exception as e:
print(f"Database error in is_bot_admin: {e}")
return False
return False
def is_server_admin(guild_id):
@@ -163,15 +216,14 @@ def is_server_admin(guild_id):
user_info = session["discord_user"]
user_id = user_info["id"]
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT permission FROM user_data WHERE user_id = %s AND guild_id = %s", (user_id, guild_id))
user_data = cursor.fetchone()
cursor.close()
connection.close()
return user_data and user_data["permission"] >= 8
try:
with get_db_cursor() as (cursor, connection):
cursor.execute("SELECT permission FROM user_data WHERE user_id = %s AND guild_id = %s", (user_id, guild_id))
user_data = cursor.fetchone()
return user_data and user_data["permission"] >= 8
except Exception as e:
print(f"Database error in is_server_admin: {e}")
return False
return False
@app.route("/")
@@ -517,38 +569,37 @@ def user_dashboard(guild_id):
def leaderboard(guild_id):
"""Zeigt das Level Leaderboard für einen bestimmten Server an."""
if "discord_user" in session:
connection = get_db_connection()
cursor = connection.cursor(dictionary=True)
try:
with get_db_cursor() as (cursor, connection):
current_date = datetime.now()
one_month_ago = current_date - timedelta(days=30)
current_date = datetime.now()
one_month_ago = current_date - timedelta(days=30)
# Hole die Leaderboard-Daten
cursor.execute("""
SELECT nickname, profile_picture, level, xp, join_date
FROM user_data
WHERE guild_id = %s
AND ban = 0
AND (leave_date IS NULL OR leave_date > %s)
ORDER BY level DESC, xp DESC
""", (guild_id, one_month_ago))
leaderboard_data = cursor.fetchall()
# Hole die Leaderboard-Daten
cursor.execute("""
SELECT nickname, profile_picture, level, xp, join_date
FROM user_data
WHERE guild_id = %s
AND ban = 0
AND (leave_date IS NULL OR leave_date > %s)
ORDER BY level DESC, xp DESC
""", (guild_id, one_month_ago))
leaderboard_data = cursor.fetchall()
# Hole den Server-Namen aus der guilds-Tabelle
cursor.execute("SELECT name FROM guilds WHERE guild_id = %s", (guild_id,))
guild_name_result = cursor.fetchone()
guild_name = guild_name_result["name"] if guild_name_result else f"Server {guild_id}"
# Hole den Server-Namen aus der guilds-Tabelle
cursor.execute("SELECT name FROM guilds WHERE guild_id = %s", (guild_id,))
guild_name_result = cursor.fetchone()
guild_name = guild_name_result["name"] if guild_name_result else f"Server {guild_id}"
cursor.close()
connection.close()
# Übergabe von enumerate und guild_name an das Template
return render_template("leaderboard.html",
leaderboard=leaderboard_data,
guild_id=guild_id,
guild_name=guild_name,
enumerate=enumerate)
# Übergabe von enumerate und guild_name an das Template
return render_template("leaderboard.html",
leaderboard=leaderboard_data,
guild_id=guild_id,
guild_name=guild_name,
enumerate=enumerate)
except Exception as e:
print(f"Database error in leaderboard: {e}")
return "Database connection error", 500
return redirect(url_for("landing_page"))