Skip to content
This repository was archived by the owner on Dec 2, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 77 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
![SlackKit](https://cloud.githubusercontent.com/assets/8311605/10260893/5ec60f96-694e-11e5-91fd-da6845942201.png)
##iOS/OS X Slack Client Library
###Description
This is a Slack client library for iOS and OS X written in Swift. It's intended to expose all of the functionality of Slack's [Real Time Messaging API](https://api.slack.com/rtm).
This is a Slack client library for iOS and OS X 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).

###Installation
####Swift Package Manager (Swift 2.2 and up)
####Swift Package Manager
Add SlackKit to your Package.swift

```swift
Expand Down Expand Up @@ -37,17 +37,88 @@ import SlackKit
###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, give it to the Client:
Once you have a token, initialize a client instance using it:
```swift
Client.sharedInstance.setAuthToken("YOUR_SLACK_AUTH_TOKEN")
let client = Client(apiToken: "YOUR_SLACK_API_TOKEN")

```
and connect:

If you want to receive messages from the Slack RTM API, connect to it.
```swift
Client.sharedInstance.connect()
client.connect()
```

Once connected, the client will begin to consume any messages sent by the Slack RTM API.

####Web API Methods
SlackKit currently supports the a subset of the Slack Web APIs that are available to bot users:

- api.test
- auth.test
- channels.history
- channels.info
- channels.list
- channels.mark
- channels.setPurpose
- channels.setTopic
- chat.delete
- chat.postMessage
- chat.update
- emoji.list
- files.delete
- files.upload
- groups.close
- groups.history
- groups.info
- groups.list
- groups.mark
- groups.open
- groups.setPurpose
- groups.setTopic
- im.close
- im.history
- im.list
- im.mark
- im.open
- mpim.close
- mpim.history
- mpim.list
- mpim.mark
- mpim.open
- pins.add
- pins.list
- pins.remove
- reactions.add
- reactions.get
- reactions.list
- reactions.remove
- rtm.start
- stars.add
- stars.remove
- team.info
- users.getPresence
- users.info
- users.list
- users.setActive
- users.setPresence

They can be accessed through a Client object’s `webAPI` property:
```swift
client.webAPI.authenticationTest({
(authenticated) -> Void in
print(authenticated)
}){(error) -> Void in
print(error)
}
```

####Delegate methods

To receive delegate callbacks for certain events, register an object as the delegate for those events:
```swift
client.slackEventsDelegate = self
```

There are a number of delegates that you can set to receive callbacks for certain events.

#####SlackEventsDelegate
Expand Down Expand Up @@ -138,18 +209,6 @@ func subteamSelfAdded(subteamID: String)
func subteamSelfRemoved(subteamID: String)
```

###Examples
####Sending a Message:
```swift
Client.sharedInstance.sendMessage(message: "Hello, world!", channelID: "CHANNEL_ID")
```

####Print a List of Users in a Channel:
```swift
let users = Client.sharedInstance.channels?["CHANNEL_ID"]?.members
print(users)
```

###Get In Touch
[@pvzig](https://twitter.com/pvzig)

Expand Down
2 changes: 1 addition & 1 deletion SlackKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SlackKit"
s.version = "0.9.7"
s.version = "0.9.6"
s.summary = "a Slack client library for iOS and OS X written in Swift"
s.homepage = "https://github.com/pvzig/SlackKit"
s.license = 'MIT'
Expand Down
12 changes: 12 additions & 0 deletions SlackKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
260EC2331C4DC61D0093B253 /* ClientExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2301C4DC61D0093B253 /* ClientExtensions.swift */; };
260EC2341C4DC61D0093B253 /* NetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2311C4DC61D0093B253 /* NetworkInterface.swift */; };
260EC2351C4DC61D0093B253 /* SlackWebAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2321C4DC61D0093B253 /* SlackWebAPI.swift */; };
26BBA1941C398E3C00BF7225 /* Bot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1871C398E3C00BF7225 /* Bot.swift */; };
26BBA1951C398E3C00BF7225 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1881C398E3C00BF7225 /* Channel.swift */; };
26BBA1961C398E3C00BF7225 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1891C398E3C00BF7225 /* Client.swift */; };
Expand All @@ -25,6 +28,9 @@

