diff --git a/Sources/APNS/Message.swift b/Sources/APNS/Message.swift index 3b5a3f9..269efc6 100644 --- a/Sources/APNS/Message.swift +++ b/Sources/APNS/Message.swift @@ -56,6 +56,7 @@ public struct Message { /// Use the development or production servers public let development: Bool + public init(priority: Priority = .immediately, profile: Profile, deviceToken: String, payload: Payload, on container: Container, development: Bool = false) throws { self.profile = profile self.priority = priority @@ -65,14 +66,14 @@ public struct Message { } internal func generateRequest(on container: Container) throws -> Request { - let request = Request(using: container) request.http.method = .POST + + request.http.headers.add(name: .connection, value: "Keep-Alive") request.http.headers.add(name: HTTPHeaderName("authorization"), value: "bearer \(self.profile.token ?? "")") request.http.headers.add(name: HTTPHeaderName("apns-id"), value: self.messageId) request.http.headers.add(name: HTTPHeaderName("apns-priority"), value: "\(self.priority.rawValue)") request.http.headers.add(name: HTTPHeaderName("apns-topic"), value: self.profile.topic) - request.http.headers.add(name: .connection, value: "Keep-Alive") if let expiration = self.expirationDate { request.http.headers.add(name: HTTPHeaderName("apns-expiration"), value: String(expiration.timeIntervalSince1970.rounded())) @@ -87,10 +88,8 @@ public struct Message { try self.profile.generateToken() } - guard let payloadBody = self.payload.body else { - throw MessageError.unableToGenerateBody - } - request.http.body = HTTPBody(string: payloadBody) + let encoder = JSONEncoder() + request.http.body = try encoder.encodeBody(from: PayloadContent(payload: self.payload)) if self.development { guard let url = URL(string: "https://api.development.push.apple.com/3/device/\(self.deviceToken)") else { diff --git a/Sources/APNS/Payload.swift b/Sources/APNS/Payload.swift index e7c224b..28f7f28 100644 --- a/Sources/APNS/Payload.swift +++ b/Sources/APNS/Payload.swift @@ -6,8 +6,9 @@ // import Foundation +import Vapor -public class Payload: Codable { +public class Payload: Content { /// The number to display as the badge of the app icon. public var badge: Int? @@ -72,7 +73,7 @@ public class Payload: Codable { public var threadId: String? /// Any extra key-value pairs to add to the JSON - public var extra: [String: String] = [:] + public var extra: [String : String] = [:] /// Empty Initializer public init() { } diff --git a/Sources/APNS/PayloadContent.swift b/Sources/APNS/PayloadContent.swift new file mode 100644 index 0000000..aa60277 --- /dev/null +++ b/Sources/APNS/PayloadContent.swift @@ -0,0 +1,75 @@ +// +// PayloadContent.swift +// APNS +// +// Created by Anthony Castelli on 4/6/18. +// + +import Foundation +import Vapor + +struct Alert: Content { + enum CodingKeys: String, CodingKey { + case title = "title" + case subtitle = "subtitle" + case body = "body" + + case titleLocKey = "title-loc-key" + case titleLocArgs = "title-loc-args" + + case actionLocKey = "action-loc-key" + + case bodyLocKey = "body-loc-key" + case bodyLocArgs = "body-loc-args" + + case launchImage = "launch-image" + } + var title: String? + var subtitle: String? + var body: String? + var titleLocKey: String? + var titleLocArgs: [String]? + var actionLocKey: String? + var bodyLocKey: String? + var bodyLocArgs: [String]? + var launchImage: String? +} + +struct APS: Content { + var alert: Alert + var badge: Int? + var sound: String? + var category: String? + var contentAvailable: Bool = false + var hasMutableContent: Bool = false +} + +struct PayloadContent: Content { + var aps: APS + var threadId: String? + var extra: [String : String] = [:] + + init(payload: Payload) { + let alert = Alert( + title: payload.title, + subtitle: payload.subtitle, + body: payload.body, + titleLocKey: payload.titleLocKey, + titleLocArgs: payload.titleLocArgs, + actionLocKey: payload.actionLocKey, + bodyLocKey: payload.bodyLocKey, + bodyLocArgs: payload.bodyLocArgs, + launchImage: payload.launchImage + ) + self.aps = APS( + alert: alert, + badge: payload.badge, + sound: payload.sound, + category: payload.category, + contentAvailable: payload.contentAvailable, + hasMutableContent: payload.hasMutableContent + ) + self.threadId = payload.threadId + self.extra = payload.extra + } +}