Files
Pocket-Poster/Pocket Poster/Controllers/PosterBoardManager.swift
T

154 lines
5.8 KiB
Swift

//
// PosterBoardManager.swift
// Pocket Poster
//
// Created by lemin on 5/31/25.
//
import Foundation
import ZIPFoundation
import UIKit
class PosterBoardManager {
private static func unzipFile(at url: URL) throws -> URL {
let fileName = url.deletingPathExtension().lastPathComponent
let fileData = try Data(contentsOf: url)
let fileManager = FileManager()
// Write the file to the Documents Directory
let docDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let path = docDir[0]
let url = path.appending(path: fileName)
// Remove All files in this directory
let existingFiles = try FileManager.default.contentsOfDirectory(at: path, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
for fileUrl in existingFiles
{
try FileManager.default.removeItem(at: fileUrl)
}
// Save our Zip file
try fileData.write(to: url, options: [.atomic])
// Unzip the Zipped Up File
var destinationURL = path
if FileManager.default.fileExists(atPath: url.path())
{
destinationURL.append(path: "directory")
try fileManager.unzipItem(at: url, to: destinationURL)
}
return destinationURL
}
static func runShortcut(named name: String) {
guard let urlEncodedName = name.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let url = URL(string: "shortcuts://run-shortcut?name=\(name)") else { return }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
static func getDescriptorsFromTendie(_ url: URL) throws -> URL? {
let unzippedDir = try unzipFile(at: url)
for dir in try FileManager.default.contentsOfDirectory(at: unzippedDir, includingPropertiesForKeys: nil, options: .skipsHiddenFiles) {
let fileName = dir.lastPathComponent
if fileName.lowercased() == "descriptor" || fileName.lowercased() == "descriptors" {
return dir
}
}
return nil
}
static func randomizeWallpaperId(url: URL) throws {
let randomizedID = Int.random(in: 9999...99999)
var files = [URL]()
if let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) {
for case let fileURL as URL in enumerator
{
do
{
let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey])
if fileAttributes.isRegularFile!
{
files.append(fileURL)
}
}
catch
{
print(error, fileURL)
}
}
}
func setPlistValue(file: String, key: String, value: Any, recursive: Bool = true) {
// thanks gpt
guard let plistData = FileManager.default.contents(atPath: file),
var plist = try? PropertyListSerialization.propertyList(from: plistData, options: [], format: nil) as? [String: Any] else {
return
}
plist[key] = value
guard let updatedData = try? PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0) else {
return
}
do {
try updatedData.write(to: URL(fileURLWithPath: file))
} catch {
print("Failed to write updated plist: \(error)")
}
}
for file in files {
switch file.lastPathComponent {
case "com.apple.posterkit.provider.descriptor.identifier":
try String(randomizedID).data(using: .utf8)?.write(to: file)
case "com.apple.posterkit.provider.contents.userInfo":
setPlistValue(file: file.path(), key: "wallpaperRepresentingIdentifier", value: randomizedID)
case "Wallpaper.plist":
setPlistValue(file: file.path(), key: "identifier", value: randomizedID, recursive: false)
default:
continue
}
}
}
static func applyTendies(_ urls: [URL], appHash: String) throws {
let _ = try SymHandler.createDescriptorsSymlink(appHash: appHash)
defer {
SymHandler.cleanup()
}
for url in urls {
// scope the resource
let accessing = url.startAccessingSecurityScopedResource()
defer {
if accessing {
url.stopAccessingSecurityScopedResource()
}
}
guard let descriptors = try getDescriptorsFromTendie(url) else { return } // TODO: Add error handling
// create the folder
for descr in try FileManager.default.contentsOfDirectory(at: descriptors, includingPropertiesForKeys: nil, options: .skipsHiddenFiles) {
if descr.lastPathComponent != "__MACOSX" {
try randomizeWallpaperId(url: descr)
let newURL = SymHandler.getDocumentsDirectory().appendingPathComponent(UUID().uuidString, conformingTo: .directory)
try FileManager.default.moveItem(at: descr, to: newURL)
do {
try FileManager.default.trashItem(at: newURL, resultingItemURL: nil)
} catch {
print(error.localizedDescription)
}
}
}
try? FileManager.default.removeItem(at: descriptors)
}
}
}