mirror of
https://github.com/Sunnyyoung/WeChatTweak-macOS.git
synced 2026-01-17 07:25:39 +08:00
Merge 7ce0a4ea25 into ebdcb7bbd2
This commit is contained in:
commit
6ed01fa60a
|
|
@ -23,8 +23,8 @@ struct Command {
|
||||||
try await Command.execute(command: "defaults read \(app.appendingPathComponent("Contents/Info.plist").path) CFBundleVersion")
|
try await Command.execute(command: "defaults read \(app.appendingPathComponent("Contents/Info.plist").path) CFBundleVersion")
|
||||||
}
|
}
|
||||||
|
|
||||||
static func patch(app: URL, config: Config) async throws {
|
static func patch(app: URL, targets: [Target]) async throws {
|
||||||
try Patcher.patch(binary: app.appendingPathComponent("Contents/MacOS/WeChat"), config: config)
|
try Patcher.patch(binary: app.appendingPathComponent("Contents/MacOS/WeChat"), entries: targets.flatMap { $0.entries })
|
||||||
}
|
}
|
||||||
|
|
||||||
static func resign(app: URL) async throws {
|
static func resign(app: URL) async throws {
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,11 @@ struct Patcher {
|
||||||
case noArchMatched
|
case noArchMatched
|
||||||
}
|
}
|
||||||
|
|
||||||
static func patch(binary: URL, config: Config) throws {
|
static func patch(binary: URL, entries: [Target.Entry]) throws {
|
||||||
guard FileManager.default.fileExists(atPath: binary.path) else {
|
guard FileManager.default.fileExists(atPath: binary.path) else {
|
||||||
throw Error.invalidFile
|
throw Error.invalidFile
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = config.targets.flatMap { $0.entries }
|
|
||||||
guard !entries.isEmpty else { throw Error.noArchMatched }
|
guard !entries.isEmpty else { throw Error.noArchMatched }
|
||||||
|
|
||||||
let fh = try FileHandle(forUpdating: binary)
|
let fh = try FileHandle(forUpdating: binary)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
//
|
//
|
||||||
// Config.swift
|
// Target.swift
|
||||||
// WeChatTweak
|
// WeChatTweak
|
||||||
//
|
//
|
||||||
// Created by Sunny Young on 2025/12/5.
|
// Created by Sunny Young on 2025/12/5.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import MachO
|
|
||||||
|
|
||||||
struct Config: Decodable {
|
struct Target: Decodable {
|
||||||
|
struct Entry: Decodable {
|
||||||
enum Arch: String, Decodable {
|
enum Arch: String, Decodable {
|
||||||
case arm64
|
case arm64
|
||||||
case x86_64
|
case x86_64
|
||||||
|
|
@ -23,7 +23,6 @@ struct Config: Decodable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Entry: Decodable {
|
|
||||||
let arch: Arch
|
let arch: Arch
|
||||||
let addr: UInt64
|
let addr: UInt64
|
||||||
let asm: Data
|
let asm: Data
|
||||||
|
|
@ -62,38 +61,8 @@ struct Config: Decodable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Target: Decodable {
|
|
||||||
let identifier: String
|
let identifier: String
|
||||||
let entries: [Entry]
|
let entries: [Entry]
|
||||||
|
|
||||||
private enum CodingKeys: CodingKey {
|
|
||||||
case identifier
|
|
||||||
case entries
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: any Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
self.identifier = try container.decode(String.self, forKey: .identifier)
|
|
||||||
self.entries = try container.decode([Entry].self, forKey: .entries)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let version: String
|
|
||||||
let targets: [Target]
|
|
||||||
|
|
||||||
static func load(url: URL) async throws -> [Config] {
|
|
||||||
if url.isFileURL {
|
|
||||||
return try JSONDecoder().decode(
|
|
||||||
[Config].self,
|
|
||||||
from: Data(contentsOf: url)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return try JSONDecoder().decode(
|
|
||||||
[Config].self,
|
|
||||||
from: try await URLSession.shared.data(from: url).0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Data {
|
private extension Data {
|
||||||
|
|
@ -20,7 +20,7 @@ extension Tweak {
|
||||||
print("------ Current version ------")
|
print("------ Current version ------")
|
||||||
print(try await Command.version(app: options.app) ?? "unknown")
|
print(try await Command.version(app: options.app) ?? "unknown")
|
||||||
print("------ Supported versions ------")
|
print("------ Supported versions ------")
|
||||||
try await Config.load(url: options.config).forEach({ print($0.version) })
|
try await Tweak.versions().forEach { print($0) }
|
||||||
Darwin.exit(EXIT_SUCCESS)
|
Darwin.exit(EXIT_SUCCESS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,25 +36,21 @@ extension Tweak {
|
||||||
|
|
||||||
mutating func run() async throws {
|
mutating func run() async throws {
|
||||||
print("------ Version ------")
|
print("------ Version ------")
|
||||||
let version = try await Command.version(app: options.app)
|
guard let version = try await Command.version(app: self.options.app), let targets = try await Tweak.load(version: version) else {
|
||||||
print("WeChat version: \(version ?? "unknown")")
|
|
||||||
|
|
||||||
print("------ Config ------")
|
|
||||||
guard let config = (try await Config.load(url: options.config)).first(where: { $0.version == version }) else {
|
|
||||||
throw Error.unsupportedVersion
|
throw Error.unsupportedVersion
|
||||||
}
|
}
|
||||||
print("Matched config: \(config)")
|
print("\(version)")
|
||||||
|
|
||||||
print("------ Patch ------")
|
print("------ Patch ------")
|
||||||
try await Command.patch(
|
try await Command.patch(
|
||||||
app: options.app,
|
app: self.options.app,
|
||||||
config: config
|
targets: targets
|
||||||
)
|
)
|
||||||
print("Done!")
|
print("Done!")
|
||||||
|
|
||||||
print("------ Resign ------")
|
print("------ Resign ------")
|
||||||
try await Command.resign(
|
try await Command.resign(
|
||||||
app: options.app
|
app: self.options.app
|
||||||
)
|
)
|
||||||
print("Done!")
|
print("Done!")
|
||||||
|
|
||||||
|
|
@ -101,7 +97,7 @@ struct Tweak: AsyncParsableCommand {
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
name: .shortAndLong,
|
name: .shortAndLong,
|
||||||
help: "Local path or Remote URL of config.json",
|
help: "Local path or Remote URL of config (default: derived from app version)",
|
||||||
transform: {
|
transform: {
|
||||||
if FileManager.default.fileExists(atPath: $0) {
|
if FileManager.default.fileExists(atPath: $0) {
|
||||||
return URL(fileURLWithPath: $0)
|
return URL(fileURLWithPath: $0)
|
||||||
|
|
@ -113,7 +109,7 @@ struct Tweak: AsyncParsableCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
var config: URL = URL(string:"https://raw.githubusercontent.com/sunnyyoung/WeChatTweak/refs/heads/master/config.json")!
|
var config: URL? = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
static let configuration = CommandConfiguration(
|
static let configuration = CommandConfiguration(
|
||||||
|
|
@ -131,6 +127,35 @@ struct Tweak: AsyncParsableCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Tweak {
|
||||||
|
static func load(url: URL) async throws -> [Target] {
|
||||||
|
let data = try await {
|
||||||
|
if url.isFileURL {
|
||||||
|
return try Data(contentsOf: url)
|
||||||
|
} else {
|
||||||
|
return try await URLSession.shared.data(from: url).0
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return try JSONDecoder().decode([Target].self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func load(version: String) async throws -> [Target]? {
|
||||||
|
guard try await Tweak.versions().contains(version) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return try await Self.load(url: URL(string: "https://raw.githubusercontent.com/sunnyyoung/WeChatTweak/master/Versions/\(version).json")!)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func versions() async throws -> [String] {
|
||||||
|
let data = try await URLSession.shared.data(
|
||||||
|
for: URLRequest(
|
||||||
|
url: URL(string: "https://api.github.com/repos/sunnyyoung/WeChatTweak/contents/Versions")!
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return (try JSONSerialization.jsonObject(with: data.0) as? [[String: Any]])?.compactMap { ($0["name"] as? NSString)?.deletingPathExtension } ?? []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
await Tweak.main()
|
await Tweak.main()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
82
Versions/31927.json
Normal file
82
Versions/31927.json
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"identifier": "revoke",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "103dba3d0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "startUpdater",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ea41c",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "startBackgroundUpdatesCheck",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ed3b4",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "checkForUpdates",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ecf9c",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "enableAutoUpdate",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ed920",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "automaticallyDownloadsUpdates",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001f6ee8",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "canCheckForUpdate",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001f6ef8",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "multiInstance",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001e1c10",
|
||||||
|
"asm": "20008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
22
Versions/31960.json
Normal file
22
Versions/31960.json
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"identifier": "revoke",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "10408a408",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "multiInstance",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001e4a38",
|
||||||
|
"asm": "20008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
82
Versions/32281.json
Normal file
82
Versions/32281.json
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"identifier": "revoke",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "103db33e0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "startUpdater",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001e9ed0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "startBackgroundUpdatesCheck",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ecb10",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "checkForUpdates",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ec73c",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "enableAutoUpdate",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ecfc0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "automaticallyDownloadsUpdates",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001f59e0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "canCheckForUpdate",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001f59e0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "multiInstance",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001e1a74",
|
||||||
|
"asm": "20008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
82
Versions/32288.json
Normal file
82
Versions/32288.json
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"identifier": "revoke",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "103db34c0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "startUpdater",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001e9ed0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "startBackgroundUpdatesCheck",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ecb10",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "checkForUpdates",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ec73c",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "enableAutoUpdate",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001ecfc0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "automaticallyDownloadsUpdates",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001f59e0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "canCheckForUpdate",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001f59e0",
|
||||||
|
"asm": "00008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "multiInstance",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"arch": "arm64",
|
||||||
|
"addr": "1001e1a74",
|
||||||
|
"asm": "20008052C0035FD6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue
Block a user