Tusker/Tusker/API/MastodonController+Push.swift

79 lines
3.0 KiB
Swift

//
// MastodonController+Push.swift
// Tusker
//
// Created by Shadowfacts on 4/9/24.
// Copyright © 2024 Shadowfacts. All rights reserved.
//
import Foundation
import Pachyderm
import PushNotifications
import CryptoKit
extension MastodonController {
func createPushSubscription(subscription: PushNotifications.PushSubscription) async throws -> Pachyderm.PushSubscription {
let req = Pachyderm.PushSubscription.create(
endpoint: subscription.endpoint,
// mastodon docs just say "Base64 encoded string of a public key from a ECDH keypair using the prime256v1 curve."
// other apps use SecKeyCopyExternalRepresentation which is documented to use X9.63 for elliptic curve keys
// and that seems to work
publicKey: subscription.secretKey.publicKey.x963Representation,
authSecret: subscription.authSecret,
alerts: .init(subscription.alerts),
policy: .init(subscription.policy)
)
return try await run(req).0
}
func updatePushSubscription(subscription: PushNotifications.PushSubscription) async throws -> Pachyderm.PushSubscription {
// when updating anything other than the alerts/policy, we need to go through the create route
return try await createPushSubscription(subscription: subscription)
}
func updatePushSubscription(alerts: PushNotifications.PushSubscription.Alerts, policy: PushNotifications.PushSubscription.Policy) async throws -> Pachyderm.PushSubscription {
let req = Pachyderm.PushSubscription.update(alerts: .init(alerts), policy: .init(policy))
var result = try await run(req).0
if instanceFeatures.pushNotificationPolicyMissingFromResponse {
// see https://github.com/mastodon/mastodon/issues/23145
// so just assume if the request was successful that it worked
result.policy = .init(policy)
}
return result
}
func deletePushSubscription() async throws {
let req = Pachyderm.PushSubscription.delete()
_ = try await run(req)
}
}
private extension Pachyderm.PushSubscription.Alerts {
init(_ alerts: PushNotifications.PushSubscription.Alerts) {
self.init(
mention: alerts.contains(.mention),
status: alerts.contains(.status),
reblog: alerts.contains(.reblog),
follow: alerts.contains(.follow),
followRequest: alerts.contains(.followRequest),
favourite: alerts.contains(.favorite),
poll: alerts.contains(.poll),
update: alerts.contains(.update),
emojiReaction: alerts.contains(.emojiReaction)
)
}
}
private extension Pachyderm.PushSubscription.Policy {
init(_ policy: PushNotifications.PushSubscription.Policy) {
switch policy {
case .all:
self = .all
case .followers:
self = .followers
case .followed:
self = .followed
}
}
}