BaumSplitter41 1 mese fa
parent
commit
ad56cbacfa
1 ha cambiato i file con 96 aggiunte e 119 eliminazioni
  1. 96 119
      VPD_BOT/cogs/change_name_badge.py

+ 96 - 119
VPD_BOT/cogs/change_name_badge.py

@@ -30,140 +30,117 @@ class changedcname(commands.Cog):
     @tasks.loop(minutes=15)
     async def change_name_badge(self):
         config = self._load_config()
-        enable_change_dc_name = config.getboolean("Role Management","enable_change_dc_name")
+        enable_change_dc_name = config.getboolean("Role Management", "enable_change_dc_name", fallback=False)
         if not enable_change_dc_name:
-            return # Exit the function if the feature is disabled in the config
+            return 
 
-
-    #Load .env file for the gameserver database
+        # Load .env file for the gameserver database
+        load_dotenv()
         dbhost = os.getenv("HOST2")
-        if dbhost is None:
-            raise ValueError("HOST2 not found in .env file")
         dbname = os.getenv("NAME2")
-        if dbname is None:
-            raise ValueError("NAME2 not found in .env file")
         dbpsswd = os.getenv("PASSWORD2")
-        if dbpsswd is None:
-            raise ValueError("PASSWORD2 not found in .env file")
         dbdb = os.getenv("DATABASE2")
-        if dbdb is None:
-            raise ValueError("DATABASE2 not found in .env file")
-        
-        #Get guild ID
-        load_dotenv()
         guild_id = os.getenv("SERVER")
-        if guild_id is None:
-            raise ValueError("SERVER not found in .env file")
-        
 
-        #Database initialization
-        conn = mysql.connector.connect(
-            host=dbhost,
-            user=dbname,
-            password=dbpsswd,
-            charset='utf8mb4',
-            collation='utf8mb4_unicode_ci'
-        )
-        cursor = conn.cursor()
-        conn.database = dbdb
-
-
-        #needed arrays
-        badgenr = []
-        charinfo = []
-        users = []
-        discord_raw = []
-        firstname = []
-        lastname = []
-        
-        #get information from database
+        if not all([dbhost, dbname, dbpsswd, dbdb, guild_id]):
+            print("Fehler: Mindestens eine .env Variable fehlt!")
+            return
+
+        guild = self.bot.get_guild(int(guild_id))
+        if not guild:
+            print("Server (Guild) nicht gefunden.")
+            return
+
+        # Database initialization
+        try:
+            conn = mysql.connector.connect(
+                host=dbhost, user=dbname, password=dbpsswd, database=dbdb,
+                charset='utf8mb4', collation='utf8mb4_unicode_ci'
+            )
+            cursor = conn.cursor()
+        except Exception as e:
+            print(f"Datenbankverbindung fehlgeschlagen: {e}")
+            return
+
+        # 1. ALLES in EINER Abfrage holen (verhindert Listen-Verschiebungen)
         cursor.execute("""
-        SELECT 
-            ny_groups_meta.internal_identifier, 
-            players.charinfo, 
-            users.discord 
-        FROM ny_groups_meta
-        JOIN players ON ny_groups_meta.character_identifier = players.citizenid
-        JOIN users ON players.userId = users.userId
-        ORDER BY ny_groups_meta.internal_identifier
+            SELECT 
+                ny_groups_meta.internal_identifier, 
+                players.charinfo, 
+                users.discord 
+            FROM ny_groups_meta
+            JOIN players ON ny_groups_meta.character_identifier = players.citizenid
+            JOIN users ON players.userId = users.userId
+            ORDER BY ny_groups_meta.internal_identifier
         """)
+        rows = cursor.fetchall()
         
-        for internal_identifier, char_info, discord in cursor.fetchall():
-            badgenr.append(internal_identifier)
-            charinfo.append(char_info)
-            discord_raw.append((discord,))
-        
-        #get users to the discordIDs
-        for discord in discord_raw:
-            discord_id = discord[0].split(":")
-            for i in range(len(discord_id)):
-                if discord_id[i].isdigit():
-                    user_id = int(discord_id[i])
-                    user = self.bot.get_user(user_id)
-                    if user is not None:
-                        users.append(user)
-                        break
-    
-        #check on duplicates
+        cursor.close()
+        conn.close()
+
+        # 2. Daten filtern und Duplikate (Twinks) aussortieren
         valid_users = {}
