import paramiko import os import json # Server-Details und Pfade SSH_HOST = "XXX.XXX.XXX.XXX" SSH_USER = "root" SSH_PASSWORD = "XXXXXXXXXX" DOCKER_VOLUME_PATH = "/media/usb0/docker-data/volumes/minecraft_mc/_data2" BEHAVIOR_PACKS_PATH = f"{DOCKER_VOLUME_PATH}/behavior_packs" RESOURCE_PACKS_PATH = f"{DOCKER_VOLUME_PATH}/resource_packs" WORLDS_PATH = f"{DOCKER_VOLUME_PATH}/worlds" WORLD_NAME = "Bedrock level" def ssh_connect(): client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(SSH_HOST, username=SSH_USER, password=SSH_PASSWORD) return client def get_mods(ssh, behavior_packs_path, resource_packs_path): # Befehl zum Auflisten der Verzeichnisse im Behavior Packs Pfad command_behavior = f'find {behavior_packs_path} -maxdepth 1 -type d' stdin, stdout, stderr = ssh.exec_command(command_behavior) behavior_packs = stdout.read().decode().strip().split('\n') # Filtere den Basispfad, leere Zeilen und unerwünschte Ordner heraus behavior_packs = [pack for pack in behavior_packs if pack and pack != behavior_packs_path and not os.path.basename(pack).startswith(("vanilla", "chemistry", "experimental"))] # Befehl zum Auflisten der Verzeichnisse im Resource Packs Pfad command_resource = f'find {resource_packs_path} -maxdepth 1 -type d' stdin, stdout, stderr = ssh.exec_command(command_resource) resource_packs = stdout.read().decode().strip().split('\n') # Filtere den Basispfad, leere Zeilen und unerwünschte Ordner heraus resource_packs = [pack for pack in resource_packs if pack and pack != resource_packs_path and not os.path.basename(pack).startswith(("vanilla", "chemistry", "experimental"))] # Bereinige die Pfade, um nur die Verzeichnisnamen zu erhalten behavior_packs = [os.path.basename(pack) for pack in behavior_packs] resource_packs = [os.path.basename(pack) for pack in resource_packs] print("Behavior Packs:") for pack in behavior_packs: print(pack) print("\nResource Packs:") for pack in resource_packs: print(pack) def mod_install_dialog(sftp): AUSWAHL = input("\nWas soll installiert werden?\n1 - Behavior Pack\n2 - Ressource Pack\n -> ") install_path = None # Initialisiere install_path mit None if AUSWAHL == "1": print("Behavior Pack wird installiert...") install_path = mod_install(sftp, "behavior") elif AUSWAHL == "2": print("Ressource Pack wird installiert...") install_path = mod_install(sftp, "ressource") if install_path: print(f"Mod wurde installiert unter: {install_path}") else: print("Installation fehlgeschlagen oder abgebrochen.") def mod_install(sftp, Pack_Type): world_name = WORLD_NAME local_dir_input = input("\nPfad zum Mod: ") local_dir = local_dir_input.strip('"').strip() local_dir_name = os.path.basename(local_dir) if Pack_Type == "behavior": remote_base_dir = BEHAVIOR_PACKS_PATH pack_type = "behavior" elif Pack_Type == "ressource": remote_base_dir = RESOURCE_PACKS_PATH pack_type = "ressource" else: print("Unbekannter Pack-Typ:", Pack_Type) return remote_dir = os.path.join(remote_base_dir, local_dir_name).replace('\\', '/') upload_directory(sftp, local_dir, remote_dir) # Extrahiere die UUID und Version aus der manifest.json uuid, version = extract_manifest_data(sftp, remote_dir) # Füge die Daten in die Welt-JSON-Datei ein world_path = os.path.join(WORLDS_PATH, world_name).replace('\\', '/') json_add(sftp, world_path, pack_type, uuid, version) return remote_dir def upload_directory(sftp, local_dir, remote_dir): """Hilfsfunktion zum rekursiven Hochladen des Inhalts eines Verzeichnisses.""" if not os.path.isdir(local_dir): print("Der angegebene Pfad ist kein Verzeichnis:", local_dir) return for item in os.listdir(local_dir): local_path = os.path.join(local_dir, item) # Konvertiere Windows-Pfade in Unix-Pfade für den Remote-Server remote_path = os.path.join(remote_dir, item).replace('\\', '/') if os.path.isdir(local_path): # Es ist ein Verzeichnis, rekursiv weitermachen try: sftp.listdir(remote_path) except IOError: sftp.mkdir(remote_path) upload_directory(sftp, local_path, remote_path) # Rekursiver Aufruf mit korrekten Pfaden else: # Es ist eine Datei, hochladen sftp.put(local_path, remote_path) def extract_manifest_data(sftp, mod_path): manifest_path = os.path.join(mod_path, "manifest.json").replace('\\', '/') try: with sftp.open(manifest_path, "r") as manifest_file: manifest_data = json.load(manifest_file) uuid = manifest_data['header']['uuid'] version = ".".join(str(v) for v in manifest_data['header']['version']) return uuid, version except Exception as e: print(f"Fehler beim Lesen der manifest.json: {e}") return None, None def json_add(sftp, world_path, pack_type, uuid, version): if pack_type == "behavior": json_file_path = os.path.join(world_path, "world_behavior_packs.json").replace('\\', '/') elif pack_type == "ressource": json_file_path = os.path.join(world_path, "world_resource_packs.json").replace('\\', '/') else: print("Unbekannter Pack-Typ") return # Stelle sicher, dass das Verzeichnis existiert try: sftp.chdir(world_path) # Versuche, in das Verzeichnis zu wechseln except IOError: print(f"Das Verzeichnis {world_path} existiert nicht auf dem Server.") return data = [] # Initialisiere eine leere Liste für den Fall, dass die Datei nicht existiert try: # Versuche, die existierende JSON-Datei zu lesen with sftp.open(json_file_path, "r") as json_file: data = json.load(json_file) except IOError: print(f"Die Datei {json_file_path} existiert nicht. Eine neue Datei wird erstellt.") # Füge das neue Pack hinzu new_pack = {"pack_id": uuid, "version": version} if new_pack not in data: data.append(new_pack) # Schreibe die aktualisierte Liste zurück in die Datei with sftp.open(json_file_path, "w") as json_file: json.dump(data, json_file, indent=4) print(f"Die Informationen wurden erfolgreich zu {json_file_path} hinzugefügt.") def remove_mod_from_json(sftp, world_path, pack_type, uuid): if pack_type == "behavior": json_file_path = os.path.join(world_path, "world_behavior_packs.json").replace('\\', '/') elif pack_type == "ressource": json_file_path = os.path.join(world_path, "world_resource_packs.json").replace('\\', '/') else: print("Unbekannter Pack-Typ") return False try: with sftp.open(json_file_path, "r") as json_file: data = json.load(json_file) except IOError: print(f"Die Datei {json_file_path} existiert nicht.") return False # Entferne den Eintrag mit der entsprechenden UUID data = [pack for pack in data if pack.get("pack_id") != uuid] # Schreibe die aktualisierte Liste zurück in die Datei with sftp.open(json_file_path, "w") as json_file: json.dump(data, json_file, indent=4) print(f"Mod mit UUID {uuid} wurde aus {json_file_path} entfernt.") return True def delete_mod_folder(sftp, mod_path): try: # Liste alle Dateien/Ordner im Mod-Ordner auf und lösche sie for item in sftp.listdir(mod_path): item_path = os.path.join(mod_path, item).replace('\\', '/') try: sftp.remove(item_path) # Versuche, die Datei zu löschen except IOError: delete_mod_folder(sftp, item_path) # Falls es ein Ordner ist, rekursiv löschen sftp.rmdir(mod_path) # Lösche den nun leeren Mod-Ordner print(f"Mod-Ordner {mod_path} wurde gelöscht.") return True except Exception as e: print(f"Fehler beim Löschen des Mod-Ordners {mod_path}: {e}") return False def mod_uninstall_dialog(sftp): pack_type_input = input("\nWelcher Typ von Mod soll deinstalliert werden?\n1 - Behavior Pack\n2 - Ressource Pack\n -> ") pack_type = "behavior" if pack_type_input == "1" else "ressource" mod_name = input("Gib den Namen des Mods ein: ").strip() # Pfade für den Mod und die JSON-Datei remote_base_dir = BEHAVIOR_PACKS_PATH if pack_type == "behavior" else RESOURCE_PACKS_PATH mod_path = os.path.join(remote_base_dir, mod_name).replace('\\', '/') world_path = os.path.join(WORLDS_PATH, WORLD_NAME).replace('\\', '/') # Extrahiere die UUID aus der manifest.json des Mods uuid, _ = extract_manifest_data(sftp, mod_path) if uuid: # Entferne den Mod aus der JSON-Datei und lösche den Mod-Ordner if remove_mod_from_json(sftp, world_path, pack_type, uuid) and delete_mod_folder(sftp, mod_path): print(f"Mod {mod_name} wurde erfolgreich deinstalliert.") else: print("Fehler beim Deinstallieren des Mods.") else: print("Mod konnte nicht gefunden oder UUID konnte nicht extrahiert werden.") if __name__ == "__main__": ssh = ssh_connect() run = True while run: AUSWAHL = input("\nBefehl eingeben:\n1 - Mods auflisten\n2 - Mod installieren\n3 - Mod deinstallieren\nq - Beenden\n -> ").strip() if(AUSWAHL == "1"): get_mods(ssh, BEHAVIOR_PACKS_PATH, RESOURCE_PACKS_PATH) elif(AUSWAHL == "2"): sftp = ssh.open_sftp() mod_install_dialog(sftp) elif(AUSWAHL == "3"): sftp = ssh.open_sftp() mod_uninstall_dialog(sftp) elif(AUSWAHL == "q"): ssh.close() run = False