113 lines
4.6 KiB
Swift
113 lines
4.6 KiB
Swift
import Foundation
|
|
import Intents
|
|
import PromiseKit
|
|
import UIKit
|
|
|
|
class FireEventIntentHandler: NSObject, FireEventIntentHandling {
|
|
typealias Intent = FireEventIntent
|
|
|
|
func resolveServer(for intent: Intent, with completion: @escaping (IntentServerResolutionResult) -> Void) {
|
|
if let server = Current.servers.server(for: intent) {
|
|
completion(.success(with: .init(server: server)))
|
|
} else {
|
|
completion(.needsValue())
|
|
}
|
|
}
|
|
|
|
func provideServerOptions(for intent: Intent, with completion: @escaping ([IntentServer]?, Error?) -> Void) {
|
|
completion(IntentServer.all, nil)
|
|
}
|
|
|
|
func provideServerOptionsCollection(
|
|
for intent: Intent,
|
|
with completion: @escaping (INObjectCollection<IntentServer>?, Error?) -> Void
|
|
) {
|
|
completion(.init(items: IntentServer.all), nil)
|
|
}
|
|
|
|
func resolveEventName(for intent: Intent, with completion: @escaping (INStringResolutionResult) -> Void) {
|
|
if let eventName = intent.eventName, eventName.isEmpty == false {
|
|
Current.Log.info("using provided \(eventName)")
|
|
completion(.success(with: eventName))
|
|
} else {
|
|
Current.Log.info("requesting a value")
|
|
completion(.needsValue())
|
|
}
|
|
}
|
|
|
|
func resolveEventData(for intent: Intent, with completion: @escaping (INStringResolutionResult) -> Void) {
|
|
if let eventData = intent.eventData, eventData.isEmpty == false {
|
|
Current.Log.info("using provided data \(eventData)")
|
|
completion(.success(with: eventData))
|
|
} else {
|
|
Current.Log.info("using empty dictionary")
|
|
completion(.notRequired())
|
|
}
|
|
}
|
|
|
|
func handle(intent: Intent, completion: @escaping (FireEventIntentResponse) -> Void) {
|
|
guard let server = Current.servers.server(for: intent) else {
|
|
completion(.failure(error: "No server provided", eventName: intent.eventName!))
|
|
return
|
|
}
|
|
|
|
Current.Log.verbose("Handling fire event shortcut \(intent)")
|
|
|
|
var eventDataDict: [String: Any] = [:]
|
|
|
|
if let storedData = intent.eventData, storedData.isEmpty == false, let data = storedData.data(using: .utf8) {
|
|
do {
|
|
if let jsonArray = try JSONSerialization.jsonObject(
|
|
with: data,
|
|
options: .allowFragments
|
|
) as? [String: Any] {
|
|
var isGenericPayload = true
|
|
|
|
if let eventName = jsonArray["eventName"] as? String {
|
|
intent.eventName = eventName
|
|
isGenericPayload = false
|
|
}
|
|
|
|
if let innerEventData = jsonArray["eventData"] as? [String: Any] {
|
|
eventDataDict = innerEventData
|
|
isGenericPayload = false
|
|
}
|
|
|
|
if isGenericPayload {
|
|
Current.Log.verbose("No known keys found, assuming generic payload")
|
|
eventDataDict = jsonArray
|
|
}
|
|
} else {
|
|
Current.Log.error("Unable to parse event data to JSON during shortcut: \(storedData)")
|
|
let resp = FireEventIntentResponse(code: .failure, userActivity: nil)
|
|
resp.error = "Unable to parse event data to JSON during shortcut"
|
|
completion(resp)
|
|
return
|
|
}
|
|
} catch let error as NSError {
|
|
Current.Log.error("Error when parsing event data to JSON during FireEvent: \(error)")
|
|
let resp = FireEventIntentResponse(code: .failure, userActivity: nil)
|
|
resp.error = "Service data not dictionary or JSON"
|
|
completion(resp)
|
|
return
|
|
}
|
|
}
|
|
|
|
firstly {
|
|
Current.api(for: server)?
|
|
.CreateEvent(eventType: intent.eventName!, eventData: eventDataDict) ??
|
|
.init(error: HomeAssistantAPI.APIError.noAPIAvailable)
|
|
}.done { _ in
|
|
Current.Log.verbose("Successfully fired event during shortcut")
|
|
let resp = FireEventIntentResponse(code: .success, userActivity: nil)
|
|
resp.eventName = intent.eventName
|
|
completion(resp)
|
|
}.catch { error in
|
|
Current.Log.error("Error when firing event in shortcut \(error)")
|
|
let resp = FireEventIntentResponse(code: .failure, userActivity: nil)
|
|
resp.error = "Error when firing event in shortcut: \(error.localizedDescription)"
|
|
completion(resp)
|
|
}
|
|
}
|
|
}
|