Skip to content

Commit

Permalink
Add initial send api functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Koray Koska committed May 26, 2017
1 parent 69a1aa1 commit 173447c
Show file tree
Hide file tree
Showing 21 changed files with 1,014 additions and 0 deletions.
130 changes: 130 additions & 0 deletions Sources/VaporFacebookBot/Send/FacebookSend.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//
// FacebookSend.swift
// VaporFacebookBot
//
// Created by Koray Koska on 25/05/2017.
//
//

import Foundation
import Vapor

public final class FacebookSend: JSONConvertible {

public var recipient: FacebookSendRecipient
public var message: FacebookSendMessage?
public var senderAction: FacebookSenderAction?
public var notificationType: FacebookSendNotificationType?

public init(recipient: FacebookSendRecipient, message: FacebookSendMessage, notificationType: FacebookSendNotificationType? = nil) {
self.recipient = recipient
self.message = message
self.notificationType = notificationType
}

public init(recipient: FacebookSendRecipient, senderAction: FacebookSenderAction, notificationType: FacebookSendNotificationType? = nil) {
self.recipient = recipient
self.senderAction = senderAction
self.notificationType = notificationType
}

public convenience init(json: JSON) throws {
let recipient = try FacebookSendRecipient(json: json.get("recipient"))
var notificationType: FacebookSendNotificationType? = nil
if let notificationTypeString = json["notification_type"]?.string {
notificationType = FacebookSendNotificationType(rawValue: notificationTypeString)
}

if let m = json["message"] {
let message = try FacebookSendMessage(json: m)
self.init(recipient: recipient, message: message, notificationType: notificationType)
} else if let s = json["sender_action"]?.string, let senderAction = FacebookSenderAction(rawValue: s) {
self.init(recipient: recipient, senderAction: senderAction, notificationType: notificationType)
} else {
throw Abort(.badRequest, metadata: "Either message or a valid sender_action (FacebookSenderAction) must be set for FacebookSend")
}
}

public func makeJSON() throws -> JSON {
var json = JSON()

try json.set("recipient", recipient)

if let message = message {
try json.set("message", message)
} else if let senderAction = senderAction {
try json.set("sender_action", senderAction)
}

if let notificationType = notificationType {
try json.set("notification_type", notificationType)
}

return json
}
}

public final class FacebookSendRecipient: JSONConvertible {

public var id: String?
public var phoneNumber: String?
public var name: (firstName: String, lastName: String)?

public init(id: String) {
self.id = id
}

public init(phoneNumber: String, name: (firstName: String, lastName: String)? = nil) {
self.phoneNumber = phoneNumber
self.name = name
}

public convenience init(json: JSON) throws {
if let id = json["id"]?.string {
self.init(id: id)
} else if let phoneNumber = json["phone_number"]?.string {
if let firstName = json["name"]?["first_name"]?.string, let lastName = json["name"]?["last_name"]?.string {
let name = (firstName: firstName, lastName: lastName)
self.init(phoneNumber: phoneNumber, name: name)
} else {
self.init(phoneNumber: phoneNumber)
}
} else {
throw Abort(.badRequest, metadata: "FacebookSendObjectRecipient must contain either id or phone_number!")
}
}

public func makeJSON() throws -> JSON {
var json = JSON()

if let id = id {
try json.set("id", id)
} else if let phoneNumber = phoneNumber {
try json.set("phone_number", phoneNumber)

if let name = name {
var nameJson = JSON()
try nameJson.set("first_name", name.firstName)
try nameJson.set("last_name", name.lastName)

try json.set("name", nameJson)
}
}

return json
}
}

public enum FacebookSenderAction: String {

case typingOn = "typing_on"
case typingOff = "typing_off"
case markSeen = "mark_seen"
}

public enum FacebookSendNotificationType: String {

case regular = "REGULAR"
case silentPush = "SILENT_PUSH"
case noPush = "NO_PUSH"
}
67 changes: 67 additions & 0 deletions Sources/VaporFacebookBot/Send/FacebookSendApi.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// FacebookSendApi.swift
// VaporFacebookBot
//
// Created by Koray Koska on 25/05/2017.
//
//

import Foundation
import Vapor
import HTTP

