From 75fa3e05e493a8cc317ae7771c7bff1891d379a5 Mon Sep 17 00:00:00 2001 From: Samuel Walker Date: Thu, 20 Jun 2024 12:07:56 -0600 Subject: [PATCH] Added GUI and improved upload capabilities --- Backend.py | 69 +++++++++++++++++++++++++-- Main.py | 22 +++++++-- Upload.py | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 214 insertions(+), 12 deletions(-) diff --git a/Backend.py b/Backend.py index fa2f888..dcfcada 100644 --- a/Backend.py +++ b/Backend.py @@ -6,13 +6,15 @@ import subprocess import time import os import datetime +import zipfile -def perform_installation(instance_name, prism_command, prism_instance_path): +def perform_installation(instance_name, prism_command, prism_instance_path, pack): try: ftp = FTP("gitea.piwalker.net") ftp.login() ftp.prot_p() + ftp.cwd(pack) # Fetching versions.json from FTP bio = io.BytesIO() @@ -57,22 +59,79 @@ def perform_installation(instance_name, prism_command, prism_instance_path): subprocess.run([prism_command, '-l', instance_name]) -def upload_pack(username, password, version_tag, fileName): +def upload_pack(username, password, version_tag, fileName, pack): ftp = FTP("gitea.piwalker.net", username, password) ftp.prot_p() + ftp.cwd(pack) bio = io.BytesIO() ftp.retrbinary("RETR versions.json", bio.write) bio.seek(0) versions = json.load(bio) bio.close() time = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") - versions.append({"Version":version_tag, "Date":time, "File":"Versions/fcs7-"+time+".mrpack"}) - with open(fileName, 'rb') as fp: - ftp.storbinary("STOR "+versions[len(versions)-1]["File"], fp) + versions.append({"Version":version_tag, "Date":time, "File":"Versions/"+pack+time+".mrpack"}) + with zipfile.ZipFile(fileName, 'r') as zin: + zipbytes = io.BytesIO() + zout = zipfile.ZipFile(zipbytes, 'w') + for item in zin.infolist(): + buffer = zin.read(item.filename) + if item.filename != "overrides/version.txt": + zout.writestr(item, buffer) + zout.writestr("overrides/version.txt", version_tag) + zout.close() + zipbytes.seek(0) + ftp.storbinary("STOR "+versions[len(versions)-1]["File"], zipbytes) bio = io.BytesIO() bio.write(json.dumps(versions).encode()) bio.seek(0) ftp.storbinary("STOR versions.json", bio) bio.close() + modpackUpdate(pack, ftp) ftp.close() +def getModpacks(): + ftp = FTP("gitea.piwalker.net") + ftp.login() + ftp.prot_p() + bio = io.BytesIO() + ftp.retrbinary("RETR modpacks.json", bio.write) + bio.seek(0) + ftp.close() + return json.load(bio) + +def uploadModpacks(modpacks, ftp): + ftp.cwd("/ftp"); + bio = io.BytesIO() + bio.write(json.dumps(modpacks).encode()) + bio.seek(0) + ftp.storbinary("STOR modpacks.json", bio) + bio.close() + +def modpackUpdate(id, ftp): + modpacks = getModpacks() + time = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") + for modpack in modpacks: + if modpack["id"] == id: + modpack["last-updated"] = time + uploadModpacks(modpacks, ftp); + +def createModpack(id, name, username, password): + modpacks = getModpacks() + time = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") + modpacks.append({"id":id, "name":name, "last-updated":time}) + ftp = FTP("gitea.piwalker.net", username, password) + ftp.prot_p() + uploadModpacks(modpacks,ftp) + ftp.mkd(id) + ftp.cwd(id) + versions = [] + bio = io.BytesIO() + bio.write(json.dumps(versions).encode()) + bio.seek(0) + ftp.storbinary("STOR versions.json", bio) + ftp.mkd("Versions") + ftp.close() + + + + diff --git a/Main.py b/Main.py index 6609765..4823516 100644 --- a/Main.py +++ b/Main.py @@ -17,6 +17,8 @@ config_file_path = 'config.ini' # Path to the configuration file def select_prism_instance_path(): global prism_instance_path_entry directory = filedialog.askdirectory() + if not directory: + return prism_instance_path_entry.delete(0, tk.END) prism_instance_path_entry.insert(0, directory) @@ -29,7 +31,7 @@ def main(): global prism_instance_path_entry - instance_name = "Familycraft Season 7" + instance_name = "Test Modpack" prism_command = "prismlauncher" # Default paths based on OS @@ -88,8 +90,17 @@ def main(): # If a stored Prism instance path exists, pre-fill the entry widget if stored_prism_instance_path: prism_instance_path_entry.insert(0, stored_prism_instance_path) - + options = [] + modpacks = Backend.getModpacks() + for modpack in modpacks: + options.append(modpack["name"]) # Button to select directory + modpack_var = StringVar(value="N/A") + modpack_label = CTkLabel(master=guitabs.tab("Launcher"), text="Select Modpack:", font=("Impact", 30)) + modpack_label.pack() + modpack_selector = CTkOptionMenu(master=guitabs.tab("Launcher"), values=options, variable=modpack_var) + modpack_selector.set(options[0]) + modpack_selector.pack() select_button = CTkButton(master=guitabs.tab("Options"), text="Browse...", command=select_prism_instance_path) select_button.pack(pady=5) @@ -97,7 +108,12 @@ def main(): def start_installation(): prism_instance_path = prism_instance_path_entry.get() app.destroy() # Close the GUI window - Backend.perform_installation(instance_name, prism_command, prism_instance_path) + for modpack in modpacks: + if modpack["name"] == modpack_var.get(): + instance_name = modpack["name"] + instance_id = modpack["id"] + break + Backend.perform_installation(instance_name, prism_command, prism_instance_path, instance_id) # Button to start installation install_button = CTkButton(master=guitabs.tab("Launcher"), text="Launch Minecraft", command=start_installation) diff --git a/Upload.py b/Upload.py index 93a4eaf..a54cee1 100644 --- a/Upload.py +++ b/Upload.py @@ -1,11 +1,138 @@ import Backend +from getpass import getpass +from customtkinter import * +from tkinter import filedialog, simpledialog, messagebox + +global version +global modpack +global modpack_name +global modpack_id +global username +global password +global modpacks + +def get_credentials(): + global username + global password + username = simpledialog.askstring("username", "Username: ") + password = simpledialog.askstring("password", "Password: ", show="*") + +def select_file(): + global fileName + global file_path_entry + file = filedialog.askopenfilename() + if file: + fileName = file + file_path_entry.insert(0, fileName) + +def update_pack(): + global modpacks + global fileName + global username + global password + global modpack + global version + get_credentials() + pack_id = None + for pack in modpacks: + if pack["name"] == modpack.get(): + pack_id = pack["id"] + Backend.upload_pack(username, password, version.get(), fileName, pack_id) + messagebox.Message(title="complete", message="Modpack updated successfuly") + +def create_pack(): + global username + global password + global modpacks + global modpack_id + global modpack_name + global version + global fileName + for pack in modpacks: + if pack["id"] == modpack_id.get(): + messagebox.Message(title="Error", message="Pack ID already exists").show() + return + if pack["name"] == modpack_name.get(): + messagebox.Message(title="Error", message="Pack name already exists").show() + return + get_credentials() + Backend.createModpack(modpack_id.get(), modpack_name.get(), username, password) + Backend.upload_pack(username, password, version.get(), fileName, modpack_id.get()) + messagebox.Message(title="complete", message="Modpack created successfully").show() def main(): + global fileName + global modpacks + global modpack_id + global version + global modpack + global modpack_name fileName = "modpack.mrpack" - username = input("Username: ") - password = getpass() - version_tag = input("Version Number: ") - Backend.upload_pack(username, password, version_tag, fileName) + + app = CTk() + app.attributes('-type', 'dialog') + app.geometry('500x400') + app.title("FamilyCraft Launcher Upload Utility") + set_appearance_mode("dark") + set_default_color_theme("blue") + + version = StringVar() + modpack = StringVar() + modpack_name = StringVar() + modpack_id = StringVar() + + + + + file_label = CTkLabel(master=app, text="Select mrpack file:", font=("Impact", 15)) + file_label.pack() + global file_path_entry + file_path_entry = CTkEntry(master=app, width=350, font=("Arial", 14)) + file_path_entry.pack(pady=5) + file_path_entry.insert(0, fileName) + browse_button = CTkButton(master=app, text="Browse...", command=select_file) + browse_button.pack(pady=5) + + version_label = CTkLabel(master=app, text="Version Number:", font=("Impact", 15)) + version_label.pack() + version_entry = CTkEntry(master=app, width=350, font=("Arial", 14), placeholder_text="0.0.0", textvariable=version) + version_entry.pack(pady=5) + + guitabs = CTkTabview(master=app, bg_color="transparent") + guitabs.pack(expand=True, fill='x', side="bottom", padx=0, pady=(10,0)) + guitabs.add("Update Pack") + guitabs.add("Create Pack") + + modpacks = Backend.getModpacks() + options = [] + for pack in modpacks: + options.append(pack["name"]) + modpack_selector = CTkOptionMenu(master=guitabs.tab("Update Pack"), values=options, variable=modpack) + modpack_selector.set(options[0]) + modpack_selector.pack() + + update_button = CTkButton(master=guitabs.tab("Update Pack"), text="Update", command=update_pack) + update_button.pack(pady=5) + + modpack_id_label = CTkLabel(master=guitabs.tab("Create Pack"), text="ID:", font=("Impact", 15)) + modpack_id_label.pack() + modpack_id_entry = CTkEntry(master=guitabs.tab("Create Pack"), width=350, font=("Arial", 14), textvariable=modpack_id) + modpack_id_entry.pack(pady=5) + + modpack_name_label = CTkLabel(master=guitabs.tab("Create Pack"), text="Name: ", font=("Impact", 15)) + modpack_name_label.pack() + modpack_name_entry = CTkEntry(master=guitabs.tab("Create Pack"), width=350, font=("Arial", 14), textvariable=modpack_name) + modpack_name_entry.pack(pady=5) + + create_button = CTkButton(master=guitabs.tab("Create Pack"), text="Create", command=create_pack) + create_button.pack(pady=5) + + + #username = input("Username: ") + #password = getpass() + #version_tag = input("Version Number: ") + #Backend.upload_pack(username, password, version_tag, fileName, "test") + app.mainloop() if __name__=="__main__":