From 0dbe28914de7a70e2f0947350e081ae1d6fa2e6e Mon Sep 17 00:00:00 2001 From: yeah-its-gloria <32610623+yeah-its-gloria@users.noreply.github.com> Date: Sat, 19 Oct 2024 18:07:42 +0200 Subject: [PATCH] Add batch downloading with NUSD scripts --- NUSGet.py | 67 +++++++++++++++++++++++++++++++++++++++-- modules/download_dsi.py | 13 +++++++- modules/download_wii.py | 14 ++++++++- qt/py/ui_MainMenu.py | 15 +++++++-- qt/ui/MainMenu.ui | 21 ++++++++++--- 5 files changed, 118 insertions(+), 12 deletions(-) diff --git a/NUSGet.py b/NUSGet.py index b0c014e..1848d34 100644 --- a/NUSGet.py +++ b/NUSGet.py @@ -11,14 +11,14 @@ from importlib.metadata import version from PySide6.QtGui import QIcon from PySide6.QtWidgets import (QApplication, QMainWindow, QMessageBox, QTreeWidgetItem, QHeaderView, QStyle, - QStyleFactory) + QStyleFactory, QFileDialog) from PySide6.QtCore import QRunnable, Slot, QThreadPool, Signal, QObject, QLibraryInfo, QTranslator, QLocale from qt.py.ui_MainMenu import Ui_MainWindow from modules.core import * -from modules.download_wii import run_nus_download_wii -from modules.download_dsi import run_nus_download_dsi +from modules.download_wii import run_nus_download_wii, run_nus_download_wii_batch +from modules.download_dsi import run_nus_download_dsi, run_nus_download_dsi_batch nusget_version = "1.2.0" @@ -63,6 +63,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.ui.setupUi(self) self.threadpool = QThreadPool() self.ui.download_btn.clicked.connect(self.download_btn_pressed) + self.ui.script_btn.clicked.connect(self.script_btn_pressed) self.ui.pack_archive_chkbox.clicked.connect(self.pack_wad_chkbox_toggled) self.ui.tid_entry.textChanged.connect(self.tid_updated) # noinspection PyUnresolvedReferences @@ -248,6 +249,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.ui.tid_entry.setEnabled(False) self.ui.version_entry.setEnabled(False) self.ui.download_btn.setEnabled(False) + self.ui.script_btn.setEnabled(False) self.ui.pack_archive_chkbox.setEnabled(False) self.ui.keep_enc_chkbox.setEnabled(False) self.ui.create_dec_chkbox.setEnabled(False) @@ -318,6 +320,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.ui.tid_entry.setEnabled(True) self.ui.version_entry.setEnabled(True) self.ui.download_btn.setEnabled(True) + self.ui.script_btn.setEnabled(True) self.ui.pack_archive_chkbox.setEnabled(True) self.ui.keep_enc_chkbox.setEnabled(True) self.ui.create_dec_chkbox.setEnabled(True) @@ -347,6 +350,64 @@ class MainWindow(QMainWindow, Ui_MainWindow): elif self.ui.console_select_dropdown.currentText() == "DSi": self.ui.pack_vwii_mode_chkbox.setEnabled(False) + def script_btn_pressed(self): + file_name = QFileDialog.getOpenFileName(self, caption=app.translate("MainWindow", "Open NUS script"), filter=app.translate("MainWindow", "NUS Scripts (*.nus *.txt)"), options=QFileDialog.Option.ReadOnly) + if len(file_name[0]) == 0: + return + + try: + file = open(file_name[0], "r") + except: + QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "Failed to open the script."), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok) + return + + content = file.readlines() + + titles = [] + for title in content: + decoded = title.replace("\n", "").split(" ", 1) + if len(decoded[0]) != 16 or len(decoded[1]) != 4: + QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "This script is invalid."), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok) + return + + try: + version = int(decoded[1], 16) + except: + QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "This script is invalid."), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok) + + titles.append((decoded[0], str(version))) + + self.ui.tid_entry.setEnabled(False) + self.ui.version_entry.setEnabled(False) + self.ui.download_btn.setEnabled(False) + self.ui.script_btn.setEnabled(False) + self.ui.pack_archive_chkbox.setEnabled(False) + self.ui.keep_enc_chkbox.setEnabled(False) + self.ui.create_dec_chkbox.setEnabled(False) + self.ui.use_local_chkbox.setEnabled(False) + self.ui.use_wiiu_nus_chkbox.setEnabled(False) + self.ui.pack_vwii_mode_chkbox.setEnabled(False) + self.ui.archive_file_entry.setEnabled(False) + self.ui.console_select_dropdown.setEnabled(False) + self.log_text = "" + self.ui.log_text_browser.setText(self.log_text) + + self.update_log_text(f"Found {len(titles)} titles, starting batch download.") + + if self.ui.console_select_dropdown.currentText() == "DSi": + worker = Worker(run_nus_download_dsi_batch, out_folder, titles, self.ui.pack_archive_chkbox.isChecked(), + self.ui.keep_enc_chkbox.isChecked(), self.ui.create_dec_chkbox.isChecked(), + self.ui.use_local_chkbox.isChecked(), self.ui.archive_file_entry.text()) + else: + worker = Worker(run_nus_download_wii_batch, out_folder, titles, self.ui.pack_archive_chkbox.isChecked(), + self.ui.keep_enc_chkbox.isChecked(), self.ui.create_dec_chkbox.isChecked(), + self.ui.use_wiiu_nus_chkbox.isChecked(), self.ui.use_local_chkbox.isChecked(), + self.ui.pack_vwii_mode_chkbox.isChecked(), self.ui.patch_ios_chkbox.isChecked()) + + worker.signals.result.connect(self.check_download_result) + worker.signals.progress.connect(self.update_log_text) + self.threadpool.start(worker) + if __name__ == "__main__": app = QApplication(sys.argv) diff --git a/modules/download_dsi.py b/modules/download_dsi.py index 9084883..bfecbd3 100644 --- a/modules/download_dsi.py +++ b/modules/download_dsi.py @@ -3,6 +3,7 @@ import os import pathlib +from typing import List, Tuple import libTWLPy @@ -116,7 +117,7 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_ title.tad.set_cert_data(libTWLPy.download_cert()) # Use a typed TAD name if there is one, and auto generate one based on the TID and version if there isn't. progress_callback.emit("Packing TAD...") - if tad_file_name != "": + if tad_file_name != "" and tad_file_name is not None: if tad_file_name[-4:] != ".tad": tad_file_name = tad_file_name + ".tad" else: @@ -132,3 +133,13 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_ if (not pack_tad_enabled and pack_tad_chkbox) or (not decrypt_contents_enabled and decrypt_contents_chkbox): return 1 return 0 + +def run_nus_download_dsi_batch(out_folder: pathlib.Path, titles: List[Tuple[str, str]], pack_tad_chkbox: bool, keep_enc_chkbox: bool, + decrypt_contents_chkbox: bool, use_local_chkbox: bool, progress_callback=None): + for title in titles: + result = run_nus_download_dsi(out_folder, title[0], title[1], pack_tad_chkbox, keep_enc_chkbox, decrypt_contents_chkbox, use_local_chkbox, None, progress_callback) + if result != 0: + return result + + progress_callback.emit(f"Batch download finished.") + return 0 diff --git a/modules/download_wii.py b/modules/download_wii.py index f8126a7..0592e1e 100644 --- a/modules/download_wii.py +++ b/modules/download_wii.py @@ -3,6 +3,7 @@ import os import pathlib +from typing import List, Tuple import libWiiPy @@ -138,7 +139,7 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_ title.wad.set_cert_data(libWiiPy.title.download_cert(wiiu_endpoint=wiiu_nus_enabled)) # Use a typed WAD name if there is one, and auto generate one based on the TID and version if there isn't. progress_callback.emit(" - Packing WAD...") - if wad_file_name != "": + if wad_file_name != "" and wad_file_name is not None: if wad_file_name[-4:] != ".wad": wad_file_name = wad_file_name + ".wad" else: @@ -165,3 +166,14 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_ if (not pack_wad_enabled and pack_wad_chkbox) or (not decrypt_contents_enabled and decrypt_contents_chkbox): return 1 return 0 + +def run_nus_download_wii_batch(out_folder: pathlib.Path, titles: List[Tuple[str, str]], pack_wad_chkbox: bool, keep_enc_chkbox: bool, + decrypt_contents_chkbox: bool, wiiu_nus_chkbox: bool, use_local_chkbox: bool, + repack_vwii_chkbox: bool, patch_ios: bool, progress_callback=None): + for title in titles: + result = run_nus_download_wii(out_folder, title[0], title[1], pack_wad_chkbox, keep_enc_chkbox, decrypt_contents_chkbox, wiiu_nus_chkbox, use_local_chkbox, repack_vwii_chkbox, patch_ios, None, progress_callback) + if result != 0: + return result + + progress_callback.emit(f"Batch download finished.") + return 0 diff --git a/qt/py/ui_MainMenu.py b/qt/py/ui_MainMenu.py index 91562f7..5a2e36a 100644 --- a/qt/py/ui_MainMenu.py +++ b/qt/py/ui_MainMenu.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'MainMenu.ui' ## -## Created by: Qt User Interface Compiler version 6.7.2 +## Created by: Qt User Interface Compiler version 6.8.0 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -145,10 +145,20 @@ class Ui_MainWindow(object): self.vertical_layout_controls.addLayout(self.horizontal_layout_title_entry) + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") self.download_btn = QPushButton(self.centralwidget) self.download_btn.setObjectName(u"download_btn") - self.vertical_layout_controls.addWidget(self.download_btn) + self.horizontalLayout.addWidget(self.download_btn) + + self.script_btn = QPushButton(self.centralwidget) + self.script_btn.setObjectName(u"script_btn") + + self.horizontalLayout.addWidget(self.script_btn) + + + self.vertical_layout_controls.addLayout(self.horizontalLayout) self.horizontalLayout_5 = QHBoxLayout() self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") @@ -380,6 +390,7 @@ class Ui_MainWindow(object): self.label_5.setText(QCoreApplication.translate("MainWindow", u"Console:", None)) self.console_select_dropdown.setCurrentText("") self.download_btn.setText(QCoreApplication.translate("MainWindow", u"Start Download", None)) + self.script_btn.setText(QCoreApplication.translate("MainWindow", u"Run Script", None)) self.label_3.setText(QCoreApplication.translate("MainWindow", u"General Settings", None)) self.label_7.setText(QCoreApplication.translate("MainWindow", u"Pack installable archive (WAD/TAD)", None)) self.archive_file_entry.setPlaceholderText(QCoreApplication.translate("MainWindow", u"File Name", None)) diff --git a/qt/ui/MainMenu.ui b/qt/ui/MainMenu.ui index f6b4bdd..46c38a6 100644 --- a/qt/ui/MainMenu.ui +++ b/qt/ui/MainMenu.ui @@ -222,11 +222,22 @@ - - - Start Download - - + + + + + Start Download + + + + + + + Run Script + + + +