From 542ad9623cf854ba7bf33c1567139c53f52027ad Mon Sep 17 00:00:00 2001 From: Hoang Hong Quan Date: Wed, 22 Oct 2025 00:59:12 +0700 Subject: [PATCH] Enhance user prompts, add temporary dir handling --- OpCore-Simplify.py | 213 +++++++++++++++--------------- Scripts/acpi_guru.py | 4 +- Scripts/compatibility_checker.py | 6 +- Scripts/config_prodigy.py | 2 +- Scripts/gathering_files.py | 3 +- Scripts/kext_maestro.py | 36 ++--- Scripts/utils.py | 99 +++++++++----- Scripts/wifi_profile_extractor.py | 2 +- 8 files changed, 197 insertions(+), 168 deletions(-) diff --git a/OpCore-Simplify.py b/OpCore-Simplify.py index ee09374..78ab484 100644 --- a/OpCore-Simplify.py +++ b/OpCore-Simplify.py @@ -29,33 +29,32 @@ class OCPE: self.s = smbios.SMBIOS() self.r = run.Run() self.u = utils.Utils() - self.result_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "Results") + self.result_dir = self.u.get_temporary_dir() def select_hardware_report(self): - self.hardware_sniffer = self.o.gather_hardware_sniffer() self.ac.dsdt = self.ac.acpi.acpi_tables = None while True: self.u.head("Select hardware report") print("") if os.name == "nt": - print("\033[93mNote:\033[0m") + print("\033[1;93mNote:\033[0m") print("- Ensure you are using the latest version of Hardware Sniffer before generating the hardware report.") print("- Hardware Sniffer will not collect information related to Resizable BAR option of GPU (disabled by default) and monitor connections in Windows PE.") print("") - if self.hardware_sniffer: - print("") - print("E. Export hardware report (Recommended)") + print("E. Export hardware report (Recommended)") print("") print("Q. Quit") print("") - user_input = self.u.request_input("Drag and drop your hardware report here (.JSON){}: ".format(" or type \"E\" to export" if self.hardware_sniffer else "")) + user_input = self.u.request_input("Drag and drop your hardware report here (.JSON) or type \"E\" to export: ") if user_input.lower() == "q": self.u.exit_program() - if self.hardware_sniffer and user_input.lower() == "e": + if user_input.lower() == "e": + hardware_sniffer = self.o.gather_hardware_sniffer() + output = self.r.run({ - "args":[self.hardware_sniffer, "-e"] + "args":[hardware_sniffer, "-e"] }) if output[-1] != 0: @@ -101,7 +100,7 @@ class OCPE: print("\033[91mImportant:\033[0m") print("Please consider these risks carefully before proceeding.") print("") - print("\033[93mNote:\033[0m") + print("\033[1;93mNote:\033[0m") print("If you experience black screen after login with OpenCore Legacy Patcher v2.2.0 or newer") print("after applying root patches, please revert to version v2.1.2.") print("") @@ -157,7 +156,7 @@ class OCPE: print(" {}. {}{}".format(darwin_version, name, label)) print("") - print("\033[93mNote:\033[0m") + print("\033[1;93mNote:\033[0m") print("- To select a major version, enter the number (e.g., 19).") print("- To specify a full version, use the Darwin version format (e.g., 22.4.6).") print("") @@ -177,9 +176,17 @@ class OCPE: return target_version def build_opencore_efi(self, hardware_report, disabled_devices, smbios_model, macos_version, needs_oclp): - self.u.head("Building OpenCore EFI") - print("") - print("1. Copy EFI base to results folder...", end=" ") + steps = [ + "Copying EFI base to results folder", + "Applying ACPI patches", + "Copying kexts and snapshotting to config.plist", + "Generating config.plist", + "Cleaning up unused drivers, resources, and tools" + ] + + title = "Building OpenCore EFI" + + self.u.progress_bar(title, steps, 0) self.u.create_folder(self.result_dir, remove_content=True) if not os.path.exists(self.k.ock_files_dir): @@ -193,8 +200,8 @@ class OCPE: if not config_data: raise Exception("Error: The file {} does not exist.".format(config_file)) - print("Done") - print("2. Apply ACPI patches...", end=" ") + + self.u.progress_bar(title, steps, 1) config_data["ACPI"]["Add"] = [] config_data["ACPI"]["Delete"] = [] config_data["ACPI"]["Patch"] = [] @@ -223,17 +230,17 @@ class OCPE: config_data["ACPI"]["Patch"].extend(self.ac.dsdt_patches) config_data["ACPI"]["Patch"] = self.ac.apply_acpi_patches(config_data["ACPI"]["Patch"]) - print("Done") - print("3. Copy kexts and snapshot to config.plist...", end=" ") + + self.u.progress_bar(title, steps, 2) kexts_directory = os.path.join(self.result_dir, "EFI", "OC", "Kexts") self.k.install_kexts_to_efi(macos_version, kexts_directory) config_data["Kernel"]["Add"] = self.k.load_kexts(hardware_report, macos_version, kexts_directory) - print("Done") - print("4. Generate config.plist...", end=" ") + + self.u.progress_bar(title, steps, 3) self.co.genarate(hardware_report, disabled_devices, smbios_model, macos_version, needs_oclp, self.k.kexts, config_data) self.u.write_file(config_file, config_data) - print("Done") - print("5. Clean up unused drivers, resources, and tools...", end=" ") + + self.u.progress_bar(title, steps, 4) files_to_remove = [] drivers_directory = os.path.join(self.result_dir, "EFI", "OC", "Drivers") @@ -269,7 +276,6 @@ class OCPE: if not tool_path in tool_loaded: files_to_remove.append(os.path.join(tools_directory, tool_path)) - removal_error = None for file_path in files_to_remove: try: if os.path.isdir(file_path): @@ -277,14 +283,10 @@ class OCPE: else: os.remove(file_path) except Exception as e: - removal_error = True print("Failed to remove file: {}".format(e)) - - if removal_error: - print("") - - print("Done") - print("") + + self.u.progress_bar(title, steps, len(steps), done=True) + print("OpenCore EFI build complete.") time.sleep(2) @@ -308,36 +310,37 @@ class OCPE: return requirements - def results(self, org_hardware_report, hardware_report): - self.u.head("Results") - print("") - print("Your OpenCore EFI for {} has been built at:".format(hardware_report.get("Motherboard").get("Name"))) - print("\t{}".format(self.result_dir)) - - bios_requirements = self.check_bios_requirements(org_hardware_report, hardware_report) - - print("") - print("\033[93mBefore using EFI, please complete the following steps:\033[0m") - print("") - - if bios_requirements: - print("* BIOS/UEFI Settings Required:") - for requirement in bios_requirements: - print(" - {}".format(requirement)) + def before_using_efi(self, org_hardware_report, hardware_report): + while True: + self.u.head("Before Using EFI") + print("") + print("\033[93mPlease complete the following steps:\033[0m") print("") - - print("* USB Mapping:") - print(" - Use USBToolBox tool to map USB ports.") - print(" - Add created UTBMap.kext into the {} folder.".format("EFI\\OC\\Kexts" if os.name == "nt" else "EFI/OC/Kexts")) - print(" - Remove UTBDefault.kext in the {} folder.".format("EFI\\OC\\Kexts" if os.name == "nt" else "EFI/OC/Kexts")) - print(" - Edit config.plist:") - print(" - Use ProperTree to open your config.plist.") - print(" - Run OC Snapshot by pressing Command/Ctrl + R.") - print(" - If you have more than 15 ports on a single controller, enable the XhciPortLimit patch.") - print(" - Save the file when finished.") - print("") - self.u.open_folder(self.result_dir) - self.u.request_input() + + bios_requirements = self.check_bios_requirements(org_hardware_report, hardware_report) + if bios_requirements: + print("* BIOS/UEFI Settings Required:") + for requirement in bios_requirements: + print(" - {}".format(requirement)) + print("") + + print("* USB Mapping:") + print(" - Use USBToolBox tool to map USB ports.") + print(" - Add created UTBMap.kext into the {} folder.".format("EFI\\OC\\Kexts" if os.name == "nt" else "EFI/OC/Kexts")) + print(" - Remove UTBDefault.kext in the {} folder.".format("EFI\\OC\\Kexts" if os.name == "nt" else "EFI/OC/Kexts")) + print(" - Edit config.plist:") + print(" - Use ProperTree to open your config.plist.") + print(" - Run OC Snapshot by pressing Command/Ctrl + R.") + print(" - If you have more than 15 ports on a single controller, enable the XhciPortLimit patch.") + print(" - Save the file when finished.") + print("") + print("Type \"AGREE\" to open the built EFI for you\n") + response = self.u.request_input("") + if response.lower() == "agree": + self.u.open_folder(self.result_dir) + break + else: + print("\033[91mInvalid input. Please try again.\033[0m") def main(self): hardware_report_path = None @@ -351,20 +354,17 @@ class OCPE: while True: self.u.head() print("") - print("Hardware Report: {}".format("No report selected" if not hardware_report_path else hardware_report_path)) + print(" Hardware Report: {}".format(hardware_report_path or 'Not selected')) print("") if hardware_report_path: - print("* Hardware Compatibility:") - if native_macos_version: - print(" - Native macOS Version: {}".format(self.c.show_macos_compatibility((native_macos_version[-1], native_macos_version[0])))) + print(" macOS Version: {}".format(os_data.get_macos_name_by_darwin(macos_version) if macos_version else 'Not selected') + (' (' + macos_version + ')' if macos_version else '') + ('. \033[1;93mRequires OpenCore Legacy Patcher\033[0m' if needs_oclp else '')) + print(" SMBIOS: {}".format(smbios_model or 'Not selected')) if disabled_devices: - print(" - Disabled Devices:") - for index, device_name in enumerate(disabled_devices, start=1): - print("{}{}. {}".format(" "*6, index, device_name)) - print("* EFI Options:") - print(" - macOS Version: {}{}{}".format("Unknown" if not macos_version else os_data.get_macos_name_by_darwin(macos_version), "" if not macos_version else " ({})".format(macos_version), ". \033[1;93mRequires OpenCore Legacy Patcher\033[0m" if needs_oclp else "")) - print(" - SMBIOS: {}".format("Unknown" if not smbios_model else smbios_model)) - print("") + print(" Disabled Devices:") + for device, _ in disabled_devices.items(): + print(" - {}".format(device)) + print("") + print("1. Select Hardware Report") print("2. Select macOS Version") print("3. Customize ACPI Patch") @@ -374,16 +374,12 @@ class OCPE: print("") print("Q. Quit") print("") + option = self.u.request_input("Select an option: ") if option.lower() == "q": self.u.exit_program() - - try: - option = int(option) - except: - continue - - if option == 1: + + if option == "1": hardware_report_path, hardware_report = self.select_hardware_report() hardware_report, native_macos_version, ocl_patched_macos_version = self.c.check_compatibility(hardware_report) macos_version = self.select_macos_version(hardware_report, native_macos_version, ocl_patched_macos_version) @@ -394,40 +390,49 @@ class OCPE: self.ac.select_acpi_patches(customized_hardware, disabled_devices) needs_oclp = self.k.select_required_kexts(customized_hardware, macos_version, needs_oclp, self.ac.patches) self.s.smbios_specific_options(customized_hardware, smbios_model, macos_version, self.ac.patches, self.k) - elif option < 7: - try: - customized_hardware - except: - self.u.request_input("\nPlease select a hardware report to proceed") - continue - if option == 2: + if not hardware_report_path: + self.u.head() + print("\n\n") + print("\033[1;93mPlease select a hardware report first.\033[0m") + print("\n\n") + self.u.request_input("Press Enter to go back...") + continue + + if option == "2": + macos_version = self.select_macos_version(hardware_report, native_macos_version, ocl_patched_macos_version) + customized_hardware, disabled_devices, needs_oclp = self.h.hardware_customization(hardware_report, macos_version) + smbios_model = self.s.select_smbios_model(customized_hardware, macos_version) + needs_oclp = self.k.select_required_kexts(customized_hardware, macos_version, needs_oclp, self.ac.patches) + self.s.smbios_specific_options(customized_hardware, smbios_model, macos_version, self.ac.patches, self.k) + elif option == "3": + self.ac.customize_patch_selection() + elif option == "4": + self.k.kext_configuration_menu(macos_version) + elif option == "5": + smbios_model = self.s.customize_smbios_model(customized_hardware, smbios_model, macos_version) + self.s.smbios_specific_options(customized_hardware, smbios_model, macos_version, self.ac.patches, self.k) + elif option == "6": + if needs_oclp and not self.show_oclp_warning(): macos_version = self.select_macos_version(hardware_report, native_macos_version, ocl_patched_macos_version) customized_hardware, disabled_devices, needs_oclp = self.h.hardware_customization(hardware_report, macos_version) smbios_model = self.s.select_smbios_model(customized_hardware, macos_version) needs_oclp = self.k.select_required_kexts(customized_hardware, macos_version, needs_oclp, self.ac.patches) self.s.smbios_specific_options(customized_hardware, smbios_model, macos_version, self.ac.patches, self.k) - elif option == 3: - self.ac.customize_patch_selection() - elif option == 4: - self.k.kext_configuration_menu(macos_version) - elif option == 5: - smbios_model = self.s.customize_smbios_model(customized_hardware, smbios_model, macos_version) - self.s.smbios_specific_options(customized_hardware, smbios_model, macos_version, self.ac.patches, self.k) - elif option == 6: - if needs_oclp and not self.show_oclp_warning(): - macos_version = self.select_macos_version(hardware_report, native_macos_version, ocl_patched_macos_version) - customized_hardware, disabled_devices, needs_oclp = self.h.hardware_customization(hardware_report, macos_version) - smbios_model = self.s.select_smbios_model(customized_hardware, macos_version) - needs_oclp = self.k.select_required_kexts(customized_hardware, macos_version, needs_oclp, self.ac.patches) - self.s.smbios_specific_options(customized_hardware, smbios_model, macos_version, self.ac.patches, self.k) - continue + continue - if not self.o.gather_bootloader_kexts(self.k.kexts, macos_version): - continue - - self.build_opencore_efi(customized_hardware, disabled_devices, smbios_model, macos_version, needs_oclp) - self.results(hardware_report, customized_hardware) + if not self.o.gather_bootloader_kexts(self.k.kexts, macos_version): + continue + + self.build_opencore_efi(customized_hardware, disabled_devices, smbios_model, macos_version, needs_oclp) + self.before_using_efi(hardware_report, customized_hardware) + + self.u.head("Result") + print("") + print("Your OpenCore EFI for {} has been built at:".format(customized_hardware.get("Motherboard").get("Name"))) + print("\t{}".format(self.result_dir)) + print("") + self.u.request_input("Press Enter to main menu...") if __name__ == '__main__': update_flag = updater.Updater().run_update() diff --git a/Scripts/acpi_guru.py b/Scripts/acpi_guru.py index e13c038..23ca153 100644 --- a/Scripts/acpi_guru.py +++ b/Scripts/acpi_guru.py @@ -3331,9 +3331,7 @@ DefinitionBlock ("", "SSDT", 2, "ZPSS", "WMIS", 0x00000000) if kext.checked: line = "\033[1;32m{}\033[0m".format(line) contents.append(line) - contents.append("\033[1;36m") - contents.append("Note: You can select multiple kexts by entering their indices separated by commas (e.g., '1, 2, 3').") - contents.append("\033[0m") + contents.append("\033[1;93mNote:\033[0m You can select multiple kexts by entering their indices separated by commas (e.g., '1, 2, 3').") contents.append("B. Back") contents.append("Q. Quit") contents.append("") diff --git a/Scripts/compatibility_checker.py b/Scripts/compatibility_checker.py index 8978a9b..1a4b348 100644 --- a/Scripts/compatibility_checker.py +++ b/Scripts/compatibility_checker.py @@ -221,7 +221,7 @@ class CompatibilityChecker: print("{}- Audio Endpoint{}: {}".format(" "*6, "s" if len(audio_endpoints) > 1 else "", ", ".join(audio_endpoints))) def check_biometric_compatibility(self): - print(" \033[93mNote:\033[0m Biometric authentication in macOS requires Apple T2 Chip,") + print(" \033[1;93mNote:\033[0m Biometric authentication in macOS requires Apple T2 Chip,") print(" which is not available for Hackintosh systems.") print("") for biometric_device, biometric_props in self.hardware_report.get("Biometric", {}).items(): @@ -273,10 +273,10 @@ class CompatibilityChecker: print("{}- Continuity Support: \033[1;32mFull\033[0m (AirDrop, Handoff, Universal Clipboard, Instant Hotspot,...)".format(" "*6)) elif device_id in pci_data.IntelWiFiIDs: print("{}- Continuity Support: \033[1;33mPartial\033[0m (Handoff and Universal Clipboard with AirportItlwm)".format(" "*6)) - print("{}\033[93mNote:\033[0m AirDrop, Universal Clipboard, Instant Hotspot,... not available".format(" "*6)) + print("{}\033[1;93mNote:\033[0m AirDrop, Universal Clipboard, Instant Hotspot,... not available".format(" "*6)) elif device_id in pci_data.AtherosWiFiIDs: print("{}- Continuity Support: \033[1;31mLimited\033[0m (No Continuity features available)".format(" "*6)) - print("{}\033[93mNote:\033[0m Atheros cards are not recommended for macOS".format(" "*6)) + print("{}\033[1;93mNote:\033[0m Atheros cards are not recommended for macOS".format(" "*6)) if "OCLP Compatibility" in device_props: print("{}- OCLP Compatibility: {}".format(" "*6, self.show_macos_compatibility(device_props.get("OCLP Compatibility")))) diff --git a/Scripts/config_prodigy.py b/Scripts/config_prodigy.py index c35afca..f85c7ca 100644 --- a/Scripts/config_prodigy.py +++ b/Scripts/config_prodigy.py @@ -286,7 +286,7 @@ class ConfigProdigy: else: contents.append(line) contents.append("") - contents.append("\033[93mNote:\033[0m") + contents.append("\033[1;93mNote:\033[0m") contents.append("- The default layout may not be optimal.") contents.append("- Test different layouts to find what works best for your system.") contents.append("") diff --git a/Scripts/gathering_files.py b/Scripts/gathering_files.py index efc7d9c..1690376 100644 --- a/Scripts/gathering_files.py +++ b/Scripts/gathering_files.py @@ -3,7 +3,6 @@ from Scripts import kext_maestro from Scripts import resource_fetcher from Scripts import utils import os -import tempfile import shutil import subprocess import platform @@ -21,7 +20,7 @@ class gatheringFiles: self.amd_vanilla_patches_url = "https://raw.githubusercontent.com/AMD-OSX/AMD_Vanilla/beta/patches.plist" self.aquantia_macos_patches_url = "https://raw.githubusercontent.com/CaseySJ/Aquantia-macOS-Patches/refs/heads/main/CaseySJ-Aquantia-Patch-Sets-1-and-2.plist" self.hyper_threading_patches_url = "https://github.com/b00t0x/CpuTopologyRebuild/raw/refs/heads/master/patches_ht.plist" - self.temporary_dir = tempfile.mkdtemp() + self.temporary_dir = self.utils.get_temporary_dir() self.ock_files_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "OCK_Files") self.bootloader_kexts_data_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "bootloader_kexts_data.json") self.download_history_file = os.path.join(self.ock_files_dir, "history.json") diff --git a/Scripts/kext_maestro.py b/Scripts/kext_maestro.py index 67b3abc..9db4240 100644 --- a/Scripts/kext_maestro.py +++ b/Scripts/kext_maestro.py @@ -122,7 +122,7 @@ class KextMaestro: for codec_properties in hardware_report.get("Sound", {}).values(): if codec_properties.get("Device ID") in codec_layouts.data: if self.utils.parse_darwin_version(macos_version) >= self.utils.parse_darwin_version("25.0.0"): - print("\n\033[93mNote:\033[0m Since macOS Tahoe 26 DP2, Apple has removed AppleHDA kext and uses the Apple T2 chip for audio management.") + print("\n\033[1;93mNote:\033[0m Since macOS Tahoe 26 DP2, Apple has removed AppleHDA kext and uses the Apple T2 chip for audio management.") print("To use AppleALC, you must rollback AppleHDA. Alternatively, you can use VoodooHDA.") print("") print("1. \033[1mAppleALC\033[0m - Requires AppleHDA rollback with \033[1;93mOpenCore Legacy Patcher\033[0m") @@ -179,8 +179,8 @@ class KextMaestro: recommended_option = 1 recommended_name = "NootRX" max_option = 3 - print("\033[93mNote:\033[0m - Since macOS Tahoe 26, WhateverGreen has known connector patching issues for AMD {} GPUs.".format(gpu_props.get("Codename"))) - print(" - To avoid this, you can use NootRX or choose not to install a GPU kext.") + print("\033[1;93mNote:\033[0m Since macOS Tahoe 26, WhateverGreen has known connector patching issues for AMD {} GPUs.".format(gpu_props.get("Codename"))) + print("To avoid this, you can use NootRX or choose not to install a GPU kext.") print("") print("1. \033[1mNootRX\033[0m - Uses latest GPU firmware") print("2. \033[1mWhateverGreen\033[0m - Uses original Apple firmware") @@ -189,16 +189,17 @@ class KextMaestro: recommended_option = 2 recommended_name = "WhateverGreen" max_option = 2 - print("\033[93mNote:\033[0m - AMD {} GPUs have two available kext options:".format(gpu_props.get("Codename"))) - print(" - You can try different kexts after installation to find the best one for your system") + print("\033[1;93mNote:\033[0m") + print("- AMD {} GPUs have two available kext options:".format(gpu_props.get("Codename"))) + print("- You can try different kexts after installation to find the best one for your system") print("") print("1. \033[1mNootRX\033[0m - Uses latest GPU firmware") print("2. \033[1mWhateverGreen\033[0m - Uses original Apple firmware") print("") if any(other_gpu_props.get("Manufacturer") == "Intel" for other_gpu_props in hardware_report.get("GPU", {}).values()): - print("\033[91mImportant:\033[0m - NootRX kext is not compatible with Intel GPUs") - print(" - Automatically selecting WhateverGreen kext due to Intel GPU compatibility") + print("\033[91mImportant:\033[0m NootRX kext is not compatible with Intel GPUs") + print("Automatically selecting WhateverGreen kext due to Intel GPU compatibility") print("") self.utils.request_input("Press Enter to continue...") continue @@ -221,9 +222,9 @@ class KextMaestro: if self.utils.parse_darwin_version(macos_version) >= self.utils.parse_darwin_version("25.0.0"): print("\n*** Found {} is AMD {} GPU.".format(gpu_name, gpu_props.get("Codename"))) print("") - print("\033[93mNote:\033[0m - Since macOS Tahoe 26, WhateverGreen has known connector patching issues for AMD GPUs.") - print(" - The current recommendation is to not use WhateverGreen.") - print(" - However, you can still try adding it to see if it works on your system.") + print("\033[1;93mNote:\033[0m Since macOS Tahoe 26, WhateverGreen has known connector patching issues for AMD GPUs.") + print("The current recommendation is to not use WhateverGreen.") + print("However, you can still try adding it to see if it works on your system.") print("") self.utils.request_input("Press Enter to continue...") break @@ -254,7 +255,7 @@ class KextMaestro: elif device_id in pci_data.IntelWiFiIDs: print("\n*** Found {} is Intel WiFi device.".format(network_name)) print("") - print("\033[93mNote:\033[0m Intel WiFi devices have two available kext options:") + print("\033[1;93mNote:\033[0m Intel WiFi devices have two available kext options:") print("") print("1. \033[1mAirportItlwm\033[0m - Uses native WiFi settings menu") print(" • Provides Handoff, Universal Clipboard, Location Services, Instant Hotspot support") @@ -303,7 +304,7 @@ class KextMaestro: selected_kexts.append("IOSkywalkFamily") elif self.utils.parse_darwin_version(macos_version) >= self.utils.parse_darwin_version("23.0.0"): print("") - print("\033[93mNote:\033[0m Since macOS Sonoma 14, iServices won't work with AirportItlwm without patches") + print("\033[1;93mNote:\033[0m Since macOS Sonoma 14, iServices won't work with AirportItlwm without patches") print("") while True: option = self.utils.request_input("Apply OCLP root patch to fix iServices? (yes/No): ").strip().lower() @@ -651,11 +652,10 @@ class KextMaestro: for index, (kext_name, is_lilu_dependent) in enumerate(incompatible_kexts, start=1): print("{:2}. {:25}{}".format(index, kext_name, " - Lilu Plugin" if is_lilu_dependent else "")) - print("\n\033[1;36m") - print("Note:") + print("\n\033[1;93mNote:\033[0m") print("- With Lilu plugins, using the \"-lilubetaall\" boot argument will force them to load.") print("- Forcing unsupported kexts can cause system instability. \033[0;31mProceed with caution.\033[0m") - print("\033[0m") + print("") option = self.utils.request_input("Do you want to force load {} on the unsupported macOS version? (yes/No): ".format("these kexts" if len(incompatible_kexts) > 1 else "this kext")) @@ -684,12 +684,12 @@ class KextMaestro: elif not self.utils.parse_darwin_version(kext.min_darwin_version) <= self.utils.parse_darwin_version(macos_version) <= self.utils.parse_darwin_version(kext.max_darwin_version): line = "\033[90m{}\033[0m".format(line) contents.append(line) - contents.append("\033[1;36m") - contents.append("Note:") + contents.append("") + contents.append("\033[1;93mNote:\033[0m") contents.append("- Lines in gray indicate kexts that are not supported by the current macOS version ({}).".format(macos_version)) contents.append("- When a plugin of a kext is selected, the entire kext will be automatically selected.") contents.append("- You can select multiple kexts by entering their indices separated by commas (e.g., '1, 2, 3').") - contents.append("\033[0m") + contents.append("") contents.append("B. Back") contents.append("Q. Quit") contents.append("") diff --git a/Scripts/utils.py b/Scripts/utils.py index 9fa8b40..19e314e 100644 --- a/Scripts/utils.py +++ b/Scripts/utils.py @@ -8,11 +8,30 @@ import binascii import subprocess import pathlib import zipfile +import tempfile class Utils: def __init__(self, script_name = "OpCore Simplify"): self.script_name = script_name + self.clean_temporary_dir() + + def clean_temporary_dir(self): + temporary_dir = tempfile.gettempdir() + + for file in os.listdir(temporary_dir): + if file.startswith("ocs_"): + if not os.path.isdir(os.path.join(temporary_dir, file)): + continue + + try: + shutil.rmtree(os.path.join(temporary_dir, file)) + except Exception as e: + pass + + def get_temporary_dir(self): + return tempfile.mkdtemp(prefix="ocs_") + def write_file(self, file_path, data): file_extension = os.path.splitext(file_path)[1] @@ -78,18 +97,13 @@ class Utils: def hex_to_bytes(self, string): try: - # Remove non-hex characters (e.g., hyphens) hex_string = re.sub(r'[^0-9a-fA-F]', '', string) if len(re.sub(r"\s+", "", string)) != len(hex_string): return string - # Convert hex string to bytes - bytes_data = binascii.unhexlify(hex_string) - - return bytes_data + return binascii.unhexlify(hex_string) except binascii.Error: - # Handle invalid hex string return string def int_to_hex(self, number): @@ -98,9 +112,7 @@ class Utils: def to_little_endian_hex(self, hex_string): hex_string = hex_string.lower().lstrip("0x") - little_endian_hex = ''.join(reversed([hex_string[i:i+2] for i in range(0, len(hex_string), 2)])) - - return little_endian_hex.upper() + return ''.join(reversed([hex_string[i:i+2] for i in range(0, len(hex_string), 2)])).upper() def string_to_hex(self, string): return ''.join(format(ord(char), '02X') for char in string) @@ -118,29 +130,20 @@ class Utils: return next((item for item in data[start:end] if item.lower() in search_item.lower()), None) def normalize_path(self, path): - # Remove all surrounding quotes if present path = re.sub(r'^[\'"]+|[\'"]+$', '', path) - # Remove trailing spaces path = path.strip() - # Expand ~ to the user's home directory path = os.path.expanduser(path) - # Normalize path separators for the target operating system - if os.name == 'nt': # Windows - # Replace single backslashes with forward slashes + if os.name == 'nt': path = path.replace('\\', '/') - # Remove redundant slashes path = re.sub(r'/+', '/', path) else: - # Remove backslashes path = path.replace('\\', '') - # Normalize the path path = os.path.normpath(path) - # Convert the path to an absolute path and normalize it according to the OS return str(pathlib.Path(path).resolve()) def parse_darwin_version(self, darwin_version): @@ -155,36 +158,47 @@ class Utils: subprocess.run(['xdg-open', folder_path]) elif os.name == 'nt': os.startfile(folder_path) - else: - raise NotImplementedError("This function is only supported on macOS, Windows, and Linux.") def request_input(self, prompt="Press Enter to continue..."): - try: - user_response = input(prompt) - except NameError: + if sys.version_info[0] < 3: user_response = raw_input(prompt) + else: + user_response = input(prompt) if not isinstance(user_response, str): user_response = str(user_response) return user_response - def clear_screen(self): - os.system('cls' if os.name=='nt' else 'clear') + def progress_bar(self, title, steps, current_step_index, done=False): + self.head(title) + print("") + if done: + for step in steps: + print(" [\033[92m✓\033[0m] {}".format(step)) + else: + for i, step in enumerate(steps): + if i < current_step_index: + print(" [\033[92m✓\033[0m] {}".format(step)) + elif i == current_step_index: + print(" [\033[1;93m>\033[0m] {}...".format(step)) + else: + print(" [ ] {}".format(step)) + print("") def head(self, text = None, width = 68, resize=True): if resize: self.adjust_window_size() - self.clear_screen() + os.system('cls' if os.name=='nt' else 'clear') if text == None: text = self.script_name - separator = "#" * width + separator = "═" * (width - 2) title = " {} ".format(text) if len(title) > width - 2: title = title[:width-4] + "..." - title = title.center(width - 2) # Center the title within the width minus 2 for the '#' characters + title = title.center(width - 2) - print("{}\n#{}#\n{}".format(separator, title, separator)) + print("╔{}╗\n║{}║\n╚{}╝".format(separator, title, separator)) def adjust_window_size(self, content=""): lines = content.splitlines() @@ -194,14 +208,27 @@ class Utils: def exit_program(self): self.head() + width = 68 print("") - print("For more information, to report errors, or to contribute to the product:") - print("* Facebook: https://www.facebook.com/macforce2601") - print("* Telegram: https://t.me/lzhoang2601") - print("* GitHub: https://github.com/lzhoang2801/OpCore-Simplify") + print("For more information, to report errors, or to contribute to the product:".center(width)) print("") - print("Thank you for using our program!") + separator = "─" * (width - 4) + print(f" ┌{separator}┐ ") + + contacts = { + "Facebook": "https://www.facebook.com/macforce2601", + "Telegram": "https://t.me/lzhoang2601", + "GitHub": "https://github.com/lzhoang2801/OpCore-Simplify" + } + + for platform, link in contacts.items(): + line = f" * {platform}: {link}" + print(f" │{line.ljust(width - 4)}│ ") + + print(f" └{separator}┘ ") print("") - self.request_input("Press Enter to exit.") + print("Thank you for using our program!".center(width)) + print("") + self.request_input("Press Enter to exit.".center(width)) sys.exit(0) \ No newline at end of file diff --git a/Scripts/wifi_profile_extractor.py b/Scripts/wifi_profile_extractor.py index dd295c7..1bcb1c2 100644 --- a/Scripts/wifi_profile_extractor.py +++ b/Scripts/wifi_profile_extractor.py @@ -226,7 +226,7 @@ class WifiProfileExtractor: self.utils.head("WiFi Profile Extractor") print("") - print("\033[93mNote:\033[0m") + print("\033[1;93mNote:\033[0m") print("- When using itlwm kext, WiFi appears as Ethernet in macOS") print("- You'll need Heliport app to manage WiFi connections in macOS") print("- This step will enable auto WiFi connections at boot time")