ModpackUpdater/Backend.py
2024-06-20 16:09:18 -06:00

211 lines
6.5 KiB
Python

from ftplib import FTP_TLS as FTP
import io
import json
import tempfile
import subprocess
import time
import os
import datetime
import zipfile
from customtkinter import *
import time
import math
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()
ftp.retrbinary("RETR versions.json", bio.write)
bio.seek(0)
versions = json.load(bio)
bio.close()
# Checking current version
version = "0.0.0"
version_file_path = os.path.join(prism_instance_path, instance_name, ".minecraft", "version.txt")
if os.path.exists(version_file_path):
with open(version_file_path, 'r') as fp:
version = fp.readline().rstrip()
# Checking if update is needed
if version != versions[-1]["Version"]:
print(f"Current version: {version}")
print(f"Latest version: {versions[-1]['Version']}")
# Downloading modpack
with tempfile.TemporaryDirectory() as temp_dir:
modpack_file_path = os.path.join(temp_dir, instance_name + ".mrpack")
with open(modpack_file_path, 'wb') as modpack:
ftpDownload(ftp, versions[-1]["File"], modpack)
# Running PrismLauncher with modpack
subprocess.Popen([prism_command, '-I', modpack_file_path])
# Waiting for installation to complete
while True:
time.sleep(5)
if os.path.exists(version_file_path):
with open(version_file_path, 'r') as fp:
version = fp.readline().rstrip()
if version == versions[-1]["Version"]:
break
except Exception as e:
print(e)
print("Unable to check for updates. Modpack may be out of date")
finally:
# Launching PrismLauncher with the instance
subprocess.run([prism_command, '-l', instance_name])
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/"+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()
def deleteModpack(username, password, id):
ftp = FTP("gitea.piwalker.net", username, password)
ftp.prot_p()
modpacks = getModpacks()
for pack in modpacks:
if pack["id"] == id:
modpacks.remove(pack)
break
uploadModpacks(modpacks, ftp)
deleteFolder(ftp, id)
def deleteFolder(ftp, path):
print("Deleting folder: "+path)
ftp.cwd(path)
for item in ftp.nlst():
try:
print("deleting file: "+path)
ftp.delete(item)
except:
deleteFolder(ftp, item)
ftp.cwd("..")
ftp.rmd(path)
def ftpDownload(ftp, file, stream):
#create tkinter window
print("downloading file: "+file)
dialog = CTk()
dialog.attributes('-type', 'dialog')
dialog.title("Downloading Modpack")
set_appearance_mode("dark")
set_default_color_theme("blue")
global pbar
pbar = CTkProgressBar(master=dialog)
pbar.pack(padx=20, pady=20)
global progress
global ETA
progress = StringVar()
ETA = StringVar()
progress_label = CTkLabel(master=dialog, textvariable=progress)
progress_label.pack()
eta_label = CTkLabel(master=dialog, textvariable=ETA)
eta_label.pack()
size = ftp.size(file)
global total
total = 0
global start
global timer
timer = 0
start = time.time()
dialog.update()
def downloadCallback(data):
global total
global pbar
global start
global progress
global ETA
global timer
stream.write(data)
total += len(data)
if time.time() - timer >= 1:
progress.set(str(round(total/1048576, 1))+" MB / "+str(round(size/1048576, 1))+" MB @ " + str(round((total/1048576)/(time.time()-start), 3))+" MB/s")
time_left = (size-total)/(total/(time.time()-start))
ETA.set("ETA: " + str(datetime.timedelta(seconds=math.ceil(time_left))))
pbar.set(total/size)
dialog.update()
timer = time.time()
ftp.retrbinary("RETR " + file, downloadCallback)
dialog.quit()