mirror of
https://github.com/leminlimez/Nugget.git
synced 2025-04-08 04:23:05 +08:00
209 lines
9.5 KiB
Python
209 lines
9.5 KiB
Python
from Sparserestore.restore import restore_files, FileToRestore, restore_file
|
|
from tweaks.tweaks import tweaks, TweakModifyType, FeatureFlagTweak, EligibilityTweak
|
|
from devicemanagement.constants import Device
|
|
|
|
from pymobiledevice3.exceptions import PyMobileDevice3Exception
|
|
from pymobiledevice3.services.diagnostics import DiagnosticsService
|
|
from pymobiledevice3 import usbmux
|
|
from pymobiledevice3.lockdown import create_using_usbmux
|
|
|
|
from pathlib import Path
|
|
import plistlib
|
|
import traceback
|
|
|
|
running = True
|
|
passed_check = False
|
|
num_tweaks = len(tweaks)
|
|
|
|
gestalt_path = Path.joinpath(Path.cwd(), "com.apple.MobileGestalt.plist")
|
|
flags_path = Path.joinpath(Path.cwd(), "Global.plist")
|
|
device = None
|
|
|
|
def print_option(num: int, active: bool, message: str):
|
|
txt = str(num) + ". "
|
|
if active:
|
|
txt = txt + "[Y] "
|
|
txt = txt + message
|
|
print(txt)
|
|
|
|
def get_apply_number(num: int) -> int:
|
|
return num + 5-num%5
|
|
|
|
while running:
|
|
print("""\n\n\n\n
|
|
|
|
,--.
|
|
,--.'| ___
|
|
,--,: : | ,--.'|_
|
|
,`--.'`| ' : ,--, | | :,'
|
|
| : : | | ,'_ /| ,----._,. ,----._,. : : ' :
|
|
: | \\ | : .--. | | : / / ' / / / ' / ,---. .;__,' /
|
|
| : ' '; |,'_ /| : . || : || : | / \\ | | |
|
|
' ' ;. ;| ' | | . .| | .\\ .| | .\\ . / / |:__,'| :
|
|
| | | \\ || | ' | | |. ; '; |. ; '; |. ' / | ' : |__
|
|
' : | ; .': | : ; ; |' . . |' . . |' ; /| | | '.'|
|
|
| | '`--' ' : `--' \\`---`-'| | `---`-'| |' | / | ; : ;
|
|
' : | : , .-./.'__/\\_: | .'__/\\_: || : | | , /
|
|
; |.' `--`----' | : : | : : \\ \\ / ---`-'
|
|
'---' \\ \\ / \\ \\ / `----'
|
|
`--`-' `--`-'
|
|
""")
|
|
print("CLI v2.2")
|
|
print("by LeminLimez")
|
|
print("Thanks @disfordottie for the clock animation and @lrdsnow for EU Enabler\n")
|
|
print("Please back up your device before using!")
|
|
|
|
while device == None:
|
|
connected_devices = usbmux.list_devices()
|
|
# Connect via usbmuxd
|
|
for current_device in connected_devices:
|
|
if current_device.is_usb:
|
|
try:
|
|
ld = create_using_usbmux(serial=current_device.serial)
|
|
vals = ld.all_values
|
|
device = Device(uuid=current_device.serial, name=vals['DeviceName'], version=vals['ProductVersion'], model=vals['ProductType'], locale=ld.locale, ld=ld)
|
|
except Exception as e:
|
|
print(traceback.format_exc())
|
|
input("Press Enter to continue...")
|
|
|
|
if device == None:
|
|
print("Please connect your device and try again!")
|
|
input("Press Enter to continue...")
|
|
|
|
print(f"Connected to {device.name}\niOS {device.version}\n")
|
|
|
|
if not passed_check and Path.exists(gestalt_path) and Path.is_file(gestalt_path):
|
|
passed_check = True
|
|
|
|
if passed_check:
|
|
count = 0
|
|
for key in tweaks:
|
|
count += 1
|
|
# do not show if the tweak is not compatible
|
|
if tweaks[key].is_compatible(device.version):
|
|
print_option(count, tweaks[key].enabled, tweaks[key].label)
|
|
if tweaks[key].divider_below:
|
|
print()
|
|
|
|
# apply will still be the number of tweaks just to keep consistency
|
|
print(f"\n{get_apply_number(num_tweaks + 1)}. Apply")
|
|
print(f"{get_apply_number(num_tweaks + 1) + 1}. Remove All Tweaks")
|
|
print(f"{get_apply_number(num_tweaks + 1) + 2}. Reset Mobile Gestalt")
|
|
print("0. Exit\n")
|
|
page = int(input("Enter a number: "))
|
|
if page == get_apply_number(num_tweaks + 1) or page == get_apply_number(num_tweaks + 1) + 1:
|
|
# either apply or reset tweaks
|
|
print()
|
|
resetting = page == (get_apply_number(num_tweaks + 1) + 1)
|
|
# set the tweaks and apply
|
|
# first open the file in read mode
|
|
with open(gestalt_path, 'rb') as in_fp:
|
|
gestalt_plist = plistlib.load(in_fp)
|
|
# create the other plists
|
|
flag_plist: dict = {}
|
|
eligibility_files = None
|
|
|
|
# verify the device credentials before continuing
|
|
if gestalt_plist["CacheExtra"]["qNNddlUK+B/YlooNoymwgA"] != device.version or gestalt_plist["CacheExtra"]["0+nc/Udy4WNG8S+Q7a/s1A"] != device.model:
|
|
print("com.apple.mobilegestalt.plist does not match the device!")
|
|
print("Please make sure you are using the correct file!")
|
|
print("If you believe this is a mistake, you can override this check.")
|
|
override = input("Do you want to overrride? (y/n) ")
|
|
if override.lower() != 'y':
|
|
continue # break applying and return to the main page
|
|
|
|
# set the plist keys
|
|
if not resetting:
|
|
for tweak in tweaks.values:
|
|
if isinstance(tweak, FeatureFlagTweak):
|
|
flag_plist = tweak.apply_tweak(flag_plist)
|
|
elif isinstance(tweak, EligibilityTweak):
|
|
tweak.set_region_code(device.locale[-2:])
|
|
eligibility_files = tweak.apply_tweak()
|
|
else:
|
|
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
|
|
|
# create the restore file list
|
|
files_to_restore = [
|
|
FileToRestore(
|
|
contents=plistlib.dumps(gestalt_plist),
|
|
restore_path="/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/",
|
|
restore_name="com.apple.MobileGestalt.plist"
|
|
),
|
|
FileToRestore(
|
|
contents=plistlib.dumps(flag_plist),
|
|
restore_path="/var/preferences/FeatureFlags/",
|
|
restore_name="Global.plist"
|
|
)
|
|
]
|
|
if eligibility_files != None:
|
|
files_to_restore += eligibility_files
|
|
# restore to the device
|
|
try:
|
|
restore_files(files=files_to_restore, reboot=True, lockdown_client=device.ld)
|
|
except Exception as e:
|
|
print(traceback.format_exc())
|
|
finally:
|
|
input("Press Enter to exit...")
|
|
running = False
|
|
elif page == get_apply_number(num_tweaks + 1) + 2:
|
|
# reset mobilegestalt
|
|
# restore to the device
|
|
try:
|
|
restore_files(files=[FileToRestore(
|
|
contents=b"",
|
|
restore_path="/var/containers/Shared/SystemGroup/systemgroup.com.apple.mobilegestaltcache/Library/Caches/",
|
|
restore_name="com.apple.MobileGestalt.plist"
|
|
)], reboot=True, lockdown_client=device.ld)
|
|
except Exception as e:
|
|
print(traceback.format_exc())
|
|
finally:
|
|
input("Press Enter to exit...")
|
|
running = False
|
|
elif page == 0:
|
|
# exit the panel
|
|
print("Goodbye!")
|
|
running = False
|
|
else:
|
|
tweak = list(tweaks.values())[page-1]
|
|
if page > 0 and page <= num_tweaks and tweak.is_compatible(device.version):
|
|
if tweak.edit_type == TweakModifyType.TEXT:
|
|
# text input
|
|
# for now it is just for set model, deal with a fix later
|
|
print("\n\nSet Model Name")
|
|
print("Leave blank to turn off custom name.\n")
|
|
name = input("Enter Model Name: ")
|
|
if name == "":
|
|
tweak.set_enabled(False)
|
|
else:
|
|
tweak.set_value(name)
|
|
elif tweak.edit_type == TweakModifyType.PICKER:
|
|
# pick between values
|
|
print("\n\nSelect a value.")
|
|
print("If you do not know which to try, start with the first option.")
|
|
values = tweak.value
|
|
for option in range(len(values)):
|
|
print_option(
|
|
num=option+1,
|
|
active=(tweak.enabled and tweak.get_selected_option() == option),
|
|
message=str(values[option])
|
|
)
|
|
print_option(num=len(values)+1, active=(not tweak.enabled), message="Disable")
|
|
picker_choice = int(input("Select option: "))
|
|
if picker_choice > 0 and picker_choice <= len(values):
|
|
tweak.set_selected_option(picker_choice-1)
|
|
elif picker_choice == len(values)+1:
|
|
tweak.set_enabled(False)
|
|
else:
|
|
tweak.toggle_enabled()
|
|
else:
|
|
print("No MobileGestalt file found!")
|
|
print(f"Please place the file in \'{Path.cwd()}\' with the name \'com.apple.MobileGestalt.plist\'")
|
|
print("Remember to make a backup of the file!!\n")
|
|
print("1. Retry")
|
|
print("2. Enter path\n")
|
|
choice = int(input("Enter number: "))
|
|
if choice == 2:
|
|
new_path = input("Enter new path to file: ")
|
|
gestalt_path = Path(new_path)
|