modified: bot.py

This commit is contained in:
SimolZimol
2025-08-18 09:29:33 +02:00
parent 2e35c2dc45
commit 96a71652eb

103
bot.py
View File

@@ -92,22 +92,28 @@ client = commands.Bot(command_prefix='-', intents=intents, owner_id = OWNER_ID)
askmultus_queue = asyncio.Queue() askmultus_queue = asyncio.Queue()
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
# Verbindung zur MySQL-Datenbank herstellen # Verbindung zur MySQL-Datenbank herstellen (OLD - now using connection pool)
db_connection = mysql.connector.connect( # db_connection = mysql.connector.connect(
host=DB_HOST, # host=DB_HOST,
port=DB_PORT, # port=DB_PORT,
user=DB_USER, # user=DB_USER,
password=DB_PASSWORD, # password=DB_PASSWORD,
database=DB_DATABASE # database=DB_DATABASE
) # )
# Cursor erstellen # Cursor erstellen (OLD - now using connection pool)
db_cursor = db_connection.cursor() # db_cursor = db_connection.cursor()
def close_database_connection(connection): def close_database_connection(connection):
connection.close() 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): 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):
"""Fügt neue Benutzerdaten in die Datenbank ein mit Connection Pool"""
connection = None
cursor = None
try:
connection = connect_to_database()
cursor = connection.cursor()
insert_query = """ 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) 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) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
@@ -115,44 +121,50 @@ def insert_user_data(user_id, guild_id, permission, points, ban, askmultus, filt
serialized_chat_history = json.dumps(chat_history) 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) 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) cursor.execute(insert_query, data)
db_connection.commit() connection.commit()
logger.info("User data inserted successfully.")
try:
retry_query(execute_insert)
print("User data inserted successfully.")
except Exception as e: 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): 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: 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" 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 # Überprüfen, ob das Feld 'chat_history' aktualisiert wird
if field == 'chat_history': if field == 'chat_history':
serialized_chat_history = json.dumps(value) 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: 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: except mysql.connector.Error as err:
logger.error(f"Database error: {err}") logger.error(f"Database error: {err}")
if db_connection.is_connected(): if connection:
db_cursor.close() connection.rollback()
db_connection.close() raise err
finally:
# Verbindung neu aufbauen if cursor:
db_connection = connect_to_database() cursor.close()
db_cursor = db_connection.cursor() if connection:
close_database_connection(connection)
# Wiederhole die Abfrage nach dem erneuten Verbinden
update_user_data(user_id, guild_id, field, value)
def connect_to_database(): def connect_to_database():
@@ -175,10 +187,7 @@ def retry_query(func, *args, retries=3, delay=5):
time.sleep(delay) time.sleep(delay)
raise RuntimeError("Max retries exceeded") raise RuntimeError("Max retries exceeded")
def get_database_cursor(): # Removed get_database_cursor() - now using connection pool directly
if not db_connection.is_connected():
db_connection.reconnect(attempts=3, delay=5)
return db_connection.cursor()
pool = mysql.connector.pooling.MySQLConnectionPool( pool = mysql.connector.pooling.MySQLConnectionPool(
pool_name="mypool", pool_name="mypool",
@@ -960,11 +969,15 @@ async def add_xp_to_user(user_id, guild_id, xp_gained, member=None):
# Aktualisiere Nickname # Aktualisiere Nickname
new_nickname = member.display_name new_nickname = member.display_name
if user_data.get("nickname") != new_nickname: if user_data.get("nickname") != new_nickname:
try:
update_user_data(user_id, guild_id, "nickname", new_nickname) update_user_data(user_id, guild_id, "nickname", new_nickname)
user_data["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 # Aktualisiere Profilbild - mit lokalem Download und Hash-Vergleich
if member.display_avatar: if member.display_avatar:
try:
discord_avatar_url = str(member.display_avatar.url) discord_avatar_url = str(member.display_avatar.url)
# Download und speichere das Profilbild lokal # Download und speichere das Profilbild lokal
local_profile_path = await download_and_save_profile_image(user_id, discord_avatar_url) local_profile_path = await download_and_save_profile_image(user_id, discord_avatar_url)
@@ -973,19 +986,27 @@ async def add_xp_to_user(user_id, guild_id, xp_gained, member=None):
if user_data.get("profile_picture") != local_profile_path: if user_data.get("profile_picture") != local_profile_path:
update_user_data(user_id, guild_id, "profile_picture", local_profile_path) update_user_data(user_id, guild_id, "profile_picture", local_profile_path)
user_data["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: else:
# Kein Profilbild vorhanden, nutze Default # Kein Profilbild vorhanden, nutze Default
try:
default_path = "/static/default_profile.png" default_path = "/static/default_profile.png"
if user_data.get("profile_picture") != default_path: if user_data.get("profile_picture") != default_path:
update_user_data(user_id, guild_id, "profile_picture", default_path) update_user_data(user_id, guild_id, "profile_picture", default_path)
user_data["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 # Aktualisiere Join-Datum - IMMER wenn member.joined_at verfügbar ist
if member.joined_at: if member.joined_at:
try:
join_date = member.joined_at.date() join_date = member.joined_at.date()
# Aktualisiere Join-Datum auch wenn es bereits existiert (für den Fall, dass es falsch war) # 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) update_user_data(user_id, guild_id, "join_date", join_date)
user_data["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'}") 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}") logger.error(f"Error updating user data during XP gain: {e}")
# Speichere die aktualisierten XP und Level in der Datenbank # Speichere die aktualisierten XP und Level in der Datenbank
try:
update_user_data(user_id, guild_id, "xp", user_data["xp"]) update_user_data(user_id, guild_id, "xp", user_data["xp"])
update_user_data(user_id, guild_id, "level", user_data["level"]) 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 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 # Download das Bild
logger.info(f"Downloading profile image for user {user_id} from {discord_url}") 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: if response.status_code == 200:
# Speichere das Bild # Speichere das Bild