public final class FacebookSendApi {

static let shared = FacebookSendApi()

public var registeredPayloadTypes: [FacebookSendAttachmentType: FacebookSendAttachmentPayload.Type] = [
FacebookSendAttachmentImage.attachmentType: FacebookSendAttachmentImage.self,
FacebookSendAttachmentAudio.attachmentType: FacebookSendAttachmentAudio.self,
FacebookSendAttachmentVideo.attachmentType: FacebookSendAttachmentVideo.self,
FacebookSendAttachmentFile.attachmentType: FacebookSendAttachmentFile.self,
FacebookSendAttachmentTemplateHolder.attachmentType: FacebookSendAttachmentTemplateHolder.self
]

public var registeredTemplateTypes: [FacebookSendAttachmentTemplateType: FacebookSendAttachmentTemplate.Type] = [
FacebookSendAttachmentGenericTemplate.templateType: FacebookSendAttachmentGenericTemplate.self,
FacebookSendAttachmentButtonTemplate.templateType: FacebookSendAttachmentButtonTemplate.self
]

public var registeredButtonTypes: [FacebookSendButtonType: FacebookSendButton.Type] = [
FacebookSendURLButton.type: FacebookSendURLButton.self,
FacebookSendPostbackButton.type: FacebookSendPostbackButton.self,
FacebookSendCallButton.type: FacebookSendCallButton.self,
FacebookSendShareButton.type: FacebookSendShareButton.self
]

public func sendMessageUrl(token: String) -> String {
return "https://graph.facebook.com/v2.6/me/messages?access_token=\(token)"
}

public var defaultHeaders: [HeaderKey: String] {
return [HeaderKey.contentType: "application/json"]
}

private init() {
}

public func send(droplet: Droplet, facebookSend: FacebookSend, token: String) throws -> Response {
let url = sendMessageUrl(token: token)

let req = Request(method: .post, uri: url, headers: defaultHeaders)
req.json = try facebookSend.makeJSON()

return try droplet.client.respond(to: req)
}

public func sendAsync(droplet: Droplet, facebookSend: FacebookSend, token: String, completion: ((_ response: Response?, _ error: Error?) -> Void)? = nil) {
background {
do {
let response = try self.send(droplet: droplet, facebookSend: facebookSend, token: token)
completion?(response, nil)
} catch {
completion?(nil, error)
}
}
}
}
46 changes: 46 additions & 0 deletions Sources/VaporFacebookBot/Send/FacebookSendAttachment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// FacebookSendAttachment.swift
// VaporFacebookBot
//
// Created by Koray Koska on 26/05/2017.
//
//

import Foundation
import Vapor

public final class FacebookSendAttachment: JSONConvertible {

public var payload: FacebookSendAttachmentPayload

public init(payload: FacebookSendAttachmentPayload) {
self.payload = payload
}

public convenience init(json: JSON) throws {
guard let type = try FacebookSendAttachmentType(rawValue: json.get("type")), let payloadType = FacebookSendApi.shared.registeredPayloadTypes[type] else {
throw Abort(.badRequest, metadata: "type must be a valid FacebookSendAttachmentType for FacebookSendAttachment")
}
let payloadJson: JSON = try json.get("payload")

self.init(payload: try payloadType.init(json: payloadJson))
}

public func makeJSON() throws -> JSON {
var json = JSON()

try json.set("type", type(of: payload).attachmentType.rawValue)
try json.set("payload", try payload.makeJSON())

return json
}
}

public enum FacebookSendAttachmentType: String {

case image = "image"
case audio = "audio"
case video = "video"
case file = "file"
case template = "template"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// FacebookSendAttachmentButtonTemplate.swift
// VaporFacebookBot
//
// Created by Koray Koska on 26/05/2017.
//
//

import Foundation
import Vapor

public final class FacebookSendAttachmentButtonTemplate: FacebookSendAttachmentTemplate {

public static var templateType: FacebookSendAttachmentTemplateType {
return .button
}

public var sharable: Bool?
public var text: String
public var buttons: [FacebookSendButton]

public init(sharable: Bool? = nil, text: String, buttons: [FacebookSendButton]) {
self.sharable = sharable
self.text = text
self.buttons = buttons
}

public convenience init(json: JSON) throws {
let sharable = json["sharable"]?.bool
let text: String = try json.get("text")

var buttons: [FacebookSendButton] = [FacebookSendButton]()
if let buttonsArray = json["buttons"]?.array {
for b in buttonsArray {
try buttons.append(FacebookSendButtonHolder(json: b).button)
}
} else {
throw Abort(.badRequest, metadata: "buttons must be an array of FacebookSendButtons in FacebookSendAttachmentButtonTemplate")
}

self.init(sharable: sharable, text: text, buttons: buttons)
}

public func makeJSON() throws -> JSON {
var json = JSON()

try json.set("template_type", type(of: self).templateType.rawValue)

try json.set("text", text)

if let sharable = sharable {
try json.set("sharable", sharable)
}

var buttonsJArr = [JSON]()
for b in buttons {
try buttonsJArr.append(b.makeJSON())
}
try json.set("buttons", buttonsJArr)

return json
}
}
Loading

0 comments on commit 173447c

Please sign in to comment.