@ -5,7 +5,7 @@ import CoreLocation
import MessageUI
import MessageUI
import location_service
import location_service
import user_portrait // 添 加 这 行
import user_portrait // 添 加 这 行
import Contacts
import MediaPlayer
import MediaPlayer
import AVFoundation
import AVFoundation
import UserNotifications
import UserNotifications
@ -74,6 +74,9 @@ public class SystemFunctionHandler: NSObject {
// 注 册 发 送 短 信 函 数
// 注 册 发 送 短 信 函 数
registerSendTextMessageFunction ( client : client )
registerSendTextMessageFunction ( client : client )
// 注 册 查 询 通 讯 录 函 数
registerGetContactsFunction ( client : client )
// 注 册 拨 打 电 话 函 数
// 注 册 拨 打 电 话 函 数
registerMakePhoneCallFunction ( client : client )
registerMakePhoneCallFunction ( client : client )
@ -181,23 +184,40 @@ public class SystemFunctionHandler: NSObject {
)
)
}
}
// / 注 册 查 询 通 讯 录 函 数
private func registerGetContactsFunction ( client : MCPClient ) {
let parameters : [ String : Any ] = [
" type " : " object " ,
" properties " : [ : ] ,
" required " : [ ]
]
let handler = GetContactsHandler ( )
_ = client . registerLocalFunction (
name : " get_contacts " ,
description : " 获取通讯录中的所有联系人 " ,
parameters : parameters ,
handler : handler
)
}
// / 注 册 拨 打 电 话 函 数
// / 注 册 拨 打 电 话 函 数
private func registerMakePhoneCallFunction ( client : MCPClient ) {
private func registerMakePhoneCallFunction ( client : MCPClient ) {
let parameters : [ String : Any ] = [
let parameters : [ String : Any ] = [
" type " : " object " ,
" type " : " object " ,
" properties " : [
" properties " : [
" contact " : [
" phone_number " : [
" type " : " string " ,
" type " : " string " ,
" description " : " 联系人姓名或电话号码 "
" description " : " 要拨打的 电话号码"
]
]
] ,
] ,
" required " : [ " contact " ]
" required " : [ " phone_number " ]
]
]
let handler = MakePhoneCallHandler ( )
let handler = MakePhoneCallHandler ( )
_ = client . registerLocalFunction (
_ = client . registerLocalFunction (
name : " make_phone_call " ,
name : " make_phone_call " ,
description : " 拨打电话 " ,
description : " 拨打指定 电话号码 " ,
parameters : parameters ,
parameters : parameters ,
handler : handler
handler : handler
)
)
@ -661,16 +681,22 @@ private class SendTextMessageHandler: NSObject, FunctionHandler, MFMessageCompos
// / 拨 打 电 话 处 理 器
// / 拨 打 电 话 处 理 器
private class MakePhoneCallHandler : FunctionHandler {
private class MakePhoneCallHandler : FunctionHandler {
func handle ( arguments : [ String : Any ] ) async throws -> String {
func handle ( arguments : [ String : Any ] ) async throws -> String {
guard let contact = arguments [ " contact " ] as ? String else {
guard let phoneNumber = arguments [ " phone_number " ] as ? String else {
throw ChatApiException ( " 缺少联系人 参数 " )
throw ChatApiException ( " 缺少电话号码 参数 " )
}
}
let result = await makePhoneCall ( contact : contact )
let result = await makePhoneCall ( phoneNumber : phoneNumber )
return " { \" result \" : \" \( result . message ) \" } "
return " { \" result \" : \" \( result . message ) \" } "
}
}
private func makePhoneCall ( contact : String ) async -> Result {
private func makePhoneCall ( phoneNumber : String ) async -> Result {
guard let url = URL ( string : " tel: \( contact ) " ) else {
// 清 理 电 话 号 码 , 移 除 空 格 和 特 殊 字 符
let cleanedNumber = phoneNumber . replacingOccurrences ( of : " " , with : " " )
. replacingOccurrences ( of : " - " , with : " " )
. replacingOccurrences ( of : " ( " , with : " " )
. replacingOccurrences ( of : " ) " , with : " " )
guard let url = URL ( string : " tel: \( cleanedNumber ) " ) else {
return Result ( success : false , message : " 无法创建电话URL " )
return Result ( success : false , message : " 无法创建电话URL " )
}
}
@ -904,6 +930,111 @@ private class OpenRecorderHandler: FunctionHandler {
// }
// }
// / 查 询 通 讯 录 处 理 器
private class GetContactsHandler : FunctionHandler {
func handle ( arguments : [ String : Any ] ) async throws -> String {
let result = await getContacts ( )
return result
}
private func getContacts ( ) async -> String {
let store = CNContactStore ( )
// 请 求 通 讯 录 权 限
let authorizationStatus = CNContactStore . authorizationStatus ( for : . contacts )
switch authorizationStatus {
case . authorized :
return await fetchContacts ( store : store )
case . notDetermined :
// 请 求 权 限
do {
let granted = try await store . requestAccess ( for : . contacts )
if granted {
return await fetchContacts ( store : store )
} else {
return createErrorResponse ( message : " 用户拒绝了通讯录访问权限 " )
}
} catch {
return createErrorResponse ( message : " 请求通讯录权限时发生错误: \( error . localizedDescription ) " )
}
case . denied , . restricted :
return createErrorResponse ( message : " 无法访问通讯录,请在设置中开启通讯录权限 " )
@ unknown default :
return createErrorResponse ( message : " 未知的权限状态 " )
}
}
private func fetchContacts ( store : CNContactStore ) async -> String {
let keysToFetch = [
CNContactGivenNameKey ,
CNContactFamilyNameKey ,
CNContactPhoneNumbersKey
] as [ CNKeyDescriptor ]
let request = CNContactFetchRequest ( keysToFetch : keysToFetch )
var contacts : [ [ String : Any ] ] = [ ]
do {
try store . enumerateContacts ( with : request ) { contact , _ in
let fullName = " \( contact . givenName ) \( contact . familyName ) " . trimmingCharacters ( in : . whitespaces )
for phoneNumber in contact . phoneNumbers {
let number = phoneNumber . value . stringValue
let label = phoneNumber . label ? ? " 未知 "
let contactInfo : [ String : Any ] = [
" name " : fullName . isEmpty ? " 未知联系人 " : fullName ,
" phone_number " : number ,
" label " : CNLabeledValue < NSString > . localizedString ( forLabel : label )
]
contacts . append ( contactInfo )
}
}
return createSuccessResponse ( contacts : contacts )
} catch {
return createErrorResponse ( message : " 获取通讯录失败: \( error . localizedDescription ) " )
}
}
private func createSuccessResponse ( contacts : [ [ String : Any ] ] ) -> String {
let response : [ String : Any ] = [
" success " : true ,
" message " : " 成功获取通讯录 " ,
" data " : [
" contacts " : contacts ,
" count " : contacts . count
]
]
do {
let jsonData = try JSONSerialization . data ( withJSONObject : response , options : . prettyPrinted )
return String ( data : jsonData , encoding : . utf8 ) ? ? " { \" success \" : false, \" message \" : \" JSON序列化失败 \" } "
} catch {
return " { \" success \" : false, \" message \" : \" JSON序列化失败: \( error . localizedDescription ) \" } "
}
}
private func createErrorResponse ( message : String ) -> String {
let response : [ String : Any ] = [
" success " : false ,
" message " : message ,
" data " : [
" contacts " : [ ] ,
" count " : 0
]
]
do {
let jsonData = try JSONSerialization . data ( withJSONObject : response , options : . prettyPrinted )
return String ( data : jsonData , encoding : . utf8 ) ? ? " { \" success \" : false, \" message \" : \" JSON序列化失败 \" } "
} catch {
return " { \" success \" : false, \" message \" : \" JSON序列化失败: \( error . localizedDescription ) \" } "
}
}
}
// / 设 置 用 户 画 像 字 段 处 理 器
// / 设 置 用 户 画 像 字 段 处 理 器
private class SetUserProfileFieldHandler : FunctionHandler {
private class SetUserProfileFieldHandler : FunctionHandler {
func handle ( arguments : [ String : Any ] ) async throws -> String {
func handle ( arguments : [ String : Any ] ) async throws -> String {