Compare commits

...

10 Commits

Author SHA1 Message Date
Peter Zignego c58abcd089 Merge pull request #67 from pvzig/0.0.6
0.0.6
2017-01-05 21:00:00 -05:00
Peter Zignego eccf73c592 JSON for error 2017-01-05 20:57:05 -05:00
Peter Zignego bed79c30b5 Use integer status codes 2017-01-05 20:48:20 -05:00
Peter Zignego 0d08f2a7c9 Update error message 2017-01-05 20:48:04 -05:00
Peter Zignego 54af4e1a67 Code quality improvements 2017-01-05 20:13:46 -05:00
Peter Zignego 1fdb849858 Add back error event type 2017-01-05 20:13:37 -05:00
Peter Zignego 44b39326b2 Use URLComponents 2017-01-05 20:13:24 -05:00
Peter Zignego 59e7d6c77c Readme… 2016-12-30 00:06:33 -05:00
Peter Zignego d333e12077 Update readme 2016-12-30 00:05:04 -05:00
Peter Zignego c63761cc2f Update readme 2016-12-30 00:01:59 -05:00
6 changed files with 217 additions and 228 deletions
+82 -91
View File
@@ -1,12 +1,10 @@
![SlackKit](https://cloud.githubusercontent.com/assets/8311605/10260893/5ec60f96-694e-11e5-91fd-da6845942201.png)
![Swift Version](https://img.shields.io/badge/Swift-DEVELOPMENT--SNAPSHOT--2016--05--09--a-orange.svg) ![Plaforms](https://img.shields.io/badge/Platforms-macOS,linux-lightgrey.svg) ![License MIT](https://img.shields.io/badge/License-MIT-lightgrey.svg) [![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)
##Alpha Linux Slack Client Library
![Swift Version](https://img.shields.io/badge/Swift-3.0-orange.svg) ![Plaforms](https://img.shields.io/badge/Platforms-Linux-lightgrey.svg) ![License MIT](https://img.shields.io/badge/License-MIT-lightgrey.svg) [![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)
##SlackKit: A Swift Slack Client Library
###Description
This is a Slack client library for Linux written in Swift. It's intended to expose all of the functionality of Slack's [Real Time Messaging API](https://api.slack.com/rtm) as well as the [web APIs](https://api.slack.com/web) that are accessible by [bot users](https://api.slack.com/bot-users).
###Disclaimer: The linux version of SlackKit is a pre-release alpha. Feel free to report issues you come across.
###Installation
####Swift Package Manager
@@ -16,6 +14,7 @@ Add SlackKit to your Package.swift
import PackageDescription
let package = Package(
name: "MySlackApp",
dependencies: [
.Package(url: "https://github.com/pvzig/SlackKit.git", majorVersion: 0, minor: 0)
]
@@ -23,20 +22,9 @@ let package = Package(
```
####Development
1. Install Homebrew: `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
2. Install `swiftenv`: `brew install kylef/formulae/swiftenv`
3. Configure your shell: `echo 'if which swiftenv > /dev/null; then eval "$(swiftenv init -)"; fi' >> ~/.bash_profile`
4. Download and install the latest Zewo compatible snapshot:
To develop an application that uses SlackKit in Xcode, simply use SwiftPM:
```
swiftenv install DEVELOPMENT-SNAPSHOT-2016-05-09-a
swiftenv local DEVELOPMENT-SNAPSHOT-2016-05-09-a
```
5. Install and Link OpenSSL: `brew install openssl`, `brew link openssl --force`
To build an application that uses SlackKit in Xcode, simply use SwiftPM. (For the 05-03 snapshot you must run `swift build` before generating an Xcode project:
```
swift build
swift build -Xlinker -L$(pwd)/.build/debug/ -Xswiftc -I/usr/local/include -Xlinker -L/usr/local/lib -X
swift package generate-xcodeproj
```
@@ -45,15 +33,18 @@ To use the library in your project import it:
import SlackKit
```
####Deployment
Deploy your application to Heroku using [this buildpack](https://github.com/pvzig/heroku-buildpack-swift). For more detailed instructions please see [this post](https://medium.com/@pvzig/building-slack-bots-in-swift-b99e243e444c).
###Examples
See the [examples folder](https://github.com/pvzig/SlackKit/tree/linux/Examples) for a few examples of how you can use SlackKit.
###Deployment
Deploy your application to Heroku using [this buildpack](https://github.com/kylef/heroku-buildpack-swift). You can also deploy your application anywhere you can deploy a docker container. For more detailed instructions please see [this post](https://medium.com/@pvzig/building-slack-bots-in-swift-b99e243e444c).
###Usage
To use SlackKit you'll need a bearer token which identifies a single user. You can generate a [full access token or create one using OAuth 2](https://api.slack.com/web).
Once you have a token, initialize a client instance using it:
```swift
let client = Client(apiToken: "YOUR_SLACK_API_TOKEN")
let client = SlackClient(apiToken: "YOUR_SLACK_API_TOKEN")
```
If you want to receive messages from the Slack RTM API, connect to it.
@@ -82,6 +73,7 @@ SlackKit currently supports the a subset of the Slack Web APIs that are availabl
- files.comments.edit
- files.comments.delete
- files.delete
- files.info
- files.upload
- groups.close
- groups.history
@@ -120,11 +112,10 @@ SlackKit currently supports the a subset of the Slack Web APIs that are availabl
They can be accessed through a Client objects `webAPI` property:
```swift
client.webAPI.authenticationTest({
(authenticated) -> Void in
print(authenticated)
}){(error) -> Void in
print(error)
client.webAPI.authenticationTest({(authenticated) in
print(authenticated)
}) {(error) in
print(error)
}
```
@@ -132,97 +123,97 @@ client.webAPI.authenticationTest({
To receive delegate callbacks for certain events, register an object as the delegate for those events:
```swift
client.slackEventsDelegate = self
client.connectionEventsDelegate = self
```
There are a number of delegates that you can set to receive callbacks for certain events.
#####SlackEventsDelegate
##### ConnectionEventsDelegate
```swift
func clientConnected()
func clientDisconnected()
func preferenceChanged(preference: String, value: AnyObject)
func userChanged(user: User)
func presenceChanged(user: User?, presence: String?)
func manualPresenceChanged(user: User?, presence: String?)
func botEvent(bot: Bot)
connected(_ client: Client)
disconnected(_ client: Client)
connectionFailed(_ client: Client, error: SlackError)
```
#####MessageEventsDelegate
##### MessageEventsDelegate
```swift
func messageSent(message: Message)
func messageReceived(message: Message)
func messageChanged(message: Message)
func messageDeleted(message: Message?)
sent(_ message: Message, client: Client)
received(_ message: Message, client: Client)
changed(_ message: Message, client: Client)
deleted(_ message: Message?, client: Client)
```
#####ChannelEventsDelegate
##### ChannelEventsDelegate
```swift
func userTyping(channel: Channel?, user: User?)
func channelMarked(channel: Channel, timestamp: String?)
func channelCreated(channel: Channel)
func channelDeleted(channel: Channel)
func channelRenamed(channel: Channel)
func channelArchived(channel: Channel)
func channelHistoryChanged(channel: Channel)
func channelJoined(channel: Channel)
func channelLeft(channel: Channel)
userTypingIn(_ channel: Channel, user: User, client: Client)
marked(_ channel: Channel, timestamp: String, client: Client)
created(_ channel: Channel, client: Client)
deleted(_ channel: Channel, client: Client)
renamed(_ channel: Channel, client: Client)
archived(_ channel: Channel, client: Client)
historyChanged(_ channel: Channel, client: Client)
joined(_ channel: Channel, client: Client)
left(_ channel: Channel, client: Client)
```
#####DoNotDisturbEventsDelegate
##### DoNotDisturbEventsDelegate
```swift
doNotDisturbUpdated(dndStatus: DoNotDisturbStatus)
doNotDisturbUserUpdated(dndStatus: DoNotDisturbStatus, user: User?)
updated(_ status: DoNotDisturbStatus, client: Client)
userUpdated(_ status: DoNotDisturbStatus, user: User, client: Client)
```
#####GroupEventsDelegate
##### GroupEventsDelegate
```swift
func groupOpened(group: Channel)
opened(_ group: Channel, client: Client)
```
#####FileEventsDelegate
##### FileEventsDelegate
```swift
func fileProcessed(file: File)
func fileMadePrivate(file: File)
func fileDeleted(file: File)
func fileCommentAdded(file: File, comment: Comment)
func fileCommentEdited(file: File, comment: Comment)
func fileCommentDeleted(file: File, comment: Comment)
processed(_ file: File, client: Client)
madePrivate(_ file: File, client: Client)
deleted(_ file: File, client: Client)
commentAdded(_ file: File, comment: Comment, client: Client)
commentEdited(_ file: File, comment: Comment, client: Client)
commentDeleted(_ file: File, comment: Comment, client: Client)
```
#####PinEventsDelegate
##### PinEventsDelegate
```swift
func itemPinned(item: Item?, channel: Channel?)
func itemUnpinned(item: Item?, channel: Channel?)
pinned(_ item: Item, channel: Channel?, client: Client)
unpinned(_ item: Item, channel: Channel?, client: Client)
```
#####StarEventsDelegate
##### StarEventsDelegate
```swift
func itemStarred(item: Item, star: Bool)
starred(_ item: Item, starred: Bool, _ client: Client)
```
#####ReactionEventsDelegate
##### ReactionEventsDelegate
```swift
func reactionAdded(reaction: String?, item: Item?, itemUser: String?)
func reactionRemoved(reaction: String?, item: Item?, itemUser: String?)
added(_ reaction: String, item: Item, itemUser: String, client: Client)
removed(_ reaction: String, item: Item, itemUser: String, client: Client)
```
#####TeamEventsDelegate
##### SlackEventsDelegate
```swift
func teamJoined(user: User)
func teamPlanChanged(plan: String)
func teamPreferencesChanged(preference: String, value: AnyObject)
func teamNameChanged(name: String)
func teamDomainChanged(domain: String)
func teamEmailDomainChanged(domain: String)
func teamEmojiChanged()
preferenceChanged(_ preference: String, value: Any?, client: Client)
userChanged(_ user: User, client: Client)
presenceChanged(_ user: User, presence: String, client: Client)
manualPresenceChanged(_ user: User, presence: String, client: Client)
botEvent(_ bot: Bot, client: Client)
```
#####SubteamEventsDelegate
##### TeamEventsDelegate
```swift
func subteamEvent(userGroup: UserGroup)
func subteamSelfAdded(subteamID: String)
func subteamSelfRemoved(subteamID: String)
userJoined(_ user: User, client: Client)
planChanged(_ plan: String, client: Client)
preferencesChanged(_ preference: String, value: Any?, client: Client)
nameChanged(_ name: String, client: Client)
domainChanged(_ domain: String, client: Client)
emailDomainChanged(_ domain: String, client: Client)
emojiChanged(_ client: Client)
```
##### SubteamEventsDelegate
```swift
event(_ userGroup: UserGroup, client: Client)
selfAdded(_ subteamID: String, client: Client)
selfRemoved(_ subteamID: String, client: Client)
```
##### TeamProfileEventsDelegate
```swift
changed(_ profile: CustomProfile, client: Client)
deleted(_ profile: CustomProfile, client: Client)
reordered(_ profile: CustomProfile, client: Client)
```
###Get In Touch
@@ -153,8 +153,10 @@ internal extension SlackClient {
subteamAddedSelf(event)
case .subteamSelfRemoved:
subteamRemovedSelf(event)
case .error:
print("Error: \(anEvent)")
case .unknown:
print("Unknown event of type: \(anEvent["type"] ?? "No Type Information")")
print("Unsupported event of type: \(anEvent["type"] ?? "No Type Information")")
}
}
+1 -2
View File
@@ -22,7 +22,6 @@
// THE SOFTWARE.
internal enum EventType: String {
case hello = "hello"
case message = "message"
case userTyping = "user_typing"
@@ -93,11 +92,11 @@ internal enum EventType: String {
case subteamSelfAdded = "subteam_self_added"
case subteamSelfRemoved = "subteam_self_removed"
case ok = "ok"
case error = "error"
case unknown = "unknown"
}
internal enum MessageSubtype: String {
case botMessage = "bot_message"
case meMessage = "me_message"
case messageChanged = "message_changed"
-15
View File
@@ -39,18 +39,3 @@ internal extension String {
return escapedString
}
}
internal extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
var requestStringFromParameters: String {
var requestString = ""
for key in self.keys {
if let value = self[key] as? String, let encodedValue = value.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) {
requestString += "&\(key)=\(encodedValue)"
} else if let value = self[key] {
requestString += "&\(key)=\(value)"
}
}
return requestString
}
}
+68 -45
View File
@@ -38,30 +38,20 @@ internal struct NetworkInterface {
}
}
internal func request(_ endpoint: Endpoint, token: String, parameters: [String: Any]?, successClosure: ([String: Any])->Void, errorClosure: (SlackError)->Void) {
var requestString = "\(apiUrl)\(endpoint.rawValue)?token=\(token)"
if let params = parameters {
requestString += params.requestStringFromParameters
internal func request(_ endpoint: Endpoint, parameters: [String: Any?], successClosure: @escaping ([String: Any])->Void, errorClosure: @escaping (SlackError)->Void) {
var components = URLComponents(string: "\(apiUrl)\(endpoint.rawValue)")
if parameters.count > 0 {
components?.queryItems = filterNilParameters(parameters).map { URLQueryItem(name: $0.0, value: "\($0.1)") }
}
guard let requestString = components?.string else {
errorClosure(SlackError.clientNetworkError)
return
}
do {
let contentNegotiation = ContentNegotiationMiddleware(mediaTypes: [.json, .urlEncodedForm], mode: .client)
var response = try client?.get(requestString, middleware: [contentNegotiation])
if let buffer = try response?.body.becomeBuffer(deadline: 3.seconds.fromNow()) {
let data = Data(bytes: buffer.bytes)
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
if let result = json as? [String: Any] {
if (result["ok"] as? Bool == true) {
successClosure(result)
} else {
if let errorString = result["error"] as? String {
throw SlackError(rawValue: errorString) ?? SlackError.unknownError
} else {
throw SlackError.unknownError
}
}
}
}
let response = try client?.get(requestString, middleware: [contentNegotiation])
successClosure(try handleResponse(response))
} catch let error {
if let slackError = error as? SlackError {
errorClosure(slackError)
@@ -71,17 +61,21 @@ internal struct NetworkInterface {
}
}
internal func uploadRequest(token: String, data: Data, parameters: [String: Any]?, successClosure: ([String: Any])->Void, errorClosure: (SlackError)->Void) {
var requestString = "\(apiUrl)\(Endpoint.filesUpload.rawValue)?token=\(token)"
if let params = parameters {
requestString = requestString + params.requestStringFromParameters
internal func uploadRequest(data: Data, parameters: [String: Any?], successClosure: @escaping ([String: Any])->Void, errorClosure: @escaping (SlackError)->Void) {
var components = URLComponents(string: "\(apiUrl)\(Endpoint.filesUpload.rawValue)")
if parameters.count > 0 {
components?.queryItems = filterNilParameters(parameters).map { URLQueryItem(name: $0.0, value: "\($0.1)") }
}
guard let requestString = components?.string else {
errorClosure(SlackError.clientNetworkError)
return
}
let boundaryConstant = randomBoundary()
let boundaryStart = "--\(boundaryConstant)\r\n"
let boundaryEnd = "\r\n--\(boundaryConstant)--\r\n"
let contentDispositionString = "Content-Disposition: form-data; name=\"file\"; filename=\"\(parameters!["filename"])\"\r\n"
let contentTypeString = "Content-Type: \(parameters!["filetype"])\r\n\r\n"
let contentDispositionString = "Content-Disposition: form-data; name=\"file\"; filename=\"\(parameters["filename"])\"\r\n"
let contentTypeString = "Content-Type: \(parameters["filetype"])\r\n\r\n"
guard let boundaryStartData = boundaryStart.data(using: .utf8), let dispositionData = contentDispositionString.data(using: .utf8), let contentTypeData = contentTypeString.data(using: .utf8), let boundaryEndData = boundaryEnd.data(using: .utf8) else {
errorClosure(SlackError.clientNetworkError)
@@ -95,26 +89,11 @@ internal struct NetworkInterface {
requestBodyData.append(contentsOf: boundaryEndData)
let header: Headers = ["Content-Type":"multipart/form-data; boundary=\(boundaryConstant)"]
do {
let body = Buffer([UInt8](requestBodyData))
var response = try client?.post(requestString, headers: header, body: body)
if let buffer = try response?.body.becomeBuffer(deadline: 3.seconds.fromNow()) {
let data = Data(bytes: buffer.bytes)
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
if let result = json as? [String: Any] {
if (result["ok"] as? Bool == true) {
successClosure(result)
} else {
if let errorString = result["error"] as? String {
throw SlackError(rawValue: errorString) ?? SlackError.unknownError
} else {
throw SlackError.unknownError
}
}
}
}
let body = Buffer([UInt8](requestBodyData))
do {
let response = try client?.post(requestString, headers: header, body: body)
successClosure(try handleResponse(response))
} catch let error {
if let slackError = error as? SlackError {
errorClosure(slackError)
@@ -124,6 +103,50 @@ internal struct NetworkInterface {
}
}
private func handleResponse(_ response: Response?) throws -> [String: Any] {
guard var response = response else {
throw SlackError.clientNetworkError
}
do {
let buffer = try response.body.becomeBuffer(deadline: 3.seconds.fromNow())
switch response.statusCode {
case 200:
let data = Data(bytes: buffer.bytes)
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] {
if json["ok"] as? Bool == true {
return json
} else if let errorString = json["error"] as? String {
throw SlackError(rawValue: errorString) ?? .unknownError
} else {
throw SlackError.clientJSONError
}
} else {
throw SlackError.unknownError
}
case 429:
throw SlackError.tooManyRequests
default:
throw SlackError.clientNetworkError
}
} catch let error {
if let slackError = error as? SlackError {
throw slackError
} else {
throw SlackError.unknownError
}
}
}
private func filterNilParameters(_ parameters: [String: Any?]) -> [String: Any] {
var finalParameters = [String: Any]()
for (key, value) in parameters {
if let unwrapped = value {
finalParameters[key] = unwrapped
}
}
return finalParameters
}
private func randomBoundary() -> String {
#if os(Linux)
return "slackkit.boundary.\(Int(random()))\(Int(random()))"
+63 -74
View File
@@ -115,8 +115,8 @@ public class SlackWebAPI {
//MARK: - RTM
public func rtmStart(simpleLatest: Bool? = nil, noUnreads: Bool? = nil, mpimAware: Bool? = nil, success: ((_ response: [String: Any])->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["simple_latest": simpleLatest, "no_unreads": noUnreads, "mpim_aware": mpimAware]
networkInterface.request(.rtmStart, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "simple_latest": simpleLatest, "no_unreads": noUnreads, "mpim_aware": mpimAware]
networkInterface.request(.rtmStart, parameters: parameters, successClosure: {(response) in
success?(response)
}) {(error) in
failure?(error)
@@ -125,7 +125,7 @@ public class SlackWebAPI {
//MARK: - Auth Test
public func authenticationTest(success: ((_ authenticated: Bool)->Void)?, failure: FailureClosure?) {
networkInterface.request(.authTest, token: token, parameters: nil, successClosure: {(response) in
networkInterface.request(.authTest, parameters: ["token": token], successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -183,8 +183,8 @@ public class SlackWebAPI {
//MARK: - Messaging
public func deleteMessage(channel: String, ts: String, success: ((_ deleted: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["channel": channel, "ts": ts]
networkInterface.request(.chatDelete, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "channel": channel, "ts": ts]
networkInterface.request(.chatDelete, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -192,17 +192,17 @@ public class SlackWebAPI {
}
public func sendMessage(channel: String, text: String, username: String? = nil, asUser: Bool? = nil, parse: ParseMode? = nil, linkNames: Bool? = nil, attachments: [Attachment?]? = nil, unfurlLinks: Bool? = nil, unfurlMedia: Bool? = nil, iconURL: String? = nil, iconEmoji: String? = nil, success: (((ts: String?, channel: String?))->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["channel":channel, "text":text.slackFormatEscaping, "as_user":asUser, "parse":parse?.rawValue, "link_names":linkNames, "unfurl_links":unfurlLinks, "unfurlMedia":unfurlMedia, "username":username, "attachments":encodeAttachments(attachments), "icon_url":iconURL, "icon_emoji":iconEmoji]
networkInterface.request(.chatPostMessage, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "channel":channel, "text":text.slackFormatEscaping, "as_user":asUser, "parse":parse?.rawValue, "link_names":linkNames, "unfurl_links":unfurlLinks, "unfurlMedia":unfurlMedia, "username":username, "attachments":encodeAttachments(attachments), "icon_url":iconURL, "icon_emoji":iconEmoji]
networkInterface.request(.chatPostMessage, parameters: parameters, successClosure: {(response) in
success?((ts: response["ts"] as? String, response["channel"] as? String))
}) {(error) in
failure?(error)
}
}
public func sendMeMessage(_ channel: String, text: String, success: (((ts: String?, channel: String?))->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["channel": channel, "text": text.slackFormatEscaping]
networkInterface.request(.chatMeMessage, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
public func sendMeMessage(channel: String, text: String, success: (((ts: String?, channel: String?))->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["token": token, "channel": channel, "text": text.slackFormatEscaping]
networkInterface.request(.chatMeMessage, parameters: parameters, successClosure: {(response) in
success?((ts: response["ts"] as? String, response["channel"] as? String))
}) {(error) in
failure?(error)
@@ -210,8 +210,8 @@ public class SlackWebAPI {
}
public func updateMessage(channel: String, ts: String, message: String, attachments: [Attachment?]? = nil, parse:ParseMode = .none, linkNames: Bool = false, success: ((_ updated: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["channel": channel, "ts": ts, "text": message.slackFormatEscaping, "parse": parse.rawValue, "link_names": linkNames, "attachments":encodeAttachments(attachments)]
networkInterface.request(.chatUpdate, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "channel": channel, "ts": ts, "text": message.slackFormatEscaping, "parse": parse.rawValue, "link_names": linkNames, "attachments":encodeAttachments(attachments)]
networkInterface.request(.chatUpdate, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -220,8 +220,8 @@ public class SlackWebAPI {
//MARK: - Do Not Disturb
public func dndInfo(user: String? = nil, success: ((_ status: DoNotDisturbStatus)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["user": user]
networkInterface.request(.dndInfo, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "user": user]
networkInterface.request(.dndInfo, parameters: parameters, successClosure: {(response) in
success?(DoNotDisturbStatus(status: response))
}) {(error) in
failure?(error)
@@ -229,8 +229,8 @@ public class SlackWebAPI {
}
public func dndTeamInfo(users: [String]? = nil, success: ((_ statuses: [String: DoNotDisturbStatus])->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["users":users?.joined(separator: ",")]
networkInterface.request(.dndTeamInfo, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "users": users?.joined(separator: ",")]
networkInterface.request(.dndTeamInfo, parameters: parameters, successClosure: {(response) in
guard let usersDictionary = response["users"] as? [String: Any] else {
success?([:])
return
@@ -243,7 +243,7 @@ public class SlackWebAPI {
//MARK: - Emoji
public func emojiList(success: ((_ emojiList: [String: Any]?)->Void)?, failure: FailureClosure?) {
networkInterface.request(.emojiList, token: token, parameters: nil, successClosure: {(response) in
networkInterface.request(.emojiList, parameters: ["token": token], successClosure: {(response) in
success?(response["emoji"] as? [String: Any])
}) {(error) in
failure?(error)
@@ -252,8 +252,8 @@ public class SlackWebAPI {
//MARK: - Files
public func deleteFile(fileID: String, success: ((_ deleted: Bool)->Void)?, failure: FailureClosure?) {
let parameters = ["file":fileID]
networkInterface.request(.filesDelete, token: token, parameters: parameters, successClosure: {(response) in
let parameters = ["token": token, "file": fileID]
networkInterface.request(.filesDelete, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -261,8 +261,8 @@ public class SlackWebAPI {
}
public func fileInfo(_ fileID: String, commentCount: Int = 100, totalPages: Int = 1, success: ((_ file: File)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["file": fileID, "count": commentCount, "totalPages": totalPages]
networkInterface.request(.filesInfo, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "file": fileID, "count": commentCount, "totalPages": totalPages]
networkInterface.request(.filesInfo, parameters: parameters, successClosure: {(response) in
var file = File(file: response["file"] as? [String: Any])
(response["comments"] as? [[String: Any]])?.forEach { comment in
let comment = Comment(comment: comment)
@@ -277,8 +277,8 @@ public class SlackWebAPI {
}
public func uploadFile(_ file: Data, filename: String, filetype: String = "auto", title: String? = nil, initialComment: String? = nil, channels: [String]? = nil, success: ((_ file: File)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["filename": filename, "filetype": filetype, "title": title, "initial_comment": initialComment, "channels": channels?.joined(separator: ",")]
networkInterface.uploadRequest(token: token, data: file, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "filename": filename, "filetype": filetype, "title": title, "initial_comment": initialComment, "channels": channels?.joined(separator: ",")]
networkInterface.uploadRequest(data: file, parameters: parameters, successClosure: {(response) in
success?(File(file: response["file"] as? [String: Any]))
}) {(error) in
failure?(error)
@@ -287,8 +287,8 @@ public class SlackWebAPI {
//MARK: - File Comments
public func addFileComment(fileID: String, comment: String, success: ((_ comment: Comment)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["file":fileID, "comment":comment.slackFormatEscaping]
networkInterface.request(.filesCommentsAdd, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "file":fileID, "comment":comment.slackFormatEscaping]
networkInterface.request(.filesCommentsAdd, parameters: parameters, successClosure: {(response) in
success?(Comment(comment: response["comment"] as? [String: Any]))
}) {(error) in
failure?(error)
@@ -296,8 +296,8 @@ public class SlackWebAPI {
}
public func editFileComment(fileID: String, commentID: String, comment: String, success: ((_ comment: Comment)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["file":fileID, "id":commentID, "comment":comment.slackFormatEscaping]
networkInterface.request(.filesCommentsEdit, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "file":fileID, "id":commentID, "comment":comment.slackFormatEscaping]
networkInterface.request(.filesCommentsEdit, parameters: parameters, successClosure: {(response) in
success?(Comment(comment: response["comment"] as? [String: Any]))
}) {(error) in
failure?(error)
@@ -305,8 +305,8 @@ public class SlackWebAPI {
}
public func deleteFileComment(fileID: String, commentID: String, success: ((_ deleted: Bool?)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["file":fileID, "id": commentID]
networkInterface.request(.filesCommentsDelete, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "file":fileID, "id": commentID]
networkInterface.request(.filesCommentsDelete, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -355,8 +355,8 @@ public class SlackWebAPI {
}
public func openGroup(channel: String, success: ((_ opened: Bool)->Void)?, failure: FailureClosure?) {
let parameters = ["channel":channel]
networkInterface.request(.groupsOpen, token: token, parameters: parameters, successClosure: {(response) in
let parameters = ["token": token, "channel":channel]
networkInterface.request(.groupsOpen, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -413,8 +413,8 @@ public class SlackWebAPI {
}
public func openIM(userID: String, success: ((_ imID: String?)->Void)?, failure: FailureClosure?) {
let parameters = ["user":userID]
networkInterface.request(.imOpen, token: token, parameters: parameters, successClosure: {(response) in
let parameters = ["token": token, "user":userID]
networkInterface.request(.imOpen, parameters: parameters, successClosure: {(response) in
let group = response["channel"] as? [String: Any]
success?(group?["id"] as? String)
}) {(error) in
@@ -456,8 +456,8 @@ public class SlackWebAPI {
}
public func openMPIM(userIDs: [String], success: ((_ mpimID: String?)->Void)?, failure: FailureClosure?) {
let parameters = ["users":userIDs.joined(separator: ",")]
networkInterface.request(.mpimOpen, token: token, parameters: parameters, successClosure: {(response) in
let parameters = ["token": token, "users":userIDs.joined(separator: ",")]
networkInterface.request(.mpimOpen, parameters: parameters, successClosure: {(response) in
let group = response["group"] as? [String: Any]
success?(group?["id"] as? String)
}) {(error) in
@@ -483,8 +483,8 @@ public class SlackWebAPI {
}
private func pin(_ endpoint: Endpoint, channel: String, file: String? = nil, fileComment: String? = nil, timestamp: String? = nil, success: ((_ ok: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["channel":channel, "file":file, "file_comment":fileComment, "timestamp":timestamp]
networkInterface.request(endpoint, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "channel":channel, "file":file, "file_comment":fileComment, "timestamp":timestamp]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -511,8 +511,8 @@ public class SlackWebAPI {
}
private func react(_ endpoint: Endpoint, name: String, file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((_ ok: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["name":name, "file":file, "file_comment":fileComment, "channel":channel, "timestamp":timestamp]
networkInterface.request(endpoint, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "name":name, "file":file, "file_comment":fileComment, "channel":channel, "timestamp":timestamp]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -539,8 +539,8 @@ public class SlackWebAPI {
}
private func star(_ endpoint: Endpoint, file: String?, fileComment: String?, channel: String?, timestamp: String?, success: ((_ ok: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["file":file, "file_comment":fileComment, "channel":channel, "timestamp":timestamp]
networkInterface.request(endpoint, token: token, parameters: filterNilParameters(parameters), successClosure: {(response) in
let parameters: [String: Any?] = ["token": token, "file":file, "file_comment":fileComment, "channel":channel, "timestamp":timestamp]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -550,7 +550,7 @@ public class SlackWebAPI {
//MARK: - Team
public func teamInfo(success: ((_ info: [String: Any]?)->Void)?, failure: FailureClosure?) {
networkInterface.request(.teamInfo, token: token, parameters: nil, successClosure: {(response) in
networkInterface.request(.teamInfo, parameters: ["token": token], successClosure: {(response) in
success?(response["team"] as? [String: Any])
}) {(error) in
failure?(error)
@@ -559,8 +559,8 @@ public class SlackWebAPI {
//MARK: - Users
public func userPresence(user: String, success: ((_ presence: String?)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["user":user]
networkInterface.request(.usersGetPresence, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "user":user]
networkInterface.request(.usersGetPresence, parameters: parameters, successClosure: {(response) in
success?(response["presence"] as? String)
}) {(error) in
failure?(error)
@@ -568,8 +568,8 @@ public class SlackWebAPI {
}
public func userInfo(id: String, success: ((_ user: User)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["user":id]
networkInterface.request(.usersInfo, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "user":id]
networkInterface.request(.usersInfo, parameters: parameters, successClosure: {(response) in
success?(User(user: response["user"] as? [String: Any]))
}) {(error) in
failure?(error)
@@ -577,8 +577,8 @@ public class SlackWebAPI {
}
public func usersList(includePresence: Bool = false, success: ((_ userList: [[String: Any]]?)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["presence":includePresence]
networkInterface.request(.usersList, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "presence":includePresence]
networkInterface.request(.usersList, parameters: parameters, successClosure: {(response) in
success?(response["members"] as? [[String: Any]])
}) {(error) in
failure?(error)
@@ -586,7 +586,7 @@ public class SlackWebAPI {
}
public func setUserActive(success: ((_ success: Bool)->Void)?, failure: FailureClosure?) {
networkInterface.request(.usersSetActive, token: token, parameters: nil, successClosure: {(response) in
networkInterface.request(.usersSetActive, parameters: ["token": token], successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -594,8 +594,8 @@ public class SlackWebAPI {
}
public func setUserPresence(presence: Presence, success: ((_ success: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["presence":presence.rawValue]
networkInterface.request(.usersSetPresence, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "presence":presence.rawValue]
networkInterface.request(.usersSetPresence, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -604,8 +604,8 @@ public class SlackWebAPI {
//MARK: - Channel Utilities
private func close(_ endpoint: Endpoint, channelID: String, success: ((_ closed: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["channel":channelID]
networkInterface.request(endpoint, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "channel":channelID]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -613,8 +613,8 @@ public class SlackWebAPI {
}
private func history(_ endpoint: Endpoint, id: String, latest: String = "\(Date().slackTimestamp)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((_ history: History)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["channel": id, "latest": latest, "oldest": oldest, "inclusive":inclusive, "count":count, "unreads":unreads]
networkInterface.request(endpoint, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "channel": id, "latest": latest, "oldest": oldest, "inclusive":inclusive, "count":count, "unreads":unreads]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(History(history: response))
}) {(error) in
failure?(error)
@@ -622,8 +622,8 @@ public class SlackWebAPI {
}
private func info(_ endpoint: Endpoint, type: ChannelType, id: String, success: ((_ channel: Channel)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["channel": id]
networkInterface.request(endpoint, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "channel": id]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(Channel(channel: response[type.rawValue] as? [String: Any]))
}) {(error) in
failure?(error)
@@ -631,8 +631,8 @@ public class SlackWebAPI {
}
private func list(_ endpoint: Endpoint, type: ChannelType, excludeArchived: Bool = false, success: ((_ channels: [[String: Any]]?)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["exclude_archived": excludeArchived]
networkInterface.request(endpoint, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "exclude_archived": excludeArchived]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(response[type.rawValue+"s"] as? [[String: Any]])
}) {(error) in
failure?(error)
@@ -640,8 +640,8 @@ public class SlackWebAPI {
}
private func mark(_ endpoint: Endpoint, channel: String, timestamp: String, success: ((_ ts: String)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["channel": channel, "ts": timestamp]
networkInterface.request(endpoint, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "channel": channel, "ts": timestamp]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(timestamp)
}) {(error) in
failure?(error)
@@ -649,8 +649,8 @@ public class SlackWebAPI {
}
private func setInfo(_ endpoint: Endpoint, type: InfoType, channel: String, text: String, success: ((_ success: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any] = ["channel": channel, type.rawValue: text]
networkInterface.request(endpoint, token: token, parameters: parameters, successClosure: {(response) in
let parameters: [String: Any] = ["token": token, "channel": channel, type.rawValue: text]
networkInterface.request(endpoint, parameters: parameters, successClosure: {(response) in
success?(true)
}) {(error) in
failure?(error)
@@ -676,17 +676,6 @@ public class SlackWebAPI {
return nil
}
//MARK: - Filter Nil Parameters
internal func filterNilParameters(_ parameters: [String: Any?]) -> [String: Any] {
var finalParameters = [String: Any]()
for (key, value) in parameters {
if let unwrapped = value {
finalParameters[key] = unwrapped
}
}
return finalParameters
}
//MARK: - Enumerate Do Not Disturb Status
private func enumerateDNDStatuses(_ statuses: [String: Any]) -> [String: DoNotDisturbStatus] {
var retVal = [String: DoNotDisturbStatus]()