Files
OpenStats/Packages/OpenStatsKit/Sources/HelperShared/HelperProtocol.swift
T
gentpan c9d722f20d 账号同步、磁盘工具、IP 归属地数据源与纯净度、弹窗与设置调整
- 账号与同步:GitHub / Google / Apple 登录后把菜单栏项目与风格等偏好同步到 getopenstats.com,换一台 Mac 登录即恢复(AccountSync 模块、SyncController、SettingsDocument、账号设置页,openstats:// 回调)
- 磁盘页成为工具页:已用 / 可清除 / 可用分段容量条、空间分析、文件系统检查、本地快照清理(辅助工具协议 v4)、其他磁盘推出
- 公网 IP:归属地数据源可选 CleanIP.io / ipapi.is / DB-IP / ipinfo.io / 本地 GeoLite2,每台 Mac 自己查、本地缓存 7 天;IPv4 / IPv6 双栈各自查询与切换;弹窗显示 ASN、运营方、原生 / 住宅等徽章与纯净度评分色带;接口区块可重置上传 / 下载统计
- 弹窗:右上角按钮改为该指标自己的图标 + 总设置;主窗口页面标题栏的开关点不动已修复;滚动条改为悬浮式,内容不再偏左;网络弹窗卡片被标题行撑宽的问题已修复
- 设置:⌘ 拖动排序说明;每个菜单栏项目单独选风格并带实时预览;网络与磁盘的进程榜单固定 5 行并平滑排序;CPU 持续高负载通知
- 设计系统:分段条、评分色带、标签徽章、胶囊切换、刷新按钮等组件与徽章配色 token
- 更新日志、架构说明、README 与译文同步
2026-09-15 03:37:24 +05:00

65 lines
3.4 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
import Security
public enum HelperConstants {
public static let machServiceName = "com.openstats.helper"
public static let launchdPlistName = "com.openstats.helper.plist"
public static let appBundleIdentifier = "com.openstats.app"
/// 与 App 版本同步;App 发现辅助工具版本不一致时提示重新安装
public static let protocolVersion = 4
/// 辅助工具对调用方的签名要求:与辅助工具自身同一团队签名的 OpenStats。
/// ad-hoc 签名的开发构建没有团队,只能校验 bundle identifier。
public static func clientRequirement(teamIdentifier: String?) -> String {
let identifier = "identifier \"\(appBundleIdentifier)\""
guard let teamIdentifier, !teamIdentifier.isEmpty else { return identifier }
return identifier + " and anchor apple generic and certificate leaf[subject.OU] = \"\(teamIdentifier)\""
}
}
public enum CodeSigningInfo {
/// 当前进程签名所属的 Team ID;ad-hoc 签名时为 nil
public static func currentTeamIdentifier() -> String? {
var code: SecCode?
guard SecCodeCopySelf([], &code) == errSecSuccess, let code else { return nil }
var staticCode: SecStaticCode?
guard SecCodeCopyStaticCode(code, [], &staticCode) == errSecSuccess, let staticCode else { return nil }
var information: CFDictionary?
guard SecCodeCopySigningInformation(staticCode, SecCSFlags(rawValue: kSecCSSigningInformation), &information) == errSecSuccess,
let dictionary = information as? [String: Any] else { return nil }
return dictionary[kSecCodeInfoTeamIdentifier as String] as? String
}
}
/// 辅助工具以 root 运行,只暴露固定的少量操作,不提供任意命令执行能力。
/// 所有回调中的 `String?` 为错误描述,nil 表示成功。
@objc public protocol OpenStatsHelperProtocol {
func protocolVersion(reply: @escaping @Sendable (Int) -> Void)
func setFanTarget(fan: Int, rpm: Double, reply: @escaping @Sendable (String?) -> Void)
func setFanAutomatic(fan: Int, reply: @escaping @Sendable (String?) -> Void)
func resetAllFans(reply: @escaping @Sendable (String?) -> Void)
func setSleepDisabled(_ disabled: Bool, reply: @escaping @Sendable (String?) -> Void)
func flushDNSCache(reply: @escaping @Sendable (String?) -> Void)
func purgeMemory(reply: @escaping @Sendable (String?) -> Void)
/// 为指定网络服务设置 DNS;`servers` 为空表示恢复自动获取。辅助工具会校验服务名与每个地址
func setDNSServers(service: String, servers: [String], reply: @escaping @Sendable (String?) -> Void)
/// 删除 Time Machine 本地快照;每个标识都按固定格式校验,逐个执行
func deleteLocalSnapshots(identifiers: [String], reply: @escaping @Sendable (String?) -> Void)
}
/// 需要管理员权限的系统维护命令。辅助工具与未安装辅助工具时的授权回退共用同一份固定命令
public enum MaintenanceCommand: String, Sendable, CaseIterable {
case flushDNS, purgeMemory
public var steps: [(path: String, arguments: [String])] {
switch self {
case .flushDNS: [("/usr/bin/dscacheutil", ["-flushcache"]), ("/usr/bin/killall", ["-HUP", "mDNSResponder"])]
case .purgeMemory: [("/usr/sbin/purge", [])]
}
}
public var shellCommand: String {
steps.map { ([$0.path] + $0.arguments).joined(separator: " ") }.joined(separator: "; ")
}
}