From 50623fba4944092fb9d2f55e33a9f409eb40666d Mon Sep 17 00:00:00 2001 From: FranzBusch Date: Tue, 28 Jun 2022 15:09:22 +0200 Subject: [PATCH] Add semantic safe API for location notifications # Motivation We want to provide new APIs that are semantically safe when sending location notifications to APNs. # Modification The PR adds new types for the location notification and a convenience method to send it notifications with the APNSClient. # Result We can now send location notifications. --- .../Location/APNSClient+Location.swift | 50 +++++++++++++ .../Location/APNSLocationNotification.swift | 74 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 Sources/APNSwift/Location/APNSClient+Location.swift create mode 100644 Sources/APNSwift/Location/APNSLocationNotification.swift diff --git a/Sources/APNSwift/Location/APNSClient+Location.swift b/Sources/APNSwift/Location/APNSClient+Location.swift new file mode 100644 index 00000000..a28c1f98 --- /dev/null +++ b/Sources/APNSwift/Location/APNSClient+Location.swift @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the APNSwift open source project +// +// Copyright (c) 2022 the APNSwift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of APNSwift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import NIOCore +import Logging + +extension APNSClient { + /// Sends a location request notification to APNs. + /// + /// - Parameters: + /// - notification: The notification to send. + /// + /// - deviceToken: The hexadecimal bytes that identify the user’s device. Your app receives the bytes for this device token + /// when registering for remote notifications. + /// + /// - deadline: Point in time by which sending the notification to APNs must complete. + /// + /// - logger: The logger to use for sending this notification. + @discardableResult + @inlinable + func sendLocationNotification( + _ notification: APNSLocationNotification, + deviceToken: String, + deadline: NIODeadline, + logger: Logger = _noOpLogger + ) async throws -> APNSResponse { + try await self.send( + // This is just to make the compiler work + payload: Int?.none, + deviceToken: deviceToken, + pushType: .location, + expiration: .none, // TODO: Figure out if expiration has any impact here + priority: notification.priority, + topic: notification.topic, + deadline: deadline, + logger: logger + ) + } +} diff --git a/Sources/APNSwift/Location/APNSLocationNotification.swift b/Sources/APNSwift/Location/APNSLocationNotification.swift new file mode 100644 index 00000000..7891a70a --- /dev/null +++ b/Sources/APNSwift/Location/APNSLocationNotification.swift @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the APNSwift open source project +// +// Copyright (c) 2022 the APNSwift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of APNSwift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import struct Foundation.UUID + +/// A location notification. +public struct APNSLocationNotification { + /// A canonical UUID that identifies the notification. If there is an error sending the notification, + /// APNs uses this value to identify the notification to your server. The canonical form is 32 lowercase hexadecimal digits, + /// displayed in five groups separated by hyphens in the form 8-4-4-4-12. An example UUID is as follows: + /// `123e4567-e89b-12d3-a456-42665544000`. + /// + /// If you omit this, a new UUID is created by APNs and returned in the response. + public var apnsID: UUID? + + /// The topic for the notification. In general, the topic is your app’s bundle ID/app ID suffixed with `.location-query`. + public var topic: String + + /// The priority of the notification. + public var priority: APNSPriority + + /// Initializes a new ``APNSLocationNotification``. + /// + /// - Important: Your dynamic payload will get encoded to the root of the JSON payload that is send to APNs. + /// It is **important** that you do not encode anything with the key `aps` + /// + /// - Parameters: + /// - priority: The priority of the notification. + /// - appID: Your app’s bundle ID/app ID. This will be suffixed with `.location-query`. + /// - apnsID: A canonical UUID that identifies the notification. + @inlinable + public init( + priority: APNSPriority, + appID: String, + apnsID: UUID? = nil + ) { + self.init( + priority: priority, + topic: appID + ".location-query", + apnsID: apnsID + ) + } + + /// Initializes a new ``APNSLocationNotification``. + /// + /// - Important: Your dynamic payload will get encoded to the root of the JSON payload that is send to APNs. + /// It is **important** that you do not encode anything with the key `aps` + /// + /// - Parameters: + /// - priority: The priority of the notification. + /// - topic: The topic for the notification. In general, the topic is your app’s bundle ID/app ID suffixed with `.location-query`. + /// - apnsID: A canonical UUID that identifies the notification. + @inlinable + public init( + priority: APNSPriority, + topic: String, + apnsID: UUID? = nil + ) { + self.priority = priority + self.topic = topic + self.apnsID = apnsID + } +}