diff --git a/bot.py b/bot.py index 9a9af03..8976f72 100644 --- a/bot.py +++ b/bot.py @@ -114,7 +114,7 @@ logger.addHandler(file_handler) #to do: # permissions system, Filter, mysql for user data, fix vision, embeds, info cmd (Server Info, user info), logs, points redo, ticket system, levels, mc ranks integration, add image gen, reaction system, dm system, better ready, resource management, bot action (aka playing) -# mysql = userid / permission / points / ban / askmultus-int / Filter-int / rank / chat-history +# mysql = userid / permission / points / ban / askmultus-int / Filter-int / rank / chat-history / guild_id # 10 filter = acc under review = nicht ok = ban add timestamp = 2 bans = unendlicher ban #perms || 10 = Owner || 8 = Admin || 5 = Mod @@ -149,7 +149,8 @@ db_cursor = db_connection.cursor() # SQL-Befehl für die Erstellung der Tabelle, falls sie noch nicht existiert create_table_query = """ CREATE TABLE IF NOT EXISTS user_data ( - user_id BIGINT PRIMARY KEY, + user_id BIGINT, + guild_id BIGINT, permission INT, points INT, ban INT, @@ -158,19 +159,20 @@ CREATE TABLE IF NOT EXISTS user_data ( rank INT, chat_history JSON, xp INT, - level INT + level INT, + PRIMARY KEY (user_id, guild_id) ); """ db_cursor.execute(create_table_query) db_connection.commit() -def insert_user_data(user_id, permission, points, ban, askmultus, filter_value, chat_history): +def insert_user_data(user_id, guild_id, permission, points, ban, askmultus, filter_value, chat_history): insert_query = """ - INSERT INTO user_data (user_id, permission, points, ban, askmultus, filter_value, rank, chat_history, xp, level) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + INSERT INTO user_data (user_id, guild_id, permission, points, ban, askmultus, filter_value, rank, chat_history, xp, level) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ serialized_chat_history = json.dumps(chat_history) - data = (user_id, permission, points, ban, askmultus, filter_value, 0, serialized_chat_history, 0, 1) # Initialisiere XP auf 0 und Level auf 1 + data = (user_id, guild_id, permission, points, ban, askmultus, filter_value, 0, serialized_chat_history, 0, 1) # Initialisiere XP auf 0 und Level auf 1 try: db_cursor.execute(insert_query, data) db_connection.commit() @@ -180,18 +182,17 @@ def insert_user_data(user_id, permission, points, ban, askmultus, filter_value, db_connection.rollback() -def update_user_data(user_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 try: - update_query = f"UPDATE user_data SET {field} = %s WHERE user_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 if field == 'chat_history': - # Serialize the chat history list to a JSON string serialized_chat_history = json.dumps(value) - db_cursor.execute(update_query, (serialized_chat_history, user_id)) + db_cursor.execute(update_query, (serialized_chat_history, user_id, guild_id)) else: - db_cursor.execute(update_query, (value, user_id)) + db_cursor.execute(update_query, (value, user_id, guild_id)) db_connection.commit() @@ -206,7 +207,7 @@ def update_user_data(user_id, field, value): db_cursor = db_connection.cursor() # Wiederhole die Abfrage nach dem erneuten Verbinden - update_user_data(user_id, field, value) + update_user_data(user_id, guild_id, field, value) def connect_to_database(): @@ -221,11 +222,11 @@ def connect_to_database(): def close_database_connection(connection): connection.close() -def load_user_data_from_mysql(user_id): +def load_user_data_from_mysql(user_id, guild_id): connection = connect_to_database() cursor = connection.cursor() - select_query = "SELECT * FROM user_data WHERE user_id = %s" - cursor.execute(select_query, (user_id,)) + select_query = "SELECT * FROM user_data WHERE user_id = %s AND guild_id = %s" + cursor.execute(select_query, (user_id, guild_id)) result = cursor.fetchone() cursor.close() @@ -235,21 +236,23 @@ def load_user_data_from_mysql(user_id): # Wenn das Level und die XP nicht vorhanden sind, initialisieren user_data = { "user_id": result[0], - "permission": result[1], - "points": result[2], - "ban": result[3], - "askmultus": result[4], - "filter_value": result[5], - "rank": result[6], - "chat_history": json.loads(result[7]) if result[7] else [], - "asknotes_history": json.loads(result[8]) if result[8] else [], - "xp": result[9], - "level": result[10] + "guild_id": result[1], + "permission": result[2], + "points": result[3], + "ban": result[4], + "askmultus": result[5], + "filter_value": result[6], + "rank": result[7], + "chat_history": json.loads(result[8]) if result[8] else [], + "asknotes_history": json.loads(result[9]) if result[9] else [], + "xp": result[10], + "level": result[11] } else: # Falls keine Benutzerdaten gefunden werden, initialisiere sie neu user_data = { "user_id": user_id, + "guild_id": guild_id, "permission": 0, # Standardberechtigung "points": 0, # Standardpunkte "ban": 0, # Standardbannstatus @@ -259,12 +262,12 @@ def load_user_data_from_mysql(user_id): "chat_history": [], # Leerer Chatverlauf "asknotes_history": [], # Leerer Chatverlauf "xp": 0, # Standard-XP - "level": 1 # Standardlevel + "level": 1 # Standardlevel } - # Fügen Sie die neuen Benutzerdaten zur Datenbank hinzu insert_user_data( user_data["user_id"], + user_data["guild_id"], user_data["permission"], user_data["points"], user_data["ban"], @@ -274,7 +277,6 @@ def load_user_data_from_mysql(user_id): user_data["asknotes_history"], user_data["xp"], user_data["level"] - ) return user_data @@ -283,28 +285,28 @@ def load_user_data_from_mysql(user_id): cached_user_data = {} pending_deletion = {} -async def cache_user_data(user_id, data): - cached_user_data[user_id] = data +async def cache_user_data(user_id, guild_id, data): + cached_user_data[(user_id, guild_id)] = data # Setze die Daten nach 30 Sekunden auf die Löschliste - if user_id not in pending_deletion: - pending_deletion[user_id] = asyncio.get_event_loop().call_later(30, lambda: remove_user_data_from_cache(user_id)) + if (user_id, guild_id) not in pending_deletion: + pending_deletion[(user_id, guild_id)] = asyncio.get_event_loop().call_later(30, lambda: remove_user_data_from_cache(user_id, guild_id)) -def remove_user_data_from_cache(user_id): +def remove_user_data_from_cache(user_id, guild_id): # Entferne den Benutzer aus dem Cache und der Löschliste - if user_id in cached_user_data: - del cached_user_data[user_id] - if user_id in pending_deletion: - pending_deletion[user_id].cancel() - del pending_deletion[user_id] + if (user_id, guild_id) in cached_user_data: + del cached_user_data[(user_id, guild_id)] + if (user_id, guild_id) in pending_deletion: + pending_deletion[(user_id, guild_id)].cancel() + del pending_deletion[(user_id, guild_id)] -def load_user_data(user_id): - if user_id in cached_user_data: - return cached_user_data[user_id] +def load_user_data(user_id, guild_id): + if (user_id, guild_id) in cached_user_data: + return cached_user_data[(user_id, guild_id)] # Daten aus der Datenbank laden oder einfügen - user_data = load_user_data_from_mysql(user_id) - asyncio.ensure_future(cache_user_data(user_id, user_data)) + user_data = load_user_data_from_mysql(user_id, guild_id) + asyncio.ensure_future(cache_user_data(user_id, guild_id, user_data)) return user_data @@ -368,7 +370,8 @@ class Giveaway: @client.hybrid_command() async def startgiveaway(ctx, platform: str, prize: str, num_winners: int, title: str, subtitle: str, duration: str): """Creates a giveaway. Only available for mods and higher.""" - user_data = load_user_data(ctx.author.id) + guild_id = ctx.guild.id + user_data = load_user_data(ctx.author.id, guild_id) if user_data["permission"] < 5: await ctx.send("You do not have permission to create a giveaway.") return @@ -418,7 +421,7 @@ async def check_giveaway(giveaway_id): # Jeden Gewinner benachrichtigen und zur Webseite schicken for winner in winners: - user_data = load_user_data(winner.id) + user_data = load_user_data(winner.id, giveaway.ctx.guild.id) # Gewinner in der Datenbank speichern (winner_dc_id) update_winner_in_db(giveaway.prize_uuid, winner.id) # Nachricht an den Gewinner senden @@ -484,10 +487,10 @@ def calculate_xp_needed_for_level(level): xp_need = 5 * (int(level) ** 2) + 50 * int(level) + 100 return int(xp_need) -async def add_xp_to_user(user_id, xp_gained): +async def add_xp_to_user(user_id, guild_id, xp_gained): """Fügt einem Benutzer XP hinzu und überprüft, ob er ein Level aufsteigt.""" # Lade Benutzerdaten (XP, Level, etc.) - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) # Füge die gewonnenen XP hinzu user_data["xp"] += xp_gained @@ -506,16 +509,17 @@ async def add_xp_to_user(user_id, xp_gained): xp_needed = calculate_xp_needed_for_level(user_data["level"]) # Speichere die aktualisierten Benutzerdaten in der Datenbank - update_user_data(user_id, "xp", user_data["xp"]) - update_user_data(user_id, "level", user_data["level"]) + update_user_data(user_id, guild_id, "xp", user_data["xp"]) + update_user_data(user_id, guild_id, "level", user_data["level"]) @client.hybrid_command() async def level(ctx): """Zeigt den aktuellen Level und XP des Benutzers an.""" user_id = ctx.author.id + guild_id = ctx.guild.id # Lade die Benutzerdaten (XP und Level) aus der Datenbank - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) # Berechne die für das nächste Level benötigten XP current_level = user_data["level"] @@ -534,14 +538,15 @@ async def level(ctx): @client.hybrid_command() async def leaderboard(ctx): """Zeigt die besten Benutzer im XP-Leaderboard an.""" + guild_id = ctx.guild.id connection = connect_to_database() cursor = connection.cursor() # Abfrage, um die Benutzer basierend auf der XP zu sortieren select_query = """ - SELECT user_id, xp, level FROM user_data ORDER BY level DESC, xp DESC LIMIT 10 + SELECT user_id, xp, level FROM user_data WHERE guild_id = %s ORDER BY level DESC, xp DESC LIMIT 10 """ - cursor.execute(select_query) + cursor.execute(select_query, (guild_id,)) result = cursor.fetchall() # Liste, um die Benutzer und ihre XP zu speichern @@ -581,8 +586,9 @@ async def on_message(message): return # Ignoriere Nachrichten von Bots user_id = message.author.id + guild_id = message.guild.id xp_gained = random.randint(2, 25) # Zufällige XP zwischen 15 und 25 vergeben - await add_xp_to_user(user_id, xp_gained) + await add_xp_to_user(user_id, guild_id, xp_gained) # Weiterleiten der Nachricht an andere Event-Handler await client.process_commands(message) @@ -627,8 +633,9 @@ async def on_command(ctx): async def points(ctx): """Shows how many points you have.""" user_id = ctx.author.id + guild_id = ctx.guild.id # Lade Benutzerdaten aus der MySQL-Datenbank - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) points = user_data["points"] @@ -643,9 +650,10 @@ async def points(ctx): async def permissionlevel(ctx): """Displays the authorisation level and rank of the user.""" user_id = ctx.author.id + guild_id = ctx.guild.id # Load user data from the MySQL database - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) permission_level = user_data["permission"] rank = "" @@ -668,18 +676,19 @@ async def permissionlevel(ctx): @client.hybrid_command() async def addpoints(ctx, user: discord.User, amount: int): """Adds a certain number of points to a user.""" - user_perms = load_user_data(ctx.author.id) + user_perms = load_user_data(ctx.author.id, ctx.guild.id) if 5 <= user_perms["permission"]: user_id = user.id + guild_id = ctx.guild.id # Lade Benutzerdaten aus der MySQL-Datenbank - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) # Füge die Punkte hinzu user_data["points"] += amount # Speichere die aktualisierten Benutzerdaten in der MySQL-Datenbank - update_user_data(user_data["user_id"], "points", user_data["points"]) + update_user_data(user_data["user_id"], guild_id, "points", user_data["points"]) embed = discord.Embed( title="Points Added", @@ -693,18 +702,19 @@ async def addpoints(ctx, user: discord.User, amount: int): @client.hybrid_command() async def resetpoints(ctx, user: discord.User): """Resets a user's points to 0.""" - user_perms = load_user_data(ctx.author.id) + user_perms = load_user_data(ctx.author.id, ctx.guild.id) if 5 <= user_perms["permission"]: user_id = user.id + guild_id = ctx.guild.id # Lade Benutzerdaten aus der MySQL-Datenbank - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) # Setze die Punkte auf 0 zurück user_data["points"] = 0 # Speichere die aktualisierten Benutzerdaten in der MySQL-Datenbank - update_user_data(user_data["user_id"], "points", user_data["points"]) + update_user_data(user_data["user_id"], guild_id, "points", user_data["points"]) embed = discord.Embed( title="Points Reset", @@ -717,7 +727,7 @@ async def resetpoints(ctx, user: discord.User): @client.hybrid_command() async def shutdown_(ctx): - user_perms = load_user_data(ctx.author.id) + user_perms = load_user_data(ctx.author.id, ctx.guild.id) if 8 <= user_perms["permission"]: await ctx.send("Shutting down the bot...") await client.logout() @@ -728,7 +738,7 @@ async def shutdown_(ctx): @client.hybrid_command() async def owner_command(ctx): try: - user_perms = load_user_data(ctx.author.id) + user_perms = load_user_data(ctx.author.id, ctx.guild.id) if 10 <= user_perms["permission"]: await client.tree.sync() await ctx.send("reloaded !") @@ -745,15 +755,16 @@ async def askmultus(ctx, *, prompt: str): return user_id = ctx.author.id + guild_id = ctx.guild.id # Lade Benutzerdaten aus der MySQL-Datenbank - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) if user_data["points"] >= 5: user_data["points"] -= 5 # Speichere die aktualisierten Benutzerdaten in der MySQL-Datenbank - update_user_data(user_data["user_id"], "points", user_data["points"]) + update_user_data(user_data["user_id"], guild_id, "points", user_data["points"]) # Define the full data and user history field for askmultus introduction = read_introduction() @@ -782,7 +793,8 @@ async def process_ai_queue(): if not askmultus_queue.empty(): ctx, user_id, user_name, prompt, channel_id, full_data, user_history_field, model = await askmultus_queue.get() - user_data = load_user_data(user_id) + guild_id = ctx.guild.id + user_data = load_user_data(user_id, guild_id) try: user_history = user_data.get(user_history_field, []) @@ -826,7 +838,7 @@ async def process_ai_queue(): user_history.append({"role": "assistant", "content": assistant_message}) # Update the relevant user history field - update_user_data(user_data["user_id"], user_history_field, json.dumps(user_history)) + update_user_data(user_data["user_id"], guild_id, user_history_field, json.dumps(user_history)) except Exception as e: logger.error(f"Processing errors: {e}") @@ -906,7 +918,8 @@ async def addbackgrounddata(ctx, *, data: str): @client.hybrid_command() async def summarize(ctx, number: int): """Summarizes the last x messages in the chat.""" - user_perms = load_user_data(ctx.author.id) + guild_id = ctx.guild.id + user_perms = load_user_data(ctx.author.id, guild_id) if 5 < user_perms["permission"]: try: # Fetch the last 10 messages in the channel @@ -968,8 +981,9 @@ async def leave(ctx): @client.hybrid_command() async def toggle_feature(ctx, feature: str, state: str): """Allows admin to enable or disable features.""" + guild_id = ctx.guild.id user_id = ctx.author.id - user_data = load_user_data(user_id) + user_data = load_user_data(user_id, guild_id) user_perms = user_data["permission"] if user_perms < 8: # Nur Admins (permission level >= 8) können Funktionen aktivieren/deaktivieren @@ -1010,7 +1024,8 @@ async def addnotes(ctx, type: str, *, source: str): await ctx.defer() # Signalisiert, dass die Bearbeitung des Befehls begonnen hat user_id = ctx.author.id - user_cache_dir = os.path.join(CACHE_DIR, str(user_id)) + guild_id = ctx.guild.id + user_cache_dir = os.path.join(CACHE_DIR, f"{str(guild_id)}_{str(user_id)}") if not os.path.exists(user_cache_dir): os.makedirs(user_cache_dir) @@ -1057,7 +1072,8 @@ async def asknotes(ctx, *, question: str): await ctx.defer() user_id = ctx.author.id - user_cache_dir = os.path.join(CACHE_DIR, str(user_id)) + guild_id = ctx.guild.id + user_cache_dir = os.path.join(CACHE_DIR, f"{str(guild_id)}_{str(user_id)}") note_file = os.path.join(user_cache_dir, "notes.txt") asknotesintroduction = read_askintroduction() @@ -1086,7 +1102,8 @@ async def asknotes(ctx, *, question: str): async def delnotes(ctx): """Deletes all saved notes and the asknotes history for the user.""" user_id = ctx.author.id - user_cache_dir = os.path.join(CACHE_DIR, str(user_id)) + guild_id = ctx.guild.id + user_cache_dir = os.path.join(CACHE_DIR, f"{str(guild_id)}_{str(user_id)}") if os.path.exists(user_cache_dir): # Lösche die gespeicherten Notizen im Cache-Ordner @@ -1094,7 +1111,7 @@ async def delnotes(ctx): # Setze die asknotes-Historie in der Datenbank zurück try: - update_user_data(user_id, "asknotes_history", None) + update_user_data(user_id, guild_id, "asknotes_history", None) await ctx.send(f"All notes and asknotes history deleted for user {ctx.author.name}.") except Exception as e: await ctx.send(f"Error deleting asknotes history: {e}")