Compare commits

...

30 Commits

Author SHA1 Message Date
Peter Zignego 28bd612ca0 Carthage search paths 2016-10-11 21:18:34 -04:00
Peter Zignego 45cf2a7ac0 Add back links for carthage 2016-10-11 21:12:31 -04:00
Peter Zignego f7c986c65c Update dependency managers 2016-10-11 21:01:17 -04:00
Peter Zignego ca43df4475 Update project file 2016-10-11 19:43:14 -04:00
Peter Zignego ef71b6abf0 Swifter compatability 2016-10-11 19:41:36 -04:00
Peter Zignego 3ff922a2c0 Project file update 2016-10-11 19:41:28 -04:00
Peter Zignego 646c371bd3 SPM compatability 2016-10-01 12:37:13 -04:00
Peter Zignego 36401009f8 Version bump 2016-09-26 00:05:13 -04:00
Peter Zignego b837554dcf Delete Package.swift until SPM compatability is restored 2016-09-25 23:54:25 -04:00
Peter Zignego 0ba0e019ae Update README.md 2016-09-25 23:52:53 -04:00
Peter Zignego 8771ef3f0a Update readme 2016-09-25 23:51:32 -04:00
Peter Zignego 71e7238483 Merge branch 'swift3'
# Conflicts:
#	README.md
#	SlackKit/Sources/Action.swift
#	SlackKit/Sources/Response.swift
#	SlackKit/Sources/SlackKit.swift
2016-09-25 20:35:45 -04:00
Peter Zignego b75c10fca6 Merge pull request #53 from pvzig/swift3-GM
Swift 3
2016-09-25 20:31:44 -04:00
Peter Zignego 50f85ac103 Carthage 2016-09-20 00:23:26 -04:00
Peter Zignego a7cbb84b34 Update starscream delegate 2016-09-20 00:23:08 -04:00
Peter Zignego ed6789c9a5 Swift 3 update 2016-09-19 23:59:10 -04:00
Peter Zignego ca444930a4 GM 2016-09-14 21:39:32 -04:00
Peter Zignego 21051864ec Add badges 2016-09-13 00:10:55 -04:00
Peter Zignego 36d1553072 Update README.md 2016-09-12 23:42:17 -04:00
Peter Zignego eb14758846 Add badges 2016-09-12 23:40:48 -04:00
Peter Zignego bf3a5c2422 Merge pull request #47 from hiragram/add-missing-scope
Add MissingScope
2016-08-21 22:40:59 -04:00
Yuya 98fd1342e7 Add MissingScope 2016-08-21 13:38:49 +09:00
Peter Zignego 183ed91cb8 Merge branch 'xcode8b4' into swift3 2016-08-03 22:47:16 -04:00
Peter Zignego c241dcf1df Xcode 8 beta 4 2016-08-03 22:47:03 -04:00
Peter Zignego 8007fa6f0f Include style in Action JSON dictionary 2016-08-02 23:24:12 -04:00
Peter Zignego 7ab973a03b Include style in Action JSON dictionary 2016-08-02 23:21:16 -04:00
Peter Zignego 1889ffeeee Fix callback bug when authing via a provided token 2016-07-26 19:11:26 -04:00
Peter Zignego 987be40c91 Fix callback bug when authing via a token 2016-07-26 19:07:53 -04:00
Peter Zignego 2e71ac6876 Bug fix 2016-07-23 11:12:14 -04:00
Peter Zignego df661762a9 Bug fix 2016-07-23 11:09:54 -04:00
55 changed files with 757 additions and 730 deletions
+1
View File
@@ -16,6 +16,7 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate
*.DS_Store
# SwiftPM
Packages/
+2 -2
View File
@@ -1,2 +1,2 @@
github "https://github.com/pvzig/swifter.git" "master"
github "https://github.com/pvzig/Starscream.git" "swift3"
git "https://github.com/daltoniam/Starscream" == 2.0.0
git "https://github.com/pvzig/swifter.git" == 3.0.4
+2 -2
View File
@@ -1,2 +1,2 @@
github "pvzig/Starscream" "98d7ccea30621d51a93ee5c155b3f670e37e037b"
github "pvzig/swifter" "8adfae89a6d34cfea1c20d53d8112d1d69e01bd0"
git "https://github.com/daltoniam/Starscream" "2.0.0"
git "https://github.com/pvzig/swifter.git" "3.0.4"
+3 -27
View File
@@ -1,26 +1,3 @@
//
// Package.swift
//
// Copyright © 2016 Peter Zignego. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import PackageDescription
let package = Package(
@@ -28,8 +5,7 @@ let package = Package(
targets: [],
dependencies: [
.Package(url: "https://github.com/pvzig/swifter.git",
majorVersion: 1, minor: 3),
.Package(url: "https://github.com/pvzig/Starscream.git", majorVersion: 1, minor: 2)
],
exclude: ["Examples", "Carthage", "Pods"]
majorVersion: 3, minor: 0),
.Package(url: "https://github.com/daltoniam/Starscream", majorVersion: 2, minor: 0)
]
)
+18
View File
@@ -0,0 +1,18 @@
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
target 'SlackKit OS X' do
pod 'Starscream', '~> 2.0.0'
pod 'Swifter', '~> 1.3.2'
end
target 'SlackKit iOS' do
pod 'Starscream', '~> 2.0.0'
pod 'Swifter', '~> 1.3.2'
end
target 'SlackKit tvOS' do
pod 'Starscream', '~> 2.0.0'
pod 'Swifter', '~> 1.3.2'
end
+15
View File
@@ -0,0 +1,15 @@
PODS:
- Starscream (2.0.0)
- Swifter (1.3.2)
DEPENDENCIES:
- Starscream (~> 2.0.0)
- Swifter (~> 1.3.2)
SPEC CHECKSUMS:
Starscream: 947c865596f0d6bb3f0203fee23228ed2d471468
Swifter: dd1800ba8eb3e28b22b8bd20f91a8561a0110fac
PODFILE CHECKSUM: 3d4e92bde92fd20d6fe672ad26f677fcbfafda1f
COCOAPODS: 1.1.0.rc.3
+80 -65
View File
@@ -1,23 +1,36 @@
![SlackKit](https://cloud.githubusercontent.com/assets/8311605/10260893/5ec60f96-694e-11e5-91fd-da6845942201.png)
![Swift Version](https://img.shields.io/badge/Swift-3.0-orange.svg) ![Plaforms](https://img.shields.io/badge/Platforms-macOS,iOS,tvOS-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) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-brightgreen.svg)](https://github.com/Carthage/Carthage)
## SlackKit: A Swift Slack Client Library
### Description
This is the Swift 3 beta branch. It will continue to track the Xcode 8 beta releases until it is officially released, at which point Swift 3 will be merged down to the master branch.
SlackKit also supports: [Swift 2.2](https://github.com/pvzig/SlackKit/), [Linux](https://github.com/pvzig/SlackKit/tree/linux)
This is a Slack client library for OS X, iOS, and tvOS 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 to [bot users](https://api.slack.com/bot-users). SlackKit also supports Slacks [OAuth 2.0](https://api.slack.com/docs/oauth) flow including the [Add to Slack](https://api.slack.com/docs/slack-button) and [Sign in with Slack](https://api.slack.com/docs/sign-in-with-slack) buttons, [incoming webhooks](https://api.slack.com/incoming-webhooks), [slash commands](https://api.slack.com/slash-commands), and [message buttons](https://api.slack.com/docs/message-buttons).
This is the **Swift 3** branch of SlackKit. SlackKit also has support for [Swift 2.3](https://github.com/pvzig/SlackKit/tree/swift2.3) and [Linux](https://github.com/pvzig/SlackKit/tree/linux).
#### Building the SlackKit Framework
To build the SlackKit project directly, first build the dependencies using Carthage or CocoaPods. To use the framework in your application, install it in one of the following ways:
### Installation
#### CocoaPods
Add SlackKit to your pod file:
```
use_frameworks!
pod 'SlackKit', '~> 3.1.2'
```
and run
```
# Use CocoaPods version >= 1.1.0.rc.2 (gem install cocoapods --pre)
pod install
```
#### Carthage
Add SlackKit to your Cartfile:
```
github "https://github.com/pvzig/slackkit.git" "swift3"
github "https://github.com/pvzig/slackkit.git"
```
and run
```
@@ -27,19 +40,22 @@ carthage bootstrap
```
carthage bootstrap --configuration "Debug"
```
Drag the built `SlackKit.framework` into your Xcode project.
#### Swift Package Manager
Add SlackKit to your Package.swift
```swift
import PackageDescription
let package = Package(
dependencies: [
.Package(url: "https://github.com/pvzig/SlackKit.git", majorVersion: 3)
]
dependencies: [
.Package(url: "https://github.com/pvzig/SlackKit.git", majorVersion: 3)
]
)
```
Run `swift build` on your applications main directory.
To use the library in your project import it:
@@ -183,23 +199,22 @@ 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
client.webAPI.authenticationTest({(auth) in
print(auth)
}, failure: {(error) in
print(error)
}
})
```
#### Delegate methods
To receive delegate callbacks for events, register an object as the delegate for those events using the `onClientInitalization` block:
```swift
let bot = SlackKit(clientID: "CLIENT_ID", clientSecret: "CLIENT_SECRET")
let bot = SlackKit(clientID: clientID, clientSecret: clientSecret)
bot.onClientInitalization = { (client: Client) in
dispatch_async(dispatch_get_main_queue(), {
client.connectionEventsDelegate = self
DispatchQueue.main.async(execute: {
client.messageEventsDelegate = self
})
})
}
```
@@ -209,90 +224,90 @@ There are a number of delegates that you can set to receive callbacks for certai
##### ConnectionEventsDelegate
```swift
clientConnected(client: Client)
clientDisconnected(client: Client)
clientConnectionFailed(client: Client, error: SlackError)
connected(_ client: Client)
disconnected(_ client: Client)
connectionFailed(_ client: Client, error: SlackError)
```
##### MessageEventsDelegate
```swift
messageSent(client: Client, message: Message)
messageReceived(client: Client, message: Message)
messageChanged(client: Client, message: Message)
messageDeleted(client: Client, message: Message?)
sent(_ message: Message, client: Client)
received(_ message: Message, client: Client)
changed(_ message: Message, client: Client)
deleted(_ message: Message?, client: Client)
```
##### ChannelEventsDelegate
```swift
userTyping(client: Client, channel: Channel, user: User)
channelMarked(client: Client, channel: Channel, timestamp: String)
channelCreated(client: Client, channel: Channel)
channelDeleted(client: Client, channel: Channel)
channelRenamed(client: Client, channel: Channel)
channelArchived(client: Client, channel: Channel)
channelHistoryChanged(client: Client, channel: Channel)
channelJoined(client: Client, channel: Channel)
channelLeft(client: Client, 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
```swift
doNotDisturbUpdated(client: Client, dndStatus: DoNotDisturbStatus)
doNotDisturbUserUpdated(client: Client, dndStatus: DoNotDisturbStatus, user: User)
updated(_ status: DoNotDisturbStatus, client: Client)
userUpdated(_ status: DoNotDisturbStatus, user: User, client: Client)
```
##### GroupEventsDelegate
```swift
groupOpened(client: Client, group: Channel)
opened(_ group: Channel, client: Client)
```
##### FileEventsDelegate
```swift
fileProcessed(client: Client, file: File)
fileMadePrivate(client: Client, file: File)
fileDeleted(client: Client, file: File)
fileCommentAdded(client: Client, file: File, comment: Comment)
fileCommentEdited(client: Client, file: File, comment: Comment)
fileCommentDeleted(client: Client, 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
```swift
itemPinned(client: Client, item: Item, channel: Channel?)
itemUnpinned(client: Client, item: Item, channel: Channel?)
pinned(_ item: Item, channel: Channel?, client: Client)
unpinned(_ item: Item, channel: Channel?, client: Client)
```
##### StarEventsDelegate
```swift
itemStarred(client: Client, item: Item, star: Bool)
starred(_ item: Item, starred: Bool, _ client: Client)
```
##### ReactionEventsDelegate
```swift
reactionAdded(client: Client, reaction: String, item: Item, itemUser: String)
reactionRemoved(client: Client, reaction: String, item: Item, itemUser: String)
added(_ reaction: String, item: Item, itemUser: String, client: Client)
removed(_ reaction: String, item: Item, itemUser: String, client: Client)
```
##### SlackEventsDelegate
```swift
preferenceChanged(client: Client, preference: String, value: AnyObject?)
userChanged(client: Client, user: User)
presenceChanged(client: Client, user: User, presence: String)
manualPresenceChanged(client: Client, user: User, presence: String)
botEvent(client: Client, bot: Bot)
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)
```
##### TeamEventsDelegate
```swift
teamJoined(client: Client, user: User)
teamPlanChanged(client: Client, plan: String)
teamPreferencesChanged(client: Client, preference: String, value: AnyObject?)
teamNameChanged(client: Client, name: String)
teamDomainChanged(client: Client, domain: String)
teamEmailDomainChanged(client: Client, domain: String)
teamEmojiChanged(client: Client)
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
subteamEvent(client: Client, userGroup: UserGroup)
subteamSelfAdded(client: Client, subteamID: String)
subteamSelfRemoved(client: Client, subteamID: String)
event(_ userGroup: UserGroup, client: Client)
selfAdded(_ subteamID: String, client: Client)
selfRemoved(_ subteamID: String, client: Client)
```
##### TeamProfileEventsDelegate
```swift
teamProfileChanged(client: Client, profile: CustomProfile)
teamProfileDeleted(client: Client, profile: CustomProfile)
teamProfileReordered(client: Client, profile: CustomProfile)
changed(_ profile: CustomProfile, client: Client)
deleted(_ profile: CustomProfile, client: Client)
reordered(_ profile: CustomProfile, client: Client)
```
### Examples
+18
View File
@@ -0,0 +1,18 @@
Pod::Spec.new do |s|
s.name = "SlackKit"
s.version = "3.1.2"
s.summary = "a Slack client library for OS X, iOS, and tvOS written in Swift"
s.homepage = "https://github.com/pvzig/SlackKit"
s.license = 'MIT'
s.author = { "Peter Zignego" => "peter@launchsoft.co" }
s.source = { :git => "https://github.com/pvzig/SlackKit.git", :tag => s.version.to_s }
s.social_media_url = 'https://twitter.com/pvzig'
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.10'
s.tvos.deployment_target = '9.0'
s.requires_arc = true
s.source_files = 'SlackKit/Sources/*.swift'
s.frameworks = 'Foundation'
s.dependency 'Starscream'
s.dependency 'Swifter'
end
+26 -16
View File
@@ -30,7 +30,6 @@
263993A71CE90EE0004A6E93 /* Client+EventHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A85FF81CE3BCEF00756C40 /* Client+EventHandling.swift */; };
263993A81CE90EE0004A6E93 /* NetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2311C4DC61D0093B253 /* NetworkInterface.swift */; };
263993A91CE90EE0004A6E93 /* EventDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18B1C398E3C00BF7225 /* EventDelegate.swift */; };
263993AB1CE90EE0004A6E93 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4307A07F1CC6D0910011D5DE /* Starscream.framework */; };
263993AD1CE90EE0004A6E93 /* SlackKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 2661A6A41BBF62FF0026F67B /* SlackKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
263993B61CE90EED004A6E93 /* Client+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16C98791CE7D3DD00692776 /* Client+Utilities.swift */; };
263993B71CE90EED004A6E93 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1881C398E3C00BF7225 /* Channel.swift */; };
@@ -50,8 +49,13 @@
263993C61CE90EED004A6E93 /* Client+EventHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A85FF81CE3BCEF00756C40 /* Client+EventHandling.swift */; };
263993C71CE90EED004A6E93 /* NetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2311C4DC61D0093B253 /* NetworkInterface.swift */; };
263993C81CE90EED004A6E93 /* EventDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18B1C398E3C00BF7225 /* EventDelegate.swift */; };
263993CA1CE90EED004A6E93 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4307A07F1CC6D0910011D5DE /* Starscream.framework */; };
263993CC1CE90EED004A6E93 /* SlackKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 2661A6A41BBF62FF0026F67B /* SlackKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
2659FC1B1DADC4E0003F3930 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4307A07F1CC6D0910011D5DE /* Starscream.framework */; };
2659FC1C1DADC4E0003F3930 /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26B30B6B1D289FA0004D4AB5 /* Swifter.framework */; };
2659FC1D1DADC4F2003F3930 /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26B30B6E1D289FB2004D4AB5 /* Swifter.framework */; };
2659FC1F1DADC4F2003F3930 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2659FC1E1DADC4F2003F3930 /* Starscream.framework */; };
2659FC201DADC4FC003F3930 /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 269B47CB1D3AE5670042D137 /* Swifter.framework */; };
2659FC221DADC4FC003F3930 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2659FC211DADC4FC003F3930 /* Starscream.framework */; };
2678B5941D3151B900CE521A /* AuthorizeResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2678B5931D3151B900CE521A /* AuthorizeResponse.swift */; };
2678B5951D3151B900CE521A /* AuthorizeResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2678B5931D3151B900CE521A /* AuthorizeResponse.swift */; };
2678B5961D3151B900CE521A /* AuthorizeResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2678B5931D3151B900CE521A /* AuthorizeResponse.swift */; };
@@ -77,7 +81,6 @@
269B47CE1D3C22FC0042D137 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269B47CD1D3C22FC0042D137 /* ClientOptions.swift */; };
269B47CF1D3C22FC0042D137 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269B47CD1D3C22FC0042D137 /* ClientOptions.swift */; };
269B47D01D3C22FC0042D137 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 269B47CD1D3C22FC0042D137 /* ClientOptions.swift */; };
26B30B6C1D289FA0004D4AB5 /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26B30B6B1D289FA0004D4AB5 /* Swifter.framework */; };
26B30B881D297A98004D4AB5 /* MessageActionRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B30B871D297A98004D4AB5 /* MessageActionRequest.swift */; };
26B30B901D298E08004D4AB5 /* MessageActionServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B30B8F1D298E08004D4AB5 /* MessageActionServer.swift */; };
26B30B921D298E12004D4AB5 /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26B30B911D298E12004D4AB5 /* Server.swift */; };
@@ -145,9 +148,6 @@
26EC14FB1D1F355A00FD3A53 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EC14F81D1F355A00FD3A53 /* Action.swift */; };
26EC15011D260B1000FD3A53 /* WebhookServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EC15001D260B1000FD3A53 /* WebhookServer.swift */; };
26EC15021D260B1000FD3A53 /* WebhookServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26EC15001D260B1000FD3A53 /* WebhookServer.swift */; };
26F76EB21D40318F00C3A3DD /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26B30B6E1D289FB2004D4AB5 /* Swifter.framework */; };
26F76EB31D40319700C3A3DD /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 269B47CB1D3AE5670042D137 /* Swifter.framework */; };
4307A0801CC6D0910011D5DE /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4307A07F1CC6D0910011D5DE /* Starscream.framework */; };
C16C987A1CE7D3DD00692776 /* Client+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16C98791CE7D3DD00692776 /* Client+Utilities.swift */; };
C1A85FF91CE3BCEF00756C40 /* Client+EventDispatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A85FF71CE3BCEF00756C40 /* Client+EventDispatching.swift */; };
C1A85FFA1CE3BCEF00756C40 /* Client+EventHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A85FF81CE3BCEF00756C40 /* Client+EventHandling.swift */; };
@@ -161,6 +161,8 @@
260EC2321C4DC61D0093B253 /* WebAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebAPI.swift; path = Sources/WebAPI.swift; sourceTree = "<group>"; };
263993B21CE90EE0004A6E93 /* SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
263993D11CE90EED004A6E93 /* SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2659FC1E1DADC4F2003F3930 /* Starscream.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Starscream.framework; path = Carthage/Build/iOS/Starscream.framework; sourceTree = "<group>"; };
2659FC211DADC4FC003F3930 /* Starscream.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Starscream.framework; path = Carthage/Build/tvOS/Starscream.framework; sourceTree = "<group>"; };
2661A6A41BBF62FF0026F67B /* SlackKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SlackKit.h; sourceTree = "<group>"; };
2678B5931D3151B900CE521A /* AuthorizeResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AuthorizeResponse.swift; path = Sources/AuthorizeResponse.swift; sourceTree = "<group>"; };
268E46131CE8F79D009F19CC /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-iOS.plist"; path = "Supporting Files/Info-iOS.plist"; sourceTree = "<group>"; };
@@ -217,8 +219,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4307A0801CC6D0910011D5DE /* Starscream.framework in Frameworks */,
26B30B6C1D289FA0004D4AB5 /* Swifter.framework in Frameworks */,
2659FC1B1DADC4E0003F3930 /* Starscream.framework in Frameworks */,
2659FC1C1DADC4E0003F3930 /* Swifter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -226,8 +228,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
263993AB1CE90EE0004A6E93 /* Starscream.framework in Frameworks */,
26F76EB21D40318F00C3A3DD /* Swifter.framework in Frameworks */,
2659FC1F1DADC4F2003F3930 /* Starscream.framework in Frameworks */,
2659FC1D1DADC4F2003F3930 /* Swifter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -235,8 +237,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
263993CA1CE90EED004A6E93 /* Starscream.framework in Frameworks */,
26F76EB31D40319700C3A3DD /* Swifter.framework in Frameworks */,
2659FC221DADC4FC003F3930 /* Starscream.framework in Frameworks */,
2659FC201DADC4FC003F3930 /* Swifter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -353,6 +355,8 @@
CA70A3A1A9A1A259960DFBCF /* Frameworks */ = {
isa = PBXGroup;
children = (
2659FC211DADC4FC003F3930 /* Starscream.framework */,
2659FC1E1DADC4F2003F3930 /* Starscream.framework */,
269B47CB1D3AE5670042D137 /* Swifter.framework */,
26B30B6E1D289FB2004D4AB5 /* Swifter.framework */,
26B30B6B1D289FA0004D4AB5 /* Swifter.framework */,
@@ -678,8 +682,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
@@ -725,8 +731,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
@@ -755,7 +763,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -782,7 +790,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -810,6 +818,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -818,7 +827,6 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/SlackKit/Supporting Files/Info-iOS.plist";
@@ -841,6 +849,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -849,7 +858,6 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/SlackKit/Supporting Files/Info-iOS.plist";
@@ -871,6 +879,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -900,6 +909,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
+9 -10
View File
@@ -30,13 +30,13 @@ public struct Action {
public let style: ActionStyle?
public let confirm: Confirm?
internal init(action:[String: AnyObject]?) {
internal init(action:[String: Any]?) {
name = action?["name"] as? String
text = action?["text"] as? String
type = action?["type"] as? String
value = action?["value"] as? String
style = ActionStyle(rawValue: action?["style"] as? String ?? "")
confirm = Confirm(confirm:action?["confirm"] as? [String: AnyObject])
confirm = Confirm(confirm:action?["confirm"] as? [String: Any])
}
public init(name: String, text: String, style: ActionStyle = .Default, value: String? = nil, confirm: Confirm? = nil) {
@@ -48,13 +48,14 @@ public struct Action {
self.confirm = confirm
}
internal func dictionary() -> [String: AnyObject] {
var dict = [String: AnyObject]()
internal var dictionary: [String: Any] {
var dict = [String: Any]()
dict["name"] = name
dict["text"] = text
dict["type"] = type
dict["value"] = value
dict["confirm"] = confirm?.dictionary()
dict["style"] = style?.rawValue
dict["confirm"] = confirm?.dictionary
return dict
}
@@ -65,7 +66,7 @@ public struct Action {
public let okText: String?
public let dismissText: String?
internal init(confirm:[String: AnyObject]?) {
internal init(confirm:[String: Any]?) {
title = confirm?["title"] as? String
text = confirm?["text"] as? String
okText = confirm?["ok_text"] as? String
@@ -79,17 +80,15 @@ public struct Action {
self.dismissText = dismissText
}
internal func dictionary() -> [String: AnyObject] {
var dict = [String: AnyObject]()
internal var dictionary: [String: Any] {
var dict = [String: Any]()
dict["title"] = title
dict["text"] = text
dict["ok_text"] = okText
dict["dismiss_text"] = dismissText
return dict
}
}
}
public enum ActionStyle: String {
+7 -8
View File
@@ -42,7 +42,7 @@ public struct Attachment {
public let footerIcon: String?
public let ts: Int?
internal init(attachment: [String: AnyObject]?) {
internal init(attachment: [String: Any]?) {
fallback = attachment?["fallback"] as? String
callbackID = attachment?["callback_id"] as? String
type = attachment?["attachment_type"] as? String
@@ -59,8 +59,8 @@ public struct Attachment {
footer = attachment?["footer"] as? String
footerIcon = attachment?["footer_icon"] as? String
ts = attachment?["ts"] as? Int
fields = (attachment?["fields"] as? [[String: AnyObject]])?.map { AttachmentField(field: $0) }
actions = (attachment?["actions"] as? [[String: AnyObject]])?.map { Action(action: $0) }
fields = (attachment?["fields"] as? [[String: Any]])?.map { AttachmentField(field: $0) }
actions = (attachment?["actions"] as? [[String: Any]])?.map { Action(action: $0) }
}
public init(fallback: String, title:String, callbackID: String? = nil, type: String? = nil, colorHex: String? = nil, pretext: String? = nil, authorName: String? = nil, authorLink: String? = nil, authorIcon: String? = nil, titleLink: String? = nil, text: String? = nil, fields: [AttachmentField]? = nil, actions: [Action]? = nil, imageURL: String? = nil, thumbURL: String? = nil, footer: String? = nil, footerIcon:String? = nil, ts:Int? = nil) {
@@ -84,8 +84,8 @@ public struct Attachment {
self.ts = ts
}
internal func dictionary() -> [String: AnyObject] {
var attachment = [String: AnyObject]()
internal var dictionary: [String: Any] {
var attachment = [String: Any]()
attachment["fallback"] = fallback
attachment["callback_id"] = callbackID
attachment["attachment_type"] = type
@@ -97,8 +97,8 @@ public struct Attachment {
attachment["title"] = title
attachment["title_link"] = titleLink
attachment["text"] = text
attachment["fields"] = fields?.map{$0.dictionary()}
attachment["actions"] = actions?.map{$0.dictionary()}
attachment["fields"] = fields?.map{$0.dictionary}
attachment["actions"] = actions?.map{$0.dictionary}
attachment["image_url"] = imageURL
attachment["thumb_url"] = thumbURL
attachment["footer"] = footer
@@ -106,7 +106,6 @@ public struct Attachment {
attachment["ts"] = ts
return attachment
}
}
public enum AttachmentColor: String {
+4 -5
View File
@@ -27,7 +27,7 @@ public struct AttachmentField {
public let value: String?
public let short: Bool?
internal init(field: [String: AnyObject]?) {
internal init(field: [String: Any]?) {
title = field?["title"] as? String
value = field?["value"] as? String
short = field?["short"] as? Bool
@@ -35,16 +35,15 @@ public struct AttachmentField {
public init(title:String, value:String, short: Bool? = nil) {
self.title = title
self.value = value.slackFormatEscaping()
self.value = value.slackFormatEscaping
self.short = short
}
internal func dictionary() -> [String: AnyObject] {
var field = [String: AnyObject]()
internal var dictionary: [String: Any] {
var field = [String: Any]()
field["title"] = title
field["value"] = value
field["short"] = short
return field
}
}
+2 -3
View File
@@ -29,8 +29,8 @@ internal struct AuthorizeRequest {
let state: String
let team: String?
var parameters: [String: AnyObject] {
var json = [String : AnyObject]()
var parameters: [String: Any] {
var json = [String : Any]()
json["scope"] = scope.map({$0.rawValue}).joined(separator: ",")
json["state"] = state
json["team"] = team
@@ -44,5 +44,4 @@ internal struct AuthorizeRequest {
self.state = state
self.team = team
}
}
+4 -5
View File
@@ -26,17 +26,16 @@ public struct Bot {
public let id: String?
internal(set) public var botToken: String?
internal(set) public var name: String?
internal(set) public var icons: [String: AnyObject]?
internal(set) public var icons: [String: Any]?
internal init(bot: [String: AnyObject]?) {
internal init(bot: [String: Any]?) {
id = bot?["id"] as? String
name = bot?["name"] as? String
icons = bot?["icons"] as? [String: AnyObject]
icons = bot?["icons"] as? [String: Any]
}
internal init(botUser: [String: AnyObject]?) {
internal init(botUser: [String: Any]?) {
id = botUser?["bot_user_id"] as? String
botToken = botUser?["bot_access_token"] as? String
}
}
+5 -5
View File
@@ -49,7 +49,7 @@ public struct Channel {
internal(set) public var usersTyping = [String]()
internal(set) public var messages = [String: Message]()
internal init(channel: [String: AnyObject]?) {
internal init(channel: [String: Any]?) {
id = channel?["id"] as? String
name = channel?["name"] as? String
created = channel?["created"] as? Int
@@ -62,8 +62,8 @@ public struct Channel {
isUserDeleted = channel?["is_user_deleted"] as? Bool
user = channel?["user"] as? String
isOpen = channel?["is_open"] as? Bool
topic = Topic(topic: channel?["topic"] as? [String: AnyObject])
purpose = Topic(topic: channel?["purpose"] as? [String: AnyObject])
topic = Topic(topic: channel?["topic"] as? [String: Any])
purpose = Topic(topic: channel?["purpose"] as? [String: Any])
isMember = channel?["is_member"] as? Bool
lastRead = channel?["last_read"] as? String
unread = channel?["unread_count"] as? Int
@@ -71,8 +71,8 @@ public struct Channel {
hasPins = channel?["has_pins"] as? Bool
members = channel?["members"] as? [String]
if let latestMsgDictionary = channel?["latest"] as? [String: AnyObject] {
latest = Message(message: latestMsgDictionary)
if let latestMesssageDictionary = channel?["latest"] as? [String: Any] {
latest = Message(dictionary: latestMesssageDictionary)
} else {
latest = Message(ts: channel?["latest"] as? String)
}
@@ -23,7 +23,7 @@
internal extension Client {
func dispatch(_ event: [String: AnyObject]) {
func dispatch(_ event: [String: Any]) {
let event = Event(event: event)
guard let type = event.type else {
return
@@ -31,7 +31,7 @@ internal extension Client {
switch type {
case .Hello:
connected = true
connectionEventsDelegate?.clientConnected(self)
connectionEventsDelegate?.connected(self)
case .Ok:
messageSent(event)
case .Message:
@@ -156,7 +156,6 @@ internal extension Client {
subteamRemovedSelf(event)
case .Error:
print("Error: \(event)")
break
}
}
@@ -173,5 +172,4 @@ internal extension Client {
messageReceived(event)
}
}
}
+47 -48
View File
@@ -39,7 +39,7 @@ internal extension Client {
message.ts = event.ts
message.text = event.text
channels[channel]?.messages[ts] = message
messageEventsDelegate?.messageSent(self, message: message)
messageEventsDelegate?.sent(message, client: self)
}
func messageReceived(_ event: Event) {
@@ -48,7 +48,7 @@ internal extension Client {
}
channels[id]?.messages[ts] = message
messageEventsDelegate?.messageReceived(self, message: message)
messageEventsDelegate?.received(message, client:self)
}
func messageChanged(_ event: Event) {
@@ -57,7 +57,7 @@ internal extension Client {
}
channels[id]?.messages[ts] = nested
messageEventsDelegate?.messageChanged(self, message: nested)
messageEventsDelegate?.changed(nested, client:self)
}
func messageDeleted(_ event: Event) {
@@ -66,7 +66,7 @@ internal extension Client {
}
_ = channels[id]?.messages.removeValue(forKey: key)
messageEventsDelegate?.messageDeleted(self, message: message)
messageEventsDelegate?.deleted(message, client:self)
}
//MARK: - Channels
@@ -77,14 +77,14 @@ internal extension Client {
}
channels[channelID]?.usersTyping.append(userID)
channelEventsDelegate?.userTyping(self, channel: channel, user: user)
channelEventsDelegate?.userTypingIn(channel, user: user, client: self)
let timeout = DispatchTime.now() + Double(Int64(5.0 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
DispatchQueue.main.after(when: timeout) {
DispatchQueue.main.asyncAfter(deadline: timeout, execute: {
if let index = self.channels[channelID]?.usersTyping.index(of: userID) {
self.channels[channelID]?.usersTyping.remove(at: index)
}
}
})
}
func channelMarked(_ event: Event) {
@@ -93,7 +93,7 @@ internal extension Client {
}
channels[id]?.lastRead = event.ts
channelEventsDelegate?.channelMarked(self, channel: channel, timestamp: timestamp)
channelEventsDelegate?.marked(channel, timestamp: timestamp, client: self)
}
func channelCreated(_ event: Event) {
@@ -102,7 +102,7 @@ internal extension Client {
}
channels[id] = channel
channelEventsDelegate?.channelCreated(self, channel: channel)
channelEventsDelegate?.created(channel, client: self)
}
func channelDeleted(_ event: Event) {
@@ -111,7 +111,7 @@ internal extension Client {
}
channels.removeValue(forKey: id)
channelEventsDelegate?.channelDeleted(self, channel: channel)
channelEventsDelegate?.deleted(channel, client: self)
}
func channelJoined(_ event: Event) {
@@ -120,7 +120,7 @@ internal extension Client {
}
channels[id] = event.channel
channelEventsDelegate?.channelJoined(self, channel: channel)
channelEventsDelegate?.joined(channel, client: self)
}
func channelLeft(_ event: Event) {
@@ -131,7 +131,7 @@ internal extension Client {
if let userID = authenticatedUser?.id, let index = channels[id]?.members?.index(of: userID) {
channels[id]?.members?.remove(at: index)
}
channelEventsDelegate?.channelLeft(self, channel: channel)
channelEventsDelegate?.left(channel, client: self)
}
func channelRenamed(_ event: Event) {
@@ -140,7 +140,7 @@ internal extension Client {
}
channels[id]?.name = channel.name
channelEventsDelegate?.channelRenamed(self, channel: channel)
channelEventsDelegate?.renamed(channel, client: self)
}
func channelArchived(_ event: Event, archived: Bool) {
@@ -149,14 +149,14 @@ internal extension Client {
}
channels[id]?.isArchived = archived
channelEventsDelegate?.channelArchived(self, channel: channel)
channelEventsDelegate?.archived(channel, client: self)
}
func channelHistoryChanged(_ event: Event) {
guard let channel = event.channel else {
return
}
channelEventsDelegate?.channelHistoryChanged(self, channel: channel)
channelEventsDelegate?.historyChanged(channel, client: self)
}
//MARK: - Do Not Disturb
@@ -166,7 +166,7 @@ internal extension Client {
}
authenticatedUser?.doNotDisturbStatus = dndStatus
doNotDisturbEventsDelegate?.doNotDisturbUpdated(self, dndStatus: dndStatus)
doNotDisturbEventsDelegate?.updated(dndStatus, client: self)
}
func doNotDisturbUserUpdated(_ event: Event) {
@@ -175,7 +175,7 @@ internal extension Client {
}
users[id]?.doNotDisturbStatus = dndStatus
doNotDisturbEventsDelegate?.doNotDisturbUserUpdated(self, dndStatus: dndStatus, user: user)
doNotDisturbEventsDelegate?.userUpdated(dndStatus, user: user, client: self)
}
//MARK: - IM & Group Open/Close
@@ -185,7 +185,7 @@ internal extension Client {
}
channels[id]?.isOpen = open
groupEventsDelegate?.groupOpened(self, group: channel)
groupEventsDelegate?.opened(channel, client: self)
}
//MARK: - Files
@@ -200,7 +200,7 @@ internal extension Client {
}
files[id] = file
fileEventsDelegate?.fileProcessed(self, file: file)
fileEventsDelegate?.processed(file, client: self)
}
func filePrivate(_ event: Event) {
@@ -209,7 +209,7 @@ internal extension Client {
}
files[id]?.isPublic = false
fileEventsDelegate?.fileMadePrivate(self, file: file)
fileEventsDelegate?.madePrivate(file, client: self)
}
func deleteFile(_ event: Event) {
@@ -220,7 +220,7 @@ internal extension Client {
if files[id] != nil {
files.removeValue(forKey: id)
}
fileEventsDelegate?.fileDeleted(self, file: file)
fileEventsDelegate?.deleted(file, client: self)
}
func fileCommentAdded(_ event: Event) {
@@ -229,7 +229,7 @@ internal extension Client {
}
files[id]?.comments[commentID] = comment
fileEventsDelegate?.fileCommentAdded(self, file: file, comment: comment)
fileEventsDelegate?.commentAdded(file, comment: comment, client: self)
}
func fileCommentEdited(_ event: Event) {
@@ -238,7 +238,7 @@ internal extension Client {
}
files[id]?.comments[commentID]?.comment = comment.comment
fileEventsDelegate?.fileCommentEdited(self, file: file, comment: comment)
fileEventsDelegate?.commentAdded(file, comment: comment, client: self)
}
func fileCommentDeleted(_ event: Event) {
@@ -247,7 +247,7 @@ internal extension Client {
}
_ = files[id]?.comments.removeValue(forKey: commentID)
fileEventsDelegate?.fileCommentDeleted(self, file: file, comment: comment)
fileEventsDelegate?.commentDeleted(file, comment: comment, client: self)
}
//MARK: - Pins
@@ -257,7 +257,7 @@ internal extension Client {
}
channels[id]?.pinnedItems.append(item)
pinEventsDelegate?.itemPinned(self, item: item, channel: channels[id])
pinEventsDelegate?.pinned(item, channel: channels[id], client: self)
}
func pinRemoved(_ event: Event) {
@@ -268,7 +268,7 @@ internal extension Client {
if let pins = channels[id]?.pinnedItems.filter({$0 != item}) {
channels[id]?.pinnedItems = pins
}
pinEventsDelegate?.itemUnpinned(self, item: item, channel: channels[id])
pinEventsDelegate?.unpinned(item, channel: channels[id], client: self)
}
//MARK: - Stars
@@ -287,7 +287,7 @@ internal extension Client {
break
}
starEventsDelegate?.itemStarred(self, item: item, star: star)
starEventsDelegate?.starred(item, starred: star, self)
}
func starMessage(_ item: Item, star: Bool) {
@@ -347,7 +347,7 @@ internal extension Client {
break
}
reactionEventsDelegate?.reactionAdded(self, reaction: reaction, item: item, itemUser: itemUser)
reactionEventsDelegate?.added(reaction, item: item, itemUser: itemUser, client: self)
}
func removedReaction(_ event: Event) {
@@ -375,7 +375,7 @@ internal extension Client {
break
}
reactionEventsDelegate?.reactionRemoved(self, reaction: key, item: item, itemUser: itemUser)
reactionEventsDelegate?.removed(key, item: item, itemUser: itemUser, client: self)
}
//MARK: - Preferences
@@ -385,7 +385,7 @@ internal extension Client {
}
authenticatedUser?.preferences?[name] = event.value
slackEventsDelegate?.preferenceChanged(self, preference: name, value: event.value)
slackEventsDelegate?.preferenceChanged(name, value: event.value, client: self)
}
//Mark: - User Change
@@ -397,7 +397,7 @@ internal extension Client {
let preferences = users[id]?.preferences
users[id] = user
users[id]?.preferences = preferences
slackEventsDelegate?.userChanged(self, user: user)
slackEventsDelegate?.userChanged(user, client: self)
}
//MARK: - User Presence
@@ -407,7 +407,7 @@ internal extension Client {
}
users[id]?.presence = event.presence
slackEventsDelegate?.presenceChanged(self, user: user, presence: presence)
slackEventsDelegate?.presenceChanged(user, presence: presence, client: self)
}
//MARK: - Team
@@ -417,7 +417,7 @@ internal extension Client {
}
users[id] = user
teamEventsDelegate?.teamJoined(self, user: user)
teamEventsDelegate?.userJoined(user, client: self)
}
func teamPlanChange(_ event: Event) {
@@ -426,7 +426,7 @@ internal extension Client {
}
team?.plan = plan
teamEventsDelegate?.teamPlanChanged(self, plan: plan)
teamEventsDelegate?.planChanged(plan, client: self)
}
func teamPreferenceChange(_ event: Event) {
@@ -435,7 +435,7 @@ internal extension Client {
}
team?.prefs?[name] = event.value
teamEventsDelegate?.teamPreferencesChanged(self, preference: name, value: event.value)
teamEventsDelegate?.preferencesChanged(name, value: event.value, client: self)
}
func teamNameChange(_ event: Event) {
@@ -444,7 +444,7 @@ internal extension Client {
}
team?.name = name
teamEventsDelegate?.teamNameChanged(self, name: name)
teamEventsDelegate?.nameChanged(name, client: self)
}
func teamDomainChange(_ event: Event) {
@@ -453,7 +453,7 @@ internal extension Client {
}
team?.domain = domain
teamEventsDelegate?.teamDomainChanged(self, domain: domain)
teamEventsDelegate?.domainChanged(domain, client: self)
}
func emailDomainChange(_ event: Event) {
@@ -462,11 +462,11 @@ internal extension Client {
}
team?.emailDomain = domain
teamEventsDelegate?.teamEmailDomainChanged(self, domain: domain)
teamEventsDelegate?.emailDomainChanged(domain, client: self)
}
func emojiChanged(_ event: Event) {
teamEventsDelegate?.teamEmojiChanged(self)
teamEventsDelegate?.emojiChanged(self)
}
//MARK: - Bots
@@ -476,7 +476,7 @@ internal extension Client {
}
bots[id] = bot
slackEventsDelegate?.botEvent(self, bot: bot)
slackEventsDelegate?.botEvent(bot, client: self)
}
//MARK: - Subteams
@@ -486,7 +486,7 @@ internal extension Client {
}
userGroups[id] = subteam
subteamEventsDelegate?.subteamEvent(self, userGroup: subteam)
subteamEventsDelegate?.event(subteam, client: self)
}
func subteamAddedSelf(_ event: Event) {
@@ -495,7 +495,7 @@ internal extension Client {
}
authenticatedUser?.userGroups![subteamID] = subteamID
subteamEventsDelegate?.subteamSelfAdded(self, subteamID: subteamID)
subteamEventsDelegate?.selfAdded(subteamID, client: self)
}
func subteamRemovedSelf(_ event: Event) {
@@ -504,7 +504,7 @@ internal extension Client {
}
_ = authenticatedUser?.userGroups?.removeValue(forKey: subteamID)
subteamEventsDelegate?.subteamSelfRemoved(self, subteamID: subteamID)
subteamEventsDelegate?.selfRemoved(subteamID, client: self)
}
//MARK: - Team Profiles
@@ -519,7 +519,7 @@ internal extension Client {
}
}
teamProfileEventsDelegate?.teamProfileChanged(self, profile: profile)
teamProfileEventsDelegate?.changed(profile, client: self)
}
func teamProfileDeleted(_ event: Event) {
@@ -533,7 +533,7 @@ internal extension Client {
}
}
teamProfileEventsDelegate?.teamProfileDeleted(self, profile: profile)
teamProfileEventsDelegate?.deleted(profile, client: self)
}
func teamProfileReordered(_ event: Event) {
@@ -547,7 +547,7 @@ internal extension Client {
}
}
teamProfileEventsDelegate?.teamProfileReordered(self, profile: profile)
teamProfileEventsDelegate?.reordered(profile, client: self)
}
//MARK: - Authenticated User
@@ -557,7 +557,6 @@ internal extension Client {
}
authenticatedUser?.presence = presence
slackEventsDelegate?.manualPresenceChanged(self, user: user, presence: presence)
slackEventsDelegate?.manualPresenceChanged(user, presence: presence, client: self)
}
}
+8 -8
View File
@@ -21,7 +21,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public enum ClientError: ErrorProtocol {
public enum ClientError: Error {
case channelDoesNotExist
case userDoesNotExist
}
@@ -29,32 +29,32 @@ public enum ClientError: ErrorProtocol {
public extension Client {
//MARK: - User & Channel
public func getChannelIDByName(_ name: String) throws -> String {
guard let id = channels.filter({$0.1.name == stripString(name)}).first?.0 else {
public func getChannelIDWith(name: String) throws -> String {
guard let id = channels.filter({$0.1.name == strip(string:name)}).first?.0 else {
throw ClientError.channelDoesNotExist
}
return id
}
public func getUserIDByName(_ name: String) throws -> String {
guard let id = users.filter({$0.1.name == stripString(name)}).first?.0 else {
public func getUserIDWith(name: String) throws -> String {
guard let id = users.filter({$0.1.name == strip(string:name)}).first?.0 else {
throw ClientError.userDoesNotExist
}
return id
}
public func getImIDForUserWithID(_ id: String, success: (imID: String?)->Void, failure: (error: SlackError)->Void) {
public func getImIDForUserWith(id: String, success: @escaping (_ imID: String?)->Void, failure: @escaping (SlackError)->Void) {
let ims = channels.filter{$0.1.isIM == true}
let channel = ims.filter{$0.1.user == id}.first
if let channel = channel {
success(imID: channel.0)
success(channel.0)
} else {
webAPI.openIM(id, success: success, failure: failure)
}
}
//MARK: - Utilities
internal func stripString(_ string: String) -> String {
internal func strip(string: String) -> String {
var strippedString = string
if string[string.startIndex] == "@" || string[string.startIndex] == "#" {
strippedString = string.substring(from: string.characters.index(string.startIndex, offsetBy: 1))
+52 -52
View File
@@ -44,7 +44,7 @@ public final class Client: WebSocketDelegate {
}
internal var webSocket: WebSocket?
private let pingPongQueue = DispatchQueue(label: "com.launchsoft.SlackKit", attributes: DispatchQueueAttributes.serial)
fileprivate let pingPongQueue = DispatchQueue(label: "com.launchsoft.SlackKit")
internal var ping: Double?
internal var pong: Double?
internal var options: ClientOptions?
@@ -75,18 +75,17 @@ public final class Client: WebSocketDelegate {
public func connect(options: ClientOptions = ClientOptions()) {
self.options = options
webAPI.rtmStart(options.simpleLatest, noUnreads: options.noUnreads, mpimAware: options.mpimAware, success: {
(response) -> Void in
webAPI.rtmStart(options.simpleLatest, noUnreads: options.noUnreads, mpimAware: options.mpimAware, success: {(response) in
guard let socketURL = response["url"] as? String, let url = URL(string: socketURL) else {
return
}
self.initialSetup(response)
self.initialSetup(JSON: response)
self.webSocket = WebSocket(url: url)
self.webSocket?.delegate = self
self.webSocket?.connect()
}, failure: {(error) -> Void in
self.connectionEventsDelegate?.clientConnectionFailed(self, error: error)
})
}, failure: {(error) in
self.connectionEventsDelegate?.connectionFailed(self, error: error)
})
}
public func disconnect() {
@@ -94,57 +93,57 @@ public final class Client: WebSocketDelegate {
}
//MARK: - RTM Message send
public func sendMessage(_ message: String, channelID: String) {
public func send(message: String, channelID: String) {
guard connected else { return }
if let data = try? formatMessageToSlackJsonString(msg: message, channel: channelID), let string = String(data: data, encoding: String.Encoding.utf8) {
if let data = try? format(message: message, channel: channelID), let string = String(data: data, encoding: String.Encoding.utf8) {
webSocket?.write(string: string)
}
}
private func formatMessageToSlackJsonString(_ message: (msg: String, channel: String)) throws -> Data {
let json: [String: AnyObject] = [
"id": Date().slackTimestamp(),
fileprivate func format(message: String, channel: String) throws -> Data {
let json: [String: Any] = [
"id": Date().slackTimestamp,
"type": "message",
"channel": message.channel,
"text": message.msg.slackFormatEscaping()
"channel": channel,
"text": message.slackFormatEscaping
]
addSentMessage(json)
return try JSONSerialization.data(withJSONObject: json, options: [])
}
private func addSentMessage(_ dictionary: [String: AnyObject]) {
fileprivate func addSentMessage(_ dictionary: [String: Any]) {
var message = dictionary
guard let id = message["id"] as? NSNumber else {
return
}
let ts = String(id)
let ts = String(describing: id)
message.removeValue(forKey: "id")
message["ts"] = ts
message["user"] = self.authenticatedUser?.id
sentMessages[ts] = Message(message: message)
sentMessages[ts] = Message(dictionary: message)
}
//MARK: - RTM Ping
private func pingRTMServerAtInterval(_ interval: TimeInterval) {
fileprivate func pingRTMServerAt(interval: TimeInterval) {
let delay = DispatchTime.now() + Double(Int64(interval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
pingPongQueue.after(when: delay, execute: {
pingPongQueue.asyncAfter(deadline: delay, execute: {
guard self.connected && self.timeoutCheck() else {
self.disconnect()
return
}
self.sendRTMPing()
self.pingRTMServerAtInterval(interval)
self.pingRTMServerAt(interval: interval)
})
}
private func sendRTMPing() {
fileprivate func sendRTMPing() {
guard connected else {
return
}
let json: [String: AnyObject] = [
"id": Date().slackTimestamp(),
"type": "ping",
let json: [String: Any] = [
"id": Date().slackTimestamp,
"type": "ping"
]
guard let data = try? JSONSerialization.data(withJSONObject: json, options: []) else {
return
@@ -155,7 +154,7 @@ public final class Client: WebSocketDelegate {
}
}
private func timeoutCheck() -> Bool {
fileprivate func timeoutCheck() -> Bool {
if let pong = pong, let ping = ping, let timeout = options?.timeout {
if pong - ping < timeout {
return true
@@ -169,62 +168,64 @@ public final class Client: WebSocketDelegate {
}
//MARK: - Client setup
private 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])
enumerateObjects(json["users"] as? Array) { (user) in self.addUser(user) }
enumerateObjects(json["channels"] as? Array) { (channel) in self.addChannel(channel) }
enumerateObjects(json["groups"] as? Array) { (group) in self.addChannel(group) }
enumerateObjects(json["mpims"] as? Array) { (mpim) in self.addChannel(mpim) }
enumerateObjects(json["ims"] as? Array) { (ims) in self.addChannel(ims) }
enumerateObjects(json["bots"] as? Array) { (bots) in self.addBot(bots) }
enumerateSubteams(json["subteams"] as? [String: AnyObject])
fileprivate func initialSetup(JSON: [String: Any]) {
team = Team(team: JSON["team"] as? [String: Any])
authenticatedUser = User(user: JSON["self"] as? [String: Any])
authenticatedUser?.doNotDisturbStatus = DoNotDisturbStatus(status: JSON["dnd"] as? [String: Any])
enumerateObjects(JSON["users"] as? Array) { (user) in self.addUser(user) }
enumerateObjects(JSON["channels"] as? Array) { (channel) in self.addChannel(channel) }
enumerateObjects(JSON["groups"] as? Array) { (group) in self.addChannel(group) }
enumerateObjects(JSON["mpims"] as? Array) { (mpim) in self.addChannel(mpim) }
enumerateObjects(JSON["ims"] as? Array) { (ims) in self.addChannel(ims) }
enumerateObjects(JSON["bots"] as? Array) { (bots) in self.addBot(bots) }
enumerateSubteams(JSON["subteams"] as? [String: Any])
}
private func addUser(_ aUser: [String: AnyObject]) {
fileprivate func addUser(_ aUser: [String: Any]) {
let user = User(user: aUser)
if let id = user.id {
users[id] = user
}
}
private func addChannel(_ aChannel: [String: AnyObject]) {
fileprivate func addChannel(_ aChannel: [String: Any]) {
let channel = Channel(channel: aChannel)
if let id = channel.id {
channels[id] = channel
}
}
private func addBot(_ aBot: [String: AnyObject]) {
fileprivate func addBot(_ aBot: [String: Any]) {
let bot = Bot(bot: aBot)
if let id = bot.id {
bots[id] = bot
}
}
private func enumerateSubteams(_ subteams: [String: AnyObject]?) {
fileprivate func enumerateSubteams(_ subteams: [String: Any]?) {
if let subteams = subteams {
if let all = subteams["all"] as? [[String: AnyObject]] {
if let all = subteams["all"] as? [[String: Any]] {
for item in all {
let u = UserGroup(userGroup: item)
self.userGroups[u.id!] = u
if let id = u.id {
self.userGroups[id] = u
}
}
}
if let auth = subteams["self"] as? [String] {
for item in auth {
authenticatedUser?.userGroups = [String: String]()
authenticatedUser?.userGroups![item] = item
authenticatedUser?.userGroups?[item] = item
}
}
}
}
// MARK: - Utilities
private func enumerateObjects(_ array: [AnyObject]?, initalizer: ([String: AnyObject])-> Void) {
fileprivate func enumerateObjects(_ array: [Any]?, initalizer: ([String: Any])-> Void) {
if let array = array {
for object in array {
if let dictionary = object as? [String: AnyObject] {
if let dictionary = object as? [String: Any] {
initalizer(dictionary)
}
}
@@ -234,30 +235,29 @@ public final class Client: WebSocketDelegate {
// MARK: - WebSocketDelegate
public func websocketDidConnect(socket: WebSocket) {
if let pingInterval = options?.pingInterval {
pingRTMServerAtInterval(pingInterval)
pingRTMServerAt(interval: pingInterval)
}
}
public func websocketDidDisconnect(_ socket: WebSocket, error: NSError?) {
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
connected = false
webSocket = nil
authenticatedUser = nil
connectionEventsDelegate?.clientDisconnected(self)
connectionEventsDelegate?.disconnected(self)
if let options = options, options.reconnect == true {
connect(options: options)
}
}
public func websocketDidReceiveMessage(_ socket: WebSocket, text: String) {
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
guard let data = text.data(using: String.Encoding.utf8) else {
return
}
if let json = (try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)) as? [String: AnyObject] {
if let json = (try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)) as? [String: Any] {
dispatch(json)
}
}
public func websocketDidReceiveData(_ socket: WebSocket, data: Data) {}
public func websocketDidReceiveData(socket: WebSocket, data: Data) {}
}
-1
View File
@@ -40,5 +40,4 @@ public struct ClientOptions {
self.timeout = timeout
self.reconnect = reconnect
}
}
+7 -8
View File
@@ -21,7 +21,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public struct Comment {
public struct Comment: Equatable {
public let id: String?
public let user: String?
internal(set) public var created: Int?
@@ -30,7 +31,7 @@ public struct Comment {
internal(set) public var stars: Int?
internal(set) public var reactions = [Reaction]()
internal init(comment:[String: AnyObject]?) {
internal init(comment:[String: Any]?) {
id = comment?["id"] as? String
created = comment?["created"] as? Int
user = comment?["user"] as? String
@@ -43,10 +44,8 @@ public struct Comment {
self.id = id
self.user = nil
}
}
extension Comment: Equatable {}
public func ==(lhs: Comment, rhs: Comment) -> Bool {
return lhs.id == rhs.id
public static func ==(lhs: Comment, rhs: Comment) -> Bool {
return lhs.id == rhs.id
}
}
+6 -6
View File
@@ -22,13 +22,14 @@
// THE SOFTWARE.
public struct CustomProfile {
internal(set) public var fields = [String: CustomProfileField]()
internal init(profile: [String: AnyObject]?) {
if let eventFields = profile?["fields"] as? [AnyObject] {
internal init(profile: [String: Any]?) {
if let eventFields = profile?["fields"] as? [Any] {
for field in eventFields {
var cpf: CustomProfileField?
if let fieldDictionary = field as? [String: AnyObject] {
if let fieldDictionary = field as? [String: Any] {
cpf = CustomProfileField(field: fieldDictionary)
} else {
cpf = CustomProfileField(id: field as? String)
@@ -38,13 +39,12 @@ public struct CustomProfile {
}
}
internal init(customFields: [String: AnyObject]?) {
internal init(customFields: [String: Any]?) {
if let customFields = customFields {
for key in customFields.keys {
let cpf = CustomProfileField(field: customFields[key] as? [String: AnyObject])
let cpf = CustomProfileField(field: customFields[key] as? [String: Any])
self.fields[key] = cpf
}
}
}
}
+2 -1
View File
@@ -22,6 +22,7 @@
// THE SOFTWARE.
public struct CustomProfileField {
internal(set) public var id: String?
internal(set) public var alt: String?
internal(set) public var value: String?
@@ -33,7 +34,7 @@ public struct CustomProfileField {
internal(set) public var possibleValues: [String]?
internal(set) public var type: String?
internal init(field: [String: AnyObject]?) {
internal init(field: [String: Any]?) {
id = field?["id"] as? String
alt = field?["alt"] as? String
value = field?["value"] as? String
+2 -2
View File
@@ -22,18 +22,18 @@
// THE SOFTWARE.
public struct DoNotDisturbStatus {
internal(set) public var enabled: Bool?
internal(set) public var nextDoNotDisturbStart: Int?
internal(set) public var nextDoNotDisturbEnd: Int?
internal(set) public var snoozeEnabled: Bool?
internal(set) public var snoozeEndtime: Int?
internal init(status: [String: AnyObject]?) {
internal init(status: [String: Any]?) {
enabled = status?["dnd_enabled"] as? Bool
nextDoNotDisturbStart = status?["next_dnd_start_ts"] as? Int
nextDoNotDisturbEnd = status?["next_dnd_end_ts"] as? Int
snoozeEnabled = status?["snooze_enabled"] as? Bool
snoozeEndtime = status?["snooze_endtime"] as? Int
}
}
+2 -1
View File
@@ -22,10 +22,11 @@
// THE SOFTWARE.
public struct Edited {
public let user: String?
public let ts: String?
internal init(edited:[String: AnyObject]?) {
internal init(edited:[String: Any]?) {
user = edited?["user"] as? String
ts = edited?["ts"] as? String
}
+17 -17
View File
@@ -22,6 +22,7 @@
// THE SOFTWARE.
internal enum EventType: String {
case Hello = "hello"
case Message = "message"
case UserTyping = "user_typing"
@@ -96,6 +97,7 @@ internal enum EventType: String {
}
internal enum MessageSubtype: String {
case BotMessage = "bot_message"
case MeMessage = "me_message"
case MessageChanged = "message_changed"
@@ -137,14 +139,14 @@ internal struct Event {
let fileID: String?
let presence: String?
let name: String?
let value: AnyObject?
let value: Any?
let plan: String?
let url: String?
let domain: String?
let emailDomain: String?
let reaction: String?
let replyTo: Double?
let reactions: [[String: AnyObject]]?
let reactions: [[String: Any]]?
let edited: Edited?
let bot: Bot?
let channel: Channel?
@@ -160,7 +162,7 @@ internal struct Event {
let subteamID: String?
var profile: CustomProfile?
init(event:[String: AnyObject]) {
init(event:[String: Any]) {
type = EventType(rawValue: event["type"] as? String ?? "ok")
ts = event["ts"] as? String
subtype = event["subtype"] as? String
@@ -182,38 +184,36 @@ internal struct Event {
emailDomain = event["email_domain"] as? String
reaction = event["reaction"] as? String
replyTo = event["reply_to"] as? Double
reactions = event["reactions"] as? [[String: AnyObject]]
bot = Bot(bot: event["bot"] as? [String: AnyObject])
edited = Edited(edited:event["edited"] as? [String: AnyObject])
dndStatus = DoNotDisturbStatus(status: event["dnd_status"] as? [String: AnyObject])
reactions = event["reactions"] as? [[String: Any]]
bot = Bot(bot: event["bot"] as? [String: Any])
edited = Edited(edited:event["edited"] as? [String: Any])
dndStatus = DoNotDisturbStatus(status: event["dnd_status"] as? [String: Any])
itemUser = event["item_user"] as? String
item = Item(item: event["item"] as? [String: AnyObject])
subteam = UserGroup(userGroup: event["subteam"] as? [String: AnyObject])
item = Item(item: event["item"] as? [String: Any])
subteam = UserGroup(userGroup: event["subteam"] as? [String: Any])
subteamID = event["subteam_id"] as? String
message = Message(message: event)
nestedMessage = Message(message: event["message"] as? [String: AnyObject])
profile = CustomProfile(profile: event["profile"] as? [String: AnyObject])
message = Message(dictionary: event)
nestedMessage = Message(dictionary: event["message"] as? [String: Any])
profile = CustomProfile(profile: event["profile"] as? [String: Any])
file = File(id: event["file"] as? String)
// Comment, Channel, and User can come across as Strings or Dictionaries
if let commentDictionary = event["comment"] as? [String: AnyObject] {
if let commentDictionary = event["comment"] as? [String: Any] {
comment = Comment(comment: commentDictionary)
} else {
comment = Comment(id: event["comment"] as? String)
}
if let userDictionary = event["user"] as? [String: AnyObject] {
if let userDictionary = event["user"] as? [String: Any] {
user = User(user: userDictionary)
} else {
user = User(id: event["user"] as? String)
}
if let channelDictionary = event["channel"] as? [String: AnyObject] {
if let channelDictionary = event["channel"] as? [String: Any] {
channel = Channel(channel: channelDictionary)
} else {
channel = Channel(id: event["channel"] as? String)
}
}
}
+48 -48
View File
@@ -22,88 +22,88 @@
// THE SOFTWARE.
public protocol ConnectionEventsDelegate: class {
func clientConnected(_ client: Client)
func clientDisconnected(_ client: Client)
func clientConnectionFailed(_ client: Client, error: SlackError)
func connected(_ client: Client)
func disconnected(_ client: Client)
func connectionFailed(_ client: Client, error: SlackError)
}
public protocol MessageEventsDelegate: class {
func messageSent(_ client: Client, message: Message)
func messageReceived(_ client: Client, message: Message)
func messageChanged(_ client: Client, message: Message)
func messageDeleted(_ client: Client, message: Message?)
func sent(_ message: Message, client: Client)
func received(_ message: Message, client: Client)
func changed(_ message: Message, client: Client)
func deleted(_ message: Message?, client: Client)
}
public protocol ChannelEventsDelegate: class {
func userTyping(_ client: Client, channel: Channel, user: User)
func channelMarked(_ client: Client, channel: Channel, timestamp: String)
func channelCreated(_ client: Client, channel: Channel)
func channelDeleted(_ client: Client, channel: Channel)
func channelRenamed(_ client: Client, channel: Channel)
func channelArchived(_ client: Client, channel: Channel)
func channelHistoryChanged(_ client: Client, channel: Channel)
func channelJoined(_ client: Client, channel: Channel)
func channelLeft(_ client: Client, channel: Channel)
func userTypingIn(_ channel: Channel, user: User, client: Client)
func marked(_ channel: Channel, timestamp: String, client: Client)
func created(_ channel: Channel, client: Client)
func deleted(_ channel: Channel, client: Client)
func renamed(_ channel: Channel, client: Client)
func archived(_ channel: Channel, client: Client)
func historyChanged(_ channel: Channel, client: Client)
func joined(_ channel: Channel, client: Client)
func left(_ channel: Channel, client: Client)
}
public protocol DoNotDisturbEventsDelegate: class {
func doNotDisturbUpdated(_ client: Client, dndStatus: DoNotDisturbStatus)
func doNotDisturbUserUpdated(_ client: Client, dndStatus: DoNotDisturbStatus, user: User)
func updated(_ status: DoNotDisturbStatus, client: Client)
func userUpdated(_ status: DoNotDisturbStatus, user: User, client: Client)
}
public protocol GroupEventsDelegate: class {
func groupOpened(_ client: Client, group: Channel)
func opened(_ group: Channel, client: Client)
}
public protocol FileEventsDelegate: class {
func fileProcessed(_ client: Client, file: File)
func fileMadePrivate(_ client: Client, file: File)
func fileDeleted(_ client: Client, file: File)
func fileCommentAdded(_ client: Client, file: File, comment: Comment)
func fileCommentEdited(_ client: Client, file: File, comment: Comment)
func fileCommentDeleted(_ client: Client, file: File, comment: Comment)
func processed(_ file: File, client: Client)
func madePrivate(_ file: File, client: Client)
func deleted(_ file: File, client: Client)
func commentAdded(_ file: File, comment: Comment, client: Client)
func commentEdited(_ file: File, comment: Comment, client: Client)
func commentDeleted(_ file: File, comment: Comment, client: Client)
}
public protocol PinEventsDelegate: class {
func itemPinned(_ client: Client, item: Item, channel: Channel?)
func itemUnpinned(_ client: Client, item: Item, channel: Channel?)
func pinned(_ item: Item, channel: Channel?, client: Client)
func unpinned(_ item: Item, channel: Channel?, client: Client)
}
public protocol StarEventsDelegate: class {
func itemStarred(_ client: Client, item: Item, star: Bool)
func starred(_ item: Item, starred: Bool, _ client: Client)
}
public protocol ReactionEventsDelegate: class {
func reactionAdded(_ client: Client, reaction: String, item: Item, itemUser: String)
func reactionRemoved(_ client: Client, reaction: String, item: Item, itemUser: String)
func added(_ reaction: String, item: Item, itemUser: String, client: Client)
func removed(_ reaction: String, item: Item, itemUser: String, client: Client)
}
public protocol SlackEventsDelegate: class {
func preferenceChanged(_ client: Client, preference: String, value: AnyObject?)
func userChanged(_ client: Client, user: User)
func presenceChanged(_ client: Client, user: User, presence: String)
func manualPresenceChanged(_ client: Client, user: User, presence: String)
func botEvent(_ client: Client, bot: Bot)
func preferenceChanged(_ preference: String, value: Any?, client: Client)
func userChanged(_ user: User, client: Client)
func presenceChanged(_ user: User, presence: String, client: Client)
func manualPresenceChanged(_ user: User, presence: String, client: Client)
func botEvent(_ bot: Bot, client: Client)
}
public protocol TeamEventsDelegate: class {
func teamJoined(_ client: Client, user: User)
func teamPlanChanged(_ client: Client, plan: String)
func teamPreferencesChanged(_ client: Client, preference: String, value: AnyObject?)
func teamNameChanged(_ client: Client, name: String)
func teamDomainChanged(_ client: Client, domain: String)
func teamEmailDomainChanged(_ client: Client, domain: String)
func teamEmojiChanged(_ client: Client)
func userJoined(_ user: User, client: Client)
func planChanged(_ plan: String, client: Client)
func preferencesChanged(_ preference: String, value: Any?, client: Client)
func nameChanged(_ name: String, client: Client)
func domainChanged(_ domain: String, client: Client)
func emailDomainChanged(_ domain: String, client: Client)
func emojiChanged(_ client: Client)
}
public protocol SubteamEventsDelegate: class {
func subteamEvent(_ client: Client, userGroup: UserGroup)
func subteamSelfAdded(_ client: Client, subteamID: String)
func subteamSelfRemoved(_ client: Client, subteamID: String)
func event(_ userGroup: UserGroup, client: Client)
func selfAdded(_ subteamID: String, client: Client)
func selfRemoved(_ subteamID: String, client: Client)
}
public protocol TeamProfileEventsDelegate: class {
func teamProfileChanged(_ client: Client, profile: CustomProfile)
func teamProfileDeleted(_ client: Client, profile: CustomProfile)
func teamProfileReordered(_ client: Client, profile: CustomProfile)
func changed(_ profile: CustomProfile, client: Client)
func deleted(_ profile: CustomProfile, client: Client)
func reordered(_ profile: CustomProfile, client: Client)
}
+3 -6
View File
@@ -25,24 +25,22 @@ import Foundation
public extension Date {
func slackTimestamp() -> Double {
var slackTimestamp: Double {
return NSNumber(value: timeIntervalSince1970).doubleValue
}
}
internal extension String {
func slackFormatEscaping() -> String {
var slackFormatEscaping: String {
var escapedString = replacingOccurrences(of: "&", with: "&amp;")
escapedString = replacingOccurrences(of: "<", with: "&lt;")
escapedString = replacingOccurrences(of: ">", with: "&gt;")
return escapedString
}
}
internal extension Dictionary where Key: StringLiteralConvertible, Value: AnyObject {
internal extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
var requestStringFromParameters: String {
var requestString = ""
@@ -56,6 +54,5 @@ internal extension Dictionary where Key: StringLiteralConvertible, Value: AnyObj
return requestString
}
}
+8 -11
View File
@@ -21,7 +21,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public struct File {
public struct File: Equatable {
public let id: String?
public let created: Int?
@@ -78,7 +78,7 @@ public struct File {
internal(set) public var comments = [String: Comment]()
internal(set) public var reactions = [Reaction]()
public init(file:[String: AnyObject]?) {
public init(file:[String: Any]?) {
id = file?["id"] as? String
created = file?["created"] as? Int
name = file?["name"] as? String
@@ -127,11 +127,11 @@ public struct File {
channels = file?["channels"] as? [String]
groups = file?["groups"] as? [String]
ims = file?["ims"] as? [String]
initialComment = Comment(comment: file?["initial_comment"] as? [String: AnyObject])
initialComment = Comment(comment: file?["initial_comment"] as? [String: Any])
stars = file?["num_stars"] as? Int
isStarred = file?["is_starred"] as? Bool
pinnedTo = file?["pinned_to"] as? [String]
reactions = Reaction.reactionsFromArray(file?["reactions"] as? [[String: AnyObject]])
reactions = Reaction.reactionsFromArray(file?["reactions"] as? [[String: Any]])
}
internal init(id:String?) {
@@ -179,11 +179,8 @@ public struct File {
linesMore = nil
initialComment = nil
}
public static func ==(lhs: File, rhs: File) -> Bool {
return lhs.id == rhs.id
}
}
extension File: Equatable {}
public func ==(lhs: File, rhs: File) -> Bool {
return lhs.id == rhs.id
}
+3 -3
View File
@@ -29,13 +29,13 @@ public struct History {
internal(set) public var messages = [Message]()
public let hasMore: Bool?
internal init(history: [String: AnyObject]?) {
internal init(history: [String: Any]?) {
if let latestStr = history?["latest"] as? String, let latestDouble = Double(latestStr) {
latest = Date(timeIntervalSince1970: TimeInterval(latestDouble))
}
if let msgs = history?["messages"] as? [[String: AnyObject]] {
if let msgs = history?["messages"] as? [[String: Any]] {
for message in msgs {
messages.append(Message(message: message))
messages.append(Message(dictionary: message))
}
}
hasMore = history?["has_more"] as? Bool
+3 -4
View File
@@ -32,7 +32,7 @@ public struct IncomingWebhook {
public let iconEmoji: String?
public let iconURL: String?
internal init(webhook: [String: AnyObject]?) {
internal init(webhook: [String: Any]?) {
url = webhook?["url"] as? String
channel = webhook?["channel"] as? String
configurationURL = webhook?["configuration_url"] as? String
@@ -51,7 +51,7 @@ public struct IncomingWebhook {
}
public func postMessage(_ response: Response, success: ((Bool)->Void)? = nil, failure: ((SlackError)->Void)? = nil) {
if let url = self.url, let data = try? JSONSerialization.data(withJSONObject: jsonBody(response.json()), options: []) {
if let url = self.url, let data = try? JSONSerialization.data(withJSONObject: jsonBody(response.json), options: []) {
NetworkInterface().customRequest(url, data: data, success: { _ in
success?(true)
}, errorClosure: {(error) in
@@ -60,7 +60,7 @@ public struct IncomingWebhook {
}
}
private func jsonBody(_ response: [String: AnyObject]) -> [String: AnyObject] {
fileprivate func jsonBody(_ response: [String: Any]) -> [String: Any] {
var json = response
json["channel"] = channel
json["username"] = username
@@ -68,5 +68,4 @@ public struct IncomingWebhook {
json["icon_url"] = iconURL
return json
}
}
+10 -12
View File
@@ -21,7 +21,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public struct Item {
public struct Item: Equatable {
public let type: String?
public let ts: String?
public let channel: String?
@@ -30,21 +31,20 @@ public struct Item {
public let comment: Comment?
public let fileCommentID: String?
internal init(item:[String: AnyObject]?) {
internal init(item:[String: Any]?) {
type = item?["type"] as? String
ts = item?["ts"] as? String
channel = item?["channel"] as? String
message = Message(message: item?["message"] as? [String: AnyObject])
message = Message(dictionary: item?["message"] as? [String: Any])
// Comment and File can come across as Strings or Dictionaries
if let commentDictionary = item?["comment"] as? [String: AnyObject] {
if let commentDictionary = item?["comment"] as? [String: Any] {
comment = Comment(comment: commentDictionary)
} else {
comment = Comment(id: item?["comment"] as? String)
}
if let fileDictionary = item?["file"] as? [String: AnyObject] {
if let fileDictionary = item?["file"] as? [String: Any] {
file = File(file: fileDictionary)
} else {
file = File(id: item?["file"] as? String)
@@ -52,10 +52,8 @@ public struct Item {
fileCommentID = item?["file_comment"] as? String
}
}
extension Item: Equatable {}
public func ==(lhs: Item, rhs: Item) -> Bool {
return lhs.type == rhs.type && lhs.channel == rhs.channel && lhs.file == rhs.file && lhs.comment == rhs.comment && lhs.message == rhs.message
public static func ==(lhs: Item, rhs: Item) -> Bool {
return lhs.type == rhs.type && lhs.channel == rhs.channel && lhs.file == rhs.file && lhs.comment == rhs.comment && lhs.message == rhs.message
}
}
+33 -36
View File
@@ -21,7 +21,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public final class Message {
public final class Message: Equatable {
public let type = "message"
public let subtype: String?
@@ -32,7 +32,7 @@ public final class Message {
internal(set) public var text: String?
public let botID: String?
public let username: String?
public let icons: [String: AnyObject]?
public let icons: [String: Any]?
public let deletedTs: String?
internal(set) var purpose: String?
internal(set) var topic: String?
@@ -51,33 +51,33 @@ public final class Message {
internal(set) public var replaceOriginal: Bool?
internal(set) public var deleteOriginal: Bool?
public init(message: [String: AnyObject]?) {
subtype = message?["subtype"] as? String
ts = message?["ts"] as? String
user = message?["user"] as? String
channel = message?["channel"] as? String
hidden = message?["hidden"] as? Bool
text = message?["text"] as? String
botID = message?["bot_id"] as? String
username = message?["username"] as? String
icons = message?["icons"] as? [String: AnyObject]
deletedTs = message?["deleted_ts"] as? String
purpose = message?["purpose"] as? String
topic = message?["topic"] as? String
name = message?["name"] as? String
members = message?["members"] as? [String]
oldName = message?["old_name"] as? String
upload = message?["upload"] as? Bool
itemType = message?["item_type"] as? String
isStarred = message?["is_starred"] as? Bool
pinnedTo = message?["pinned_to"] as? [String]
comment = Comment(comment: message?["comment"] as? [String: AnyObject])
file = File(file: message?["file"] as? [String: AnyObject])
reactions = Reaction.reactionsFromArray(message?["reactions"] as? [[String: AnyObject]])
attachments = (message?["attachments"] as? [[String: AnyObject]])?.map{Attachment(attachment: $0)}
responseType = ResponseType(rawValue: message?["response_type"] as? String ?? "")
replaceOriginal = message?["replace_original"] as? Bool
deleteOriginal = message?["delete_original"] as? Bool
public init(dictionary: [String: Any]?) {
subtype = dictionary?["subtype"] as? String
ts = dictionary?["ts"] as? String
user = dictionary?["user"] as? String
channel = dictionary?["channel"] as? String
hidden = dictionary?["hidden"] as? Bool
text = dictionary?["text"] as? String
botID = dictionary?["bot_id"] as? String
username = dictionary?["username"] as? String
icons = dictionary?["icons"] as? [String: Any]
deletedTs = dictionary?["deleted_ts"] as? String
purpose = dictionary?["purpose"] as? String
topic = dictionary?["topic"] as? String
name = dictionary?["name"] as? String
members = dictionary?["members"] as? [String]
oldName = dictionary?["old_name"] as? String
upload = dictionary?["upload"] as? Bool
itemType = dictionary?["item_type"] as? String
isStarred = dictionary?["is_starred"] as? Bool
pinnedTo = dictionary?["pinned_to"] as? [String]
comment = Comment(comment: dictionary?["comment"] as? [String: Any])
file = File(file: dictionary?["file"] as? [String: Any])
reactions = Reaction.reactionsFromArray(dictionary?["reactions"] as? [[String: Any]])
attachments = (dictionary?["attachments"] as? [[String: Any]])?.map{Attachment(attachment: $0)}
responseType = ResponseType(rawValue: dictionary?["response_type"] as? String ?? "")
replaceOriginal = dictionary?["replace_original"] as? Bool
deleteOriginal = dictionary?["delete_original"] as? Bool
}
internal init(ts:String?) {
@@ -94,11 +94,8 @@ public final class Message {
comment = nil
file = nil
}
}
extension Message: Equatable {}
public func ==(lhs: Message, rhs: Message) -> Bool {
return lhs.ts == rhs.ts && lhs.user == rhs.user && lhs.text == rhs.text
public static func ==(lhs: Message, rhs: Message) -> Bool {
return lhs.ts == rhs.ts && lhs.user == rhs.user && lhs.text == rhs.text
}
}
+6 -7
View File
@@ -35,18 +35,17 @@ internal struct MessageActionRequest: Request {
let originalMessage: Message?
let responseURL: String
init(response: [String: AnyObject]?) {
action = (response?["actions"] as? [[String:AnyObject]])?.map({Action(action: $0)}).first
init(response: [String: Any]?) {
action = (response?["actions"] as? [[String:Any]])?.map({Action(action: $0)}).first
callbackID = response?["callback_id"] as? String
team = Team(team: response?["team"] as? [String: AnyObject])
channel = Channel(channel: response?["channel"] as? [String: AnyObject])
user = User(user: response?["channel"] as? [String: AnyObject])
team = Team(team: response?["team"] as? [String: Any])
channel = Channel(channel: response?["channel"] as? [String: Any])
user = User(user: response?["channel"] as? [String: Any])
actionTS = response?["action_ts"] as? String
messageTS = response?["message_ts"] as? String
attachmentID = response?["attachment_id"] as? String
token = response?["token"] as? String
originalMessage = Message(message: response?["original_message"] as? [String: AnyObject])
originalMessage = Message(dictionary: response?["original_message"] as? [String: Any])
responseURL = response?["response_url"] as? String ?? ""
}
}
@@ -36,5 +36,4 @@ public struct MessageActionResponder {
return nil
}
}
}
+1 -2
View File
@@ -21,7 +21,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public class MessageActionServer: Server {
open class MessageActionServer: Server {
internal let responder: MessageActionResponder
@@ -42,5 +42,4 @@ public class MessageActionServer: Server {
}
}
}
}
+7 -7
View File
@@ -27,7 +27,7 @@ internal struct NetworkInterface {
private let apiUrl = "https://slack.com/api/"
internal func request(_ endpoint: Endpoint, token: String? = nil, parameters: [String: AnyObject]?, successClosure: ([String: AnyObject])->Void, errorClosure: (SlackError)->Void) {
internal func request(_ endpoint: Endpoint, token: String? = nil, parameters: [String: Any]?, successClosure: @escaping ([String: Any])->Void, errorClosure: @escaping (SlackError)->Void) {
var requestString = "\(apiUrl)\(endpoint.rawValue)?"
if let token = token {
requestString += "token=\(token)"
@@ -40,6 +40,7 @@ internal struct NetworkInterface {
return
}
let request = URLRequest(url:url)
URLSession.shared.dataTask(with: request) {
(data, response, internalError) -> Void in
self.handleResponse(data, response: response, internalError: internalError, successClosure: {(json) in
@@ -50,7 +51,7 @@ internal struct NetworkInterface {
}.resume()
}
internal func customRequest(_ url: String, data: Data, success: (Bool)->Void, errorClosure: (SlackError)->Void) {
internal func customRequest(_ url: String, data: Data, success: @escaping (Bool)->Void, errorClosure: @escaping (SlackError)->Void) {
guard let url = URL(string: url.removePercentEncoding()) else {
errorClosure(SlackError.ClientNetworkError)
return
@@ -68,10 +69,10 @@ internal struct NetworkInterface {
} else {
errorClosure(SlackError.ClientNetworkError)
}
}.resume()
}.resume()
}
internal func uploadRequest(_ token: String, data: Data, parameters: [String: AnyObject]?, successClosure: ([String: AnyObject])->Void, errorClosure: (SlackError)->Void) {
internal func uploadRequest(_ token: String, data: Data, parameters: [String: Any]?, successClosure: @escaping ([String: Any])->Void, errorClosure: @escaping (SlackError)->Void) {
var requestString = "\(apiUrl)\(Endpoint.FilesUpload.rawValue)?token=\(token)"
if let params = parameters {
requestString = requestString + params.requestStringFromParameters
@@ -110,13 +111,13 @@ internal struct NetworkInterface {
}.resume()
}
private func handleResponse(_ data: Data?, response:URLResponse?, internalError:NSError?, successClosure: ([String: AnyObject])->Void, errorClosure: (SlackError)->Void) {
private func handleResponse(_ data: Data?, response:URLResponse?, internalError:Error?, successClosure: ([String: Any])->Void, errorClosure: (SlackError)->Void) {
guard let data = data, let response = response as? HTTPURLResponse else {
errorClosure(SlackError.ClientNetworkError)
return
}
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] else {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
errorClosure(SlackError.ClientJSONError)
return
}
@@ -149,5 +150,4 @@ internal struct NetworkInterface {
private func randomBoundary() -> String {
return String(format: "slackkit.boundary.%08x%08x", arc4random(), arc4random())
}
}
+3 -3
View File
@@ -31,14 +31,14 @@ internal struct OAuthResponse {
let incomingWebhook: IncomingWebhook?
let bot: Bot?
init(response: [String: AnyObject]?) {
init(response: [String: Any]?) {
accessToken = response?["access_token"] as? String
scope = (response?["scope"] as? String)?.components(separatedBy: ",").flatMap{Scope(rawValue:$0)}
userID = response?["user_id"] as? String
teamName = response?["team_name"] as? String
teamID = response?["team_id"] as? String
incomingWebhook = IncomingWebhook(webhook: response?["incoming_webhook"] as? [String: AnyObject])
bot = Bot(botUser: response?["bot"] as? [String: AnyObject])
incomingWebhook = IncomingWebhook(webhook: response?["incoming_webhook"] as? [String: Any])
bot = Bot(botUser: response?["bot"] as? [String: Any])
}
}
+9 -10
View File
@@ -30,14 +30,14 @@ internal protocol OAuthDelegate {
public struct OAuthServer {
private let oauthURL = "https://slack.com/oauth/authorize"
fileprivate let oauthURL = "https://slack.com/oauth/authorize"
private let http = HttpServer()
private let clientID: String
private let clientSecret: String
private let state: String?
private let redirectURI: String?
private var delegate: OAuthDelegate?
fileprivate let http = HttpServer()
fileprivate let clientID: String
fileprivate let clientSecret: String
fileprivate let state: String?
fileprivate let redirectURI: String?
fileprivate var delegate: OAuthDelegate?
internal init(clientID: String, clientSecret: String, state: String? = nil, redirectURI: String? = nil, port:in_port_t = 8080, forceIPV4: Bool = false, delegate: OAuthDelegate? = nil) throws {
self.clientID = clientID
@@ -61,7 +61,7 @@ public struct OAuthServer {
http.stop()
}
private func oauthRoute() {
fileprivate func oauthRoute() {
http["/oauth"] = { request in
guard let response = AuthorizeResponse(queryParameters: request.queryParams), response.state == self.state else {
return .badRequest(.text("Bad request."))
@@ -78,7 +78,7 @@ public struct OAuthServer {
}
}
private func oauthURLRequest(_ authorize: AuthorizeRequest) -> URLRequest? {
fileprivate func oauthURLRequest(_ authorize: AuthorizeRequest) -> URLRequest? {
var requestString = "\(oauthURL)?client_id=\(authorize.clientID)"
requestString += authorize.parameters.requestStringFromParameters
guard let url = URL(string: requestString) else {
@@ -91,5 +91,4 @@ public struct OAuthServer {
let request = AuthorizeRequest(clientID: clientID, scope: scope, redirectURI: redirectURI, state: state, team: team)
return oauthURLRequest(request)
}
}
+7 -9
View File
@@ -21,11 +21,12 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public struct Reaction {
public struct Reaction: Equatable {
public let name: String?
internal(set) public var user: String?
internal init(reaction:[String: AnyObject]?) {
internal init(reaction:[String: Any]?) {
name = reaction?["name"] as? String
}
@@ -34,7 +35,7 @@ public struct Reaction {
self.user = user
}
static func reactionsFromArray(_ array: [[String: AnyObject]]?) -> [Reaction] {
static func reactionsFromArray(_ array: [[String: Any]]?) -> [Reaction] {
var reactions = [Reaction]()
if let array = array {
for reaction in array {
@@ -48,10 +49,7 @@ public struct Reaction {
return reactions
}
}
extension Reaction: Equatable {}
public func ==(lhs: Reaction, rhs: Reaction) -> Bool {
return lhs.name == rhs.name
public static func ==(lhs: Reaction, rhs: Reaction) -> Bool {
return lhs.name == rhs.name
}
}
+3 -4
View File
@@ -33,12 +33,11 @@ public struct Response {
self.attachments = attachments
}
internal func json() -> [String: AnyObject] {
var json = [String : AnyObject]()
internal var json: [String: Any] {
var json = [String : Any]()
json["text"] = text
json["response_type"] = responseType?.rawValue
json["attachments"] = attachments?.flatMap({$0.dictionary()})
json["attachments"] = attachments?.map({$0.dictionary})
return json
}
}
+9 -10
View File
@@ -34,7 +34,7 @@ internal protocol Request {
var responseURL: String { get }
}
public class Server {
open class Server {
internal let http = HttpServer()
internal let token: String
@@ -43,7 +43,7 @@ public class Server {
self.token = token
}
public func start(_ port: in_port_t = 8080, forceIPV4: Bool = false) {
open func start(_ port: in_port_t = 8080, forceIPV4: Bool = false) {
do {
try http.start(port, forceIPv4: forceIPV4)
} catch let error as NSError {
@@ -51,7 +51,7 @@ public class Server {
}
}
public func stop() {
open func stop() {
http.stop()
}
@@ -60,20 +60,20 @@ public class Server {
case .text(let body):
return .ok(.text(body))
case .json(let response):
return .ok(.json(response.json()))
return .ok(.json(response.json as AnyObject))
case .badRequest:
return .badRequest(.text("Bad request."))
}
}
internal func dictionaryFromRequest(_ body: [UInt8]) -> [String: AnyObject]? {
internal func dictionaryFromRequest(_ body: [UInt8]) -> [String: Any]? {
let string = String(data: Data(bytes: UnsafePointer<UInt8>(body), count: body.count), encoding: String.Encoding.utf8)
if let body = string?.components(separatedBy: "&") {
var dict: [String: AnyObject] = [:]
var dict: [String: Any] = [:]
for argument in body {
let kv = argument.components(separatedBy: "=")
if let key = kv.first, let value = kv.last {
dict[key] = value
dict[key] = value as Any?
}
}
return dict
@@ -81,11 +81,10 @@ public class Server {
return nil
}
internal func jsonFromRequest(_ string: String) -> [String: AnyObject]? {
internal func jsonFromRequest(_ string: String) -> [String: Any]? {
guard let data = string.data(using: String.Encoding.utf8) else {
return nil
}
return (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: AnyObject] ?? nil
return (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: Any] ?? nil
}
}
+3 -1
View File
@@ -21,7 +21,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public enum SlackError: String, ErrorProtocol {
public enum SlackError: String, Error {
case AccountInactive = "account_inactive"
case AlreadyArchived = "already_archived"
case AlreadyInChannel = "already_in_channel"
@@ -73,6 +74,7 @@ public enum SlackError: String, ErrorProtocol {
case MigrationInProgress = "migration_in_progress"
case MissingDuration = "missing_duration"
case MissingPostType = "missing_post_type"
case MissingScope = "missing_scope"
case NameTaken = "name_taken"
case NoChannel = "no_channel"
case NoComment = "no_comment"
+4 -3
View File
@@ -27,7 +27,7 @@ public final class SlackKit: OAuthDelegate {
internal(set) public var oauth: OAuthServer?
internal(set) public var clients: [String: Client] = [:]
private let clientOptions: ClientOptions
fileprivate let clientOptions: ClientOptions
// Initalization block
public var onClientInitalization: ((Client) -> Void)?
@@ -35,7 +35,9 @@ public final class SlackKit: OAuthDelegate {
public init(withAPIToken token: String, clientOptions: ClientOptions = ClientOptions()) {
self.clientOptions = clientOptions
let client = Client(apiToken: token)
self.onClientInitalization?(client)
DispatchQueue.main.async(execute: {
self.onClientInitalization?(client)
})
clients[token] = client
client.connect(options: self.clientOptions)
}
@@ -61,5 +63,4 @@ public final class SlackKit: OAuthDelegate {
client.connect(options: self.clientOptions)
}
}
}
+4 -4
View File
@@ -29,19 +29,19 @@ public struct Team {
internal(set) public var emailDomain: String?
internal(set) public var messageEditWindowMinutes: Int?
internal(set) public var overStorageLimit: Bool?
internal(set) public var prefs: [String: AnyObject]?
internal(set) public var prefs: [String: Any]?
internal(set) public var plan: String?
internal(set) public var icon: TeamIcon?
internal init(team: [String: AnyObject]?) {
internal init(team: [String: Any]?) {
id = team?["id"] as? String
name = team?["name"] as? String
domain = team?["domain"] as? String
emailDomain = team?["email_domain"] as? String
messageEditWindowMinutes = team?["msg_edit_window_mins"] as? Int
overStorageLimit = team?["over_storage_limit"] as? Bool
prefs = team?["prefs"] as? [String: AnyObject]
prefs = team?["prefs"] as? [String: Any]
plan = team?["plan"] as? String
icon = TeamIcon(icon: team?["icon"] as? [String: AnyObject])
icon = TeamIcon(icon: team?["icon"] as? [String: Any])
}
}
+2 -1
View File
@@ -22,6 +22,7 @@
// THE SOFTWARE.
public struct TeamIcon {
internal(set) public var image34: String?
internal(set) public var image44: String?
internal(set) public var image68: String?
@@ -31,7 +32,7 @@ public struct TeamIcon {
internal(set) public var imageOriginal: String?
internal(set) public var imageDefault: Bool?
internal init(icon: [String: AnyObject]?) {
internal init(icon: [String: Any]?) {
image34 = icon?["image_34"] as? String
image44 = icon?["image_44"] as? String
image68 = icon?["image_68"] as? String
+2 -1
View File
@@ -22,11 +22,12 @@
// THE SOFTWARE.
public struct Topic {
public let value: String?
public let creator: String?
public let lastSet: Int?
internal init(topic: [String: AnyObject]?) {
internal init(topic: [String: Any]?) {
value = topic?["value"] as? String
creator = topic?["creator"] as? String
lastSet = topic?["last_set"] as? Int
+8 -8
View File
@@ -24,6 +24,7 @@
public struct User {
public struct Profile {
internal(set) public var firstName: String?
internal(set) public var lastName: String?
internal(set) public var realName: String?
@@ -37,7 +38,7 @@ public struct User {
internal(set) public var image192: String?
internal(set) public var customProfile: CustomProfile?
internal init(profile: [String: AnyObject]?) {
internal init(profile: [String: Any]?) {
firstName = profile?["first_name"] as? String
lastName = profile?["last_name"] as? String
realName = profile?["real_name"] as? String
@@ -49,11 +50,10 @@ public struct User {
image48 = profile?["image_48"] as? String
image72 = profile?["image_72"] as? String
image192 = profile?["image_192"] as? String
customProfile = CustomProfile(customFields: profile?["fields"] as? [String: AnyObject])
customProfile = CustomProfile(customFields: profile?["fields"] as? [String: Any])
}
}
public let id: String?
internal(set) public var name: String?
internal(set) public var deleted: Bool?
@@ -73,15 +73,15 @@ public struct User {
internal(set) public var timeZone: String?
internal(set) public var timeZoneLabel: String?
internal(set) public var timeZoneOffSet: Int?
internal(set) public var preferences: [String: AnyObject]?
internal(set) public var preferences: [String: Any]?
// Client properties
internal(set) public var userGroups: [String: String]?
internal init(user: [String: AnyObject]?) {
internal init(user: [String: Any]?) {
id = user?["id"] as? String
name = user?["name"] as? String
deleted = user?["deleted"] as? Bool
profile = Profile(profile: user?["profile"] as? [String: AnyObject])
profile = Profile(profile: user?["profile"] as? [String: Any])
color = user?["color"] as? String
isAdmin = user?["is_admin"] as? Bool
isOwner = user?["is_owner"] as? Bool
@@ -96,11 +96,11 @@ public struct User {
timeZone = user?["tz"] as? String
timeZoneLabel = user?["tz_label"] as? String
timeZoneOffSet = user?["tz_offset"] as? Int
preferences = user?["prefs"] as? [String: AnyObject]
preferences = user?["prefs"] as? [String: Any]
}
internal init(id: String?) {
self.id = id
self.isBot = nil
}
}
}
+3 -4
View File
@@ -37,11 +37,11 @@ public struct UserGroup {
public let createdBy: String?
internal(set) public var updatedBy: String?
internal(set) public var deletedBy: String?
internal(set) public var preferences: [String: AnyObject]?
internal(set) public var preferences: [String: Any]?
internal(set) public var users: [String]?
internal(set) public var userCount: Int?
internal init(userGroup: [String: AnyObject]?) {
internal init(userGroup: [String: Any]?) {
id = userGroup?["id"] as? String
teamID = userGroup?["team_id"] as? String
isUserGroup = userGroup?["is_usergroup"] as? Bool
@@ -56,11 +56,10 @@ public struct UserGroup {
createdBy = userGroup?["created_by"] as? String
updatedBy = userGroup?["updated_by"] as? String
deletedBy = userGroup?["deleted_by"] as? String
preferences = userGroup?["prefs"] as? [String: AnyObject]
preferences = userGroup?["prefs"] as? [String: Any]
users = userGroup?["users"] as? [String]
if let count = userGroup?["user_count"] as? String {
userCount = Int(count)
}
}
}
+230 -230
View File
@@ -24,6 +24,7 @@
import Foundation
internal enum Endpoint: String {
case APITest = "api.test"
case AuthRevoke = "auth.revoke"
case AuthTest = "auth.test"
@@ -83,7 +84,7 @@ internal enum Endpoint: String {
public final class WebAPI {
public typealias FailureClosure = (error: SlackError)->Void
public typealias FailureClosure = (_ error: SlackError)->Void
public enum InfoType: String {
case Purpose = "purpose"
@@ -100,14 +101,14 @@ public final class WebAPI {
case Away = "away"
}
private enum ChannelType: String {
fileprivate enum ChannelType: String {
case Channel = "channel"
case Group = "group"
case IM = "im"
}
private let networkInterface: NetworkInterface
private let token: String
fileprivate let networkInterface: NetworkInterface
fileprivate let token: String
public init(token: String) {
self.networkInterface = NetworkInterface()
@@ -115,625 +116,625 @@ public final class WebAPI {
}
//MARK: - RTM
public func rtmStart(_ simpleLatest: Bool? = nil, noUnreads: Bool? = nil, mpimAware: Bool? = nil, success: ((response: [String: AnyObject])->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject?] = ["simple_latest": simpleLatest, "no_unreads": noUnreads, "mpim_aware": mpimAware]
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: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(response: response)
success?(response)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Auth
public func authenticationTest(_ success: ((authenticated: Bool)->Void)?, failure: FailureClosure?) {
public func authenticationTest(_ success: ((_ authenticated: Bool)->Void)?, failure: FailureClosure?) {
networkInterface.request(.AuthTest, token: token, parameters: nil, successClosure: {
(response) -> Void in
success?(authenticated: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public static func oauthAccess(_ clientID: String, clientSecret: String, code: String, redirectURI: String? = nil, success: ((response: [String: AnyObject])->Void)?, failure: ((SlackError)->Void)?) {
let parameters: [String: AnyObject?] = ["client_id": clientID, "client_secret": clientSecret, "code": code, "redirect_uri": redirectURI]
public static func oauthAccess(_ clientID: String, clientSecret: String, code: String, redirectURI: String? = nil, success: ((_ response: [String: Any])->Void)?, failure: ((SlackError)->Void)?) {
let parameters: [String: Any?] = ["client_id": clientID, "client_secret": clientSecret, "code": code, "redirect_uri": redirectURI]
NetworkInterface().request(.OAuthAccess, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(response:response)
success?(response)
}) {(error) -> Void in
failure?(error)
}
}
public static func oauthRevoke(_ token: String, test: Bool? = nil, success: ((revoked:Bool)->Void)?, failure: ((SlackError)->Void)?) {
let parameters: [String: AnyObject?] = ["token": token, "test": test]
public static func oauthRevoke(_ token: String, test: Bool? = nil, success: ((_ revoked:Bool)->Void)?, failure: ((SlackError)->Void)?) {
let parameters: [String: Any?] = ["token": token, "test": test]
NetworkInterface().request(.AuthRevoke, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(revoked:true)
success?(true)
}) {(error) -> Void in
failure?(error)
}
}
//MARK: - Channels
public func channelHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: History)->Void)?, failure: FailureClosure?) {
public func channelHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((_ history: History)->Void)?, failure: FailureClosure?) {
history(.ChannelsHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history: history)
success?(history)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func channelInfo(_ id: String, success: ((channel: Channel)->Void)?, failure: FailureClosure?) {
public func channelInfo(_ id: String, success: ((_ channel: Channel)->Void)?, failure: FailureClosure?) {
info(.ChannelsInfo, type:ChannelType.Channel, id: id, success: {
(channel) -> Void in
success?(channel: channel)
success?(channel)
}) { (error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func channelsList(_ excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
public func channelsList(_ excludeArchived: Bool = false, success: ((_ channels: [[String: Any]]?)->Void)?, failure: FailureClosure?) {
list(.ChannelsList, type:ChannelType.Channel, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
success?(channels)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func markChannel(_ channel: String, timestamp: String, success: ((ts: String)->Void)?, failure: FailureClosure?) {
public func markChannel(_ channel: String, timestamp: String, success: ((_ ts: String)->Void)?, failure: FailureClosure?) {
mark(.ChannelsMark, channel: channel, timestamp: timestamp, success: {
(ts) -> Void in
success?(ts:timestamp)
success?(timestamp)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func setChannelPurpose(_ channel: String, purpose: String, success: ((purposeSet: Bool)->Void)?, failure: FailureClosure?) {
public func setChannelPurpose(_ channel: String, purpose: String, success: ((_ purposeSet: Bool)->Void)?, failure: FailureClosure?) {
setInfo(.ChannelsSetPurpose, type: .Purpose, channel: channel, text: purpose, success: {
(purposeSet) -> Void in
success?(purposeSet: purposeSet)
success?(purposeSet)
}) { (error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func setChannelTopic(_ channel: String, topic: String, success: ((topicSet: Bool)->Void)?, failure: FailureClosure?) {
public func setChannelTopic(_ channel: String, topic: String, success: ((_ topicSet: Bool)->Void)?, failure: FailureClosure?) {
setInfo(.ChannelsSetTopic, type: .Topic, channel: channel, text: topic, success: {
(topicSet) -> Void in
success?(topicSet: topicSet)
success?(topicSet)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Messaging
public func deleteMessage(_ channel: String, ts: String, success: ((deleted: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": channel, "ts": ts]
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) -> Void in
success?(deleted: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
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: AnyObject?] = ["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]
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, "icon_url": iconURL, "icon_emoji": iconEmoji, "attachments": encodeAttachments(attachments)]
networkInterface.request(.ChatPostMessage, token: token, parameters: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?((ts: response["ts"] as? String, response["channel"] as? String))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
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: AnyObject?] = ["channel": channel, "ts": ts, "text": message.slackFormatEscaping(), "parse": parse.rawValue, "link_names": linkNames, "attachments":encodeAttachments(attachments)]
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: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(updated: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Do Not Disturb
public func dndInfo(_ user: String? = nil, success: ((status: DoNotDisturbStatus)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject?] = ["user": user]
public func dndInfo(_ user: String? = nil, success: ((_ status: DoNotDisturbStatus)->Void)?, failure: FailureClosure?) {
let parameters: [String: Any?] = ["user": user]
networkInterface.request(.DNDInfo, token: token, parameters: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(status: DoNotDisturbStatus(status: response))
success?(DoNotDisturbStatus(status: response))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func dndTeamInfo(_ users: [String]? = nil, success: ((statuses: [String: DoNotDisturbStatus])->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject?] = ["users":users?.joined(separator: ",")]
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: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
guard let usersDictionary = response["users"] as? [String: AnyObject] else {
success?(statuses: [:])
guard let usersDictionary = response["users"] as? [String: Any] else {
success?([:])
return
}
success?(statuses: self.enumerateDNDStatuses(usersDictionary))
success?(self.enumerateDNDStatuses(usersDictionary))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Emoji
public func emojiList(_ success: ((emojiList: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
public func emojiList(_ success: ((_ emojiList: [String: Any]?)->Void)?, failure: FailureClosure?) {
networkInterface.request(.EmojiList, token: token, parameters: nil, successClosure: {
(response) -> Void in
success?(emojiList: response["emoji"] as? [String: AnyObject])
success?(response["emoji"] as? [String: Any])
}) { (error) -> Void in
failure?(error: error)
failure?(error)
}
}
//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: {
public func deleteFile(_ fileID: String, success: ((_ deleted: Bool)->Void)?, failure: FailureClosure?) {
let parameters = ["file": fileID]
networkInterface.request(.FilesDelete, token: token, parameters: parameters as [String : Any]?, successClosure: {
(response) -> Void in
success?(deleted: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func fileInfo(_ fileID: String, commentCount: Int = 100, totalPages: Int = 1, success: ((file: File)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["file":fileID, "count": commentCount, "totalPages":totalPages]
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
var file = File(file: response["file"] as? [String: AnyObject])
(response["comments"] as? [[String: AnyObject]])?.forEach { comment in
var file = File(file: response["file"] as? [String: Any])
(response["comments"] as? [[String: Any]])?.forEach { comment in
let comment = Comment(comment: comment)
if let id = comment.id {
file.comments[id] = comment
}
}
success?(file: file)
success?(file)
}) {(error) in
failure?(error: error)
failure?(error)
}
}
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: AnyObject?] = ["file":file, "filename": filename, "filetype":filetype, "title":title, "initial_comment":initialComment, "channels":channels?.joined(separator: ",")]
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?] = ["file": file, "filename": filename, "filetype": filetype, "title": title, "initial_comment": initialComment, "channels": channels?.joined(separator: ",")]
networkInterface.uploadRequest(token, data: file, parameters: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(file: File(file: response["file"] as? [String: AnyObject]))
success?(File(file: response["file"] as? [String: Any]))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - File Comments
public func addFileComment(_ fileID: String, comment: String, success: ((comment: Comment)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["file":fileID, "comment":comment.slackFormatEscaping()]
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) -> Void in
success?(comment: Comment(comment: response["comment"] as? [String: AnyObject]))
success?(Comment(comment: response["comment"] as? [String: Any]))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func editFileComment(_ fileID: String, commentID: String, comment: String, success: ((comment: Comment)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["file":fileID, "id":commentID, "comment":comment.slackFormatEscaping()]
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) -> Void in
success?(comment: Comment(comment: response["comment"] as? [String: AnyObject]))
success?(Comment(comment: response["comment"] as? [String: Any]))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func deleteFileComment(_ fileID: String, commentID: String, success: ((deleted: Bool?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["file":fileID, "id": commentID]
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) -> Void in
success?(deleted: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Groups
public func closeGroup(_ groupID: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
public func closeGroup(_ groupID: String, success: ((_ closed: Bool)->Void)?, failure: FailureClosure?) {
close(.GroupsClose, channelID: groupID, success: {
(closed) -> Void in
success?(closed:closed)
success?(closed)
}) {(error) -> Void in
failure?(error:error)
failure?(error)
}
}
public func groupHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: History)->Void)?, failure: FailureClosure?) {
public func groupHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((_ history: History)->Void)?, failure: FailureClosure?) {
history(.GroupsHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history: history)
success?(history)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func groupInfo(_ id: String, success: ((channel: Channel)->Void)?, failure: FailureClosure?) {
public func groupInfo(_ id: String, success: ((_ channel: Channel)->Void)?, failure: FailureClosure?) {
info(.GroupsInfo, type:ChannelType.Group, id: id, success: {
(channel) -> Void in
success?(channel: channel)
success?(channel)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func groupsList(_ excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
public func groupsList(_ excludeArchived: Bool = false, success: ((_ channels: [[String: Any]]?)->Void)?, failure: FailureClosure?) {
list(.GroupsList, type:ChannelType.Group, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
success?(channels)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func markGroup(_ channel: String, timestamp: String, success: ((ts: String)->Void)?, failure: FailureClosure?) {
public func markGroup(_ channel: String, timestamp: String, success: ((_ ts: String)->Void)?, failure: FailureClosure?) {
mark(.GroupsMark, channel: channel, timestamp: timestamp, success: {
(ts) -> Void in
success?(ts: timestamp)
success?(timestamp)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func openGroup(_ channel: String, success: ((opened: Bool)->Void)?, failure: FailureClosure?) {
public func openGroup(_ channel: String, success: ((_ opened: Bool)->Void)?, failure: FailureClosure?) {
let parameters = ["channel":channel]
networkInterface.request(.GroupsOpen, token: token, parameters: parameters, successClosure: {
networkInterface.request(.GroupsOpen, token: token, parameters: parameters as [String: Any]?, successClosure: {
(response) -> Void in
success?(opened: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func setGroupPurpose(_ channel: String, purpose: String, success: ((purposeSet: Bool)->Void)?, failure: FailureClosure?) {
public func setGroupPurpose(_ channel: String, purpose: String, success: ((_ purposeSet: Bool)->Void)?, failure: FailureClosure?) {
setInfo(.GroupsSetPurpose, type: .Purpose, channel: channel, text: purpose, success: {
(purposeSet) -> Void in
success?(purposeSet: purposeSet)
success?(purposeSet)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func setGroupTopic(_ channel: String, topic: String, success: ((topicSet: Bool)->Void)?, failure: FailureClosure?) {
public func setGroupTopic(_ channel: String, topic: String, success: ((_ topicSet: Bool)->Void)?, failure: FailureClosure?) {
setInfo(.GroupsSetTopic, type: .Topic, channel: channel, text: topic, success: {
(topicSet) -> Void in
success?(topicSet: topicSet)
success?(topicSet)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - IM
public func closeIM(_ channel: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
public func closeIM(_ channel: String, success: ((_ closed: Bool)->Void)?, failure: FailureClosure?) {
close(.IMClose, channelID: channel, success: {
(closed) -> Void in
success?(closed: closed)
success?(closed)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func imHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: History)->Void)?, failure: FailureClosure?) {
public func imHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((_ history: History)->Void)?, failure: FailureClosure?) {
history(.IMHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history: history)
success?(history)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func imsList(_ excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
public func imsList(_ excludeArchived: Bool = false, success: ((_ channels: [[String: Any]]?)->Void)?, failure: FailureClosure?) {
list(.IMList, type:ChannelType.IM, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
success?(channels)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func markIM(_ channel: String, timestamp: String, success: ((ts: String)->Void)?, failure: FailureClosure?) {
public func markIM(_ channel: String, timestamp: String, success: ((_ ts: String)->Void)?, failure: FailureClosure?) {
mark(.IMMark, channel: channel, timestamp: timestamp, success: {
(ts) -> Void in
success?(ts: timestamp)
success?(timestamp)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func openIM(_ userID: String, success: ((imID: String?)->Void)?, failure: FailureClosure?) {
let parameters = ["user":userID]
networkInterface.request(.IMOpen, token: token, parameters: parameters, successClosure: {
public func openIM(_ userID: String, success: ((_ imID: String?)->Void)?, failure: FailureClosure?) {
let parameters = ["user": userID]
networkInterface.request(.IMOpen, token: token, parameters: parameters as [String: Any]?, successClosure: {
(response) -> Void in
let group = response["channel"] as? [String: AnyObject]
success?(imID: group?["id"] as? String)
let group = response["channel"] as? [String: Any]
success?(group?["id"] as? String)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - MPIM
public func closeMPIM(_ channel: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
public func closeMPIM(_ channel: String, success: ((_ closed: Bool)->Void)?, failure: FailureClosure?) {
close(.MPIMClose, channelID: channel, success: {
(closed) -> Void in
success?(closed: closed)
success?(closed)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func mpimHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: History)->Void)?, failure: FailureClosure?) {
public func mpimHistory(_ id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((_ history: History)->Void)?, failure: FailureClosure?) {
history(.MPIMHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history: history)
success?(history)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func mpimsList(_ excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
public func mpimsList(_ excludeArchived: Bool = false, success: ((_ channels: [[String: Any]]?)->Void)?, failure: FailureClosure?) {
list(.MPIMList, type:ChannelType.Group, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
success?(channels)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func markMPIM(_ channel: String, timestamp: String, success: ((ts: String)->Void)?, failure: FailureClosure?) {
public func markMPIM(_ channel: String, timestamp: String, success: ((_ ts: String)->Void)?, failure: FailureClosure?) {
mark(.MPIMMark, channel: channel, timestamp: timestamp, success: {
(ts) -> Void in
success?(ts: timestamp)
success?(timestamp)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
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: {
public func openMPIM(_ userIDs: [String], success: ((_ mpimID: String?)->Void)?, failure: FailureClosure?) {
let parameters = ["users": userIDs.joined(separator: ",")]
networkInterface.request(.MPIMOpen, token: token, parameters: parameters as [String: Any]?, successClosure: {
(response) -> Void in
let group = response["group"] as? [String: AnyObject]
success?(mpimID: group?["id"] as? String)
let group = response["group"] as? [String: Any]
success?(group?["id"] as? String)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Pins
public func pinItem(_ channel: String, file: String? = nil, fileComment: String? = nil, timestamp: String? = nil, success: ((pinned: Bool)->Void)?, failure: FailureClosure?) {
public func pinItem(_ channel: String, file: String? = nil, fileComment: String? = nil, timestamp: String? = nil, success: ((_ pinned: Bool)->Void)?, failure: FailureClosure?) {
pin(.PinsAdd, channel: channel, file: file, fileComment: fileComment, timestamp: timestamp, success: {
(ok) -> Void in
success?(pinned: ok)
success?(ok)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func unpinItem(_ channel: String, file: String? = nil, fileComment: String? = nil, timestamp: String? = nil, success: ((unpinned: Bool)->Void)?, failure: FailureClosure?) {
public func unpinItem(_ channel: String, file: String? = nil, fileComment: String? = nil, timestamp: String? = nil, success: ((_ unpinned: Bool)->Void)?, failure: FailureClosure?) {
pin(.PinsRemove, channel: channel, file: file, fileComment: fileComment, timestamp: timestamp, success: {
(ok) -> Void in
success?(unpinned: ok)
success?(ok)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
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: AnyObject?] = ["channel":channel, "file":file, "file_comment":fileComment, "timestamp":timestamp]
fileprivate 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: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(ok: true)
success?(true)
}){(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Reactions
// One of file, file_comment, or the combination of channel and timestamp must be specified.
public func addReaction(_ name: String, file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((reacted: Bool)->Void)?, failure: FailureClosure?) {
public func addReaction(_ name: String, file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((_ reacted: Bool)->Void)?, failure: FailureClosure?) {
react(.ReactionsAdd, name: name, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(reacted: ok)
success?(ok)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
// One of file, file_comment, or the combination of channel and timestamp must be specified.
public func removeReaction(_ name: String, file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((unreacted: Bool)->Void)?, failure: FailureClosure?) {
public func removeReaction(_ name: String, file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((_ unreacted: Bool)->Void)?, failure: FailureClosure?) {
react(.ReactionsRemove, name: name, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(unreacted: ok)
success?(ok)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
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: AnyObject?] = ["name":name, "file":file, "file_comment":fileComment, "channel":channel, "timestamp":timestamp]
fileprivate 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: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(ok: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Stars
// One of file, file_comment, channel, or the combination of channel and timestamp must be specified.
public func addStar(_ file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((starred: Bool)->Void)?, failure: FailureClosure?) {
public func addStar(_ file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((_ starred: Bool)->Void)?, failure: FailureClosure?) {
star(.StarsAdd, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(starred: ok)
success?(ok)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
// One of file, file_comment, channel, or the combination of channel and timestamp must be specified.
public func removeStar(_ file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((unstarred: Bool)->Void)?, failure: FailureClosure?) {
public func removeStar(_ file: String? = nil, fileComment: String? = nil, channel: String? = nil, timestamp: String? = nil, success: ((_ unstarred: Bool)->Void)?, failure: FailureClosure?) {
star(.StarsRemove, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(unstarred: ok)
success?(ok)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
private func star(_ endpoint: Endpoint, file: String?, fileComment: String?, channel: String?, timestamp: String?, success: ((ok: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject?] = ["file":file, "file_comment":fileComment, "channel":channel, "timestamp":timestamp]
fileprivate 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: WebAPI.filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(ok: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Team
public func teamInfo(_ success: ((info: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
public func teamInfo(_ success: ((_ info: [String: Any]?)->Void)?, failure: FailureClosure?) {
networkInterface.request(.TeamInfo, token: token, parameters: nil, successClosure: {
(response) -> Void in
success?(info: response["team"] as? [String: AnyObject])
success?(response["team"] as? [String: Any])
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Users
public func userPresence(_ user: String, success: ((presence: String?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["user":user]
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) -> Void in
success?(presence: response["presence"] as? String)
success?(response["presence"] as? String)
}){(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func userInfo(_ id: String, success: ((user: User)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["user":id]
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) -> Void in
success?(user: User(user: response["user"] as? [String: AnyObject]))
success?(User(user: response["user"] as? [String: Any]))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func usersList(_ includePresence: Bool = false, success: ((userList: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["presence":includePresence]
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) -> Void in
success?(userList: response["members"] as? [[String: AnyObject]])
success?(response["members"] as? [[String: Any]])
}){(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func setUserActive(_ success: ((success: Bool)->Void)?, failure: FailureClosure?) {
public func setUserActive(_ success: ((_ success: Bool)->Void)?, failure: FailureClosure?) {
networkInterface.request(.UsersSetActive, token: token, parameters: nil, successClosure: {
(response) -> Void in
success?(success: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
public func setUserPresence(_ presence: Presence, success: ((success: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["presence":presence.rawValue]
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) -> Void in
success?(success:true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Channel Utilities
private func close(_ endpoint: Endpoint, channelID: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel":channelID]
fileprivate 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) -> Void in
success?(closed: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
private func history(_ endpoint: Endpoint, id: String, latest: String = "\(Date().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: History)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": id, "latest": latest, "oldest": oldest, "inclusive":inclusive, "count":count, "unreads":unreads]
fileprivate func history(_ endpoint: Endpoint, id: String, latest: String = "\(Date().timeIntervalSince1970)", 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) -> Void in
success?(history: History(history: response))
success?(History(history: response))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
private func info(_ endpoint: Endpoint, type: ChannelType, id: String, success: ((channel: Channel)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": id]
fileprivate 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) -> Void in
success?(channel: Channel(channel: response[type.rawValue] as? [String: AnyObject]))
success?(Channel(channel: response[type.rawValue] as? [String: Any]))
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
private func list(_ endpoint: Endpoint, type: ChannelType, excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["exclude_archived": excludeArchived]
fileprivate 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) -> Void in
success?(channels: response[type.rawValue+"s"] as? [[String: AnyObject]])
success?(response[type.rawValue+"s"] as? [[String: Any]])
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
private func mark(_ endpoint: Endpoint, channel: String, timestamp: String, success: ((ts: String)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": channel, "ts": timestamp]
fileprivate 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) -> Void in
success?(ts: timestamp)
success?(timestamp)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
private func setInfo(_ endpoint: Endpoint, type: InfoType, channel: String, text: String, success: ((success: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": channel, type.rawValue: text]
fileprivate 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) -> Void in
success?(success: true)
success?(true)
}) {(error) -> Void in
failure?(error: error)
failure?(error)
}
}
//MARK: - Encode Attachments
private func encodeAttachments(_ attachments: [Attachment?]?) -> String? {
fileprivate func encodeAttachments(_ attachments: [Attachment?]?) -> String? {
if let attachments = attachments {
var attachmentArray: [[String: AnyObject]] = []
var attachmentArray: [[String: Any]] = []
for attachment in attachments {
if let attachment = attachment {
attachmentArray.append(attachment.dictionary())
attachmentArray.append(attachment.dictionary)
}
}
do {
@@ -747,8 +748,8 @@ public final class WebAPI {
}
//MARK: - Filter Nil Parameters
internal static func filterNilParameters(_ parameters: [String: AnyObject?]) -> [String: AnyObject] {
var finalParameters = [String: AnyObject]()
internal static func filterNilParameters(_ parameters: [String: Any?]) -> [String: Any] {
var finalParameters = [String: Any]()
for (key, value) in parameters {
if let unwrapped = value {
finalParameters[key] = unwrapped
@@ -758,12 +759,11 @@ public final class WebAPI {
}
//MARK: - Enumerate Do Not Disturb Status
private func enumerateDNDStatuses(_ statuses: [String: AnyObject]) -> [String: DoNotDisturbStatus] {
fileprivate func enumerateDNDStatuses(_ statuses: [String: Any]) -> [String: DoNotDisturbStatus] {
var retVal = [String: DoNotDisturbStatus]()
for key in statuses.keys {
retVal[key] = DoNotDisturbStatus(status: statuses[key] as? [String: AnyObject])
retVal[key] = DoNotDisturbStatus(status: statuses[key] as? [String: Any])
}
return retVal
}
}
+1 -2
View File
@@ -34,7 +34,7 @@ internal struct WebhookRequest: Request {
let text: String
let responseURL: String
init(request: [String: AnyObject]?) {
init(request: [String: Any]?) {
token = request?["token"] as? String
teamID = request?["team_id"] as? String ?? ""
teamDomain = request?["team_domain"] as? String ?? ""
@@ -46,5 +46,4 @@ internal struct WebhookRequest: Request {
text = request?["text"] as? String ?? ""
responseURL = request?["response_url"] as? String ?? ""
}
}
+3 -4
View File
@@ -21,14 +21,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public class WebhookServer: Server {
open class WebhookServer: Server {
public init(token: String, route: String, response: Response) {
super.init(token: token)
addRoute(route, response: response)
}
public func addRoute(_ route: String, response: Response) {
open func addRoute(_ route: String, response: Response) {
http["/\(route)"] = { request in
let webhookRequest = WebhookRequest(request: self.dictionaryFromRequest(request.body))
if webhookRequest.token == self.token {
@@ -39,12 +39,11 @@ public class WebhookServer: Server {
}
}
private func replyForResponse(_ response: Response) -> Reply {
fileprivate func replyForResponse(_ response: Response) -> Reply {
if response.attachments == nil && response.responseType == nil {
return Reply.text(body: response.text)
} else {
return Reply.json(response: response)
}
}
}
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>3.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>3.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>3.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>