modified: bot.py

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

157
bot.py
View File

@@ -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