232 lines
8.7 KiB
Python
232 lines
8.7 KiB
Python
# -----------------------read me?---------------------------
|
|
|
|
|
|
# compiling this is super easy, just run `pip install wget pyinstaller certifi` and then
|
|
# compile with `python -m PyInstaller --onefile installer.py --icon image.ico`
|
|
|
|
# (wget is a dependency for this python script that doesnt come with python by default)
|
|
# (and pyinstaller is the packagey thingamajig that compiles the code into an executable.)
|
|
|
|
# also, peep the organized code blocks!! am i cool or what?
|
|
|
|
|
|
# -----------------import dependencies----------------------
|
|
|
|
|
|
import wget; import os; import platform;
|
|
import time; import sys; import certifi
|
|
import shutil; import tarfile
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
# -----------define some functions ahead of time------------
|
|
|
|
|
|
# idea! consolidate both delete things and add an extra option to the functions that toggles-
|
|
# -error outputs using an if statement in the function's code `if quiet = true then... else...`
|
|
|
|
# as far as i can tell, i wanted to add an "option" to the function that toggled the warning m-
|
|
# -essage, so i dont have to use all this space here defining functions i dont really need.
|
|
|
|
class customerror(Exception):
|
|
def __init__(self, message):
|
|
self.message = message
|
|
super().__init__(self.message)
|
|
|
|
def delete_directory_warn(directory_to_delete, warn=False):
|
|
#this defines a function to delete a directory (no shit)
|
|
try:
|
|
shutil.rmtree(str(directory_to_delete))
|
|
except OSError as e:
|
|
print("[ERR!]: %s - %s." % (e.filename, e.strerror))
|
|
|
|
def delete_file_warn(file_to_delete):
|
|
#this defines a function to delete a file (no shit)
|
|
try:
|
|
os.remove(str(file_to_delete))
|
|
except OSError as e:
|
|
print("[ERR!]: %s - %s." % (e.filename, e.strerror))
|
|
|
|
def delete_directory(directory_to_delete):
|
|
#this defines a function to delete a directory (without any warnings)
|
|
try:
|
|
shutil.rmtree(str(directory_to_delete))
|
|
except:
|
|
pass
|
|
|
|
def delete_file(file_to_delete):
|
|
#this defines a function to delete a file (without any warnings)
|
|
try:
|
|
os.remove(str(file_to_delete))
|
|
except:
|
|
pass
|
|
|
|
def compress_tar(folder_path, output_file):
|
|
#this defines a function to compress a folder into a tarball
|
|
with tarfile.open(output_file, "w:gz") as tar:
|
|
tar.add(folder_path, arcname=os.path.basename(folder_path))
|
|
#gemini lowkey slayed w this one
|
|
|
|
def extract_tar(tar_file_path, extract_to):
|
|
#this defines a function to decompress a tar.gz file
|
|
with tarfile.open(tar_file_path, 'r') as tar:
|
|
tar.extractall(extract_to, filter="data")
|
|
|
|
def print_ascii_art():
|
|
#someone's gonna think im a furry or a femboy or some shit because of this.
|
|
print()
|
|
print()
|
|
print(" :+++++=")
|
|
print(" -++++++.")
|
|
print(" :++++++. .")
|
|
print(" .++++++. -=. -: .::")
|
|
print(" =+++++. :=. =- .--:. -")
|
|
print(" =+++++. .+ =: -=. :=")
|
|
print(" =+++++. +. :.=* .=: =:")
|
|
print(" =++++= .+ +. -- :+ .=")
|
|
print(" .+++++= .= ..=: :. =")
|
|
print(" .++=++- .= .+- =")
|
|
print(" ==++*=::.. * +")
|
|
print(" =*#-+- .:---:. :=-- .-=%. --=#- ..::.--")
|
|
print(" :#=-*- .::--:.*: .+ #@. - *@@- .. -#:")
|
|
print(" ++:*. .:--==:--:: .%%-.. :=.")
|
|
print(" =++.:...::::::..... :---+-:. .:.: --")
|
|
print(" *=..:::.. .=.")
|
|
print(" :-. .=:::")
|
|
print(" ..:=. :-..-:---:")
|
|
print(" ==:- .=-: :=-")
|
|
print(" .= =- :--. .--")
|
|
print(" -- :-:. -= .::::-:=.")
|
|
print(" :- =- :+ .+")
|
|
print(" --- -: .+ +.")
|
|
print(" := -= .+ =:")
|
|
print(" +. -: =: :=.")
|
|
print(" -. .=: --.....::-:")
|
|
print(" .=- .= :-:----- .::::.")
|
|
print(" .-: .= ..+:")
|
|
print(" -=......:.:-:+ :=")
|
|
print(" .::--::... := -")
|
|
print(" =: =:")
|
|
print(" --::.--")
|
|
print(" ....")
|
|
print()
|
|
|
|
def check_if_exists_and_delete_file(filepath):
|
|
#deletes old downloaded mod archives
|
|
if os.path.exists(filepath):
|
|
print("Found previously downloaded archive, deleting...")
|
|
os.remove(filepath)
|
|
else:
|
|
pass
|
|
|
|
def check_for_launcher_files(filepath, launchername):
|
|
#checks for evidence of 3rd party launchers and sets a variable flag if a launcher is installed
|
|
if os.path.exists(filepath):
|
|
global detectedlauncher
|
|
detectedlauncher = str(launchername)
|
|
print("[INFO]: Detected Minecraft launcher: " + str(launchername))
|
|
else:
|
|
print("[DBUG]: " + launchername + " not detected.")
|
|
|
|
|
|
# --------------------the real shit!------------------------
|
|
|
|
|
|
#detect operating system and find home, minecraft, & mod folders
|
|
homedir = os.path.expanduser("~")
|
|
os.chdir(homedir)
|
|
|
|
global mcfolder
|
|
global modfolder
|
|
# `global` sets these variables to exist outside of the scope of these specific `if` statements.
|
|
|
|
if platform.system() == "Linux":
|
|
print("[INFO]: Operating system detected: Linux")
|
|
|
|
detectedlauncher = "OfficialLauncher"
|
|
check_for_launcher_files(str(Path.cwd()) + "/.local/share/PrismLauncher", "PrismLauncherPackage")
|
|
check_for_launcher_files(str(Path.cwd()) + "/.var/app/org.prismlauncher.PrismLauncher/data/PrismLauncher/", "PrismLauncherFlatpak")
|
|
|
|
if detectedlauncher == "OfficialLauncher":
|
|
print("[INFO]: No 3rd party launchers detected, falling back to default official launcher directories")
|
|
os.chdir(".minecraft")
|
|
|
|
if detectedlauncher == "PrismLauncherPackage":
|
|
print("[INFO]: Using Prism Launcher (native) directory settings.")
|
|
os.chdir(".local/share/PrismLauncher/instances/1.20.1/minecraft/")
|
|
|
|
if detectedlauncher == "PrismLauncherFlatpak":
|
|
print("[INFO]: Using Prism Launcher (Flatpak) directory settings.")
|
|
os.chdir(".var/app/org.prismlauncher.PrismLauncher/data/PrismLauncher/instances/1.20.1/minecraft/")
|
|
|
|
mcfolder = str(Path.cwd())
|
|
modfolder = mcfolder + '/mods'
|
|
print("[INFO]: Changed current working directory to '" + str(mcfolder) + "'")
|
|
|
|
time.sleep(1)
|
|
print(); print("Backing up minecraft install...")
|
|
print("Don't close the window! This'll take a moment...")
|
|
|
|
compress_tar(mcfolder, "backup.tar.gz")
|
|
|
|
elif platform.system() == "Windows":
|
|
print("Operating system detected: Windows")
|
|
|
|
try:
|
|
os.chdir("AppData/Roaming/.minecraft")
|
|
except:
|
|
print("[ERR!] Fatal: Minecraft directory not found. (Is Minecraft installed?)")
|
|
print("[ERR!] Fatal: This window will close in 10 seconds...")
|
|
print
|
|
time.sleep(10)
|
|
exit
|
|
|
|
mcfolder = str(Path.cwd())
|
|
print("[INFO]: Changed current working directory to '" + str(mcfolder) + "'")
|
|
|
|
time.sleep(1)
|
|
print(); print("Backing up minecraft install...")
|
|
print("Don't close the window! This'll take a moment...")
|
|
|
|
modfolder = str(mcfolder) + '/mods'
|
|
compress_tar(mcfolder, "backup.tar.gz")
|
|
|
|
os.chdir(mcfolder)
|
|
time.sleep(2)
|
|
# unclear if this timeout is necessary for UX
|
|
|
|
# clear out preexisting mods
|
|
delete_file("mods.tar.gz")
|
|
delete_directory("mods")
|
|
print("Deleting mod folder contents...")
|
|
os.mkdir(str("mods"))
|
|
|
|
# download mod archive from git repo and extract
|
|
print("Fetching mods...")
|
|
|
|
os.environ['SSL_CERT_FILE'] = certifi.where()
|
|
# this line fixes SSL errors after compiling with PyInstaller as long as certifi is imported alongside it
|
|
|
|
try:
|
|
wget.download('https://git.sarushinobie.dev/saru/family-minecraft-modpack/releases/download/0.1.2/mods.tar.gz')
|
|
# this is insane. `wget` the fucking goat. who knew windows package manager was so cool?
|
|
except:
|
|
print(); print("[ERR!] Fatal: Download failed! (Is Adolin online?)"); print()
|
|
|
|
extract_tar('mods.tar.gz', 'mods')
|
|
# ('tarfile', 'directory to extract to')
|
|
|
|
print(""); print("sigma!")
|
|
print("all done!")
|
|
print("This window will exit and close in ten seconds. :)")
|
|
time.sleep(9)
|
|
print_ascii_art()
|
|
# print boykisser to console
|
|
time.sleep(1)
|
|
sys.exit
|
|
|
|
|
|
# --------------------the real shit!------------------------
|
|
|