4 Commits
Author SHA1 Message Date
big-duckie 1783201372 Slug now updates when use changes mod name.
Added folder selection dialog to options menu.
Fixed bug where options were not being saved to the correct path.
2024-11-27 18:47:17 -07:00
big-duckie 42b3abe357 Fix some bugs when trying to extract mod info from the jar. 2024-11-15 21:43:59 -07:00
big-duckie 115087fd8a Fix some bugs that happen when registering the mod with solder. 2024-11-15 21:43:00 -07:00
big-duckie 19615a8b34 Fix issues with relative paths when scripts are packaged into binaries. 2024-11-15 15:47:59 -07:00
3 changed files with 76 additions and 52 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ build-cli:
source venv/bin/activate && pyinstaller --onefile --icon=wrenchIcon.ico solderPacker.py
build-gui:
source venv/bin/activate && pyinstaller --windowed --onefile --icon=wrenchIcon.ico solderPackerGUI.py
source venv/bin/activate && pyinstaller --windowed --onefile --icon=wrenchIcon.ico --add-data="wrenchIcon.ico:." solderPackerGUI.py
clean:
- rm -r venv
+8 -5
View File
@@ -38,7 +38,7 @@ class SolderPacker:
def register_mod(self, mod_slug: str, mod_name: str, mod_author: str, mod_description: str, mod_url: str):
resp = requests.get(f"{self.solder_url}/api/mod/{mod_slug}")
if resp.status_code == 404:
if resp.status_code != 200:
mod_data = {
"name": mod_slug,
"pretty_name": mod_name,
@@ -46,12 +46,15 @@ class SolderPacker:
"description": mod_description,
"link": mod_url
}
requests.post(f"{self.solder_url}/mod/create", cookies={"technic_solder_session": self.solder_key},
data=mod_data, headers={"Origin": self.solder_url, "X-Requested-With": "XMLHttpRequest"})
resp = requests.get(f"{self.solder_url}/api/mod/{mod_slug}")
resp = requests.post(f"{self.solder_url}/mod/create",
cookies={"technic_solder_session": self.solder_key},
data=mod_data,
headers={"Origin": self.solder_url, "Referer": f"{self.solder_url}/mod/create"})
if resp.status_code == 404:
logging.debug("failed to register mod")
return False
resp = requests.get(f"{self.solder_url}/api/mod/{mod_slug}")
return resp.json()
else:
logging.debug("mod already registered")
+65 -44
View File
@@ -16,14 +16,14 @@ from solderPacker import SolderPacker
# Globals
config = {}
base_path = os.path.dirname(os.path.realpath(__file__))
base_path = os.path.dirname(__file__)
class Form(QtW.QMainWindow):
def __init__(self):
QtW.QMainWindow.__init__(self)
self.setMinimumSize(400, 500)
self.setWindowIcon(QtG.QIcon(f"{base_path}{os.sep}wrenchIcon.ico"))
self.setMinimumSize(500, 600)
self.setWindowIcon(QtG.QIcon(os.path.join(base_path, "wrenchIcon.ico")))
self.setWindowTitle("Solder Packer")
self.thread_pool = QtC.QThreadPool()
@@ -39,6 +39,7 @@ class Form(QtW.QMainWindow):
mod_title_label = QtW.QLabel("Mod Name")
self.mod_title_edit = QtW.QLineEdit("")
self.mod_title_edit.textChanged.connect(self.update_slug)
layout.addWidget(mod_title_label, 1, 1)
layout.addWidget(self.mod_title_edit, 1, 2)
@@ -108,40 +109,49 @@ class Form(QtW.QMainWindow):
self.solder_packer.solder_url = config["url"]
self.solder_packer.solder_key = config["token"]
def update_slug(self):
self.mod_slug_edit.setText(slugify(self.mod_title_edit.text(),
replacements=[["&", "and"], ["$", "s"], ["'", ""]]))
def file_dropped(self, file_path: str):
self.jar_path = file_path
self.btn_process.setText("Process")
if config["extract"]:
jar = zipfile.ZipFile(file_path, "r")
loaders = []
if "META-INF/mods.toml" in jar.namelist():
# This jar file uses FML
logging.debug("identified mod as forge mod")
loaders.append("forge")
mod_toml = toml.loads(jar.read("META-INF/mods.toml").decode("utf-8"))
# This mess is to catch if the mod is using the Jar version for versioning. It extracts it from the
# MANIFEST.MF and places it where it should be in the toml.
if mod_toml["mods"][0]["version"] == "${file.jarVersion}":
if mod_toml.get("mods", [{}])[0].get("version") == "${file.jarVersion}":
try:
mod_toml["mods"][0]["version"] = re.findall(
r"Implementation-Version: (.*)", jar.read("META-INF/MANIFEST.MF").decode("utf-8"))[0]
except IndexError:
mod_toml["mods"][0]["version"] = "0.0.0"
# Update form with data
self.mod_title_edit.setText(mod_toml.get("mods", [{}])[0].get("displayName", ""))
self.mod_slug_edit.setText(slugify(mod_toml.get("mods", [{}])[0].get("displayName", ""),
replacements=[["&", "and"], ["$", "s"], ["'", ""]]))
self.mod_version_edit.setText(mod_toml.get("mods", [{}])[0].get("version", ""))
self.mod_loader_edit.setText("forge")
self.mod_author_edit.setText(mod_toml.get("mods", [{}])[0].get("authors", ""))
self.mod_url_edit.setText(mod_toml.get("mods", [{}])[0].get("displayURL", ""))
self.mod_desc_edit.setPlainText(mod_toml.get("mods", [{}])[0].get("description", ""))
elif "fabric.mod.json" in jar.namelist():
self.mod_title_edit.setText(mod_toml.get("mods", [{}])[0].get("displayName", "").strip())
self.mod_slug_edit.setText(slugify(self.mod_title_edit.text(),
replacements=[["&", "and"], ["$", "s"], ["'", ""]]).strip())
self.mod_version_edit.setText(mod_toml.get("mods", [{}])[0].get("version", "").strip())
self.mod_author_edit.setText(mod_toml.get("mods", [{}])[0].get("authors", "").strip())
self.mod_url_edit.setText(mod_toml.get("mods", [{}])[0].get("displayURL", "").strip())
self.mod_desc_edit.setPlainText(mod_toml.get("mods", [{}])[0].get("description", "").strip())
if "fabric.mod.json" in jar.namelist():
# This jar file uses Fabric
logging.debug("identified mod as fabric mod")
loaders.append("fabric")
mod_json = json.loads(jar.read("fabric.mod.json").decode("utf-8"))
# Update form with data
self.mod_title_edit.setText(mod_json.get("name", ""))
self.mod_title_edit.setText(mod_json.get("name", "").strip())
self.mod_slug_edit.setText(slugify(mod_json.get("name", ""),
replacements=[["&", "and"], ["$", "s"], ["'", ""]]))
self.mod_version_edit.setText(mod_json.get("version", ""))
self.mod_loader_edit.setText("fabric")
self.mod_version_edit.setText(mod_json.get("version", "").strip())
# Some spaghetti code for dealing with the possibility of authors being a []string or a dict.
authors = mod_json.get("authors", [])
@@ -151,28 +161,29 @@ class Form(QtW.QMainWindow):
author_list.append(author.get("name"))
elif len(authors) > 0 and type(authors[0]) == str:
author_list = authors
self.mod_author_edit.setText(", ".join(author_list))
self.mod_url_edit.setText(mod_json.get("contact", {}).get("homepage", ""))
self.mod_desc_edit.setPlainText(mod_json.get("description", ""))
elif "quilt.mod.json" in jar.namelist():
self.mod_author_edit.setText(", ".join(author_list).strip())
self.mod_url_edit.setText(mod_json.get("contact", {}).get("homepage", "").strip())
self.mod_desc_edit.setPlainText(mod_json.get("description", "").strip())
if "quilt.mod.json" in jar.namelist():
# This jar file uses Quilt
logging.debug("identified mod as quilt mod")
loaders.append("quilt")
mod_json = json.loads(jar.read("quilt.mod.json").decode("utf-8"))
# Update form with data
self.mod_title_edit.setText(mod_json.get("quilt_loader", {}).get("metadata", {}).get("name", ""))
self.mod_title_edit.setText(
mod_json.get("quilt_loader", {}).get("metadata", {}).get("name", "").strip())
self.mod_slug_edit.setText(slugify(mod_json.get("quilt_loader", {}).get("metadata", {}).get("name", ""),
replacements=[["&", "and"], ["$", "s"], ["'", ""]]))
self.mod_version_edit.setText(mod_json.get("quilt_loader", {}).get("version", ""))
self.mod_loader_edit.setText("quilt")
self.mod_author_edit.setText(
", ".join(mod_json.get("quilt_loader", {}).get("metadata", {}).get("contributors", {}).keys()))
replacements=[["&", "and"], ["$", "s"], ["'", ""]]).strip())
self.mod_version_edit.setText(mod_json.get("quilt_loader", {}).get("version", "").strip())
self.mod_author_edit.setText(", ".join(
mod_json.get("quilt_loader", {}).get("metadata", {}).get("contributors", {}).keys()).strip())
self.mod_url_edit.setText(
mod_json.get("quilt_loader", {}).get("metadata", {}).get("contact", {}).get("homepage", ""))
mod_json.get("quilt_loader", {}).get("metadata", {}).get("contact", {}).get("homepage", "").strip())
self.mod_desc_edit.setPlainText(
mod_json.get("quilt_loader", {}).get("metadata", {}).get("description", ""))
else:
logging.debug("failed to identify mod loader")
mod_json.get("quilt_loader", {}).get("metadata", {}).get("description", "").strip())
self.mod_loader_edit.setText("+".join(loaders))
jar.close()
def process_click(self):
@@ -203,15 +214,17 @@ class Form(QtW.QMainWindow):
def finished_processing(self):
self.btn_process.setEnabled(True)
self.btn_process.setText("Process")
self.btn_process.setText("Finished")
def failed_processing(self):
def failed_processing(self, err):
dialog = QtW.QMessageBox(self)
dialog.setWindowTitle("Error")
dialog.setText("There was an error processing this JAR.")
dialog.exec()
self.finished_processing()
logging.debug(err)
self.btn_process.setEnabled(True)
self.btn_process.setText("Failed")
class FileDropArea(QtW.QLabel):
@@ -238,9 +251,9 @@ class OptionsDialog(QtW.QDialog):
def __init__(self, parent=None):
QtW.QDialog.__init__(self, parent)
self.setMinimumSize(300, 200)
self.setMinimumSize(400, 200)
self.setWindowIcon(QtG.QIcon(f"{base_path}{os.sep}wrenchIcon.ico"))
self.setWindowIcon(QtG.QIcon(os.path.join(base_path, "wrenchIcon.ico")))
self.setWindowTitle("Options")
layout = QtW.QGridLayout()
@@ -252,10 +265,15 @@ class OptionsDialog(QtW.QDialog):
self.input_export_folder = QtW.QLineEdit(config["path"])
layout.addWidget(self.input_export_folder, 1, 2)
self.btn_export_folder = QtW.QPushButton("Browse")
self.btn_export_folder.clicked.connect(self.select_folder)
layout.addWidget(self.btn_export_folder, 1, 3)
self.input_technic_url = QtW.QLineEdit(config["url"])
layout.addWidget(self.input_technic_url, 2, 2)
layout.addWidget(self.input_technic_url, 2, 2, 1, 2)
self.input_technic_cookie = QtW.QLineEdit(config["token"])
layout.addWidget(self.input_technic_cookie, 3, 2)
layout.addWidget(self.input_technic_cookie, 3, 2, 1, 2)
self.checkbox_extract_data = QtW.QCheckBox("Extract Mod Info")
self.checkbox_extract_data.setChecked(config["extract"])
@@ -263,10 +281,10 @@ class OptionsDialog(QtW.QDialog):
self.checkbox_upload_data = QtW.QCheckBox("Upload Data")
self.checkbox_upload_data.setChecked(config["upload"])
layout.addWidget(self.checkbox_upload_data, 4, 2)
layout.addWidget(self.checkbox_upload_data, 4, 2, 1, 2)
button_save = QtW.QPushButton("Save")
layout.addWidget(button_save, 5, 1, 1, 2)
layout.addWidget(button_save, 5, 1, 1, 3)
button_save.clicked.connect(self.save_options)
def save_options(self):
@@ -276,11 +294,14 @@ class OptionsDialog(QtW.QDialog):
config["extract"] = (self.checkbox_extract_data.checkState() == QtC.Qt.CheckState.Checked)
config["upload"] = (self.checkbox_upload_data.checkState() == QtC.Qt.CheckState.Checked)
with open(f"{base_path}{os.sep}config.toml", "w") as f:
toml.dump(config, f)
f.close()
with open(os.path.join(os.getcwd(), "config.toml"), "w") as configFile:
toml.dump(config, configFile)
configFile.close()
self.close()
def select_folder(self):
self.input_export_folder.setText(str(QtW.QFileDialog.getExistingDirectory(self, "Select Folder")))
@QtC.Slot()
def closeEvent(self, event):
self.closed.emit()
@@ -318,7 +339,7 @@ if __name__ == '__main__':
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
try:
config = toml.load(f"{base_path}{os.sep}config.toml")
config = toml.load(os.path.join(os.getcwd(), "config.toml"))
except FileNotFoundError:
config = {}
@@ -327,7 +348,7 @@ if __name__ == '__main__':
config["token"] = get_default(config, "token", os.environ.get("SOLDER_KEY") or "")
config["extract"] = get_default(config, "extract", True)
config["upload"] = get_default(config, "upload", False)
with open(f"{base_path}{os.sep}config.toml", "w") as f:
with open(os.path.join(os.getcwd(), "config.toml"), "w") as f:
toml.dump(config, f)
f.close()