diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8ca8e99 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: generics +dist: trusty +sudo: required +script: + - swift build +before_install: + - TOOLCHAIN_TYPE=swift-3.0.2-release + - TOOLCHAIN_VERSION=swift-3.0.2-RELEASE + - sudo apt-get install clang uuid-dev libcurl4-openssl-dev + - wget https://swift.org/builds/${TOOLCHAIN_TYPE}/ubuntu1404/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-ubuntu14.04.tar.gz + - tar -zxvf ${TOOLCHAIN_VERSION}-ubuntu14.04.tar.gz + - sudo mv ${TOOLCHAIN_VERSION}-ubuntu14.04 /usr/swift + - export PATH=/usr/swift/usr/bin:"${PATH}" diff --git a/Package.swift b/Package.swift index 11dad77..24c459b 100644 --- a/Package.swift +++ b/Package.swift @@ -3,8 +3,7 @@ import PackageDescription let package = Package( name: "ZEGBot", dependencies: [ - .Package(url: "https://github.com/PerfectlySoft/Perfect.git", versions: Version(0,0,0).. [Self]? + static func array(from json: JSON) -> [Self]? } -extension Update: JSONConvertible { - - internal init?(from jsonConvertibleObject: Any?) { +extension ArrayConvertible where Self: JSONConvertible { + + internal static func array(from json: JSON) -> [Self]? { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let updateId = jsonDictionary[PARAM.UPDATE_ID] as? Int - else { - - Log.warning(on: jsonConvertibleObject) + guard let jsonArray = json.array else { + Log.warning(on: json) return nil - } + return jsonArray.map({ Self(from: $0) }).flatMap({ $0 }) + + } + +} + +extension Update: JSONConvertible, ArrayConvertible { + + internal init?(from json: JSON) { + guard let updateId = json[PARAM.UPDATE_ID].int else { + Log.warning(on: json) + return nil + } self.update_id = updateId - self.message = Message(from: jsonDictionary[PARAM.MESSAGE]) - self.edited_message = Message(from: jsonDictionary[PARAM.EDITED_MESSAGE]) + self.message = Message(from: json[PARAM.MESSAGE]) + self.edited_message = Message(from: json[PARAM.EDITED_MESSAGE]) } @@ -48,56 +56,51 @@ extension Update: JSONConvertible { extension Message { - internal convenience init?(from jsonConvertibleObject: Any?) { + internal convenience init?(from json: JSON) { - self.init() + guard !json.isEmpty else { return nil } - guard jsonConvertibleObject != nil else { return nil } + self.init() - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let messageId = jsonDictionary[PARAM.MESSAGE_ID] as? Int, - let date = jsonDictionary[PARAM.DATE] as? Int, - let chat = Chat(from: jsonDictionary[PARAM.CHAT]) - else { - - Log.warning(on: jsonConvertibleObject) + guard let messageId = json[PARAM.MESSAGE_ID].int, + let date = json[PARAM.DATE].int, + let chat = Chat(from: json[PARAM.CHAT]) else { + Log.warning(on: json) return nil - } self.message_id = messageId self.date = date self.chat = chat - self.from = User(from: jsonDictionary[PARAM.FROM]) - self.forward_from = User(from: jsonDictionary[PARAM.FORWARD_FROM]) - self.forward_from_chat = Chat(from: jsonDictionary[PARAM.FORWARD_FROM_CHAT]) - self.forward_date = jsonDictionary[PARAM.FORWARD_DATE] as? Int - self.reply_to_message = Message(from: jsonDictionary[PARAM.REPLY_TO_MESSAGE]) - self.edit_date = jsonDictionary[PARAM.EDIT_DATE] as? Int - self.text = jsonDictionary[PARAM.TEXT] as? String - self.entities = MessageEntity.array(from: jsonDictionary[PARAM.ENTITIES]) - self.audio = Audio(from: jsonDictionary[PARAM.AUDIO]) - self.document = Document(from: jsonDictionary[PARAM.DOCUMENT]) - self.photo = PhotoSize.array(from: jsonDictionary[PARAM.PHOTO]) - self.sticker = Sticker(from: jsonDictionary[PARAM.STICKER]) - self.video = Video(from: jsonDictionary[PARAM.VIDEO]) - self.voice = Voice(from: jsonDictionary[PARAM.VOICE]) - self.caption = jsonDictionary[PARAM.CAPTION] as? String - self.contact = Contact(from: jsonDictionary[PARAM.CONTACT]) - self.location = Location(from: jsonDictionary[PARAM.LOCATION]) - self.venue = Venue(from: jsonDictionary[PARAM.VENUE]) - self.new_chat_member = User(from: jsonDictionary[PARAM.NEW_CHAT_MEMBER]) - self.left_chat_member = User(from: jsonDictionary[PARAM.LEFT_CHAT_MEMBER]) - self.new_chat_title = jsonDictionary[PARAM.NEW_CHAT_TITLE] as? String - self.new_chat_photo = PhotoSize.array(from: jsonDictionary[PARAM.NEW_CHAT_PHOTO]) - self.delete_chat_photo = jsonDictionary[PARAM.DELETE_CHAT_PHOTO] as? Bool - self.group_chat_created = jsonDictionary[PARAM.GROUP_CHAT_CREATED] as? Bool - self.supergroup_chat_created = jsonDictionary[PARAM.SUPER_GROUP_CHAT_CREATED] as? Bool - self.channel_chat_created = jsonDictionary[PARAM.CHANNEL_CHAT_CREATED] as? Bool - self.migrate_to_chat_id = jsonDictionary[PARAM.MIGRATE_TO_CHAT_ID] as? Int - self.migrate_from_chat_id = jsonDictionary[PARAM.MIGRATE_FROM_CHAT_ID] as? Int - self.pinned_message = Message(from: jsonDictionary[PARAM.PINNED_MESSAGE]) + self.from = User(from: json[PARAM.FROM]) + self.forward_from = User(from: json[PARAM.FORWARD_FROM]) + self.forward_from_chat = Chat(from: json[PARAM.FORWARD_FROM_CHAT]) + self.forward_date = json[PARAM.FORWARD_DATE].int + self.reply_to_message = Message(from: json[PARAM.REPLY_TO_MESSAGE]) + self.edit_date = json[PARAM.EDIT_DATE].int + self.text = json[PARAM.TEXT].string + self.entities = MessageEntity.array(from: json[PARAM.ENTITIES]) + self.audio = Audio(from: json[PARAM.AUDIO]) + self.document = Document(from: json[PARAM.DOCUMENT]) + self.photo = PhotoSize.array(from: json[PARAM.PHOTO]) + self.sticker = Sticker(from: json[PARAM.STICKER]) + self.video = Video(from: json[PARAM.VIDEO]) + self.voice = Voice(from: json[PARAM.VOICE]) + self.caption = json[PARAM.CAPTION].string + self.contact = Contact(from: json[PARAM.CONTACT]) + self.location = Location(from: json[PARAM.LOCATION]) + self.venue = Venue(from: json[PARAM.VENUE]) + self.new_chat_member = User(from: json[PARAM.NEW_CHAT_MEMBER]) + self.left_chat_member = User(from: json[PARAM.LEFT_CHAT_MEMBER]) + self.new_chat_title = json[PARAM.NEW_CHAT_TITLE].string + self.new_chat_photo = PhotoSize.array(from: json[PARAM.NEW_CHAT_PHOTO]) + self.delete_chat_photo = json[PARAM.DELETE_CHAT_PHOTO].bool + self.group_chat_created = json[PARAM.GROUP_CHAT_CREATED].bool + self.supergroup_chat_created = json[PARAM.SUPER_GROUP_CHAT_CREATED].bool + self.channel_chat_created = json[PARAM.CHANNEL_CHAT_CREATED].bool + self.migrate_to_chat_id = json[PARAM.MIGRATE_TO_CHAT_ID].int + self.migrate_from_chat_id = json[PARAM.MIGRATE_FROM_CHAT_ID].int + self.pinned_message = Message(from: json[PARAM.PINNED_MESSAGE]) } @@ -105,27 +108,22 @@ extension Message { extension Chat: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let id = jsonDictionary[PARAM.ID] as? Int, - let type = Chat.sType(from: jsonDictionary[PARAM.TYPE] as? String) - else { - - Log.warning(on: jsonConvertibleObject) + guard let id = json[PARAM.ID].int, + let type = Chat.sType(from: json[PARAM.TYPE].string) else { + Log.warning(on: json) return nil - } self.id = id self.type = type - self.title = jsonDictionary[PARAM.TITLE] as? String - self.username = jsonDictionary[PARAM.USERNAME] as? String - self.first_name = jsonDictionary[PARAM.FIRST_NAME] as? String - self.last_name = jsonDictionary[PARAM.LAST_NAME] as? String + self.title = json[PARAM.TITLE].string + self.username = json[PARAM.USERNAME].string + self.first_name = json[PARAM.FIRST_NAME].string + self.last_name = json[PARAM.LAST_NAME].string } @@ -133,25 +131,20 @@ extension Chat: JSONConvertible { extension User: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let id = jsonDictionary[PARAM.ID] as? Int, - let firstName = jsonDictionary[PARAM.FIRST_NAME] as? String - else { - - Log.warning(on: jsonConvertibleObject) + guard let id = json[PARAM.ID].int, + let firstName = json[PARAM.FIRST_NAME].string else { + Log.warning(on: json) return nil - } self.id = id self.first_name = firstName - self.last_name = jsonDictionary[PARAM.LAST_NAME] as? String - self.username = jsonDictionary[PARAM.USERNAME] as? String + self.last_name = json[PARAM.LAST_NAME].string + self.username = json[PARAM.USERNAME].string } @@ -159,83 +152,44 @@ extension User: JSONConvertible { extension MessageEntity: JSONConvertible, ArrayConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let type = MessageEntity.sType(from: jsonDictionary[PARAM.TYPE] as? String), - let offset = jsonDictionary[PARAM.OFFSET] as? Int, - let length = jsonDictionary[PARAM.LENGTH] as? Int - else { - - Log.warning(on: jsonConvertibleObject) + guard let type = MessageEntity.sType(from: json[PARAM.TYPE].string), + let offset = json[PARAM.OFFSET].int, + let length = json[PARAM.LENGTH].int else { + Log.warning(on: json) return nil - } self.type = type self.offset = offset self.length = length - self.url = jsonDictionary[PARAM.URL] as? String - self.user = User(from: jsonDictionary[PARAM.USER]) - } - - internal static func array(from jsonConvertibleObject: Any?) -> [MessageEntity]? { - - guard jsonConvertibleObject != nil else { return nil } - - guard let - jsonArray = jsonConvertibleObject as? [Any] - else { - - Log.warning(on: jsonConvertibleObject) - return nil - - } - - var messageEntities = [MessageEntity]() - - for jsonDictionaryObject in jsonArray { - - if let messageEntity = MessageEntity(from: jsonDictionaryObject) { - - messageEntities.append(messageEntity) - - } - - } - - return messageEntities - + self.url = json[PARAM.URL].string + self.user = User(from: json[PARAM.USER]) } } extension Audio: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let fileId = jsonDictionary[PARAM.FILE_ID] as? String, - let duration = jsonDictionary[PARAM.DURATION] as? Int - else { - - Log.warning(on: jsonConvertibleObject) + guard let fileId = json[PARAM.FILE_ID].string, + let duration = json[PARAM.DURATION].int else { + Log.warning(on: json) return nil - } self.file_id = fileId self.duration = duration - self.performer = jsonDictionary[PARAM.PERFORMER] as? String - self.title = jsonDictionary[PARAM.TITLE] as? String - self.mime_type = jsonDictionary[PARAM.MIME_SIZE] as? String - self.file_size = jsonDictionary[PARAM.FILE_SIZE] as? Int + self.performer = json[PARAM.PERFORMER].string + self.title = json[PARAM.TITLE].string + self.mime_type = json[PARAM.MIME_SIZE].string + self.file_size = json[PARAM.FILE_SIZE].int } @@ -243,25 +197,20 @@ extension Audio: JSONConvertible { extension Document: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let fileId = jsonDictionary[PARAM.FILE_ID] as? String - else { - - Log.warning(on: jsonConvertibleObject) + guard let fileId = json[PARAM.FILE_ID].string else { + Log.warning(on: json) return nil - } self.file_id = fileId - self.thumb = PhotoSize(from: jsonDictionary[PARAM.THUMB]) - self.file_name = jsonDictionary[PARAM.FILE_NAME] as? String - self.mime_type = jsonDictionary[PARAM.MIME_TYPE] as? String - self.file_size = jsonDictionary[PARAM.FILE_SIZE] as? Int + self.thumb = PhotoSize(from: json[PARAM.THUMB]) + self.file_name = json[PARAM.FILE_NAME].string + self.mime_type = json[PARAM.MIME_TYPE].string + self.file_size = json[PARAM.FILE_SIZE].int } @@ -269,55 +218,21 @@ extension Document: JSONConvertible { extension PhotoSize: JSONConvertible, ArrayConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let fileId = jsonDictionary[PARAM.FILE_ID] as? String, - let width = jsonDictionary[PARAM.WIDTH] as? Int, - let height = jsonDictionary[PARAM.HEIGHT] as? Int - else { - - Log.warning(on: jsonConvertibleObject) + guard let fileId = json[PARAM.FILE_ID].string, + let width = json[PARAM.WIDTH].int, + let height = json[PARAM.HEIGHT].int else { + Log.warning(on: json) return nil - } self.file_id = fileId self.width = width self.height = height - self.file_size = jsonDictionary[PARAM.FILE_SIZE] as? Int - - } - - internal static func array(from jsonConvertibleObject: Any?) -> [PhotoSize]? { - - guard jsonConvertibleObject != nil else { return nil } - - guard let - jsonArray = jsonConvertibleObject as? [Any] - else { - - Log.warning(on: jsonConvertibleObject) - return nil - - } - - var photoSizes = [PhotoSize]() - - for jsonDictionaryObject in jsonArray { - - if let photoSize = PhotoSize(from: jsonDictionaryObject) { - - photoSizes.append(photoSize) - - } - - } - - return photoSizes + self.file_size = json[PARAM.FILE_SIZE].int } @@ -325,28 +240,23 @@ extension PhotoSize: JSONConvertible, ArrayConvertible { extension Sticker: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let fileId = jsonDictionary[PARAM.FILE_ID] as? String, - let width = jsonDictionary[PARAM.WIDTH] as? Int, - let height = jsonDictionary[PARAM.HEIGHT] as? Int - else { - - Log.warning(on: jsonConvertibleObject) + guard let fileId = json[PARAM.FILE_ID].string, + let width = json[PARAM.WIDTH].int, + let height = json[PARAM.HEIGHT].int else { + Log.warning(on: json) return nil - } self.file_id = fileId self.width = width self.height = height - self.thumb = PhotoSize(from: jsonDictionary[PARAM.THUMB]) - self.emoji = jsonDictionary[PARAM.EMOJI] as? String - self.file_size = jsonDictionary[PARAM.FILE_SIZE] as? Int + self.thumb = PhotoSize(from: json[PARAM.THUMB]) + self.emoji = json[PARAM.EMOJI].string + self.file_size = json[PARAM.FILE_SIZE].int } @@ -354,30 +264,25 @@ extension Sticker: JSONConvertible { extension Video: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let fileId = jsonDictionary[PARAM.FILE_ID] as? String, - let width = jsonDictionary[PARAM.WIDTH] as? Int, - let height = jsonDictionary[PARAM.HEIGHT] as? Int, - let duration = jsonDictionary[PARAM.DURATION] as? Int - else { - - Log.warning(on: jsonConvertibleObject) + guard let fileId = json[PARAM.FILE_ID].string, + let width = json[PARAM.WIDTH].int, + let height = json[PARAM.HEIGHT].int, + let duration = json[PARAM.DURATION].int else { + Log.warning(on: json) return nil - } self.file_id = fileId self.width = width self.height = height self.duration = duration - self.thumb = PhotoSize(from: jsonDictionary[PARAM.THUMB]) - self.mime_type = jsonDictionary[PARAM.MIME_TYPE] as? String - self.file_size = jsonDictionary[PARAM.FILE_SIZE] as? Int + self.thumb = PhotoSize(from: json[PARAM.THUMB]) + self.mime_type = json[PARAM.MIME_TYPE].string + self.file_size = json[PARAM.FILE_SIZE].int } @@ -385,25 +290,20 @@ extension Video: JSONConvertible { extension Voice: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let fileId = jsonDictionary[PARAM.FILE_ID] as? String, - let duration = jsonDictionary[PARAM.DURATION] as? Int - else { - - Log.warning(on: jsonConvertibleObject) + guard let fileId = json[PARAM.FILE_ID].string, + let duration = json[PARAM.DURATION].int else { + Log.warning(on: json) return nil - } self.file_id = fileId self.duration = duration - self.mime_type = jsonDictionary[PARAM.MIME_TYPE] as? String - self.file_size = jsonDictionary[PARAM.FILE_SIZE] as? Int + self.mime_type = json[PARAM.MIME_TYPE].string + self.file_size = json[PARAM.FILE_SIZE].int } @@ -411,25 +311,20 @@ extension Voice: JSONConvertible { extension Contact: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let phoneNumber = jsonDictionary[PARAM.PHONE_NUMBER] as? String, - let firstName = jsonDictionary[PARAM.FIRST_NAME] as? String - else { - - Log.warning(on: jsonConvertibleObject) + guard let phoneNumber = json[PARAM.PHONE_NUMBER].string, + let firstName = json[PARAM.FIRST_NAME].string else { + Log.warning(on: json) return nil - } self.phone_number = phoneNumber self.first_name = firstName - self.last_name = jsonDictionary[PARAM.LAST_NAME] as? String - self.user_id = jsonDictionary[PARAM.USER_ID] as? Int + self.last_name = json[PARAM.LAST_NAME].string + self.user_id = json[PARAM.USER_ID].int } @@ -437,19 +332,14 @@ extension Contact: JSONConvertible { extension Location: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let longitude = jsonDictionary[PARAM.LONGITUDE] as? Double, - let latitude = jsonDictionary[PARAM.LATITUDE] as? Double - else { - - Log.warning(on: jsonConvertibleObject) + guard let longitude = json[PARAM.LONGITUDE].double, + let latitude = json[PARAM.LATITUDE].double else { + Log.warning(on: json) return nil - } self.longitude = longitude @@ -461,26 +351,22 @@ extension Location: JSONConvertible { extension Venue: JSONConvertible { - internal init?(from jsonConvertibleObject: Any?) { + internal init?(from json: JSON) { - guard jsonConvertibleObject != nil else { return nil } + guard !json.isEmpty else { return nil } - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let location = Location(from: jsonDictionary[PARAM.LOCATION]), - let title = jsonDictionary[PARAM.TITLE] as? String, - let address = jsonDictionary[PARAM.ADDRESS] as? String - else { - - Log.warning(on: jsonConvertibleObject) + guard let location = Location(from: json[PARAM.LOCATION]), + let title = json[PARAM.TITLE].string, + let address = json[PARAM.ADDRESS].string else { + Log.warning(on: json) return nil - } self.location = location self.title = title self.address = address - self.foursquare_id = jsonDictionary[PARAM.FOURSQUARE_ID] as? String + self.foursquare_id = json[PARAM.FOURSQUARE_ID].string } + } diff --git a/Sources/Methods.swift b/Sources/Methods.swift index 2dc2168..3a0962d 100644 --- a/Sources/Methods.swift +++ b/Sources/Methods.swift @@ -10,7 +10,8 @@ import PerfectCURL import cURL -import PerfectLib +import SwiftyJSON +import Foundation extension ZEGBot { @@ -30,11 +31,11 @@ extension ZEGBot { if disableNotification { payload[PARAM.DISABLE_NOTIFICATION] = true } payload.append(contentOf: receiver.receiverIdentifier) - guard let responseDictionary = perform(method: PARAM.SEND_MESSAGE, payload: payload) as? [String: Any] else { + guard let responseJSON = perform(method: PARAM.SEND_MESSAGE, payload: payload) else { return nil } - return Message(from: responseDictionary[PARAM.RESULT]) + return Message(from: responseJSON[PARAM.RESULT]) } @@ -50,11 +51,11 @@ extension ZEGBot { if disableNotification { payload[PARAM.DISABLE_NOTIFICATION] = true } payload.append(contentOf: receiver.receiverIdentifier) - guard let responseDictionary = perform(method: PARAM.FORWARD_MESSAGE, payload: payload) as? [String: Any] else { + guard let responseJSON = perform(method: PARAM.FORWARD_MESSAGE, payload: payload) else { return nil } - return Message(from: responseDictionary[PARAM.RESULT]) + return Message(from: responseJSON[PARAM.RESULT]) } @@ -146,11 +147,11 @@ extension ZEGBot { if disableNotification { payload[PARAM.DISABLE_NOTIFICATION] = true } payload.append(contentOf: receiver.receiverIdentifier) - guard let responseDictionary = perform(method: PARAM.SEND_LOCATION, payload: payload) as? [String: Any] else { + guard let responseJSON = perform(method: PARAM.SEND_LOCATION, payload: payload) else { return nil } - return Message(from: responseDictionary[PARAM.RESULT]) + return Message(from: responseJSON[PARAM.RESULT]) } @discardableResult @@ -163,18 +164,21 @@ extension ZEGBot { PARAM.LATITUDE: latitude, PARAM.LONGITUDE: longitude, PARAM.TITLE: title, - PARAM.ADDRESS: address, + PARAM.ADDRESS: address + ] + let optionalPayload: [String: Any?] = [ PARAM.FOURSQUARE_ID: foursquare_id ] + payload.append(contentOf: optionalPayload) if disableNotification { payload[PARAM.DISABLE_NOTIFICATION] = true } payload.append(contentOf: receiver.receiverIdentifier) - guard let responseDictionary = perform(method: PARAM.SEND_VENUE, payload: payload) as? [String: Any] else { + guard let responseJSON = perform(method: PARAM.SEND_VENUE, payload: payload) else { return nil } - return Message(from: responseDictionary[PARAM.RESULT]) + return Message(from: responseJSON[PARAM.RESULT]) } @@ -185,18 +189,21 @@ extension ZEGBot { var payload: [String: Any] = [ PARAM.PHONE_NUMBER: phoneNumber, - PARAM.FIRST_NAME: firstName, PARAM.LAST_NAME: lastName ] + let optionalPayload: [String: Any?] = [ + PARAM.FIRST_NAME: firstName + ] + payload.append(contentOf: optionalPayload) if disableNotification { payload[PARAM.DISABLE_NOTIFICATION] = true } payload.append(contentOf: receiver.receiverIdentifier) - guard let responseDictionary = perform(method: PARAM.SEND_CONTACT, payload: payload) as? [String: Any] else { + guard let responseJSON = perform(method: PARAM.SEND_CONTACT, payload: payload) else { return nil } - return Message(from: responseDictionary[PARAM.RESULT]) + return Message(from: responseJSON[PARAM.RESULT]) } @@ -226,22 +233,18 @@ extension ZEGBot { payload.append(contentOf: receiver.receiverIdentifier) payload.append(contentOf: options) - guard let responseDictionary = perform(method: content.sendingMethod, payload: payload) as? [String: Any] else { + guard let responseJSON = perform(method: content.sendingMethod, payload: payload) else { return nil } - return Message(from: responseDictionary[PARAM.RESULT]) + return Message(from: responseJSON[PARAM.RESULT]) } - internal func perform(method: String, payload: [String: Any]) -> Any? { - - var bodyBytes = [UInt8]() + internal func perform(method: String, payload: [String: Any]) -> JSON? { - do { - bodyBytes.append(contentsOf: try payload.jsonEncodedString().bytes()) - } catch { - Log.warning(on: payload) + guard var bodyBytes = JSON(payload).rawString()?.bytes() else { + Log.warning(onMethod: method) return nil } @@ -250,14 +253,7 @@ extension ZEGBot { curl.setOption(CURLOPT_POSTFIELDS, v: &bodyBytes) curl.setOption(CURLOPT_HTTPHEADER, s: PARAM.POST_JSON_HEADER_CONTENT_TYPE) - let responseString = curl.performFully().2.reduce("", { a, b in a + String(UnicodeScalar(b)) }) - - do { - return try responseString.jsonDecode() - } catch { - Log.warning(on: responseString) - return nil - } + return JSON(data: Data(bytes: curl.performFully().2)) } diff --git a/Sources/Utilities.swift b/Sources/Utilities.swift index 332155f..2a7d6df 100644 --- a/Sources/Utilities.swift +++ b/Sources/Utilities.swift @@ -6,8 +6,6 @@ // // -import PerfectLib - extension String { func bytes() -> [UInt8]{ @@ -16,14 +14,23 @@ extension String { } -extension Log { +struct Log { + + static func warning(message: String) { + print("[⚠️WARN] \(message)") + } static func warning(on object: Any) { - self.warning(message: "===>>>===<<<===") + self.warning(message: "====>>>====<<<====") self.warning(message: "Failed to convert:") self.warning(message: "\(object)") } + static func warning(onMethod method: String) { + self.warning(message: "====>>>====<<<====") + self.warning(message: "Failed in method: \(method)") + } + } extension Dictionary { @@ -34,4 +41,10 @@ extension Dictionary { } } + mutating func append(contentOf dictionary: [Key: Value?]) { + for (key, optionalValue) in dictionary { + if let value = optionalValue { self[key] = value } + } + } + } diff --git a/Sources/ZEGBot.swift b/Sources/ZEGBot.swift index 22b44e1..871209f 100644 --- a/Sources/ZEGBot.swift +++ b/Sources/ZEGBot.swift @@ -10,8 +10,8 @@ import cURL import PerfectCURL -import PerfectLib import PerfectThread +import SwiftyJSON public struct ZEGBot { @@ -61,59 +61,14 @@ extension ZEGBot { /* For getUpdates. */ static func decodeUpdates(from jsonString: String) -> [Update]? { - do { - - let jsonConvertibleObject = try jsonString.jsonDecode() - - guard let - jsonDictionary = jsonConvertibleObject as? [String: Any], - let updatesDictionaryArrayObject = jsonDictionary["result"], - let updatesDictionaryArray = updatesDictionaryArrayObject as? [Any] - else { - - Log.warning(on: jsonConvertibleObject) - return nil - - } - - var updates = [Update]() - - for updateDictionaryObject in updatesDictionaryArray { - - if let update = Update(from: updateDictionaryObject) { - - updates.append(update) - - } - - } - - return updates - - } catch { - - Log.warning(on: jsonString) - return nil - - } + return Update.array(from: JSON.parse(string: jsonString)[PARAM.RESULT]) } /* For webhook. */ static func decodeUpdate(from jsonString: String) -> Update? { - do { - - let jsonConvertibleObject = try jsonString.jsonDecode() - - return Update(from: jsonConvertibleObject) - - } catch { - - Log.warning(on: jsonString) - return nil - - } + return Update(from: JSON.parse(string: jsonString)[PARAM.RESULT]) }