mirror of
https://github.com/leminlimez/Nugget.git
synced 2025-04-08 04:23:05 +08:00
generate live video wallpaper
This commit is contained in:
@@ -123,6 +123,7 @@ If you would like to read more about the inner workings of the exploit and iOS r
|
|||||||
- [JJTech](https://github.com/JJTech0130) for Sparserestore/[TrollRestore](https://github.com/JJTech0130/TrollRestore)
|
- [JJTech](https://github.com/JJTech0130) for Sparserestore/[TrollRestore](https://github.com/JJTech0130/TrollRestore)
|
||||||
- [PosterRestore](https://discord.gg/gWtzTVhMvh) for their help with PosterBoard
|
- [PosterRestore](https://discord.gg/gWtzTVhMvh) for their help with PosterBoard
|
||||||
- Special thanks to dootskyre, [Middo](https://twitter.com/MWRevamped), [dulark](https://github.com/dularkian), forcequitOS, and pingubow for their work on this. It would not have been possible without them!
|
- Special thanks to dootskyre, [Middo](https://twitter.com/MWRevamped), [dulark](https://github.com/dularkian), forcequitOS, and pingubow for their work on this. It would not have been possible without them!
|
||||||
|
- Also thanks to [Snoolie for aar handling](https://github.com/0xilis/python-aar-stuff)
|
||||||
- [disfordottie](https://x.com/disfordottie) for some global flag features
|
- [disfordottie](https://x.com/disfordottie) for some global flag features
|
||||||
- [Mikasa-san](https://github.com/Mikasa-san) for [Quiet Daemon](https://github.com/Mikasa-san/QuietDaemon)
|
- [Mikasa-san](https://github.com/Mikasa-san) for [Quiet Daemon](https://github.com/Mikasa-san/QuietDaemon)
|
||||||
- [sneakyf1shy](https://github.com/f1shy-dev) for [AI Eligibility](https://gist.github.com/f1shy-dev/23b4a78dc283edd30ae2b2e6429129b5) (iOS 18.1 beta 4 and below)
|
- [sneakyf1shy](https://github.com/f1shy-dev) for [AI Eligibility](https://gist.github.com/f1shy-dev/23b4a78dc283edd30ae2b2e6429129b5) (iOS 18.1 beta 4 and below)
|
||||||
|
|||||||
0
controllers/__init__.py
Normal file
0
controllers/__init__.py
Normal file
21
controllers/aar/LICENSE
Normal file
21
controllers/aar/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 0xilis
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
0
controllers/aar/__init__.py
Normal file
0
controllers/aar/__init__.py
Normal file
60
controllers/aar/aar.py
Normal file
60
controllers/aar/aar.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
'''
|
||||||
|
Created by Snoolie K (0xilis) on 2025 March 18.
|
||||||
|
Licensed under MIT. Please credit if using.
|
||||||
|
'''
|
||||||
|
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# make a .aar of one contexts.plist file
|
||||||
|
def wrap_in_aar(input_file, input_mov, output_file):
|
||||||
|
# Since I only need to care about a contents.plist (and in the future the mov file), I am hardcoding the header...
|
||||||
|
header = bytearray.fromhex("4141303125005459503146504154500E00636F6E74656E74732E706C697374444154418E13")
|
||||||
|
|
||||||
|
with open(input_file, 'rb') as f:
|
||||||
|
file_data = f.read()
|
||||||
|
|
||||||
|
file_size = len(file_data)
|
||||||
|
|
||||||
|
if file_size <= 0xFFFF:
|
||||||
|
# Our size can fit in a 2 byte AA_FIELD_TYPE_BLOB, yay
|
||||||
|
header[-2:] = struct.pack('<H', file_size)
|
||||||
|
else:
|
||||||
|
'''
|
||||||
|
Our contents.plist is over 64KB. This means it won't fit in a uint16_t.
|
||||||
|
Instead, we update the A subtype for our DAT (2 byte AA_FIELD_TYPE_BLOB)
|
||||||
|
To be a B subtype (4 byte AA_FIELD_TYPE_BLOB). This also means we will
|
||||||
|
need to change the header size to 0x27 since we are adding 2 bytes by doing this.
|
||||||
|
'''
|
||||||
|
header[-3] = 0x42
|
||||||
|
header[-2:] = struct.pack('<I', file_size)
|
||||||
|
header[4] = 0x27
|
||||||
|
# Hardcoded settlingEffect.mov header
|
||||||
|
header2 = bytearray.fromhex("4141303129005459503146504154501200736574746C696E674566666563742E6D6F7644415441F4B8")
|
||||||
|
|
||||||
|
with open(input_mov, 'rb') as f:
|
||||||
|
file_data2 = f.read()
|
||||||
|
|
||||||
|
file_size2 = len(file_data2)
|
||||||
|
|
||||||
|
if file_size2 <= 0xFFFF:
|
||||||
|
# Our size can fit in a 2 byte AA_FIELD_TYPE_BLOB, yay
|
||||||
|
header2[-2:] = struct.pack('<H', file_size2)
|
||||||
|
else:
|
||||||
|
'''
|
||||||
|
Our settlingEffect.mov is over 64KB. This means it won't fit in a uint16_t.
|
||||||
|
Instead, we update the A subtype for our DAT (2 byte AA_FIELD_TYPE_BLOB)
|
||||||
|
To be a B subtype (4 byte AA_FIELD_TYPE_BLOB). This also means we will
|
||||||
|
need to change the header size to 0x27 since we are adding 2 bytes by doing this.
|
||||||
|
'''
|
||||||
|
header2[-3] = 0x42
|
||||||
|
header2[-2:] = struct.pack('<I', file_size2)
|
||||||
|
header2[4] = 0x2B
|
||||||
|
|
||||||
|
# Write the header and file data to the output file
|
||||||
|
with open(output_file, 'wb') as f:
|
||||||
|
f.write(header)
|
||||||
|
f.write(file_data)
|
||||||
|
f.write(header2)
|
||||||
|
f.write(file_data2)
|
||||||
|
|
||||||
|
wrap_in_aar('contents.plist', 'settlingEffect.mov', 'output.aar')
|
||||||
8
controllers/files_handler.py
Normal file
8
controllers/files_handler.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import sys
|
||||||
|
from os import path, getcwd
|
||||||
|
|
||||||
|
def get_bundle_files(name: str):
|
||||||
|
try:
|
||||||
|
return path.join(sys._MEIPASS, name)
|
||||||
|
except:
|
||||||
|
return path.join(getcwd(), name)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
88D1F444-E2B3-43C4-BB15-790C67EDEA56
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"version" : 10,
|
||||||
|
"layers" : [
|
||||||
|
{
|
||||||
|
"frame" : {
|
||||||
|
"Width" : 1042.4546142208774,
|
||||||
|
"Height" : 2868.5230711043873,
|
||||||
|
"Y" : -0.52307110438732707,
|
||||||
|
"X" : 174.92435703479578
|
||||||
|
},
|
||||||
|
"filename" : "portrait-layer_background.HEIC",
|
||||||
|
"zPosition" : 5,
|
||||||
|
"identifier" : "background"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame" : {
|
||||||
|
"Width" : 1182.5,
|
||||||
|
"Height" : 2569.25,
|
||||||
|
"Y" : 149.37503513892489,
|
||||||
|
"X" : 68.749995738267913
|
||||||
|
},
|
||||||
|
"filename" : "portrait-layer_settling-video.MOV",
|
||||||
|
"zPosition" : 5,
|
||||||
|
"identifier" : "settling-video"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties" : {
|
||||||
|
"portraitLayout" : {
|
||||||
|
"clockIntersection" : 2,
|
||||||
|
"deviceResolution" : {
|
||||||
|
"Width" : 750,
|
||||||
|
"Height" : 1334
|
||||||
|
},
|
||||||
|
"visibleFrame" : {
|
||||||
|
"Width" : 886.43178410794587,
|
||||||
|
"Height" : 2569.25,
|
||||||
|
"Y" : 149.37496486107506,
|
||||||
|
"X" : 252.31008241168968
|
||||||
|
},
|
||||||
|
"timeFrame" : {
|
||||||
|
"Width" : 763.51324337831068,
|
||||||
|
"Height" : 227.26499250374812,
|
||||||
|
"Y" : 2135.0546874997553,
|
||||||
|
"X" : 313.76935277650728
|
||||||
|
},
|
||||||
|
"clockLayerOrder" : "ClockAboveForeground",
|
||||||
|
"hasTopEdgeContact" : false,
|
||||||
|
"inactiveFrame" : {
|
||||||
|
"Width" : 913.02473763118462,
|
||||||
|
"Height" : 2646.3274999999999,
|
||||||
|
"Y" : 149.39630414678933,
|
||||||
|
"X" : 239.01360565007042
|
||||||
|
},
|
||||||
|
"imageSize" : {
|
||||||
|
"Width" : 1320,
|
||||||
|
"Height" : 2868
|
||||||
|
},
|
||||||
|
"parallaxPadding" : {
|
||||||
|
"Width" : 61.45927036481757,
|
||||||
|
"Height" : 151.28435782108946
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settlingEffectEnabled" : true,
|
||||||
|
"depthEnabled" : false,
|
||||||
|
"clockAreaLuminance" : 0.64877637987012982,
|
||||||
|
"parallaxDisabled" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>colorSuggestions</key>
|
||||||
|
<array/>
|
||||||
|
<key>kind</key>
|
||||||
|
<string>Original</string>
|
||||||
|
<key>parameters</key>
|
||||||
|
<dict>
|
||||||
|
<key>clockColor</key>
|
||||||
|
<array>
|
||||||
|
<real>1</real>
|
||||||
|
<real>1</real>
|
||||||
|
<real>1</real>
|
||||||
|
</array>
|
||||||
|
<key>clockVibrancy</key>
|
||||||
|
<real>0.0</real>
|
||||||
|
<key>headroomLook</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,5 @@
|
|||||||
from .tweak_classes import Tweak
|
from .tweak_classes import Tweak
|
||||||
|
from controllers.files_handler import get_bundle_files
|
||||||
from Sparserestore.restore import FileToRestore
|
from Sparserestore.restore import FileToRestore
|
||||||
from devicemanagement.constants import Version
|
from devicemanagement.constants import Version
|
||||||
|
|
||||||
@@ -47,10 +48,7 @@ class EligibilityTweak(Tweak):
|
|||||||
return None
|
return None
|
||||||
print(f"Applying EU Enabler for region \'{self.code}\'...")
|
print(f"Applying EU Enabler for region \'{self.code}\'...")
|
||||||
# get the plists directory
|
# get the plists directory
|
||||||
try:
|
source_dir = get_bundle_files("files/eligibility")
|
||||||
source_dir = path.join(sys._MEIPASS, "files/eligibility")
|
|
||||||
except:
|
|
||||||
source_dir = path.join(getcwd(), "files/eligibility")
|
|
||||||
|
|
||||||
# start with eligibility.plist
|
# start with eligibility.plist
|
||||||
file_path = path.join(source_dir, 'eligibility.plist')
|
file_path = path.join(source_dir, 'eligibility.plist')
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ import zipfile
|
|||||||
import uuid
|
import uuid
|
||||||
import re
|
import re
|
||||||
from random import randint
|
from random import randint
|
||||||
|
from shutil import copytree
|
||||||
from PySide6 import QtWidgets, QtCore, QtGui
|
from PySide6 import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
from .tweak_classes import Tweak
|
from .tweak_classes import Tweak
|
||||||
from Sparserestore.restore import FileToRestore
|
from Sparserestore.restore import FileToRestore
|
||||||
from controllers.plist_handler import set_plist_value
|
from controllers.plist_handler import set_plist_value
|
||||||
|
from controllers.files_handler import get_bundle_files
|
||||||
|
from controllers.aar.aar import wrap_in_aar
|
||||||
from qt.ui_mainwindow import Ui_Nugget
|
from qt.ui_mainwindow import Ui_Nugget
|
||||||
|
|
||||||
class TendieFile:
|
class TendieFile:
|
||||||
@@ -150,9 +153,41 @@ class PosterboardTweak(Tweak):
|
|||||||
isAdding=True,
|
isAdding=True,
|
||||||
randomizeUUID=True
|
randomizeUUID=True
|
||||||
)
|
)
|
||||||
|
elif name == "video-descriptor" or name == "video-descriptors":
|
||||||
|
self.recursive_add(
|
||||||
|
files_to_restore,
|
||||||
|
os.path.join(curr_path, folder),
|
||||||
|
restore_path="/Library/Application Support/PRBPosterExtensionDataStore/61/Extensions/com.apple.PhotosUIPrivate.PhotosPosterProvider/descriptors",
|
||||||
|
isAdding=True,
|
||||||
|
randomizeUUID=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.recursive_add(files_to_restore, os.path.join(curr_path, folder), isAdding=False)
|
self.recursive_add(files_to_restore, os.path.join(curr_path, folder), isAdding=False)
|
||||||
|
|
||||||
|
def create_live_photo_files(self, output_dir: str):
|
||||||
|
if self.videoThumbnail != None and self.videoFile != None:
|
||||||
|
source_dir = get_bundle_files("files/posterboard/1F20C883-EA98-4CCE-9923-0C9A01359721")
|
||||||
|
video_output_dir = os.path.join(output_dir, "video-descriptor/1F20C883-EA98-4CCE-9923-0C9A01359721")
|
||||||
|
copytree(source_dir, video_output_dir, dirs_exist_ok=True)
|
||||||
|
contents_path = os.path.join(video_output_dir, "versions/0/contents/0EFB6A0F-7052-4D24-8859-AB22BADF2E93")
|
||||||
|
# replace the heic files first
|
||||||
|
with open(self.videoThumbnail, "rb") as thumb:
|
||||||
|
contents = thumb.read()
|
||||||
|
to_override = ["input.segmentation/asset.resource/Adjusted.HEIC", "input.segmentation/asset.resource/proxy.heic", "output.layerStack/portrait-layer_background.HEIC"]
|
||||||
|
for file in to_override:
|
||||||
|
with open(os.path.join(contents_path, file), "w") as overriding:
|
||||||
|
overriding.write(contents)
|
||||||
|
del contents
|
||||||
|
# now replace video
|
||||||
|
with open(self.videoFile, "rb") as vid:
|
||||||
|
contents = vid.read()
|
||||||
|
with open(os.path.join(contents_path, "output.layerStack/portrait-layer_settling-video.MOV"), "w") as overriding:
|
||||||
|
overriding.write(contents)
|
||||||
|
del contents
|
||||||
|
aar_path = os.path.join(contents_path, "input.segmentation/segmentation.data.aar")
|
||||||
|
wrap_in_aar(aar_path, self.videoFile, aar_path)
|
||||||
|
|
||||||
|
|
||||||
def apply_tweak(self, files_to_restore: list[FileToRestore], output_dir: str):
|
def apply_tweak(self, files_to_restore: list[FileToRestore], output_dir: str):
|
||||||
# unzip the file
|
# unzip the file
|
||||||
if not self.enabled:
|
if not self.enabled:
|
||||||
@@ -169,11 +204,12 @@ class PosterboardTweak(Tweak):
|
|||||||
domain=f"AppDomain-{self.bundle_id}"
|
domain=f"AppDomain-{self.bundle_id}"
|
||||||
))
|
))
|
||||||
return
|
return
|
||||||
elif self.tendies == None or len(self.tendies) == 0:
|
elif (self.tendies == None or len(self.tendies) == 0) and (self.videoThumbnail == None or self.videoThumbnail == None):
|
||||||
return
|
return
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
# try to get past directory name limit on windows
|
# try to get past directory name limit on windows
|
||||||
output_dir = "\\\\?\\" + output_dir
|
output_dir = "\\\\?\\" + output_dir
|
||||||
|
self.create_live_photo_files(output_dir)
|
||||||
for tendie in self.tendies:
|
for tendie in self.tendies:
|
||||||
zip_output = os.path.join(output_dir, str(uuid.uuid4()))
|
zip_output = os.path.join(output_dir, str(uuid.uuid4()))
|
||||||
os.makedirs(zip_output)
|
os.makedirs(zip_output)
|
||||||
|
|||||||
Reference in New Issue
Block a user