{"repo": "chrn11/deepseekusage-app", "files": {"ios/DeepSeekUsage/Services/KeychainManager.swift": {"ff75de8339e9c4d43c32ab2c955b710a581c79a1": {"t": 1785745900.809167, "n": 4518, "h": "7efcca83cedb8202", "c": "import Foundation\nimport Security\n\n/// 钥匙串管理器 — 安全存储 API Key 和平台 Cookie\nenum KeychainManager {\n\n static let loginStatusChanged = Notification.Name(\"com.deepseekusage.loginStatusChanged\")\n\n private static let service = \"com.deepseekusage.app\"\n\n // MARK: - 通用存储\n\n private static func save(data: Data, account: String) throws {\n try? delete(account: account)\n\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecValueData as String: data,\n kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly\n ]\n\n let status = SecItemAdd(query as CFDictionary, nil)\n guard status == errSecSuccess else {\n throw KeychainError.unableToSave(status: status)\n }\n }\n\n private static func load(account: String) -> Data? {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecReturnData as String: true,\n kSecMatchLimit as String: kSecMatchLimitOne\n ]\n\n var item: CFTypeRef?\n let status = SecItemCopyMatching(query as CFDictionary, &item)\n\n guard status == errSecSuccess,\n let data = item as? Data else { return nil }\n return data\n }\n\n private static func delete(account: String) throws {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account\n ]\n\n let status = SecItemDelete(query as CFDictionary)\n guard status == errSecSuccess || status == errSecItemNotFound else {\n throw KeychainError.unableToDelete(status: status)\n }\n }\n\n // MARK: - API Key\n\n private static let apiKeyAccount = \"deepseek_api_key\"\n\n static func saveAPIKey(_ key: String) throws {\n guard !key.isEmpty else { try deleteAPIKey(); return }\n try save(data: key.data(using: .utf8)!, account: apiKeyAccount)\n }\n\n static func loadAPIKey() -> String? {\n guard let data = load(account: apiKeyAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteAPIKey() throws {\n try delete(account: apiKeyAccount)\n }\n\n static var hasAPIKey: Bool { loadAPIKey() != nil }\n\n // MARK: - 平台 Cookie\n\n private static let cookieAccount = \"deepseek_platform_cookie\"\n\n static func saveCookie(_ cookie: String) throws {\n guard !cookie.isEmpty else { try deleteCookie(); return }\n try save(data: cookie.data(using: .utf8)!, account: cookieAccount)\n }\n\n static func loadCookie() -> String? {\n guard let data = load(account: cookieAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteCookie() throws { try delete(account: cookieAccount) }\n static var hasCookie: Bool { loadCookie() != nil }\n\n // MARK: - Bearer Token(登录返回的 auth token)\n\n private static let tokenAccount = \"deepseek_bearer_token\"\n\n static func saveToken(_ token: String) throws {\n guard !token.isEmpty else { try deleteToken(); return }\n try save(data: token.data(using: .utf8)!, account: tokenAccount)\n }\n\n static func loadToken() -> String? {\n guard let data = load(account: tokenAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteToken() throws { try delete(account: tokenAccount) }\n static var hasToken: Bool { loadToken() != nil }\n\n // MARK: - 登录凭据一并清理\n\n static func logoutPlatform() {\n try? deleteCookie()\n try? deleteToken()\n NotificationCenter.default.post(name: loginStatusChanged, object: nil)\n }\n\n // 兼容旧方法名\n static func save(key: String) throws { try saveAPIKey(key) }\n static func load() -> String? { loadAPIKey() }\n static func delete() throws { try deleteAPIKey() }\n static var hasKey: Bool { hasAPIKey }\n}\n\nenum KeychainError: LocalizedError {\n case unableToSave(status: OSStatus)\n case unableToDelete(status: OSStatus)\n\n var errorDescription: String? {\n switch self {\n case .unableToSave(let s): return \"保存失败 (OSStatus: \\(s))\"\n case .unableToDelete(let s): return \"删除失败 (OSStatus: \\(s))\"\n }\n }\n}\n"}, "fc3d29abc64e48e2088632b9ab07569ae2e49da5": {"t": 1785757776.939265, "n": 4518, "h": "7efcca83cedb8202", "c": "import Foundation\nimport Security\n\n/// 钥匙串管理器 — 安全存储 API Key 和平台 Cookie\nenum KeychainManager {\n\n static let loginStatusChanged = Notification.Name(\"com.deepseekusage.loginStatusChanged\")\n\n private static let service = \"com.deepseekusage.app\"\n\n // MARK: - 通用存储\n\n private static func save(data: Data, account: String) throws {\n try? delete(account: account)\n\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecValueData as String: data,\n kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly\n ]\n\n let status = SecItemAdd(query as CFDictionary, nil)\n guard status == errSecSuccess else {\n throw KeychainError.unableToSave(status: status)\n }\n }\n\n private static func load(account: String) -> Data? {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecReturnData as String: true,\n kSecMatchLimit as String: kSecMatchLimitOne\n ]\n\n var item: CFTypeRef?\n let status = SecItemCopyMatching(query as CFDictionary, &item)\n\n guard status == errSecSuccess,\n let data = item as? Data else { return nil }\n return data\n }\n\n private static func delete(account: String) throws {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account\n ]\n\n let status = SecItemDelete(query as CFDictionary)\n guard status == errSecSuccess || status == errSecItemNotFound else {\n throw KeychainError.unableToDelete(status: status)\n }\n }\n\n // MARK: - API Key\n\n private static let apiKeyAccount = \"deepseek_api_key\"\n\n static func saveAPIKey(_ key: String) throws {\n guard !key.isEmpty else { try deleteAPIKey(); return }\n try save(data: key.data(using: .utf8)!, account: apiKeyAccount)\n }\n\n static func loadAPIKey() -> String? {\n guard let data = load(account: apiKeyAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteAPIKey() throws {\n try delete(account: apiKeyAccount)\n }\n\n static var hasAPIKey: Bool { loadAPIKey() != nil }\n\n // MARK: - 平台 Cookie\n\n private static let cookieAccount = \"deepseek_platform_cookie\"\n\n static func saveCookie(_ cookie: String) throws {\n guard !cookie.isEmpty else { try deleteCookie(); return }\n try save(data: cookie.data(using: .utf8)!, account: cookieAccount)\n }\n\n static func loadCookie() -> String? {\n guard let data = load(account: cookieAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteCookie() throws { try delete(account: cookieAccount) }\n static var hasCookie: Bool { loadCookie() != nil }\n\n // MARK: - Bearer Token(登录返回的 auth token)\n\n private static let tokenAccount = \"deepseek_bearer_token\"\n\n static func saveToken(_ token: String) throws {\n guard !token.isEmpty else { try deleteToken(); return }\n try save(data: token.data(using: .utf8)!, account: tokenAccount)\n }\n\n static func loadToken() -> String? {\n guard let data = load(account: tokenAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteToken() throws { try delete(account: tokenAccount) }\n static var hasToken: Bool { loadToken() != nil }\n\n // MARK: - 登录凭据一并清理\n\n static func logoutPlatform() {\n try? deleteCookie()\n try? deleteToken()\n NotificationCenter.default.post(name: loginStatusChanged, object: nil)\n }\n\n // 兼容旧方法名\n static func save(key: String) throws { try saveAPIKey(key) }\n static func load() -> String? { loadAPIKey() }\n static func delete() throws { try deleteAPIKey() }\n static var hasKey: Bool { hasAPIKey }\n}\n\nenum KeychainError: LocalizedError {\n case unableToSave(status: OSStatus)\n case unableToDelete(status: OSStatus)\n\n var errorDescription: String? {\n switch self {\n case .unableToSave(let s): return \"保存失败 (OSStatus: \\(s))\"\n case .unableToDelete(let s): return \"删除失败 (OSStatus: \\(s))\"\n }\n }\n}\n"}, "898f574deef3096911d29acf580dc9bae50ee519": {"t": 1785757778.086351, "n": 4344, "h": "c58c888ba18b72e6", "c": "import Foundation\nimport Security\n\n/// 钥匙串管理器 — 安全存储 API Key 和平台 Cookie\nenum KeychainManager {\n\n private static let service = \"com.deepseekusage.app\"\n\n // MARK: - 通用存储\n\n private static func save(data: Data, account: String) throws {\n try? delete(account: account)\n\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecValueData as String: data,\n kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly\n ]\n\n let status = SecItemAdd(query as CFDictionary, nil)\n guard status == errSecSuccess else {\n throw KeychainError.unableToSave(status: status)\n }\n }\n\n private static func load(account: String) -> Data? {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecReturnData as String: true,\n kSecMatchLimit as String: kSecMatchLimitOne\n ]\n\n var item: CFTypeRef?\n let status = SecItemCopyMatching(query as CFDictionary, &item)\n\n guard status == errSecSuccess,\n let data = item as? Data else { return nil }\n return data\n }\n\n private static func delete(account: String) throws {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account\n ]\n\n let status = SecItemDelete(query as CFDictionary)\n guard status == errSecSuccess || status == errSecItemNotFound else {\n throw KeychainError.unableToDelete(status: status)\n }\n }\n\n // MARK: - API Key\n\n private static let apiKeyAccount = \"deepseek_api_key\"\n\n static func saveAPIKey(_ key: String) throws {\n guard !key.isEmpty else { try deleteAPIKey(); return }\n try save(data: key.data(using: .utf8)!, account: apiKeyAccount)\n }\n\n static func loadAPIKey() -> String? {\n guard let data = load(account: apiKeyAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteAPIKey() throws {\n try delete(account: apiKeyAccount)\n }\n\n static var hasAPIKey: Bool { loadAPIKey() != nil }\n\n // MARK: - 平台 Cookie\n\n private static let cookieAccount = \"deepseek_platform_cookie\"\n\n static func saveCookie(_ cookie: String) throws {\n guard !cookie.isEmpty else { try deleteCookie(); return }\n try save(data: cookie.data(using: .utf8)!, account: cookieAccount)\n }\n\n static func loadCookie() -> String? {\n guard let data = load(account: cookieAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteCookie() throws { try delete(account: cookieAccount) }\n static var hasCookie: Bool { loadCookie() != nil }\n\n // MARK: - Bearer Token(登录返回的 auth token)\n\n private static let tokenAccount = \"deepseek_bearer_token\"\n\n static func saveToken(_ token: String) throws {\n guard !token.isEmpty else { try deleteToken(); return }\n try save(data: token.data(using: .utf8)!, account: tokenAccount)\n }\n\n static func loadToken() -> String? {\n guard let data = load(account: tokenAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteToken() throws { try delete(account: tokenAccount) }\n static var hasToken: Bool { loadToken() != nil }\n\n // MARK: - 登录凭据一并清理\n\n static func logoutPlatform() {\n try? deleteCookie()\n try? deleteToken()\n }\n\n // 兼容旧方法名\n static func save(key: String) throws { try saveAPIKey(key) }\n static func load() -> String? { loadAPIKey() }\n static func delete() throws { try deleteAPIKey() }\n static var hasKey: Bool { hasAPIKey }\n}\n\nenum KeychainError: LocalizedError {\n case unableToSave(status: OSStatus)\n case unableToDelete(status: OSStatus)\n\n var errorDescription: String? {\n switch self {\n case .unableToSave(let s): return \"保存失败 (OSStatus: \\(s))\"\n case .unableToDelete(let s): return \"删除失败 (OSStatus: \\(s))\"\n }\n }\n}\n"}, "cd6c5df3f598f8ad587190ab5873f6a1d17ddabc": {"t": 1785757779.4477327, "n": 3658, "h": "00c884c57bca2054", "c": "import Foundation\nimport Security\n\n/// 钥匙串管理器 — 安全存储 API Key 和平台 Cookie\nenum KeychainManager {\n\n private static let service = \"com.deepseekusage.app\"\n\n // MARK: - 通用存储\n\n private static func save(data: Data, account: String) throws {\n try? delete(account: account)\n\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecValueData as String: data,\n kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly\n ]\n\n let status = SecItemAdd(query as CFDictionary, nil)\n guard status == errSecSuccess else {\n throw KeychainError.unableToSave(status: status)\n }\n }\n\n private static func load(account: String) -> Data? {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecReturnData as String: true,\n kSecMatchLimit as String: kSecMatchLimitOne\n ]\n\n var item: CFTypeRef?\n let status = SecItemCopyMatching(query as CFDictionary, &item)\n\n guard status == errSecSuccess,\n let data = item as? Data else { return nil }\n return data\n }\n\n private static func delete(account: String) throws {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account\n ]\n\n let status = SecItemDelete(query as CFDictionary)\n guard status == errSecSuccess || status == errSecItemNotFound else {\n throw KeychainError.unableToDelete(status: status)\n }\n }\n\n // MARK: - API Key\n\n private static let apiKeyAccount = \"deepseek_api_key\"\n\n static func saveAPIKey(_ key: String) throws {\n guard !key.isEmpty else { try deleteAPIKey(); return }\n try save(data: key.data(using: .utf8)!, account: apiKeyAccount)\n }\n\n static func loadAPIKey() -> String? {\n guard let data = load(account: apiKeyAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteAPIKey() throws {\n try delete(account: apiKeyAccount)\n }\n\n static var hasAPIKey: Bool { loadAPIKey() != nil }\n\n // MARK: - 平台 Cookie(登录 platform.deepseek.com 后获取)\n\n private static let cookieAccount = \"deepseek_platform_cookie\"\n\n static func saveCookie(_ cookie: String) throws {\n guard !cookie.isEmpty else { try deleteCookie(); return }\n try save(data: cookie.data(using: .utf8)!, account: cookieAccount)\n }\n\n static func loadCookie() -> String? {\n guard let data = load(account: cookieAccount) else { return nil }\n return String(data: data, encoding: .utf8)\n }\n\n static func deleteCookie() throws {\n try delete(account: cookieAccount)\n }\n\n static var hasCookie: Bool { loadCookie() != nil }\n\n // 兼容旧方法名\n static func save(key: String) throws { try saveAPIKey(key) }\n static func load() -> String? { loadAPIKey() }\n static func delete() throws { try deleteAPIKey() }\n static var hasKey: Bool { hasAPIKey }\n}\n\nenum KeychainError: LocalizedError {\n case unableToSave(status: OSStatus)\n case unableToDelete(status: OSStatus)\n\n var errorDescription: String? {\n switch self {\n case .unableToSave(let s): return \"保存失败 (OSStatus: \\(s))\"\n case .unableToDelete(let s): return \"删除失败 (OSStatus: \\(s))\"\n }\n }\n}\n"}, "a66696eba82f98490028625d313ce09630b760d3": {"t": 1785757780.8911517, "n": 2602, "h": "817f22baba147487", "c": "import Foundation\nimport Security\n\n/// 钥匙串管理器 — 安全存储 DeepSeek API Key\n///\n/// Keychain 是 iOS 系统级的安全存储,数据加密存储在设备上。\n/// 即使 App 被删除重装(如果使用此访问组),数据也不会丢失。\nenum KeychainManager {\n\n private static let service = \"com.deepseekusage.app\"\n private static let account = \"deepseek_api_key\"\n\n // MARK: - 保存\n\n static func save(key: String) throws {\n guard !key.isEmpty else {\n try delete()\n return\n }\n\n let data = key.data(using: .utf8)!\n\n // 先尝试删除旧的\n try? delete()\n\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecValueData as String: data,\n kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly\n ]\n\n let status = SecItemAdd(query as CFDictionary, nil)\n guard status == errSecSuccess else {\n throw KeychainError.unableToSave(status: status)\n }\n }\n\n // MARK: - 读取\n\n static func load() -> String? {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account,\n kSecReturnData as String: true,\n kSecMatchLimit as String: kSecMatchLimitOne\n ]\n\n var item: CFTypeRef?\n let status = SecItemCopyMatching(query as CFDictionary, &item)\n\n guard status == errSecSuccess,\n let data = item as? Data,\n let key = String(data: data, encoding: .utf8) else {\n return nil\n }\n\n return key\n }\n\n // MARK: - 删除\n\n static func delete() throws {\n let query: [String: Any] = [\n kSecClass as String: kSecClassGenericPassword,\n kSecAttrService as String: service,\n kSecAttrAccount as String: account\n ]\n\n let status = SecItemDelete(query as CFDictionary)\n guard status == errSecSuccess || status == errSecItemNotFound else {\n throw KeychainError.unableToDelete(status: status)\n }\n }\n\n // MARK: - 是否存在\n\n static var hasKey: Bool {\n load() != nil\n }\n}\n\nenum KeychainError: LocalizedError {\n case unableToSave(status: OSStatus)\n case unableToDelete(status: OSStatus)\n\n var errorDescription: String? {\n switch self {\n case .unableToSave(let s): return \"保存 API Key 失败 (OSStatus: \\(s))\"\n case .unableToDelete(let s): return \"删除 API Key 失败 (OSStatus: \\(s))\"\n }\n }\n}\n"}}}}