Skip to content

Commit

Permalink
Merge pull request ZekeSnider#28 from ZekeSnider/zeke.http-server
Browse files Browse the repository at this point in the history
Add REST API
  • Loading branch information
ZekeSnider authored Dec 29, 2019
2 parents 9c299f5 + 051db5f commit 86f47da
Show file tree
Hide file tree
Showing 336 changed files with 37,603 additions and 5,807 deletions.
23 changes: 19 additions & 4 deletions Jared.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
00FC0A452FD8C8D0FCDA16D4 /* Pods_Jared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4589B5638BC576CC8AB2700A /* Pods_Jared.framework */; };
1D6188C0EEA4AA406C15CC9E /* Pods_Jared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4589B5638BC576CC8AB2700A /* Pods_Jared.framework */; };
7F0E931D1D02FC250096BABE /* Global.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0E931C1D02FC250096BABE /* Global.swift */; };
7F84B6221CC506790059A82B /* JaredFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F84B6211CC506790059A82B /* JaredFramework.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand All @@ -31,9 +32,10 @@
B37E82821FA85B210069E15D /* SendTextSingleBuddy.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B37E82811FA85B210069E15D /* SendTextSingleBuddy.scpt */; };
B39A65E01CC1FB1B003E26B0 /* Routing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B39A65DF1CC1FB1B003E26B0 /* Routing.swift */; };
B39F2B391CB3BCA700C0D35C /* SendText.scpt in Resources */ = {isa = PBXBuildFile; fileRef = B39F2B381CB3BCA700C0D35C /* SendText.scpt */; };
B3AECB5E2207CE2C003E32F8 /* Pods_Jared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4589B5638BC576CC8AB2700A /* Pods_Jared.framework */; };
B3A4C61423B867E300B7F009 /* MessageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3A4C61323B867E300B7F009 /* MessageRequest.swift */; };
B3AECB5F2207CE33003E32F8 /* JaredFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F84B61F1CC506790059A82B /* JaredFramework.framework */; };
B3BBA7D11CB3284A00E1749C /* CoreModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = B39EC17D1CB01FEF002C3161 /* CoreModule.swift */; };
B3C59284224DD17900116ECB /* JaredWebServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3C59283224DD17900116ECB /* JaredWebServer.swift */; };
B3EF1DA02206849000953DE7 /* WebHookManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3327DC522066427009DD882 /* WebHookManager.swift */; };
B3EF1DA4220687DD00953DE7 /* URLProtocolMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3EF1DA3220687DD00953DE7 /* URLProtocolMock.swift */; };
B3EF1DA62206DFEA00953DE7 /* Route.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3EF1DA52206DFEA00953DE7 /* Route.swift */; };
Expand Down Expand Up @@ -116,9 +118,11 @@
B39EC1751CB01F55002C3161 /* Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Message.swift; path = ../Jared/Message.swift; sourceTree = "<group>"; };
B39EC17D1CB01FEF002C3161 /* CoreModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreModule.swift; sourceTree = "<group>"; };
B39F2B381CB3BCA700C0D35C /* SendText.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = SendText.scpt; sourceTree = "<group>"; };
B3A4C61323B867E300B7F009 /* MessageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequest.swift; sourceTree = "<group>"; };
B3BBA7CC1CB3259A00E1749C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/CoreStrings.strings; sourceTree = "<group>"; };
B3BBA7CF1CB327C200E1749C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Main.strings; sourceTree = "<group>"; };
B3BBA7D01CB327C200E1749C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/CoreStrings.strings; sourceTree = "<group>"; };
B3C59283224DD17900116ECB /* JaredWebServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JaredWebServer.swift; sourceTree = "<group>"; };
B3EF1DA3220687DD00953DE7 /* URLProtocolMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLProtocolMock.swift; sourceTree = "<group>"; };
B3EF1DA52206DFEA00953DE7 /* Route.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Route.swift; sourceTree = "<group>"; };
B3EF1DA92206E09B00953DE7 /* Jared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Jared.swift; sourceTree = "<group>"; };
Expand All @@ -143,6 +147,7 @@
files = (
7F84B6261CC506790059A82B /* JaredFramework.framework in Frameworks */,
1D6188C0EEA4AA406C15CC9E /* Pods_Jared.framework in Frameworks */,
00FC0A452FD8C8D0FCDA16D4 /* Pods_Jared.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -151,7 +156,6 @@
buildActionMask = 2147483647;
files = (
B3AECB5F2207CE33003E32F8 /* JaredFramework.framework in Frameworks */,
B3AECB5E2207CE2C003E32F8 /* Pods_Jared.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -262,6 +266,8 @@
B39A65DF1CC1FB1B003E26B0 /* Routing.swift */,
B3327DC522066427009DD882 /* WebHookManager.swift */,
B3327DC32206607B009DD882 /* ContactHelper.swift */,
B3C59283224DD17900116ECB /* JaredWebServer.swift */,
B3A4C61323B867E300B7F009 /* MessageRequest.swift */,
B35CE7142196AD4E002F52A7 /* DatabaseHandler.swift */,
7F0E931C1D02FC250096BABE /* Global.swift */,
B3BBA7CD1CB3259A00E1749C /* CoreStrings.strings */,
Expand Down Expand Up @@ -369,6 +375,7 @@
TargetAttributes = {
7F84B61E1CC506790059A82B = {
CreatedOnToolsVersion = 7.3;
DevelopmentTeam = C7LJ587XF3;
LastSwiftMigration = 1010;
ProvisioningStyle = Automatic;
};
Expand Down Expand Up @@ -447,13 +454,19 @@
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Jared/Pods-Jared-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/CocoaAsyncSocket/CocoaAsyncSocket.framework",
"${BUILT_PRODUCTS_DIR}/HTTPParserC/HTTPParserC.framework",
"${BUILT_PRODUCTS_DIR}/Realm/Realm.framework",
"${BUILT_PRODUCTS_DIR}/RealmSwift/RealmSwift.framework",
"${BUILT_PRODUCTS_DIR}/Telegraph/Telegraph.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaAsyncSocket.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HTTPParserC.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RealmSwift.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Telegraph.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand Down Expand Up @@ -529,6 +542,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B3A4C61423B867E300B7F009 /* MessageRequest.swift in Sources */,
B39A65E01CC1FB1B003E26B0 /* Routing.swift in Sources */,
B3BBA7D11CB3284A00E1749C /* CoreModule.swift in Sources */,
B36563EF1F3D68980064B114 /* TouchBarTextFieldExtension.swift in Sources */,
Expand All @@ -540,6 +554,7 @@
B316D1A61F3FFDF100AFF063 /* CoreModuleRealm.swift in Sources */,
B375A65921EB14470073F09F /* AboutViewController.swift in Sources */,
7F0E931D1D02FC250096BABE /* Global.swift in Sources */,
B3C59284224DD17900116ECB /* JaredWebServer.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -604,7 +619,7 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = C7LJ587XF3;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
Expand All @@ -630,7 +645,7 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = C7LJ587XF3;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
Expand Down
1 change: 0 additions & 1 deletion Jared/DatabaseHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class DatabaseHandler {
querySinceID = getCurrentMaxRecordID()
}


deinit {
shouldExitThread = true
if sqlite3_close(db) != SQLITE_OK {
Expand Down
99 changes: 99 additions & 0 deletions Jared/JaredWebServer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import Foundation
import Telegraph
import JaredFramework

class JaredWebServer: NSObject {
static var DEFAULT_PORT = 3000
var defaults: UserDefaults!
var server: Server!
var port: Int!

override init() {
super.init()
defaults = UserDefaults.standard
server = Server()
server.route(.POST, "message", JaredWebServer.handleMessageRequest)

port = assignPort()

defaults.addObserver(self, forKeyPath: "RestApiIsDisabled", options: .new, context: nil)
updateServerState()
}

deinit {
UserDefaults.standard.removeObserver(self, forKeyPath: "JaredIsDisabled")
}

// Attempt to pull the port number from the config
func assignPort() -> Int {
let filemanager = FileManager.default
let appsupport = filemanager.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
let supportDir = appsupport.appendingPathComponent("Jared")
let configPath = supportDir.appendingPathComponent("config.json")
do {
// If config file does not exist, use default port
guard filemanager.fileExists(atPath: configPath.path) else {
return JaredWebServer.DEFAULT_PORT
}

//Read the JSON config file
let jsonData = try! NSData(contentsOfFile: supportDir.appendingPathComponent("config.json").path, options: .mappedIfSafe)

// If the JSON format is not as expected at all, use the default port
guard let jsonResult = try? JSONSerialization.jsonObject(with: jsonData as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String:AnyObject] else {
return JaredWebServer.DEFAULT_PORT
}

guard let serverConfig = jsonResult?["webserver"] as? [String : AnyObject] else {
return JaredWebServer.DEFAULT_PORT
}

guard let configPort = serverConfig["port"] as? NSNumber else {
return JaredWebServer.DEFAULT_PORT
}

return Int(truncating: configPort)
}
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if (keyPath == "RestApiIsDisabled") {
updateServerState()
}
}

func updateServerState() {
if (defaults.bool(forKey: "RestApiIsDisabled")) {
stop()
} else {
start()
}
}

func start() {
try? server.start(port: port)
}

func stop() {
server.stop()
}

static func handleMessageRequest(request: HTTPRequest) -> HTTPResponse {
// Attempt to decode the request body to the MessageRequest struct
do {
let parsedBody = try JSONDecoder().decode(MessageRequest.self, from: request.body)

if let textBody = parsedBody.body as? TextBody {
Jared.Send(textBody.message, to: parsedBody.recipient)
return HTTPResponse()
}
else {
return HTTPResponse(HTTPStatus(code: 400, phrase: "Bad Request"), headers: HTTPHeaders(), content: "Image body types are not supported yet.")
}
} catch {
return HTTPResponse(HTTPStatus(code: 400, phrase: "Bad Request"), headers: HTTPHeaders(), content: error.localizedDescription)
}
}
}


45 changes: 45 additions & 0 deletions Jared/MessageRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// MessageRequest.swift
// Jared
//
// Created by Zeke Snider on 12/28/19.
// Copyright © 2019 Zeke Snider. All rights reserved.
//

import Foundation
import JaredFramework

// Struct that defines what parameters are accepted in requests
public struct MessageRequest: Decodable {
public var body: MessageBody
public var recipient: RecipientEntity

enum CodingKeys : String, CodingKey {
case body
case recipient
}

enum ParameterError: Error {
case runtimeError(String)
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

if let textBody = try? container.decode(TextBody.self, forKey: .body) {
self.body = textBody
} else if let imageBody = try? container.decode(ImageBody.self, forKey: .body) {
self.body = imageBody
} else {
throw ParameterError.runtimeError("the body parameter is incorrectly formatted")
}

if let person = try? container.decode(Person.self, forKey: .recipient) {
self.recipient = person
} else if let group = try? container.decode(Group.self, forKey: .recipient) {
self.recipient = group
} else {
throw ParameterError.runtimeError("the recipient parameter is incorrectly formatted")
}
}
}
5 changes: 4 additions & 1 deletion Jared/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@
"routes": {
},
"webhooks": [
]
],
"webserver": {
"port": 3000
}
}
4 changes: 2 additions & 2 deletions JaredFramework/Bodies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public protocol MessageBody: Codable {}
public struct TextBody: MessageBody, Codable {
public var message: String

public init(_ inMessage: String) {
message = inMessage
public init(_ message: String) {
self.message = message
}
}

Expand Down
12 changes: 10 additions & 2 deletions JaredFramework/Entities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ public struct Person: SenderEntity, RecipientEntity, Codable, Equatable {
public var handle: String
public var isMe: Bool = false

public init(givenName: String?, handle: String, isMe: Bool) {
enum CodingKeys : String, CodingKey{
case handle
}

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

public init(givenName: String?, handle: String, isMe: Bool?) {
self.givenName = givenName
self.handle = handle
self.isMe = isMe
self.isMe = isMe ?? false
}

public static func == (lhs: Person, rhs: Person) -> Bool {
Expand Down
2 changes: 1 addition & 1 deletion JaredFramework/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0</string>
<string>2.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
1 change: 0 additions & 1 deletion JaredUI/AboutViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import Cocoa

class AboutViewController: NSViewController {

@IBAction func updateButtonClicked(_ sender: Any) {
NSWorkspace.shared.open(URL(string: "https://github.com/zekesnider/jared/releases")!)
}
Expand Down
2 changes: 1 addition & 1 deletion JaredUI/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import Contacts

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

var Router = MessageRouting()
var Server = JaredWebServer()

func applicationDidFinishLaunching(_ aNotification: Notification) {
// If this is the first run of the application, request access
Expand Down
Loading

0 comments on commit 86f47da

Please sign in to comment.