-        blacklisted_ids = []
-        ignored_duplicates = []
-        unique_users = []
-        unique_badgenr = []
-        unique_charinfo = []
-
-        for user, badge, cinfo in zip(users, badgenr, charinfo):
-            if user is None:
-                continue 
+        blacklisted_ids = set()
+
+        for badge, char_data, discord_str in rows:
+            if not discord_str:
+                continue
+
+            # Discord ID extrahieren
+            discord_id_parts = discord_str.split(":")
+            user_id = None
+            for part in discord_id_parts:
+                if part.isdigit():
+                    user_id = int(part)
+                    break
             
-            #delete users if they are duplicated
-            if user.id in blacklisted_ids:
-                ignored_duplicates.append((user, badge, cinfo))
+            if not user_id:
                 continue
-            elif user.id in valid_users:
-                first_entry = valid_users.pop(user.id)
-                ignored_duplicates.append(first_entry)
-                ignored_duplicates.append((user, badge, cinfo))
-                blacklisted_ids.append(user.id)
-            else:
-                valid_users[user.id] = (user, badge, cinfo)
-
-        for user, badge, cinfo in valid_users.values():
-            unique_users.append(user)
-            unique_badgenr.append(badge)
-            unique_charinfo.append(cinfo)
-
-        users = unique_users
-        badgenr = unique_badgenr
-        charinfo = unique_charinfo
-        print(f"Unique users: {len(users)}, Ignored duplicates: {len(ignored_duplicates)}")
-
-        #get charname
-        for char_data in charinfo:
-            try:
-                char_dict = json.loads(char_data)
-                firstname.append(char_dict.get("firstname", ""))
-                lastname.append(char_dict.get("lastname", ""))
-            except (json.JSONDecodeError, KeyError, TypeError):
-                firstname.append("")
-                lastname.append("")
-
-
-        #change username        
-        for user, badge, first, last in zip(users, badgenr, firstname, lastname):
-            nick = f"[{badge}] {first} {last}"
-            try:
-                guild = self.bot.get_guild(int(guild_id))
-                member = guild.get_member(user.id)
-                #print(f"Changing nickname for {user.name} to {nick}")
-                if member:
-                    await member.edit(nick=nick)
-            except Exception as e:
-                #print(f"Failed to change nickname for {user.name}: {e}")
+
+            # --- DEIN DUPLIKAT-SCHUTZ ---
+            # Wenn der User schon geblacklistet ist, überspringen
+            if user_id in blacklisted_ids:
+                continue 
+            
+            # Wenn wir den User zum ZWEITEN Mal sehen, ist es ein Duplikat
+            if user_id in valid_users:
+                del valid_users[user_id] # Von den gültigen löschen
+                blacklisted_ids.add(user_id) # Auf die Blacklist setzen
                 continue
-      
-        cursor.close()
-        conn.close()
+
+            # Vornamen und Nachnamen aus JSON holen
+            firstname, lastname = "", ""
+            if char_data:
+                try:
+                    char_dict = json.loads(char_data)
+                    firstname = char_dict.get("firstname", "")
+                    lastname = char_dict.get("lastname", "")
+                except (json.JSONDecodeError, KeyError, TypeError):
+                    pass 
+
+            # Ziel-Nickname generieren und auf 32 Zeichen limitieren (Discord Limit)
+            target_nick = f"[{badge}] {firstname} {lastname}".strip()
+            if len(target_nick) > 32:
+                target_nick = target_nick[:32]
+
+            # User in die Liste der "sicheren" Einträge packen
+            valid_users[user_id] = target_nick
+
+
+        # 3. Namen auf dem Discord-Server aktualisieren
+        print(f"Aktualisiere {len(valid_users)} User. Duplikate ignoriert: {len(blacklisted_ids)}")
+        
+        for user_id, target_nick in valid_users.items():
+            member = guild.get_member(user_id)
+            if member:
+                # WICHTIG: Nur ändern, wenn der Name nicht schon exakt so ist! (Schützt vor Discord API Sperren)
+                if member.display_name != target_nick:
+                    try:
+                        await member.edit(nick=target_nick)
+                    except discord.Forbidden:
+                        pass # Der Bot hat nicht die Rechte (User hat höhere Rolle als der Bot)
+                    except Exception as e:
+                        print(f"Fehler beim Ändern des Namens von User {user_id}: {e}")
 
 def setup(bot: discord.Bot):
     bot.add_cog(changedcname(bot))