mastodon-app-ufficiale-ipho.../MastodonIntent/SendPostIntentHandler.swift

107 lines
3.9 KiB
Swift

//
// SendPostIntentHandler.swift
// MastodonIntent
//
// Created by Cirno MainasuK on 2021-7-26.
//
import Foundation
import Intents
import Combine
import CoreData
import CoreDataStack
import MastodonSDK
final class SendPostIntentHandler: NSObject, SendPostIntentHandling {
var disposeBag = Set<AnyCancellable>()
lazy var coreDataStack = CoreDataStack()
lazy var managedObjectContext = coreDataStack.persistentContainer.viewContext
func handle(intent: SendPostIntent, completion: @escaping (SendPostIntentResponse) -> Void) {
managedObjectContext.performAndWait {
let request = MastodonAuthentication.sortedFetchRequest
let authentications = (try? self.managedObjectContext.fetch(request)) ?? []
let _authentication = authentications.sorted(by: { $0.activedAt > $1.activedAt }).first
guard let authentication = _authentication else {
let failureReason = APIService.APIError.implicit(.authenticationMissing).errorDescription ?? "Fail to Send Post"
completion(SendPostIntentResponse.failure(failureReason: failureReason))
return
}
let box = MastodonAuthenticationBox(
authenticationRecord: .init(objectID: authentication.objectID),
domain: authentication.domain,
userID: authentication.userID,
appAuthorization: .init(accessToken: authentication.appAccessToken),
userAuthorization: .init(accessToken: authentication.userAccessToken)
)
let visibility: Mastodon.Entity.Status.Visibility = {
switch intent.visibility {
case .unknown: return .public
case .public: return .public
case .followersOnly: return .private
}
}()
let query = Mastodon.API.Statuses.PublishStatusQuery(
status: intent.content,
mediaIDs: nil,
pollOptions: nil,
pollExpiresIn: nil,
inReplyToID: nil,
sensitive: nil,
spoilerText: nil,
visibility: visibility
)
let idempotencyKey = UUID().uuidString
Just(Void())
.asyncMap {
try await APIService.shared.publishStatus(
domain: box.domain,
idempotencyKey: idempotencyKey,
query: query,
authenticationBox: box
)
}
.sink { _completion in
switch _completion {
case .failure(let error):
let failureReason = error.localizedDescription
completion(SendPostIntentResponse.failure(failureReason: failureReason))
case .finished:
break
}
} receiveValue: { response in
let post = Post(identifier: response.value.id, display: intent.content ?? "")
post.url = URL(string: response.value.url ?? response.value.uri)
let result = SendPostIntentResponse(code: .success, userActivity: nil)
result.post = post
completion(result)
}
.store(in: &disposeBag)
}
}
func resolveContent(for intent: SendPostIntent, with completion: @escaping (INStringResolutionResult) -> Void) {
guard let content = intent.content, !content.isEmpty else {
completion(.needsValue())
return
}
completion(.success(with: content))
}
func resolveVisibility(for intent: SendPostIntent, with completion: @escaping (PostVisibilityResolutionResult) -> Void) {
completion(.success(with: intent.visibility))
}
}