/* Begin PBXFileReference section */
26072A341BB48B3A00CD650C /* SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
260EC2301C4DC61D0093B253 /* ClientExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ClientExtensions.swift; path = Sources/ClientExtensions.swift; sourceTree = "<group>"; };
260EC2311C4DC61D0093B253 /* NetworkInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NetworkInterface.swift; path = Sources/NetworkInterface.swift; sourceTree = "<group>"; };
260EC2321C4DC61D0093B253 /* SlackWebAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SlackWebAPI.swift; path = Sources/SlackWebAPI.swift; sourceTree = "<group>"; };
2661A6A41BBF62FF0026F67B /* SlackKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SlackKit.h; sourceTree = "<group>"; };
266E05F01BBF780C00840D76 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
26BBA1871C398E3C00BF7225 /* Bot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Bot.swift; path = Sources/Bot.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -90,16 +96,19 @@
26BBA1871C398E3C00BF7225 /* Bot.swift */,
26BBA1881C398E3C00BF7225 /* Channel.swift */,
26BBA1891C398E3C00BF7225 /* Client.swift */,
260EC2301C4DC61D0093B253 /* ClientExtensions.swift */,
26BBA18A1C398E3C00BF7225 /* Event.swift */,
26BBA18B1C398E3C00BF7225 /* EventDelegate.swift */,
26BBA18C1C398E3C00BF7225 /* EventDispatcher.swift */,
26BBA18D1C398E3C00BF7225 /* EventHandler.swift */,
26BBA18E1C398E3C00BF7225 /* File.swift */,
26BBA18F1C398E3C00BF7225 /* Message.swift */,
260EC2311C4DC61D0093B253 /* NetworkInterface.swift */,
26BBA1901C398E3C00BF7225 /* Team.swift */,
26BBA1911C398E3C00BF7225 /* Types.swift */,
26BBA1921C398E3C00BF7225 /* User.swift */,
26BBA1931C398E3C00BF7225 /* UserGroup.swift */,
260EC2321C4DC61D0093B253 /* SlackWebAPI.swift */,
2661A6A41BBF62FF0026F67B /* SlackKit.h */,
266E05F01BBF780C00840D76 /* Info.plist */,
);
Expand Down Expand Up @@ -236,9 +245,12 @@
26BBA1971C398E3C00BF7225 /* Event.swift in Sources */,
26BBA1941C398E3C00BF7225 /* Bot.swift in Sources */,
26BBA19B1C398E3C00BF7225 /* File.swift in Sources */,
260EC2351C4DC61D0093B253 /* SlackWebAPI.swift in Sources */,
26BBA19C1C398E3C00BF7225 /* Message.swift in Sources */,
26BBA19D1C398E3C00BF7225 /* Team.swift in Sources */,
260EC2331C4DC61D0093B253 /* ClientExtensions.swift in Sources */,
26BBA1A01C398E3C00BF7225 /* UserGroup.swift in Sources */,
260EC2341C4DC61D0093B253 /* NetworkInterface.swift in Sources */,
26BBA1981C398E3C00BF7225 /* EventDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
79 changes: 33 additions & 46 deletions SlackKit/Sources/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,50 +50,46 @@ public class Client: WebSocketDelegate {
public var reactionEventsDelegate: ReactionEventsDelegate?
public var teamEventsDelegate: TeamEventsDelegate?
public var subteamEventsDelegate: SubteamEventsDelegate?

internal var token = "SLACK_AUTH_TOKEN"

private var token = "SLACK_AUTH_TOKEN"
public func setAuthToken(token: String) {
self.token = token
}

private var webSocket: WebSocket?
private var dispatcher: EventDispatcher?

required public init() {
public var webAPI: SlackWebAPI {
return SlackWebAPI(client: self)
}

internal var webSocket: WebSocket?
private var dispatcher: EventDispatcher?

internal let api = NetworkInterface()

public static let sharedInstance = Client()
required public init(apiToken: String) {
self.token = apiToken
}

//MARK: - Connection
public func connect() {
dispatcher = EventDispatcher(client: self)
let request = NSURLRequest(URL: NSURL(string:"https://slack.com/api/rtm.start?token="+token)!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.currentQueue()!) {
(response, data, error) -> Void in
guard let data = data else {
return
webAPI.rtmStart(success: {
(response) -> Void in
self.initialSetup(response)
if let socketURL = response["url"] as? String {
let url = NSURL(string: socketURL)
self.webSocket = WebSocket(url: url!)
self.webSocket?.delegate = self
self.webSocket?.connect()
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: AnyObject]
if (result["ok"] as! Bool == true) {
self.initialSetup(result)
let socketURL = NSURL(string: result["url"] as! String)
self.webSocket = WebSocket(url: socketURL!)
self.webSocket?.delegate = self
self.webSocket?.connect()
}
} catch _ {
print(error)
}
}
}, failure:nil)
}

//MARK: - Message send
public func sendMessage(message: String, channelID: String) {
if (connected) {
if let data = formatMessageToSlackJsonString(msg: message, channel: channelID) {
let string = NSString(data: data, encoding: NSUTF8StringEncoding)
self.webSocket?.writeString(string as! String)
webSocket?.writeString(string as! String)
}
}
}
Expand All @@ -103,7 +99,7 @@ public class Client: WebSocketDelegate {
"id": NSDate().timeIntervalSince1970,
"type": "message",
"channel": message.channel,
"text": slackFormatEscaping(message.msg)
"text": message.msg.slackFormatEscaping()
]
addSentMessage(json)
do {
Expand All @@ -124,15 +120,8 @@ public class Client: WebSocketDelegate {
sentMessages[ts!.stringValue] = Message(message: message)
}

private func slackFormatEscaping(string: String) -> String {
var escapedString = string.stringByReplacingOccurrencesOfString("&", withString: "&amp;")
escapedString = escapedString.stringByReplacingOccurrencesOfString("<", withString: "&lt;")
escapedString = escapedString.stringByReplacingOccurrencesOfString(">", withString: "&gt;")
return escapedString
}

//MARK: - Client setup
private func initialSetup(json: [String: AnyObject]) {
internal func initialSetup(json: [String: AnyObject]) {
team = Team(team: json["team"] as? [String: AnyObject])
authenticatedUser = User(user: json["self"] as? [String: AnyObject])
authenticatedUser?.doNotDisturbStatus = DoNotDisturbStatus(status: json["dnd"] as? [String: AnyObject])
Expand All @@ -145,7 +134,7 @@ public class Client: WebSocketDelegate {
enumerateSubteams(json["subteams"] as? [String: AnyObject])
}

private func enumerateUsers(users: [AnyObject]?) {
internal func enumerateUsers(users: [AnyObject]?) {
if let users = users {
for user in users {
let u = User(user: user as? [String: AnyObject])
Expand All @@ -154,7 +143,7 @@ public class Client: WebSocketDelegate {
}
}

private func enumerateChannels(channels: [AnyObject]?) {
internal func enumerateChannels(channels: [AnyObject]?) {
if let channels = channels {
for channel in channels {
let c = Channel(channel: channel as? [String: AnyObject])
Expand All @@ -163,7 +152,7 @@ public class Client: WebSocketDelegate {
}
}

private func enumerateGroups(groups: [AnyObject]?) {
internal func enumerateGroups(groups: [AnyObject]?) {
if let groups = groups {
for group in groups {
let g = Channel(channel: group as? [String: AnyObject])
Expand All @@ -172,7 +161,7 @@ public class Client: WebSocketDelegate {
}
}

private func enumerateIMs(ims: [AnyObject]?) {
internal func enumerateIMs(ims: [AnyObject]?) {
if let ims = ims {
for im in ims {
let i = Channel(channel: im as? [String: AnyObject])
Expand All @@ -181,7 +170,7 @@ public class Client: WebSocketDelegate {
}
}

private func enumerateMPIMs(mpims: [AnyObject]?) {
internal func enumerateMPIMs(mpims: [AnyObject]?) {
if let mpims = mpims {
for mpim in mpims {
let m = Channel(channel: mpim as? [String: AnyObject])
Expand All @@ -190,7 +179,7 @@ public class Client: WebSocketDelegate {
}
}

private func enumerateBots(bots: [AnyObject]?) {
internal func enumerateBots(bots: [AnyObject]?) {
if let bots = bots {
for bot in bots {
let b = Bot(bot: bot as? [String: AnyObject])
Expand All @@ -199,7 +188,7 @@ public class Client: WebSocketDelegate {
}
}

private func enumerateSubteams(subteams: [String: AnyObject]?) {
internal func enumerateSubteams(subteams: [String: AnyObject]?) {
if let subteams = subteams {
if let all = subteams["all"] as? [[String: AnyObject]] {
for item in all {
Expand All @@ -217,8 +206,7 @@ public class Client: WebSocketDelegate {
}

// MARK: - WebSocketDelegate
public func websocketDidConnect(socket: WebSocket) {
}
public func websocketDidConnect(socket: WebSocket) {}

public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
connected = false
Expand All @@ -241,7 +229,6 @@ public class Client: WebSocketDelegate {
}
}

public func websocketDidReceiveData(socket: WebSocket, data: NSData) {
}
public func websocketDidReceiveData(socket: WebSocket, data: NSData) {}

}
Loading