From 96a71652eb2a3201c27daf01b1355fe07e4da928 Mon Sep 17 00:00:00 2001 From: SimolZimol <70102430+SimolZimol@users.noreply.github.com> Date: Mon, 18 Aug 2025 09:29:33 +0200 Subject: [PATCH] modified: bot.py --- bot.py | 157 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 64 deletions(-) diff --git a/bot.py b/bot.py index 117d518..75f5bf5 100644 --- a/bot.py +++ b/bot.py @@ -92,67 +92,79 @@ client = commands.Bot(command_prefix='-', intents=intents, owner_id = OWNER_ID) askmultus_queue = asyncio.Queue() loop = asyncio.get_event_loop() -# Verbindung zur MySQL-Datenbank herstellen -db_connection = mysql.connector.connect( - host=DB_HOST, - port=DB_PORT, - user=DB_USER, - password=DB_PASSWORD, - database=DB_DATABASE -) +# Verbindung zur MySQL-Datenbank herstellen (OLD - now using connection pool) +# db_connection = mysql.connector.connect( +# host=DB_HOST, +# port=DB_PORT, +# user=DB_USER, +# password=DB_PASSWORD, +# database=DB_DATABASE +# ) -# Cursor erstellen -db_cursor = db_connection.cursor() +# Cursor erstellen (OLD - now using connection pool) +# db_cursor = db_connection.cursor() def close_database_connection(connection): connection.close() def insert_user_data(user_id, guild_id, permission, points, ban, askmultus, filter_value, chat_history, xp=0, level=1, nickname="", profile_picture="", join_date=None, leave_date=None): - insert_query = """ - INSERT INTO user_data (user_id, guild_id, permission, points, ban, askmultus, filter_value, rank, chat_history, xp, level, nickname, profile_picture, join_date, leave_date) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) - """ - serialized_chat_history = json.dumps(chat_history) - data = (user_id, guild_id, permission, points, ban, askmultus, filter_value, 0, serialized_chat_history, xp, level, nickname, profile_picture, join_date, leave_date) - - def execute_insert(): - cursor = get_database_cursor() - cursor.execute(insert_query, data) - db_connection.commit() - + """Fügt neue Benutzerdaten in die Datenbank ein mit Connection Pool""" + connection = None + cursor = None try: - retry_query(execute_insert) - print("User data inserted successfully.") + connection = connect_to_database() + cursor = connection.cursor() + insert_query = """ + INSERT INTO user_data (user_id, guild_id, permission, points, ban, askmultus, filter_value, rank, chat_history, xp, level, nickname, profile_picture, join_date, leave_date) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + """ + serialized_chat_history = json.dumps(chat_history) + data = (user_id, guild_id, permission, points, ban, askmultus, filter_value, 0, serialized_chat_history, xp, level, nickname, profile_picture, join_date, leave_date) + + cursor.execute(insert_query, data) + connection.commit() + logger.info("User data inserted successfully.") except Exception as e: - print(f"Error inserting user data after retries: {e}") + logger.error(f"Error inserting user data: {e}") + if connection: + connection.rollback() + raise e + finally: + if cursor: + cursor.close() + if connection: + close_database_connection(connection) def update_user_data(user_id, guild_id, field, value): - global db_connection, db_cursor # global-Deklaration muss vor dem Zugriff erfolgen + """Aktualisiert Benutzerdaten in der Datenbank mit Connection Pool""" + connection = None + cursor = None try: + connection = connect_to_database() + cursor = connection.cursor() update_query = f"UPDATE user_data SET {field} = %s WHERE user_id = %s AND guild_id = %s" # Überprüfen, ob das Feld 'chat_history' aktualisiert wird if field == 'chat_history': serialized_chat_history = json.dumps(value) - db_cursor.execute(update_query, (serialized_chat_history, user_id, guild_id)) + cursor.execute(update_query, (serialized_chat_history, user_id, guild_id)) else: - db_cursor.execute(update_query, (value, user_id, guild_id)) + cursor.execute(update_query, (value, user_id, guild_id)) - db_connection.commit() + connection.commit() + logger.debug(f"Successfully updated {field} for user {user_id} in guild {guild_id}") except mysql.connector.Error as err: logger.error(f"Database error: {err}") - if db_connection.is_connected(): - db_cursor.close() - db_connection.close() - - # Verbindung neu aufbauen - db_connection = connect_to_database() - db_cursor = db_connection.cursor() - - # Wiederhole die Abfrage nach dem erneuten Verbinden - update_user_data(user_id, guild_id, field, value) + if connection: + connection.rollback() + raise err + finally: + if cursor: + cursor.close() + if connection: + close_database_connection(connection) def connect_to_database(): @@ -175,10 +187,7 @@ def retry_query(func, *args, retries=3, delay=5): time.sleep(delay) raise RuntimeError("Max retries exceeded") -def get_database_cursor(): - if not db_connection.is_connected(): - db_connection.reconnect(attempts=3, delay=5) - return db_connection.cursor() +# Removed get_database_cursor() - now using connection pool directly pool = mysql.connector.pooling.MySQLConnectionPool( pool_name="mypool", @@ -960,32 +969,44 @@ async def add_xp_to_user(user_id, guild_id, xp_gained, member=None): # Aktualisiere Nickname new_nickname = member.display_name if user_data.get("nickname") != new_nickname: - update_user_data(user_id, guild_id, "nickname", new_nickname) - user_data["nickname"] = new_nickname + try: + update_user_data(user_id, guild_id, "nickname", new_nickname) + user_data["nickname"] = new_nickname + except Exception as e: + logger.error(f"Failed to update nickname for user {user_id}: {e}") # Aktualisiere Profilbild - mit lokalem Download und Hash-Vergleich if member.display_avatar: - discord_avatar_url = str(member.display_avatar.url) - # Download und speichere das Profilbild lokal - local_profile_path = await download_and_save_profile_image(user_id, discord_avatar_url) - - # Speichere den lokalen Pfad in der Datenbank statt der Discord URL - if user_data.get("profile_picture") != local_profile_path: - update_user_data(user_id, guild_id, "profile_picture", local_profile_path) - user_data["profile_picture"] = local_profile_path + try: + discord_avatar_url = str(member.display_avatar.url) + # Download und speichere das Profilbild lokal + local_profile_path = await download_and_save_profile_image(user_id, discord_avatar_url) + + # Speichere den lokalen Pfad in der Datenbank statt der Discord URL + if user_data.get("profile_picture") != local_profile_path: + update_user_data(user_id, guild_id, "profile_picture", local_profile_path) + user_data["profile_picture"] = local_profile_path + except Exception as e: + logger.error(f"Failed to update profile picture for user {user_id}: {e}") else: # Kein Profilbild vorhanden, nutze Default - default_path = "/static/default_profile.png" - if user_data.get("profile_picture") != default_path: - update_user_data(user_id, guild_id, "profile_picture", default_path) - user_data["profile_picture"] = default_path + try: + default_path = "/static/default_profile.png" + if user_data.get("profile_picture") != default_path: + update_user_data(user_id, guild_id, "profile_picture", default_path) + user_data["profile_picture"] = default_path + except Exception as e: + logger.error(f"Failed to set default profile picture for user {user_id}: {e}") # Aktualisiere Join-Datum - IMMER wenn member.joined_at verfügbar ist if member.joined_at: - join_date = member.joined_at.date() - # Aktualisiere Join-Datum auch wenn es bereits existiert (für den Fall, dass es falsch war) - update_user_data(user_id, guild_id, "join_date", join_date) - user_data["join_date"] = join_date + try: + join_date = member.joined_at.date() + # Aktualisiere Join-Datum auch wenn es bereits existiert (für den Fall, dass es falsch war) + update_user_data(user_id, guild_id, "join_date", join_date) + user_data["join_date"] = join_date + except Exception as e: + logger.error(f"Failed to update join date for user {user_id}: {e}") logger.info(f"Updated user data for {member.display_name} (ID: {user_id}) - Nickname: {new_nickname}, Join Date: {join_date if member.joined_at else 'N/A'}") @@ -993,8 +1014,11 @@ async def add_xp_to_user(user_id, guild_id, xp_gained, member=None): logger.error(f"Error updating user data during XP gain: {e}") # Speichere die aktualisierten XP und Level in der Datenbank - update_user_data(user_id, guild_id, "xp", user_data["xp"]) - update_user_data(user_id, guild_id, "level", user_data["level"]) + try: + update_user_data(user_id, guild_id, "xp", user_data["xp"]) + update_user_data(user_id, guild_id, "level", user_data["level"]) + except Exception as e: + logger.error(f"Failed to update XP/Level for user {user_id}: {e}") return level_up # Gibt zurück, ob ein Level-Up stattgefunden hat @@ -1594,7 +1618,12 @@ async def download_and_save_profile_image(user_id, discord_url): # Download das Bild logger.info(f"Downloading profile image for user {user_id} from {discord_url}") - response = requests.get(discord_url, timeout=10) + + # Use a session with timeout for better connection handling + session = requests.Session() + session.timeout = (10, 15) # (connection timeout, read timeout) + + response = session.get(discord_url, timeout=15) if response.status_code == 200: # Speichere das Bild