Extract APNS code to own type

This commit is contained in:
Christoph Hagen 2022-09-05 18:16:10 +02:00
parent f2f802a24f
commit 34edc88611
2 changed files with 89 additions and 79 deletions

View File

@ -0,0 +1,85 @@
import Foundation
import APNSwift
import NIO
import Crypto
struct APNSInterface {
private struct Payload: Codable {}
private var apnsConfiguration: APNSClientConfiguration!
private var apnsNotification: APNSAlertNotification<Payload>!
private let apnsEventGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
private let apnsRequestEncoder = JSONEncoder()
private let apnsResponseDecoder = JSONDecoder()
init?(_ config: ServerConfiguration) {
guard let key = load(keyAtPath: config.privateKeyFilePath) else {
return nil
}
let authentication = APNSClientConfiguration.AuthenticationMethod.jwt(
privateKey: key,
keyIdentifier: config.keyIdentifier,
teamIdentifier: config.teamIdentifier)
apnsConfiguration = APNSClientConfiguration(
authenticationMethod: authentication,
environment: .sandbox)
let alert = APNSAlertNotificationContent(
title: .raw(config.messageTitle),
body: .raw(config.messageBody))
apnsNotification = APNSAlertNotification(
alert: alert,
expiration: .none,
priority: .immediately,
topic: config.topic,
payload: Payload(),
sound: .default)
}
func sendPush(to tokens: Set<String>) async {
let client = APNSClient(
configuration: apnsConfiguration,
eventLoopGroupProvider: .shared(apnsEventGroup),
responseDecoder: apnsResponseDecoder,
requestEncoder: apnsRequestEncoder)
log(info: "Client created")
do {
for token in tokenStorage.tokens {
log(info: "Sending push to \(token.prefix(6))...")
try await client.sendAlertNotification(
apnsNotification,
deviceToken: token,
deadline: .now() + .seconds(10))
log(info: "Sent push to \(token.prefix(6))...")
}
} catch let error as APNSError {
print(error)
} catch {
log(error: error.localizedDescription)
}
do {
log("Closing client")
try client.syncShutdown()
} catch {
log(error: error.localizedDescription)
}
}
}
private func load(keyAtPath path: String) -> P256.Signing.PrivateKey? {
do {
guard let key = try P256.Signing.PrivateKey.loadFrom(filePath: path) else {
print("Failed to read key \(path)")
return nil
}
return key
} catch {
print("Failed to load key \(error)")
return nil
}
}

View File

@ -1,17 +1,7 @@
import Vapor
import SwiftyGPIO
import APNSwift
import NIO
import Crypto
private struct Payload: Codable {}
private var apnsConfiguration: APNSClientConfiguration!
private var apnsNotification: APNSAlertNotification<Payload>!
private let apnsEventGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
private let apnsRequestEncoder = JSONEncoder()
private let apnsResponseDecoder = JSONDecoder()
var apns: APNSInterface?
var tokenStorage: TokenStorage!
// configures your application
@ -33,7 +23,8 @@ public func configure(_ app: Application) throws {
app.http.server.configuration.port = config.port
guard configureAPNS(config) else {
apns = .init(config)
guard apns != nil else {
serverStatus = .failedToStart
return
}
@ -53,47 +44,6 @@ private extension JSONDecoder {
}
}
private func load(keyAtPath path: String) -> P256.Signing.PrivateKey? {
do {
guard let key = try P256.Signing.PrivateKey.loadFrom(filePath: path) else {
print("Failed to read key \(path)")
return nil
}
return key
} catch {
print("Failed to load key \(error)")
return nil
}
}
private func configureAPNS(_ config: ServerConfiguration) -> Bool {
guard let key = load(keyAtPath: config.privateKeyFilePath) else {
return false
}
let authentication = APNSClientConfiguration.AuthenticationMethod.jwt(
privateKey: key,
keyIdentifier: config.keyIdentifier,
teamIdentifier: config.teamIdentifier)
apnsConfiguration = APNSClientConfiguration(
authenticationMethod: authentication,
environment: .sandbox)
let alert = APNSAlertNotificationContent(
title: .raw(config.messageTitle),
body: .raw(config.messageBody))
apnsNotification = APNSAlertNotification(
alert: alert,
expiration: .none,
priority: .immediately,
topic: config.topic,
payload: Payload(),
sound: .default)
return true
}
private func configureGPIO(_ config: ServerConfiguration) {
let gpio = RaspberryGPIO(
name: "GPIO\(config.buttonPin)",
@ -116,31 +66,6 @@ private func sendPush() {
return
}
Task(priority: .userInitiated) {
let client = APNSClient(
configuration: apnsConfiguration,
eventLoopGroupProvider: .shared(apnsEventGroup),
responseDecoder: apnsResponseDecoder,
requestEncoder: apnsRequestEncoder)
log(info: "Client created")
do {
for token in tokenStorage.tokens {
log(info: "Sending push to \(token.prefix(6))...")
try await client.sendAlertNotification(
apnsNotification,
deviceToken: token,
deadline: .now() + .seconds(10))
log(info: "Sent push to \(token.prefix(6))...")
}
} catch let error as APNSError {
print(error)
} catch {
log(error: error.localizedDescription)
}
do {
log("Closing client")
try client.syncShutdown()
} catch {
log(error: error.localizedDescription)
}
await apns?.sendPush(to: tokenStorage.tokens)
}
}