import Foundation import UIKit import CoreLocation import Contacts import EventKit /// 系统功能处理器 class SystemFunctionHandler { private let TAG = "SystemFunctionHandler" private let context: Any static let ACTION_EXIT_INTERACTION = "com.yunqiinnovation.deepsound.action.EXIT_INTERACTION" /// 初始化系统功能处理器 /// - Parameter context: 应用上下文 init(context: Any) { self.context = context } /// 注册所有系统功能 /// - Parameter client: MCP客户端 func registerAllFunctions(client: MCPClient) { // 注册退出交互函数 registerExitInteractionFunction(client) // 注册翻译模式函数 registerTranslationModeFunction(client) // 注册发送短信函数 registerSendTextMessageFunction(client) // 注册拨打电话函数 registerMakePhoneCallFunction(client) // 注册打开应用函数 registerOpenAppFunction(client) // 注册设置提醒函数 registerSetReminderFunction(client) // 注册获取当前时间函数 registerGetCurrentTimeFunction(client) // 注册获取当前位置函数 registerGetCurrentLocationFunction(client) print("\(TAG) 所有系统功能注册完成") } /// 注册退出交互函数 private func registerExitInteractionFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [:], "required": [] ] // 创建函数处理器 let handler = ExitInteractionHandler() // 注册函数 client.registerLocalFunction( name: "exit_interaction", description: "结束当前交互", parameters: parameters, handler: handler ) print("\(TAG) 已注册退出交互功能") } /// 注册翻译模式函数 private func registerTranslationModeFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [:], "required": [] ] // 创建函数处理器 let handler = TranslationModeHandler() // 注册函数 client.registerLocalFunction( name: "enter_translation_mode", description: "用户请求进入实时翻译模式时,启动实时翻译功能", parameters: parameters, handler: handler ) print("\(TAG) 已注册翻译模式功能") } /// 注册发送短信函数 private func registerSendTextMessageFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [ "contact": [ "type": "string", "description": "联系人姓名或电话号码" ], "message": [ "type": "string", "description": "短信内容" ] ], "required": ["contact", "message"] ] // 创建函数处理器 let handler = SendTextMessageHandler() // 注册函数 client.registerLocalFunction( name: "send_text_message", description: "发送短信", parameters: parameters, handler: handler ) print("\(TAG) 已注册发送短信功能") } /// 注册拨打电话函数 private func registerMakePhoneCallFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [ "contact": [ "type": "string", "description": "联系人姓名或电话号码" ] ], "required": ["contact"] ] // 创建函数处理器 let handler = MakePhoneCallHandler() // 注册函数 client.registerLocalFunction( name: "make_phone_call", description: "拨打电话", parameters: parameters, handler: handler ) print("\(TAG) 已注册拨打电话功能") } /// 注册打开应用函数 private func registerOpenAppFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [ "app_name": [ "type": "string", "description": "应用名称" ] ], "required": ["app_name"] ] // 创建函数处理器 let handler = OpenAppHandler() // 注册函数 client.registerLocalFunction( name: "open_app", description: "当用户请求打开特定应用时,启动相应应用", parameters: parameters, handler: handler ) print("\(TAG) 已注册打开应用功能") } /// 注册设置提醒函数 private func registerSetReminderFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [ "title": [ "type": "string", "description": "提醒标题" ], "content": [ "type": "string", "description": "提醒内容" ], "time": [ "type": "string", "description": "提醒时间,格式为'yyyy-MM-dd HH:mm',如'2023-12-31 14:30'" ] ], "required": ["title", "time"] ] // 创建函数处理器 let handler = SetReminderHandler() // 注册函数 client.registerLocalFunction( name: "set_reminder", description: "设置提醒事项", parameters: parameters, handler: handler ) print("\(TAG) 已注册设置提醒功能") } /// 注册获取当前时间函数 private func registerGetCurrentTimeFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [ "format": [ "type": "string", "description": "时间格式,可选,默认为标准格式" ] ], "required": [] ] // 创建函数处理器 let handler = GetCurrentTimeHandler() // 注册函数 client.registerLocalFunction( name: "get_current_time", description: "获取当前日期和时间", parameters: parameters, handler: handler ) print("\(TAG) 已注册获取当前时间功能") } /// 注册获取当前位置函数 private func registerGetCurrentLocationFunction(_ client: MCPClient) { // 定义函数参数 let parameters: [String: Any] = [ "type": "object", "properties": [:], "required": [] ] // 创建函数处理器 let handler = GetCurrentLocationHandler() // 注册函数 client.registerLocalFunction( name: "get_current_location", description: "获取当前地理位置", parameters: parameters, handler: handler ) print("\(TAG) 已注册获取当前位置功能") } } /// 退出交互处理器 class ExitInteractionHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { // 发送通知和广播 NotificationCenter.default.post( name: Notification.Name(SystemFunctionHandler.ACTION_EXIT_INTERACTION), object: nil, userInfo: ["timestamp": Date().timeIntervalSince1970] ) return "{\"result\": \"已结束当前交互\"}" } } /// 翻译模式处理器 class TranslationModeHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { // 发送通知 NotificationCenter.default.post( name: Notification.Name("com.yunqiinnovation.deepsound.ACTION_ENTER_TRANSLATION_MODE"), object: nil, userInfo: ["timestamp": Date().timeIntervalSince1970] ) return "{\"result\": \"已进入实时翻译模式\"}" } } /// 发送短信处理器 class SendTextMessageHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { guard let contact = arguments["contact"] as? String, let message = arguments["message"] as? String else { return "{\"result\": \"发送短信失败:缺少联系人或消息内容\"}" } // iOS不允许应用直接发送短信,但可以打开短信应用 if let url = URL(string: "sms:\(contact)&body=\(message.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")") { DispatchQueue.main.async { UIApplication.shared.open(url, options: [:], completionHandler: nil) } return "{\"result\": \"已打开短信应用,收件人:\(contact)\"}" } return "{\"result\": \"发送短信失败:无法打开短信应用\"}" } } /// 拨打电话处理器 class MakePhoneCallHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { guard let contact = arguments["contact"] as? String else { return "{\"result\": \"拨打电话失败:缺少联系人\"}" } let phoneNumber = contact.replacingOccurrences(of: "[^+0-9]", with: "", options: .regularExpression) if let url = URL(string: "tel://\(phoneNumber)") { DispatchQueue.main.async { UIApplication.shared.open(url, options: [:], completionHandler: nil) } return "{\"result\": \"正在拨打\(contact)的电话\"}" } return "{\"result\": \"拨打电话失败:无法拨打电话\"}" } } /// 打开应用处理器 class OpenAppHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { guard let appName = arguments["app_name"] as? String else { return "{\"result\": \"打开应用失败:缺少应用名称\"}" } // iOS没有直接打开其他应用的API,只能通过URL Scheme // 这里只是模拟返回成功,实际上无法在iOS上实现这个功能 return "{\"result\": \"打开应用功能在iOS上受限,无法直接打开\(appName)\"}" } } /// 设置提醒处理器 class SetReminderHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { guard let title = arguments["title"] as? String, let timeStr = arguments["time"] as? String else { return "{\"result\": \"设置提醒失败:缺少标题或时间\"}" } let content = arguments["content"] as? String ?? "" // 解析时间 let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd HH:mm" guard let date = dateFormatter.date(from: timeStr) else { return "{\"result\": \"设置提醒失败:时间格式无效,请使用'yyyy-MM-dd HH:mm'格式\"}" } // 使用EventKit添加提醒 let eventStore = EKEventStore() let event = EKEvent(eventStore: eventStore) event.title = title event.notes = content event.startDate = date event.endDate = date.addingTimeInterval(3600) // 1小时后 event.calendar = eventStore.defaultCalendarForNewEvents do { try eventStore.save(event, span: .thisEvent) return "{\"result\": \"已创建提醒: \(title), 时间: \(timeStr)\"}" } catch { return "{\"result\": \"设置提醒失败:\(error.localizedDescription)\"}" } } } /// 获取当前时间处理器 class GetCurrentTimeHandler: FunctionHandler { func handle(arguments: [String: Any]) async throws -> String { let format = arguments["format"] as? String let calendar = Calendar.current let date = Date() let dateFormatter = DateFormatter() dateFormatter.locale = Locale(identifier: "zh_CN") let timeStr: String switch format?.lowercased() { case "short": dateFormatter.dateFormat = "HH:mm" timeStr = dateFormatter.string(from: date) case "date": dateFormatter.dateFormat = "yyyy年MM月dd日" timeStr = dateFormatter.string(from: date) case "time": dateFormatter.dateFormat = "HH:mm:ss" timeStr = dateFormatter.string(from: date) case "full": dateFormatter.dateFormat = "yyyy年MM月dd日 EEEE HH:mm:ss" timeStr = dateFormatter.string(from: date) case "iso": dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" timeStr = dateFormatter.string(from: date) default: dateFormatter.dateFormat = "yyyy年MM月dd日 HH:mm" timeStr = dateFormatter.string(from: date) } // 获取星期几 let weekDay: String if format == "full" { weekDay = "" // 已经包含在dateFormatter里 } else { let weekDayNum = calendar.component(.weekday, from: date) switch weekDayNum { case 1: weekDay = "星期日" case 2: weekDay = "星期一" case 3: weekDay = "星期二" case 4: weekDay = "星期三" case 5: weekDay = "星期四" case 6: weekDay = "星期五" case 7: weekDay = "星期六" default: weekDay = "" } } // 格式化结果 let resultTime: String if format == "short" || format == "time" { resultTime = timeStr } else if format == "full" { resultTime = timeStr // already contains weekday } else { resultTime = "\(timeStr) \(weekDay)" } return "{\"result\": \"\(resultTime)\", \"time\": \"\(resultTime)\"}" } } /// 获取当前位置处理器 class GetCurrentLocationHandler: FunctionHandler { private let locationManager = CLLocationManager() private var locationCompletionHandler: ((String, Bool) -> Void)? func handle(arguments: [String: Any]) async throws -> String { return await withCheckedContinuation { continuation in self.getLocation { message, success in continuation.resume(returning: "{\"result\": \"\(message)\", \"success\": \(success)}") } } } private func getLocation(completion: @escaping (String, Bool) -> Void) { locationCompletionHandler = completion // 检查权限 let authStatus = CLLocationManager.authorizationStatus() if authStatus == .denied || authStatus == .restricted { completion("需要位置权限才能获取当前位置", false) return } // 检查位置服务是否开启 if !CLLocationManager.locationServicesEnabled() { completion("位置服务未启用,请打开GPS或网络定位", false) return } // 如果有最后的位置,使用它 if let lastLocation = locationManager.location { let message = "当前位置: 经度 \(lastLocation.coordinate.longitude), 纬度 \(lastLocation.coordinate.latitude)" completion(message, true) return } // 否则请求更新 locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() // 设置超时 DispatchQueue.main.asyncAfter(deadline: .now() + 10) { [weak self] in if let handler = self?.locationCompletionHandler { self?.locationManager.stopUpdatingLocation() handler("获取位置超时,请稍后重试", false) self?.locationCompletionHandler = nil } } } } // 扩展以接收位置更新 extension GetCurrentLocationHandler: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last, let handler = locationCompletionHandler else { return } manager.stopUpdatingLocation() let message = "当前位置: 经度 \(location.coordinate.longitude), 纬度 \(location.coordinate.latitude)" handler(message, true) locationCompletionHandler = nil } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { manager.stopUpdatingLocation() locationCompletionHandler?("获取位置失败: \(error.localizedDescription)", false) locationCompletionHandler = nil } }