Compare commits

..

241 Commits

Author SHA1 Message Date
Peter Zignego 435607d170 Update SlackKit.swift 2017-06-03 22:18:00 -04:00
Peter Zignego 8094bd2c6c Update .swift-version 2017-06-03 18:02:35 -04:00
Peter Zignego 6ccce1875b Merge branch '4.0' of https://github.com/SlackKit/SlackKit into 4.0 2017-06-02 15:35:16 -04:00
Peter Zignego 433fc1a8ff Add platform 2017-06-02 15:34:58 -04:00
Peter Zignego 4f64c952b8 Update README.md 2017-06-02 15:26:08 -04:00
Peter Zignego 139b25a7f0 Add SKServer 2017-06-02 15:25:46 -04:00
Peter Zignego f013840cae SlackKit v4 2017-04-15 15:33:06 -04:00
Peter Zignego 007ec7ab69 License headers 2017-03-10 19:35:29 -05:00
Peter Zignego b93d411f63 More precise os preprocessor 2017-03-10 18:39:25 -05:00
Peter Zignego 741a23809d Additional linux fixes 2017-03-10 18:32:24 -05:00
Peter Zignego a92fd36c17 Additional fixes for linux 2017-03-10 18:29:19 -05:00
Peter Zignego e122610c04 Linux compilation fixes 2017-03-10 18:19:30 -05:00
Peter Zignego 0539e0bac2 Update .swift-version 2017-03-10 17:32:14 -05:00
Peter Zignego 3416161818 Clean up 2017-03-10 17:29:43 -05:00
Peter Zignego 32a4aa13ea Clean up 2017-03-10 17:28:22 -05:00
Peter Zignego cf188ffb6a Gardening 2017-03-10 17:28:06 -05:00
Peter Zignego f1a1963ac8 Acess control 2017-03-10 17:27:51 -05:00
Peter Zignego 645797b72e Add OAuth config 2017-03-09 19:25:09 -05:00
Peter Zignego b9f808f70e Rename ClientOptions to RTMOptions 2017-03-09 19:24:51 -05:00
Peter Zignego 74ef3979f5 Renaming 2017-03-07 18:16:21 -05:00
Peter Zignego 992879f54f Update copyright year 2017-03-07 01:41:38 -05:00
Peter Zignego ccdf9d5d3c SKServer 2017-03-07 01:29:27 -05:00
Peter Zignego 0336b5a9b6 Synchronous request 2017-03-07 01:28:59 -05:00
Peter Zignego aefbeafd28 Break out WebAPI 2017-03-06 20:29:50 -05:00
Peter Zignego bc6c07f045 Update SKCore 2017-03-06 20:28:13 -05:00
Peter Zignego db24e66d33 Postpone events 2017-02-22 22:12:34 -05:00
Peter Zignego ef70f935c1 Renaming… 2017-02-22 22:12:16 -05:00
Peter Zignego afbf8ab6fe Naming… 2017-02-22 21:42:43 -05:00
Peter Zignego d39296f496 SKServer initial 2017-02-22 21:13:07 -05:00
Peter Zignego eafceb4645 Split Client from RTM 2017-02-22 19:54:07 -05:00
Peter Zignego 83cf85a27a SKCommon -> SKCore 2017-02-22 19:53:13 -05:00
Peter Zignego 06e250a954 RTM clean up 2017-02-21 23:10:13 -05:00
Peter Zignego 5b6622a961 v4 WIP 2017-02-20 13:10:45 -05:00
Peter Zignego a58e291d2e Organization 2017-02-04 18:21:37 -05:00
Peter Zignego a0e1f9844e Access control, organization 2017-02-04 13:32:26 -05:00
Peter Zignego 7d524ddeac Split to Common, Client, Server 2017-02-04 12:48:03 -05:00
Peter Zignego 94c9f7fe5a Bump version 2017-01-25 12:31:34 -05:00
Peter Zignego be8a5879f3 Merge pull request #77 from norwoodsystems/master
Updated podspec
2017-01-25 12:29:03 -05:00
kiancheong c657919704 Updated podspec 2017-01-25 14:42:19 +08:00
Peter Zignego abeef21d7a Merge pull request #75 from sersoft-gmbh/master
Fix author_name in Attachment, add Markdown fields for Attachments, fix optionality
2017-01-21 10:53:28 -05:00
Florian Friedrich 79e3b14593 Add missing ? in AttachmentField initializer 2017-01-20 16:16:35 +01:00
Florian Friedrich d9a4cda9b0 Made AttachmentField init params optional, fix author_name key in Attachment, add markdown fields to attachment 2017-01-20 16:11:08 +01:00
Peter Zignego 12b316da0b Merge pull request #73 from strogonoff/patch-1
OAuth: scopes must be supplied
2017-01-18 09:20:53 -05:00
Anton Strogonoff 13cade5c00 OAuth: scopes must be supplied
Slack API spec requires the "scope" parameter when requesting authorization code. Without it a token cannot be obtained as request fails with an error.
2017-01-18 16:21:03 +07:00
Peter Zignego 051e8dd6c8 Fix podspec 2017-01-16 22:11:52 -05:00
Peter Zignego 1adea1c54e Fix podspec 2017-01-16 22:02:43 -05:00
Peter Zignego aa51cfb2fd Version bump 2017-01-16 21:37:49 -05:00
Peter Zignego 6b8885bd29 Merge pull request #72 from pvzig/3.1.8
3.1.8
2017-01-16 21:34:58 -05:00
Peter Zignego e0fbf1ab4e Add logging of unsupported events 2017-01-16 21:32:21 -05:00
Peter Zignego 366c6e7b77 Merge pull request #68 from pvzig/master-project-structure
Project organization
2017-01-06 17:59:37 -05:00
Peter Zignego 378c116d9b Project organization 2017-01-06 17:42:06 -05:00
Peter Zignego 58bade8ec9 Bump version 2017-01-04 22:10:18 -05:00
Peter Zignego 7d7f5c40d6 Update readme 2017-01-04 22:09:18 -05:00
Peter Zignego c9fd54d106 Merge pull request #66 from pvzig/3.1.7
3.1.7
2017-01-04 22:08:10 -05:00
Peter Zignego 2f1ce799ad URLComponents and WebAPI clean up 2017-01-04 22:06:47 -05:00
Peter Zignego 7f02f4cf99 Update readme 2017-01-03 22:07:57 -05:00
Peter Zignego a9066c0d0a Bump version 2017-01-03 21:29:49 -05:00
Peter Zignego 29739dba74 Merge pull request #65 from pvzig/minor-updates
Code styling
2017-01-03 21:20:00 -05:00
Peter Zignego d60a7094a4 Readme 2017-01-03 21:18:58 -05:00
Peter Zignego 7edd4210f6 Code quality improvements 2017-01-02 22:41:03 -05:00
Peter Zignego 2abaecbd14 Lowercase enums 2017-01-02 22:39:56 -05:00
Peter Zignego 346499e03b Update podspec version 2016-11-25 12:46:48 -05:00
Peter Zignego bc72a52bf5 Update readme 2016-11-24 12:37:48 -05:00
Peter Zignego 0ebd3cb0e7 Merge pull request #60 from pvzig/ios-fix
Fix iOS crash + Swift 3 style changes
2016-11-24 12:19:39 -05:00
Peter Zignego 5d7064ee13 Podfile + versioning 2016-11-24 12:16:53 -05:00
Peter Zignego d02768ddad Bump starscream version 2016-11-24 12:01:54 -05:00
Peter Zignego dbc7b361c8 Merge branch 'master' into ios-fix 2016-11-24 11:59:50 -05:00
Peter Zignego a0de46e3c7 Code quality improvements 2016-11-20 22:10:44 -05:00
Peter Zignego 2d6e19baee Bump starscream version 2016-11-20 22:07:06 -05:00
Peter Zignego 21ec3cb2a1 Fix iOS crash 2016-11-20 22:04:50 -05:00
Peter Zignego cb542da068 Merge pull request #59 from MarcusSmith/master
Fix File Upload Bug
2016-11-18 14:16:18 -05:00
Marcus Smith 788b4e4f7a Remove File data from upload's query parameters, which was preventing a proper URL from being created from the request string 2016-11-18 14:14:02 -05:00
Peter Zignego 24b2292cba Request string bugfix 2016-11-17 16:48:00 -05:00
Peter Zignego 72866262d2 Fix request string bug 2016-11-17 16:30:28 -05:00
Peter Zignego acabbb6c03 Update README.md 2016-11-17 15:04:18 -05:00
Peter Zignego fff0f0befc Merge branch 'master' of https://github.com/pvzig/SlackKit into ios-fix
# Conflicts:
#	SlackKit/Sources/WebAPI.swift
2016-11-17 14:44:35 -05:00
Peter Zignego cf0675dac2 Merge pull request #58 from stucarney/master
Added missing support for chat.meMessage endpoint
2016-11-17 09:08:54 -05:00
Stu Carney 1cffa0ba74 Added missing support for chat.meMessage endpoint 2016-11-16 20:00:22 -06:00
Peter Zignego 9ebd8182a6 Lowercase enums 2016-11-13 17:26:32 -05:00
Peter Zignego 63a8ae7f08 Lowercase enums 2016-11-13 15:34:27 -05:00
Peter Zignego 992f94e870 Lowercase error enums 2016-11-13 15:32:50 -05:00
Peter Zignego 1c476c77ad Lowercase enums 2016-11-11 14:59:43 -05:00
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
Peter Zignego c428cac537 Update readme 2016-07-20 21:44:30 -04:00
Peter Zignego 18c6516df9 Remove Cocoapods 2016-07-20 21:32:57 -04:00
Peter Zignego fe450a7db2 Set swift version 2016-07-20 21:32:41 -04:00
Peter Zignego bb57f59553 Swift 3 support 2016-07-20 18:31:03 -04:00
Peter Zignego e5a4a67bdb Fix imports for SPM 2016-07-18 00:07:03 -04:00
Peter Zignego 1e304f1f6d Update podfile.lock 2016-07-17 23:29:06 -04:00
Peter Zignego 81ebf86abd Update podfile and podspec 2016-07-17 23:04:03 -04:00
Peter Zignego afa16e98b3 Update podspec 2016-07-17 22:50:13 -04:00
Peter Zignego 6596bb2861 SlackKit 2.0.0 2016-07-17 22:20:15 -04:00
Peter Zignego fd12ab0600 Readme updates 2016-07-17 21:49:27 -04:00
Peter Zignego 31508e44dc Merge branch 'feature/message-buttons'
# Conflicts:
#	README.md
#	SlackKit.xcodeproj/project.pbxproj
#	SlackKit/Sources/MessageActionResponder.swift
#	SlackKit/Supporting Files/Info-iOS.plist
#	SlackKit/Supporting Files/Info-tvOS.plist
#	SlackKit/Supporting Files/Info.plist
2016-07-17 21:39:14 -04:00
Peter Zignego b980f371f6 SlackKit 2.0.0 2016-07-17 21:30:56 -04:00
Peter Zignego 9526d739e1 Oauth 2016-07-07 20:22:44 -04:00
Peter Zignego c3af5c33be Increment version 2016-07-04 14:35:51 -04:00
Peter Zignego c6258c57a0 Merge pull request #43 from pvzig/spm-fix
SPM fix
2016-07-04 14:32:31 -04:00
Peter Zignego 45e075aca2 Update readme 2016-07-04 14:30:52 -04:00
Peter Zignego 5ebe40a389 Remove example 2016-07-04 13:15:32 -04:00
Peter Zignego 0a5a8f83f7 Remove example target 2016-07-04 13:14:03 -04:00
Peter Zignego 8f4a287ad0 Fix Package.swift 2016-07-04 13:13:28 -04:00
Peter Zignego deadc8855a Webhook and server 2016-07-04 12:38:06 -04:00
Peter Zignego 98155f00b7 Remove bundled sample 2016-07-02 16:42:36 -04:00
Peter Zignego a55d3be65b Message buttons 2016-06-26 14:39:12 -04:00
Peter Zignego 3b8f1834f0 Code improvements 2016-06-25 18:52:53 -04:00
Peter Zignego 34972eb8af Types get their own .swift files 2016-06-25 18:51:48 -04:00
Peter Zignego f21179f567 Model type organization 2016-06-23 00:13:52 -04:00
Peter Zignego e1bf5a160f Merge pull request #41 from hamin/make-some-channel-setters-public
Make the following Chanel setters public 'unreadCountDisplay', 'unrea…
2016-06-19 22:00:07 -04:00
Haris Amin c66a5fe0db Make the following Chanel setters public 'unreadCountDisplay', 'unread', and 'lastRead' 2016-06-19 17:48:31 -04:00
Peter Zignego f03908bcc7 Merge pull request #38 from natestedman/master
Remove curly quotes from Carthage instructions
2016-06-04 11:13:55 -04:00
Nate Stedman 591b0d9d55 Remove curly quotes from Carthage instructions. 2016-06-04 08:55:23 -04:00
Peter Zignego 6e83fb93d8 Merge pull request #36 from pvzig/feature/additional-footer-fields
1.1.1
2016-06-01 17:22:02 -04:00
Peter Zignego c1d202f433 Increment version 2016-06-01 17:21:23 -04:00
Peter Zignego c7db8ac578 Add new Attachment footer fields
https://api.slack.com/docs/attachments
2016-06-01 17:17:27 -04:00
Peter Zignego d2e430e5bf Merge pull request #35 from pvzig/feature/model-object-improvements
1.1.0
2016-05-22 22:33:12 -04:00
Peter Zignego ebe169bf2a Update podspec 2016-05-22 22:30:29 -04:00
Peter Zignego ca36653dc4 Update readme 2016-05-22 22:30:21 -04:00
Peter Zignego 94895edfac Bump version 2016-05-22 22:27:34 -04:00
Peter Zignego 3ea13ac6c4 Multiple target naming clean up 2016-05-22 22:27:25 -04:00
Peter Zignego e94adfc019 Make timestamp non-optional 2016-05-22 21:59:51 -04:00
Peter Zignego 1291323c5a Remove unused variable 2016-05-22 21:30:41 -04:00
Peter Zignego 4ceb452e6b File reordering 2016-05-22 21:30:27 -04:00
Peter Zignego 457504e786 Code quality 2016-05-22 18:38:00 -04:00
Peter Zignego 6d9a939575 Files only come as an ID via RTM (API change)
https://medium.com/slack-developer-blog/changes-to-file-events-in-the-real-time-messaging-api-5fa75c8c4d99#.1f3k421tz
2016-05-22 18:12:46 -04:00
Peter Zignego efc3847a20 Merge remote-tracking branch 'michallaskowski/remove-unneded-optionals' into feature/model-object-improvements
# Conflicts:
#	SlackKit/Sources/Message.swift
#	SlackKit/Sources/SlackWebAPI.swift
2016-05-21 15:28:28 -04:00
Peter Zignego 3ed139b503 Merge pull request #33 from hamin/fix-message-reactions-parsing
Fixes parsing of Reaction from Message response. It now properly adds…
2016-05-21 12:26:51 -04:00
Peter Zignego a4d9083f72 Merge pull request #34 from muratayusuke/feature/handle_http_error
Hanlde HTTP error
2016-05-21 12:25:18 -04:00
muratayusuke 67b2fa95b3 Hanlde HTTP error 2016-05-21 15:06:57 +09:00
Haris Amin e031f85447 Fixes parsing of Reaction from Message response. It now properly adds users to a parsed Reaction 2016-05-21 01:16:34 -04:00
Peter Zignego 0b1dc6068e Merge remote-tracking branch 'michallaskowski/slack-web-api-without-client' 2016-05-17 20:21:20 -04:00
Peter Zignego b027b5b779 Readme styling 2016-05-15 21:16:09 -04:00
Peter Zignego e507c85ca2 Update readme with note about slow carthage build times 2016-05-15 21:14:43 -04:00
michallaskowski 145dfccfae Remove unneeded Array extension 2016-05-15 23:16:55 +02:00
michallaskowski b4ca2bcc07 Delete optionals from EventDelegate where possible, fix reactionRemoved 2016-05-15 23:16:55 +02:00
michallaskowski 85b2d920ad Gardening Client.swift 2016-05-15 23:16:55 +02:00
michallaskowski 6415a113ed Remove failable initializers 2016-05-15 23:16:55 +02:00
Peter Zignego 3a2324b279 Fix readme 2016-05-15 16:29:40 -04:00
Peter Zignego d647a6b0c9 Update podspec 2016-05-15 16:27:47 -04:00
Peter Zignego 4230d7841c Merge pull request #32 from pvzig/feature/carthage-support
Feature/carthage support
2016-05-15 16:22:18 -04:00
Peter Zignego 8995a54d15 Fix project file and schemes after merge 2016-05-15 16:16:26 -04:00
Peter Zignego ba43a123ea Merge branch 'master' into feature/carthage-support
# Conflicts:
#	SlackKit.podspec
#	SlackKit.xcodeproj/project.pbxproj
#	SlackKit.xcodeproj/xcshareddata/xcschemes/SlackKit.xcscheme
2016-05-15 15:57:27 -04:00
Peter Zignego d00419dc18 Framework build details 2016-05-15 15:41:42 -04:00
Peter Zignego 15f3a30ba9 Framework build details 2016-05-15 15:39:47 -04:00
Peter Zignego befa53e3a9 Update ignore 2016-05-15 15:28:43 -04:00
Peter Zignego 35dfa840e8 Revert "Use submodule to handle core dependency"
This reverts commit edf56e1678.
2016-05-15 15:25:36 -04:00
Peter Zignego edf56e1678 Use submodule to handle core dependency 2016-05-15 15:21:47 -04:00
Peter Zignego 3eab323564 Ignore Cartfile.resolved 2016-05-15 15:04:34 -04:00
Peter Zignego 0b2ee1d10e Clean up project file 2016-05-15 14:51:15 -04:00
michallaskowski 5444948940 Do not hold Client instance in SlackWebAPI 2016-05-15 20:40:05 +02:00
Peter Zignego 13335b5de1 Add additional shared schemes 2016-05-15 14:09:21 -04:00
Peter Zignego c8d8e18db6 Move AttachmentColor enum 2016-05-14 20:11:14 -04:00
Peter Zignego c11321c116 File name comment fixes 2016-05-14 20:08:54 -04:00
Michal Laskowski 0041a118a7 Fix circular dependencies (#30)
* Remove EventDispatcher, EventHandler classes; extend Client

* Make delegates weak

* Remove unneded 'if let delegate = '

* Move files around
2016-05-14 19:51:08 -04:00
Michal Laskowski 6cb5280cf5 Add tvOS target to podspec 2016-05-11 10:12:15 -05:00
Peter Zignego 9cad043957 Add shared scheme 2016-05-06 15:02:39 -04:00
Peter Zignego fa15ed8751 Merge pull request #28 from hamin/add-larger-thumbs-to-file
Adding support for larger size File thumbs
2016-05-04 12:02:42 -04:00
Haris Amin 0c9c146d58 Adding support for larger size File thumbs 2016-05-04 01:58:43 -04:00
Peter Zignego 109a20fac2 Readme update 2016-04-27 23:18:19 -04:00
Peter Zignego a6cf1e3cb6 Revert "Delete and add Cartfile.resolved to ignore"
This reverts commit d3c16bed5f.
2016-04-27 23:17:41 -04:00
Peter Zignego d3c16bed5f Delete and add Cartfile.resolved to ignore 2016-04-27 23:07:55 -04:00
Peter Zignego 797d95ab75 Update readme 2016-04-27 22:54:30 -04:00
Nate Stedman efb7bc9458 Use Carthage for resolving dependencies. 2016-04-27 22:34:28 -04:00
Peter Zignego 79e59f23fb Bump version number 2016-04-27 19:33:48 -04:00
Peter Zignego 01e199659e Update readme 2016-04-27 19:30:48 -04:00
Peter Zignego 851b2f5e14 Merge pull request #27 from pvzig/1.0.2
v1.0.2
2016-04-27 19:26:26 -04:00
Peter Zignego c506512800 Add files.info 2016-04-27 19:18:12 -04:00
Peter Zignego 20fa05605b Merge branch 'master' of https://github.com/pvzig/SlackRTMKit 2016-04-27 17:44:55 -04:00
Peter Zignego 30baf1f76c Add clientConnectionFailed delegate 2016-04-27 17:44:51 -04:00
Peter Zignego 1c3f01f861 Fix typo in example 2016-04-27 17:39:23 -04:00
Peter Zignego 47dc9b3d9f Merge pull request #25 from muratayusuke/feature/make_token_public
Make token public
2016-04-25 10:28:45 -04:00
muratayusuke b9e828ef3d Make token public 2016-04-24 18:44:40 +09:00
Peter Zignego b2be8d0170 Merge pull request #24 from pvzig/1.0.1
v1.0.1
2016-04-09 11:40:17 -04:00
Peter Zignego 45be1b7a3f Bump version number 2016-04-09 11:33:22 -04:00
Peter Zignego 09aa72d43e Update readme to include explanation of Leaderboard example 2016-04-09 11:24:47 -04:00
Peter Zignego bf4b55bbd6 Add leaderboard bot example 2016-04-09 11:02:30 -04:00
Peter Zignego a82279fad1 Code cleanup and improvement 2016-04-04 23:49:25 -04:00
Peter Zignego 500e489d5d Add AttachmentField type and AttachmentColor enum 2016-04-04 21:26:09 -04:00
Peter Zignego 874f4f51e1 Fix send message optional parameter handling 2016-04-03 21:04:49 -04:00
Peter Zignego 654f419f4e Support for rtm.start parameters 2016-04-03 15:45:53 -04:00
Peter Zignego a7c25fe33b Version bump 2016-03-22 21:55:26 -04:00
Peter Zignego d2037f4cc5 Merge pull request #23 from pvzig/feature/client-improvements
Feature/client-improvements
2016-03-22 21:44:20 -04:00
Peter Zignego b87232dfb5 Readme updates 2016-03-22 21:38:17 -04:00
Peter Zignego 9e5678739f Update readme 2016-03-22 21:34:45 -04:00
Peter Zignego 5cc8582d65 Code cleanup 2016-03-22 21:29:16 -04:00
Peter Zignego aa078934c0 File comment web api errors 2016-03-22 20:56:10 -04:00
Peter Zignego 5c157caea3 Client improvements - disconnect, ping-pong, timeout, reconnect 2016-03-22 20:50:29 -04:00
Peter Zignego b567113b5f Update Starscream dependency version 2016-03-22 20:44:58 -04:00
Peter Zignego 5b08fb6031 Merge pull request #21 from pvzig/feature/file-comment
Add support for file comment web API calls
2016-03-19 14:21:52 -04:00
Peter Zignego b48f33fb72 Add support for file comment web API calls 2016-03-19 14:12:04 -04:00
Peter Zignego deccb727a1 Merge pull request #20 from pvzig/feature/reactions-itemUser
Add support for the item user reaction property
2016-03-15 23:48:55 -04:00
Peter Zignego 8f1df8d138 Add support for the itemUser reaction property 2016-03-15 23:48:08 -04:00
Peter Zignego 0048710e24 Merge pull request #19 from pvzig/feature/dnd-read
DND Read Scope Web API implementation
2016-03-15 23:38:08 -04:00
Peter Zignego f6da0ddd32 DND read scope fixes 2016-03-15 23:37:33 -04:00
Peter Zignego 513485e704 DND Read Scope Web API implementation 2016-03-15 23:28:38 -04:00
Peter Zignego fb3719c29d Merge pull request #18 from pvzig/feature/rtm-team-profile
Add support for team profile events
2016-03-15 22:48:43 -04:00
Peter Zignego 76fdc55f9e Team profile events 2016-03-15 22:45:45 -04:00
Peter Zignego 687b57fc1f Version bump 2016-03-01 23:08:24 -05:00
Peter Zignego 319dc9a095 Merge pull request #17 from muratayusuke/bugfix/ignore_int_param
Bugfix: Do not ignore Int and Bool parameters when making requests to the web api
2016-03-01 12:47:20 -05:00
muratayusuke 64440b5c5b Do not ignore Int/Bool param such as count 2016-03-02 02:25:37 +09:00
Peter Zignego 3efe5752cb Merge pull request #16 from pvzig/feature/history-object
Feature/history object
2016-02-28 12:41:22 -05:00
Peter Zignego 31f69e3afd Move History struct to Types.swift, minor changes 2016-02-28 12:40:04 -05:00
muratayusuke 72b29562e5 Introduce history type 2016-02-28 12:29:12 -05:00
Peter Zignego 2b26eb35d7 Merge pull request #14 from pvzig/fix/team-object
fix/team-object
2016-02-27 14:13:53 -05:00
Peter Zignego c4c8e99c0b Bug fixes, team icon support 2016-02-27 14:10:35 -05:00
muratayusuke 5efe222196 Add team icon 2016-02-27 14:06:24 -05:00
Peter Zignego e56ff971b2 Merge pull request #12 from hamin/public-message-initializer
Making Message struct initializer public.
2016-02-27 13:48:42 -05:00
Haris Amin 18b8a31d85 Making Message struct initializer public. 2016-02-27 13:38:52 -05:00
Peter Zignego d386730c75 Project file update 2016-02-21 10:31:13 -05:00
Peter Zignego bc6e94d99a Merge pull request #11 from pvzig/feature/message-attachments
Message attachment support
2016-02-21 10:27:41 -05:00
Peter Zignego 89f5e3786e Message attachment support 2016-02-21 10:18:32 -05:00
Peter Zignego 0665ea0270 Add sample app 2016-02-18 18:21:17 -05:00
35 changed files with 866 additions and 3685 deletions
+6 -3
View File
@@ -16,8 +16,11 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate
.build
*.DS_Store
# SwiftPM
Packages/
.build
# CocoaPods
#
@@ -26,10 +29,10 @@ Packages/
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
Pods/
SlackKit.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Checkouts
Carthage/Build
+1
View File
@@ -0,0 +1 @@
3.1.1
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2016 Peter Zignego
Copyright (c) 2017 Peter Zignego
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+7 -26
View File
@@ -1,33 +1,14 @@
//
// 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(
name: "SlackKit",
targets: [],
targets: [
Target(name: "SlackKit")
],
dependencies: [
.Package(url: "https://github.com/pvzig/Starscream.git",
majorVersion: 1),
.Package(url: "https://github.com/SlackKit/SKCore", "4.0.0"),
.Package(url: "https://github.com/SlackKit/SKClient", "4.0.0"),
.Package(url: "https://github.com/SlackKit/SKRTMAPI", "4.0.0"),
.Package(url: "https://github.com/SlackKit/SKServer", "4.0.0")
]
)
+25 -4
View File
@@ -1,7 +1,28 @@
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
target 'SlackKit' do
pod 'Starscream'
target 'SlackKit macOS' do
platform :osx, '10.11'
pod 'SKCore'
pod 'SKClient'
pod 'SKWebAPI'
pod 'SKRTMAPI'
pod 'SKServer'
end
target 'SlackKit iOS' do
platform :ios, '9.0'
pod 'SKCore'
pod 'SKClient'
pod 'SKWebAPI'
pod 'SKRTMAPI'
pod 'SKServer'
end
target 'SlackKit tvOS' do
platform :tvos, '9.0'
pod 'SKCore'
pod 'SKClient'
pod 'SKWebAPI'
pod 'SKRTMAPI'
pod 'SKServer'
end
-10
View File
@@ -1,10 +0,0 @@
PODS:
- Starscream (1.0.2)
DEPENDENCIES:
- Starscream
SPEC CHECKSUMS:
Starscream: 40e2c4c1c770d811f24116b8b7dbeb4542c56767
COCOAPODS: 0.39.0
+164 -174
View File
@@ -1,215 +1,205 @@
![SlackKit](https://cloud.githubusercontent.com/assets/8311605/10260893/5ec60f96-694e-11e5-91fd-da6845942201.png)
##iOS/OS X Slack Client Library
###Description
This is a Slack client library for iOS and OS X written in Swift. It's intended to expose all of the functionality of Slack's [Real Time Messaging API](https://api.slack.com/rtm) as well as the [web APIs](https://api.slack.com/web) that are accessible by [bot users](https://api.slack.com/bot-users).
<p align="center"><img src="https://cloud.githubusercontent.com/assets/8311605/24083714/e921a0d4-0cb2-11e7-8384-d42113ef5056.png" alt="SlackKit" width="500"/></p>
###Installation
####Swift Package Manager
Add SlackKit to your Package.swift
![Swift Version](https://img.shields.io/badge/Swift-3.1.1-orange.svg)
![Plaforms](https://img.shields.io/badge/Platforms-macOS,iOS,tvOS,Linux-lightgrey.svg)
![License MIT](https://img.shields.io/badge/License-MIT-lightgrey.svg)
[![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-brightgreen.svg)](https://github.com/Carthage/Carthage)
[![CocoaPods compatible](https://img.shields.io/badge/CocoaPods-compatible-brightgreen.svg)](https://cocoapods.org)
## SlackKit: Slack Apps in Swift
### Description
SlackKit makes it easy to build Slack apps 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).
### Installation
#### 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: 0)
]
dependencies: [
.Package(url: "https://github.com/SlackKit/SlackKit.git", "4.0.0")
]
)
```
#### Carthage
Run `swift-build` on your applications main directory.
Add `SlackKit` to your `Cartfile`:
```
github "SlackKit/SlackKit"
```
#### CocoaPods
Add `SlackKit` to your `Podfile`:
####CocoaPods
Add the pod to your podfile:
```
pod 'SlackKit'
```
and run
```
pod install
```
To use the library in your project import it:
```
### Usage
#### The Basics
Create a bot user with an API token:
```swift
import SlackKit
```
###Usage
To use SlackKit you'll need a bearer token which identifies a single user. You can generate a [full access token or create one using OAuth 2](https://api.slack.com/web).
Once you have a token, initialize a client instance using it:
```swift
let client = Client(apiToken: "YOUR_SLACK_API_TOKEN")
```
If you want to receive messages from the Slack RTM API, connect to it.
```swift
client.connect()
```
Once connected, the client will begin to consume any messages sent by the Slack RTM API.
####Web API Methods
SlackKit currently supports the a subset of the Slack Web APIs that are available to bot users:
- api.test
- auth.test
- channels.history
- channels.info
- channels.list
- channels.mark
- channels.setPurpose
- channels.setTopic
- chat.delete
- chat.postMessage
- chat.update
- emoji.list
- files.delete
- files.upload
- groups.close
- groups.history
- groups.info
- groups.list
- groups.mark
- groups.open
- groups.setPurpose
- groups.setTopic
- im.close
- im.history
- im.list
- im.mark
- im.open
- mpim.close
- mpim.history
- mpim.list
- mpim.mark
- mpim.open
- pins.add
- pins.list
- pins.remove
- reactions.add
- reactions.get
- reactions.list
- reactions.remove
- rtm.start
- stars.add
- stars.remove
- team.info
- users.getPresence
- users.info
- users.list
- users.setActive
- users.setPresence
They can be accessed through a Client objects `webAPI` property:
```swift
client.webAPI.authenticationTest({
(authenticated) -> Void in
print(authenticated)
}){(error) -> Void in
print(error)
let bot = SlackKit()
bot.addRTMBotWithAPIToken("xoxb-SLACK-BOT-TOKEN")
// Register for event notifications
bot.notificationForEvent(.message) { (event, _) in
// Your bot logic here
print(event.message)
}
```
####Delegate methods
or create a ready-to-launch Slack app with your [applications `Client ID` and `Client Secret`](https://api.slack.com/apps):
To receive delegate callbacks for certain events, register an object as the delegate for those events:
```swift
client.slackEventsDelegate = self
import SlackKit
let bot = SlackKit()
let oauthConfig = OAuthConfig(clientID: "CLIENT_ID", clientSecret: "CLIENT_SECRET")
bot.addServer(oauth: oauthConfig)
```
There are a number of delegates that you can set to receive callbacks for certain events.
or just make calls to the Slack Web API:
#####SlackEventsDelegate
```swift
func clientConnected()
func clientDisconnected()
func preferenceChanged(preference: String, value: AnyObject)
func userChanged(user: User)
func presenceChanged(user: User?, presence: String?)
func manualPresenceChanged(user: User?, presence: String?)
func botEvent(bot: Bot)
import SlackKit
let bot = SlackKit()
bot.addWebAPIAccessWithToken("xoxb-SLACK-BOT-TOKEN")
bot.webAPI?.authenticationTest(success: { (success) in
print(success)
}, failure: nil)
```
#####MessageEventsDelegate
#### Slash Commands
After [configuring your slash command in Slack](https://my.slack.com/services/new/slash-commands) (you can also provide slash commands as part of a [Slack App](https://api.slack.com/slack-apps)), create a route, response middleware for that route, and add it to a responder:
```swift
func messageSent(message: Message)
func messageReceived(message: Message)
func messageChanged(message: Message)
func messageDeleted(message: Message?)
let slackkit = SlackKit()
let middleware = ResponseMiddleware(token: "SLASH_COMMAND_TOKEN", response: SKResponse(text: "👋"))
let route = RequestRoute(path: "/hello", middleware: middleware)
let responder = SlackKitResponder(routes: [route])
slackkit.addServer(responder: responder)
```
When a user enters that slash command, it will hit your configured route and return the response you specified.
#### Message Buttons
Add [message buttons](https://api.slack.com/docs/message-buttons) to your responses for additional interactivity.
To send messages with actions, add them to an attachment and send them using the Web API:
```swift
let helloAction = Action(name: "hello", text: "🌎")
let attachment = Attachment(fallback: "Hello World", title: "Welcome to SlackKit", callbackID: "hello_world", actions: [helloAction])
slackkit.webAPI?.sendMessage(channel: "CXXXXXX", text: "", attachments: [attachment], success: nil, failure: nil)
```
#####ChannelEventsDelegate
To respond to message actions, add a `RequestRoute` with `MessageActionMiddleware` using your apps verification token to your `SlackKitResponder`:
```swift
func userTyping(channel: Channel?, user: User?)
func channelMarked(channel: Channel, timestamp: String?)
func channelCreated(channel: Channel)
func channelDeleted(channel: Channel)
func channelRenamed(channel: Channel)
func channelArchived(channel: Channel)
func channelHistoryChanged(channel: Channel)
func channelJoined(channel: Channel)
func channelLeft(channel: Channel)
let response = ResponseMiddleware(token: "SLACK_APP_VERIFICATION_TOKEN", response: SKResponse(text: "Hello, world!"))
let actionRoute = MessageActionRoute(action: helloAction, middleware: response)
let actionMiddleware = MessageActionMiddleware(token: "SLACK_APP_VERIFICATION_TOKEN", routes:[actionRoute])
let actions = RequestRoute(path: "/actions", middleware: actionMiddleware)
let responder = SlackKitResponder(routes: [actions])
slackkit.addServer(responder: responder)
```
#####DoNotDisturbEventsDelegate
```swift
doNotDisturbUpdated(dndStatus: DoNotDisturbStatus)
doNotDisturbUserUpdated(dndStatus: DoNotDisturbStatus, user: User?)
```
#### OAuth
Slack has [many different oauth scopes](https://api.slack.com/docs/oauth-scopes) that can be combined in different ways. If your application does not request the proper OAuth scopes, your API calls will fail.
#####GroupEventsDelegate
```swift
func groupOpened(group: Channel)
```
If you authenticate using OAuth and the Add to Slack or Sign in with Slack buttons this is handled for you.
#####FileEventsDelegate
```swift
func fileProcessed(file: File)
func fileMadePrivate(file: File)
func fileDeleted(file: File)
func fileCommentAdded(file: File, comment: Comment)
func fileCommentEdited(file: File, comment: Comment)
func fileCommentDeleted(file: File, comment: Comment)
```
For local development of things like OAuth, slash commands, and message buttons, you may want to use a tool like [ngrok](https://ngrok.com).
#####PinEventsDelegate
```swift
func itemPinned(item: Item?, channel: Channel?)
func itemUnpinned(item: Item?, channel: Channel?)
```
#### Web API Methods
SlackKit currently supports the a subset of the Slack Web APIs that are available to bot users:
#####StarEventsDelegate
```swift
func itemStarred(item: Item, star: Bool)
```
| Web APIs |
| ------------- |
| `api.test`|
| `api.revoke`|
| `auth.test`|
| `channels.history`|
| `channels.info`|
| `channels.list`|
| `channels.mark`|
| `channels.setPurpose`|
| `channels.setTopic`|
| `chat.delete`|
| `chat.meMessage`|
| `chat.postMessage`|
| `chat.update`|
| `emoji.list`|
| `files.comments.add`|
| `files.comments.edit`|
| `files.comments.delete`|
| `files.delete`|
| `files.info`|
| `files.upload`|
| `groups.close`|
| `groups.history`|
| `groups.info`|
| `groups.list`|
| `groups.mark`|
| `groups.open`|
| `groups.setPurpose`|
| `groups.setTopic`|
| `im.close`|
| `im.history`|
| `im.list`|
| `im.mark`|
| `im.open`|
| `mpim.close`|
| `mpim.history`|
| `mpim.list`|
| `mpim.mark`|
| `mpim.open`|
| `oauth.access`|
| `pins.add`|
| `pins.list`|
| `pins.remove`|
| `reactions.add`|
| `reactions.get`|
| `reactions.list`|
| `reactions.remove`|
| `rtm.start`|
| `stars.add`|
| `stars.remove`|
| `team.info`|
| `users.getPresence`|
| `users.info`|
| `users.list`|
| `users.setActive`|
| `users.setPresence`|
#####ReactionEventsDelegate
```swift
func reactionAdded(reaction: String?, item: Item?)
func reactionRemoved(reaction: String?, item: Item?)
```
Dont need the whole banana? Want more control over the low-level implementation details? Use the extensible modules SlackKit is built on:
#####TeamEventsDelegate
```swift
func teamJoined(user: User)
func teamPlanChanged(plan: String)
func teamPreferencesChanged(preference: String, value: AnyObject)
func teamNameChanged(name: String)
func teamDomainChanged(domain: String)
func teamEmailDomainChanged(domain: String)
func teamEmojiChanged()
```
| Module | Slack Service |
| ------------- |------------- |
| **[SKClient](https://github.com/SlackKit/SKClient)** | Write your own client implementation|
| **[SKRTMAPI](https://github.com/SlackKit/SKRTMAPI)** | Connect to the Slack RTM API|
| **[SKServer](https://github.com/SlackKit/SKServer)** | Spin up a server|
| **[SKWebAPI](https://github.com/SlackKit/SKWebAPI)** | Access the Slack Web API|
#####SubteamEventsDelegate
```swift
func subteamEvent(userGroup: UserGroup)
func subteamSelfAdded(subteamID: String)
func subteamSelfRemoved(subteamID: String)
```
### Examples
You can find the source code for several example applications [here](https://github.com/SlackKit/Examples).
### Tutorials
Coming soon!
###Get In Touch
[@pvzig](https://twitter.com/pvzig)
### Get In Touch
Twitter: [@pvzig](https://twitter.com/pvzig)
<peter@launchsoft.co>
Email: <peter@launchsoft.co>
-30
View File
@@ -1,30 +0,0 @@
//
// SlackKit.h
//
// 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 <Foundation/Foundation.h>
//! Project version number for SlackKit.
FOUNDATION_EXPORT double SlackKitVersionNumber;
//! Project version string for SlackKit.
FOUNDATION_EXPORT const unsigned char SlackKitVersionString[];
+12 -8
View File
@@ -1,16 +1,20 @@
Pod::Spec.new do |s|
s.name = "SlackKit"
s.version = "0.9.8"
s.summary = "a Slack client library for iOS and OS X written in Swift"
s.version = "4.0.0"
s.summary = "Write Slack apps 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.source = { :git => "https://github.com/SlackKit/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.9'
s.ios.deployment_target = '9.0'
s.osx.deployment_target = '10.11'
s.tvos.deployment_target = '9.0'
s.requires_arc = true
s.source_files = 'SlackKit/Sources/*.swift'
s.source_files = 'Sources/*.swift'
s.frameworks = 'Foundation'
s.dependency 'Starscream', '~> 1.0.2'
end
s.dependency 'SKCore'
s.dependency 'SKClient'
s.dependency 'SKRTMAPI'
s.dependency 'SKServer'
end
+303 -174
View File
@@ -7,129 +7,106 @@
objects = {
/* Begin PBXBuildFile section */
2601D61B1C7646B80012BF22 /* SlackWebAPIErrorDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2601D61A1C7646B80012BF22 /* SlackWebAPIErrorDispatcher.swift */; };
260EC2331C4DC61D0093B253 /* ClientExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2301C4DC61D0093B253 /* ClientExtensions.swift */; };
260EC2341C4DC61D0093B253 /* NetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2311C4DC61D0093B253 /* NetworkInterface.swift */; };
260EC2351C4DC61D0093B253 /* SlackWebAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260EC2321C4DC61D0093B253 /* SlackWebAPI.swift */; };
26BBA1941C398E3C00BF7225 /* Bot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1871C398E3C00BF7225 /* Bot.swift */; };
26BBA1951C398E3C00BF7225 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1881C398E3C00BF7225 /* Channel.swift */; };
26BBA1961C398E3C00BF7225 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1891C398E3C00BF7225 /* Client.swift */; };
26BBA1971C398E3C00BF7225 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18A1C398E3C00BF7225 /* Event.swift */; };
26BBA1981C398E3C00BF7225 /* EventDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18B1C398E3C00BF7225 /* EventDelegate.swift */; };
26BBA1991C398E3C00BF7225 /* EventDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18C1C398E3C00BF7225 /* EventDispatcher.swift */; };
26BBA19A1C398E3C00BF7225 /* EventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18D1C398E3C00BF7225 /* EventHandler.swift */; };
26BBA19B1C398E3C00BF7225 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18E1C398E3C00BF7225 /* File.swift */; };
26BBA19C1C398E3C00BF7225 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA18F1C398E3C00BF7225 /* Message.swift */; };
26BBA19D1C398E3C00BF7225 /* Team.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1901C398E3C00BF7225 /* Team.swift */; };
26BBA19E1C398E3C00BF7225 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1911C398E3C00BF7225 /* Types.swift */; };
26BBA19F1C398E3C00BF7225 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1921C398E3C00BF7225 /* User.swift */; };
26BBA1A01C398E3C00BF7225 /* UserGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BBA1931C398E3C00BF7225 /* UserGroup.swift */; };
FFE3AC870D1C42EF276CCA2D /* Pods_SlackKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 407A2ABFC0611867E2BE34D0 /* Pods_SlackKit.framework */; };
266687051E95CB9F00777D94 /* SlackKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 266687041E95CB9F00777D94 /* SlackKit.swift */; };
266687061E95CB9F00777D94 /* SlackKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 266687041E95CB9F00777D94 /* SlackKit.swift */; };
266687071E95CB9F00777D94 /* SlackKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 266687041E95CB9F00777D94 /* SlackKit.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
2601D61A1C7646B80012BF22 /* SlackWebAPIErrorDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SlackWebAPIErrorDispatcher.swift; path = Sources/SlackWebAPIErrorDispatcher.swift; sourceTree = "<group>"; };
26072A341BB48B3A00CD650C /* SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
260EC2301C4DC61D0093B253 /* ClientExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ClientExtensions.swift; path = Sources/ClientExtensions.swift; sourceTree = "<group>"; };
260EC2311C4DC61D0093B253 /* NetworkInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NetworkInterface.swift; path = Sources/NetworkInterface.swift; sourceTree = "<group>"; };
260EC2321C4DC61D0093B253 /* SlackWebAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SlackWebAPI.swift; path = Sources/SlackWebAPI.swift; sourceTree = "<group>"; };
2661A6A41BBF62FF0026F67B /* SlackKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SlackKit.h; sourceTree = "<group>"; };
266E05F01BBF780C00840D76 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
26BBA1871C398E3C00BF7225 /* Bot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Bot.swift; path = Sources/Bot.swift; sourceTree = "<group>"; };
26BBA1881C398E3C00BF7225 /* Channel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Channel.swift; path = Sources/Channel.swift; sourceTree = "<group>"; };
26BBA1891C398E3C00BF7225 /* Client.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Client.swift; path = Sources/Client.swift; sourceTree = "<group>"; };
26BBA18A1C398E3C00BF7225 /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Event.swift; path = Sources/Event.swift; sourceTree = "<group>"; };
26BBA18B1C398E3C00BF7225 /* EventDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EventDelegate.swift; path = Sources/EventDelegate.swift; sourceTree = "<group>"; };
26BBA18C1C398E3C00BF7225 /* EventDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EventDispatcher.swift; path = Sources/EventDispatcher.swift; sourceTree = "<group>"; };
26BBA18D1C398E3C00BF7225 /* EventHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EventHandler.swift; path = Sources/EventHandler.swift; sourceTree = "<group>"; };
26BBA18E1C398E3C00BF7225 /* File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = File.swift; path = Sources/File.swift; sourceTree = "<group>"; };
26BBA18F1C398E3C00BF7225 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Message.swift; path = Sources/Message.swift; sourceTree = "<group>"; };
26BBA1901C398E3C00BF7225 /* Team.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Team.swift; path = Sources/Team.swift; sourceTree = "<group>"; };
26BBA1911C398E3C00BF7225 /* Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Types.swift; path = Sources/Types.swift; sourceTree = "<group>"; };
26BBA1921C398E3C00BF7225 /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = User.swift; path = Sources/User.swift; sourceTree = "<group>"; };
26BBA1931C398E3C00BF7225 /* UserGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UserGroup.swift; path = Sources/UserGroup.swift; sourceTree = "<group>"; };
407A2ABFC0611867E2BE34D0 /* Pods_SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4347F92F3932C96C23B10B2A /* Pods-SlackKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SlackKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-SlackKit/Pods-SlackKit.release.xcconfig"; sourceTree = "<group>"; };
F59B6A12F1C4C4E24C58E1BF /* Pods-SlackKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SlackKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SlackKit/Pods-SlackKit.debug.xcconfig"; sourceTree = "<group>"; };
266687041E95CB9F00777D94 /* SlackKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlackKit.swift; sourceTree = "<group>"; };
2684F17D1E95AA6900536DCC /* SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2684F1E41E95ABD400536DCC /* SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2684F2081E95ABD600536DCC /* SlackKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlackKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2684F20D1E95AF8C00536DCC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
26072A301BB48B3A00CD650C /* Frameworks */ = {
2684F1791E95AA6900536DCC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F1DE1E95ABD400536DCC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F2021E95ABD600536DCC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FFE3AC870D1C42EF276CCA2D /* Pods_SlackKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0C2928E508A686B69F9F0117 /* Pods */ = {
266687031E95CB9F00777D94 /* Sources */ = {
isa = PBXGroup;
children = (
F59B6A12F1C4C4E24C58E1BF /* Pods-SlackKit.debug.xcconfig */,
4347F92F3932C96C23B10B2A /* Pods-SlackKit.release.xcconfig */,
266687041E95CB9F00777D94 /* SlackKit.swift */,
);
name = Pods;
sourceTree = "<group>";
path = Sources;
sourceTree = SOURCE_ROOT;
};
26072A2A1BB48B3A00CD650C = {
2684F1731E95AA6900536DCC = {
isa = PBXGroup;
children = (
2661A6811BBF60E60026F67B /* SlackKit */,
26072A351BB48B3A00CD650C /* Products */,
0C2928E508A686B69F9F0117 /* Pods */,
CA70A3A1A9A1A259960DFBCF /* Frameworks */,
2684F17F1E95AA6900536DCC /* SlackKit */,
2684F17E1E95AA6900536DCC /* Products */,
);
sourceTree = "<group>";
};
26072A351BB48B3A00CD650C /* Products */ = {
2684F17E1E95AA6900536DCC /* Products */ = {
isa = PBXGroup;
children = (
26072A341BB48B3A00CD650C /* SlackKit.framework */,
2684F17D1E95AA6900536DCC /* SlackKit.framework */,
2684F1E41E95ABD400536DCC /* SlackKit.framework */,
2684F2081E95ABD600536DCC /* SlackKit.framework */,
);
name = Products;
sourceTree = "<group>";
};
2661A6811BBF60E60026F67B /* SlackKit */ = {
2684F17F1E95AA6900536DCC /* SlackKit */ = {
isa = PBXGroup;
children = (
26BBA1871C398E3C00BF7225 /* Bot.swift */,
26BBA1881C398E3C00BF7225 /* Channel.swift */,
26BBA1891C398E3C00BF7225 /* Client.swift */,
260EC2301C4DC61D0093B253 /* ClientExtensions.swift */,
26BBA18A1C398E3C00BF7225 /* Event.swift */,
26BBA18B1C398E3C00BF7225 /* EventDelegate.swift */,
26BBA18C1C398E3C00BF7225 /* EventDispatcher.swift */,
26BBA18D1C398E3C00BF7225 /* EventHandler.swift */,
26BBA18E1C398E3C00BF7225 /* File.swift */,
26BBA18F1C398E3C00BF7225 /* Message.swift */,
260EC2311C4DC61D0093B253 /* NetworkInterface.swift */,
260EC2321C4DC61D0093B253 /* SlackWebAPI.swift */,
2601D61A1C7646B80012BF22 /* SlackWebAPIErrorDispatcher.swift */,
26BBA1901C398E3C00BF7225 /* Team.swift */,
26BBA1911C398E3C00BF7225 /* Types.swift */,
26BBA1921C398E3C00BF7225 /* User.swift */,
26BBA1931C398E3C00BF7225 /* UserGroup.swift */,
2661A6A41BBF62FF0026F67B /* SlackKit.h */,
266E05F01BBF780C00840D76 /* Info.plist */,
266687031E95CB9F00777D94 /* Sources */,
2684F20C1E95AF8C00536DCC /* Supporting Files */,
);
path = SlackKit;
name = SlackKit;
path = SKCore;
sourceTree = "<group>";
};
CA70A3A1A9A1A259960DFBCF /* Frameworks */ = {
2684F20C1E95AF8C00536DCC /* Supporting Files */ = {
isa = PBXGroup;
children = (
407A2ABFC0611867E2BE34D0 /* Pods_SlackKit.framework */,
2684F20D1E95AF8C00536DCC /* Info.plist */,
);
name = Frameworks;
sourceTree = "<group>";
path = "Supporting Files";
sourceTree = SOURCE_ROOT;
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
26072A311BB48B3A00CD650C /* Headers */ = {
2684F17A1E95AA6900536DCC /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F1DF1E95ABD400536DCC /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F2031E95ABD600536DCC /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -139,60 +116,116 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
26072A331BB48B3A00CD650C /* SlackKit */ = {
2684F17C1E95AA6900536DCC /* SlackKit macOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 26072A3C1BB48B3B00CD650C /* Build configuration list for PBXNativeTarget "SlackKit" */;
buildConfigurationList = 2684F1851E95AA6900536DCC /* Build configuration list for PBXNativeTarget "SlackKit macOS" */;
buildPhases = (
EBD7A091EB278C5BA34791C5 /* Check Pods Manifest.lock */,
26072A2F1BB48B3A00CD650C /* Sources */,
26072A301BB48B3A00CD650C /* Frameworks */,
26072A311BB48B3A00CD650C /* Headers */,
26072A321BB48B3A00CD650C /* Resources */,
AC19A945F408269E4B4132CC /* Copy Pods Resources */,
2684F1781E95AA6900536DCC /* Sources */,
2684F1791E95AA6900536DCC /* Frameworks */,
2684F17A1E95AA6900536DCC /* Headers */,
2684F17B1E95AA6900536DCC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = SlackKit;
productName = SlackRTMKit;
productReference = 26072A341BB48B3A00CD650C /* SlackKit.framework */;
name = "SlackKit macOS";
productName = SKCore;
productReference = 2684F17D1E95AA6900536DCC /* SlackKit.framework */;
productType = "com.apple.product-type.framework";
};
2684F1C21E95ABD400536DCC /* SlackKit iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2684F1E11E95ABD400536DCC /* Build configuration list for PBXNativeTarget "SlackKit iOS" */;
buildPhases = (
2684F1C31E95ABD400536DCC /* Sources */,
2684F1DE1E95ABD400536DCC /* Frameworks */,
2684F1DF1E95ABD400536DCC /* Headers */,
2684F1E01E95ABD400536DCC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "SlackKit iOS";
productName = SKCore;
productReference = 2684F1E41E95ABD400536DCC /* SlackKit.framework */;
productType = "com.apple.product-type.framework";
};
2684F1E61E95ABD600536DCC /* SlackKit tvOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2684F2051E95ABD600536DCC /* Build configuration list for PBXNativeTarget "SlackKit tvOS" */;
buildPhases = (
2684F1E71E95ABD600536DCC /* Sources */,
2684F2021E95ABD600536DCC /* Frameworks */,
2684F2031E95ABD600536DCC /* Headers */,
2684F2041E95ABD600536DCC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "SlackKit tvOS";
productName = SKCore;
productReference = 2684F2081E95ABD600536DCC /* SlackKit.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
26072A2B1BB48B3A00CD650C /* Project object */ = {
2684F1741E95AA6900536DCC /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "Launch Software LLC";
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = "Peter Zignego";
TargetAttributes = {
26072A331BB48B3A00CD650C = {
CreatedOnToolsVersion = 7.0;
2684F17C1E95AA6900536DCC = {
CreatedOnToolsVersion = 8.3;
ProvisioningStyle = Manual;
};
2684F1C21E95ABD400536DCC = {
DevelopmentTeam = U63DWZL52M;
};
2684F1E61E95ABD600536DCC = {
DevelopmentTeam = U63DWZL52M;
};
};
};
buildConfigurationList = 26072A2E1BB48B3A00CD650C /* Build configuration list for PBXProject "SlackKit" */;
buildConfigurationList = 2684F1771E95AA6900536DCC /* Build configuration list for PBXProject "SlackKit" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 26072A2A1BB48B3A00CD650C;
productRefGroup = 26072A351BB48B3A00CD650C /* Products */;
mainGroup = 2684F1731E95AA6900536DCC;
productRefGroup = 2684F17E1E95AA6900536DCC /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
26072A331BB48B3A00CD650C /* SlackKit */,
2684F17C1E95AA6900536DCC /* SlackKit macOS */,
2684F1C21E95ABD400536DCC /* SlackKit iOS */,
2684F1E61E95ABD600536DCC /* SlackKit tvOS */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
26072A321BB48B3A00CD650C /* Resources */ = {
2684F17B1E95AA6900536DCC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F1E01E95ABD400536DCC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F2041E95ABD600536DCC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -201,71 +234,40 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
AC19A945F408269E4B4132CC /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SlackKit/Pods-SlackKit-resources.sh\"\n";
showEnvVarsInLog = 0;
};
EBD7A091EB278C5BA34791C5 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
26072A2F1BB48B3A00CD650C /* Sources */ = {
2684F1781E95AA6900536DCC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
26BBA1991C398E3C00BF7225 /* EventDispatcher.swift in Sources */,
26BBA1951C398E3C00BF7225 /* Channel.swift in Sources */,
26BBA19F1C398E3C00BF7225 /* User.swift in Sources */,
26BBA19E1C398E3C00BF7225 /* Types.swift in Sources */,
26BBA1961C398E3C00BF7225 /* Client.swift in Sources */,
26BBA19A1C398E3C00BF7225 /* EventHandler.swift in Sources */,
26BBA1971C398E3C00BF7225 /* Event.swift in Sources */,
26BBA1941C398E3C00BF7225 /* Bot.swift in Sources */,
26BBA19B1C398E3C00BF7225 /* File.swift in Sources */,
260EC2351C4DC61D0093B253 /* SlackWebAPI.swift in Sources */,
26BBA19C1C398E3C00BF7225 /* Message.swift in Sources */,
26BBA19D1C398E3C00BF7225 /* Team.swift in Sources */,
260EC2331C4DC61D0093B253 /* ClientExtensions.swift in Sources */,
26BBA1A01C398E3C00BF7225 /* UserGroup.swift in Sources */,
2601D61B1C7646B80012BF22 /* SlackWebAPIErrorDispatcher.swift in Sources */,
260EC2341C4DC61D0093B253 /* NetworkInterface.swift in Sources */,
26BBA1981C398E3C00BF7225 /* EventDelegate.swift in Sources */,
266687051E95CB9F00777D94 /* SlackKit.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F1C31E95ABD400536DCC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
266687061E95CB9F00777D94 /* SlackKit.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2684F1E71E95ABD600536DCC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
266687071E95CB9F00777D94 /* SlackKit.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
26072A3A1BB48B3B00CD650C /* Debug */ = {
2684F1831E95AA6900536DCC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -273,12 +275,16 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
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;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
@@ -298,20 +304,23 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
26072A3B1BB48B3B00CD650C /* Release */ = {
2684F1841E95AA6900536DCC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -319,12 +328,16 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
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;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
@@ -338,77 +351,193 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
26072A3D1BB48B3B00CD650C /* Debug */ = {
2684F1861E95AA6900536DCC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = F59B6A12F1C4C4E24C58E1BF /* Pods-SlackKit.debug.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = SlackKit/Info.plist;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = com.launchsoft.SlackKit;
PRODUCT_NAME = SlackKit;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
26072A3E1BB48B3B00CD650C /* Release */ = {
2684F1871E95AA6900536DCC /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4347F92F3932C96C23B10B2A /* Pods-SlackKit.release.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = SlackKit/Info.plist;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = com.launchsoft.SlackKit;
PRODUCT_NAME = SlackKit;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
2684F1E21E95ABD400536DCC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = U63DWZL52M;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.launchsoft.SlackKit;
PRODUCT_NAME = SlackKit;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
2684F1E31E95ABD400536DCC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = U63DWZL52M;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.launchsoft.SlackKit;
PRODUCT_NAME = SlackKit;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
2684F2061E95ABD600536DCC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = U63DWZL52M;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.launchsoft.SlackKit;
PRODUCT_NAME = SlackKit;
SDKROOT = appletvos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Debug;
};
2684F2071E95ABD600536DCC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = U63DWZL52M;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.launchsoft.SlackKit;
PRODUCT_NAME = SlackKit;
SDKROOT = appletvos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
26072A2E1BB48B3A00CD650C /* Build configuration list for PBXProject "SlackKit" */ = {
2684F1771E95AA6900536DCC /* Build configuration list for PBXProject "SlackKit" */ = {
isa = XCConfigurationList;
buildConfigurations = (
26072A3A1BB48B3B00CD650C /* Debug */,
26072A3B1BB48B3B00CD650C /* Release */,
2684F1831E95AA6900536DCC /* Debug */,
2684F1841E95AA6900536DCC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
26072A3C1BB48B3B00CD650C /* Build configuration list for PBXNativeTarget "SlackKit" */ = {
2684F1851E95AA6900536DCC /* Build configuration list for PBXNativeTarget "SlackKit macOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
26072A3D1BB48B3B00CD650C /* Debug */,
26072A3E1BB48B3B00CD650C /* Release */,
2684F1861E95AA6900536DCC /* Debug */,
2684F1871E95AA6900536DCC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2684F1E11E95ABD400536DCC /* Build configuration list for PBXNativeTarget "SlackKit iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2684F1E21E95ABD400536DCC /* Debug */,
2684F1E31E95ABD400536DCC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
2684F2051E95ABD600536DCC /* Build configuration list for PBXNativeTarget "SlackKit tvOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2684F2061E95ABD600536DCC /* Debug */,
2684F2071E95ABD600536DCC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 26072A2B1BB48B3A00CD650C /* Project object */;
rootObject = 2684F1741E95AA6900536DCC /* Project object */;
}
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:SlackRTMKit.xcodeproj">
location = "self:SKCore.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F1C21E95ABD400536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit iOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F1C21E95ABD400536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit iOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F1C21E95ABD400536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit iOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F17C1E95AA6900536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit macOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F17C1E95AA6900536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit macOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F17C1E95AA6900536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit macOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F1E61E95ABD600536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit tvOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F1E61E95ABD600536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit tvOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2684F1E61E95ABD600536DCC"
BuildableName = "SlackKit.framework"
BlueprintName = "SlackKit tvOS"
ReferencedContainer = "container:SlackKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:SlackKit.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
-30
View File
@@ -1,30 +0,0 @@
//
// SlackKit.h
//
// 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 <Foundation/Foundation.h>
//! Project version number for SlackKit.
FOUNDATION_EXPORT double SlackKitVersionNumber;
//! Project version string for SlackKit.
FOUNDATION_EXPORT const unsigned char SlackKitVersionString[];
-36
View File
@@ -1,36 +0,0 @@
//
// Bot.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.
public struct Bot {
public let id: String?
internal(set) public var name: String?
internal(set) public var icons: [String: AnyObject]?
internal init?(bot: [String: AnyObject]?) {
id = bot?["id"] as? String
name = bot?["name"] as? String
icons = bot?["icons"] as? [String: AnyObject]
}
}
-88
View File
@@ -1,88 +0,0 @@
//
// Channel.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.
public struct Channel {
public let id: String?
public let created: Int?
public let creator: String?
internal(set) public var name: String?
internal(set) public var isArchived: Bool?
internal(set) public var isGeneral: Bool?
public let isGroup: Bool?
public let isIM: Bool?
public let isMPIM: Bool?
internal(set) public var user: String?
internal(set) public var isUserDeleted: Bool?
internal(set) public var isOpen: Bool?
internal(set) public var topic: Topic?
internal(set) public var purpose: Topic?
internal(set) public var isMember: Bool?
internal(set) public var lastRead: String?
internal(set) public var latest: Message?
internal(set) public var unread: Int?
internal(set) public var unreadCountDisplay: Int?
internal(set) public var hasPins: Bool?
internal(set) public var members = [String]()
// Client use
internal(set) public var pinnedItems = [Item]()
internal(set) public var usersTyping = [String]()
internal(set) public var messages = [String: Message]()
internal init?(channel: [String: AnyObject]?) {
id = channel?["id"] as? String
name = channel?["name"] as? String
created = channel?["created"] as? Int
creator = channel?["creator"] as? String
isArchived = channel?["is_archived"] as? Bool
isGeneral = channel?["is_general"] as? Bool
isGroup = channel?["is_group"] as? Bool
isIM = channel?["is_im"] as? Bool
isMPIM = channel?["is_mpim"] as? Bool
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])
isMember = channel?["is_member"] as? Bool
lastRead = channel?["last_read"] as? String
latest = Message(message: channel?["latest"] as? [String: AnyObject])
unread = channel?["unread_count"] as? Int
unreadCountDisplay = channel?["unread_count_display"] as? Int
hasPins = channel?["has_pins"] as? Bool
if let members = channel?["members"] as? [String] {
self.members = members
}
}
internal init?(id:String?) {
self.id = id
created = nil
creator = nil
isGroup = false
isIM = false
isMPIM = false
}
}
-234
View File
@@ -1,234 +0,0 @@
//
// Client.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 Foundation
import Starscream
public class Client: WebSocketDelegate {
internal(set) public var connected = false
internal(set) public var authenticated = false
internal(set) public var authenticatedUser: User?
internal(set) public var team: Team?
internal(set) public var channels = [String: Channel]()
internal(set) public var users = [String: User]()
internal(set) public var userGroups = [String: UserGroup]()
internal(set) public var bots = [String: Bot]()
internal(set) public var files = [String: File]()
internal(set) public var sentMessages = [String: Message]()
//MARK: - Delegates
public var slackEventsDelegate: SlackEventsDelegate?
public var messageEventsDelegate: MessageEventsDelegate?
public var doNotDisturbEventsDelegate: DoNotDisturbEventsDelegate?
public var channelEventsDelegate: ChannelEventsDelegate?
public var groupEventsDelegate: GroupEventsDelegate?
public var fileEventsDelegate: FileEventsDelegate?
public var pinEventsDelegate: PinEventsDelegate?
public var starEventsDelegate: StarEventsDelegate?
public var reactionEventsDelegate: ReactionEventsDelegate?
public var teamEventsDelegate: TeamEventsDelegate?
public var subteamEventsDelegate: SubteamEventsDelegate?
internal var token = "SLACK_AUTH_TOKEN"
public func setAuthToken(token: String) {
self.token = token
}
public var webAPI: SlackWebAPI {
return SlackWebAPI(client: self)
}
internal var webSocket: WebSocket?
private var dispatcher: EventDispatcher?
internal let api = NetworkInterface()
required public init(apiToken: String) {
self.token = apiToken
}
public func connect() {
dispatcher = EventDispatcher(client: self)
webAPI.rtmStart(success: {
(response) -> Void in
self.initialSetup(response)
if let socketURL = response["url"] as? String {
let url = NSURL(string: socketURL)
self.webSocket = WebSocket(url: url!)
self.webSocket?.delegate = self
self.webSocket?.connect()
}
}, failure:nil)
}
//MARK: - Message send
public func sendMessage(message: String, channelID: String) {
if (connected) {
if let data = formatMessageToSlackJsonString(msg: message, channel: channelID) {
let string = NSString(data: data, encoding: NSUTF8StringEncoding)
webSocket?.writeString(string as! String)
}
}
}
private func formatMessageToSlackJsonString(message: (msg: String, channel: String)) -> NSData? {
let json: [String: AnyObject] = [
"id": NSDate().timeIntervalSince1970,
"type": "message",
"channel": message.channel,
"text": message.msg.slackFormatEscaping()
]
addSentMessage(json)
do {
let data = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted)
return data
}
catch _ {
return nil
}
}
private func addSentMessage(dictionary: [String: AnyObject]) {
var message = dictionary
let ts = message["id"] as? NSNumber
message.removeValueForKey("id")
message["ts"] = ts?.stringValue
message["user"] = self.authenticatedUser?.id
sentMessages[ts!.stringValue] = Message(message: message)
}
//MARK: - Client setup
internal func initialSetup(json: [String: AnyObject]) {
team = Team(team: json["team"] as? [String: AnyObject])
authenticatedUser = User(user: json["self"] as? [String: AnyObject])
authenticatedUser?.doNotDisturbStatus = DoNotDisturbStatus(status: json["dnd"] as? [String: AnyObject])
enumerateUsers(json["users"] as? Array)
enumerateChannels(json["channels"] as? Array)
enumerateGroups(json["groups"] as? Array)
enumerateMPIMs(json["mpims"] as? Array)
enumerateIMs(json["ims"] as? Array)
enumerateBots(json["bots"] as? Array)
enumerateSubteams(json["subteams"] as? [String: AnyObject])
}
internal func enumerateUsers(users: [AnyObject]?) {
if let users = users {
for user in users {
let u = User(user: user as? [String: AnyObject])
self.users[u!.id!] = u
}
}
}
internal func enumerateChannels(channels: [AnyObject]?) {
if let channels = channels {
for channel in channels {
let c = Channel(channel: channel as? [String: AnyObject])
self.channels[c!.id!] = c
}
}
}
internal func enumerateGroups(groups: [AnyObject]?) {
if let groups = groups {
for group in groups {
let g = Channel(channel: group as? [String: AnyObject])
self.channels[g!.id!] = g
}
}
}
internal func enumerateIMs(ims: [AnyObject]?) {
if let ims = ims {
for im in ims {
let i = Channel(channel: im as? [String: AnyObject])
self.channels[i!.id!] = i
}
}
}
internal func enumerateMPIMs(mpims: [AnyObject]?) {
if let mpims = mpims {
for mpim in mpims {
let m = Channel(channel: mpim as? [String: AnyObject])
self.channels[m!.id!] = m
}
}
}
internal func enumerateBots(bots: [AnyObject]?) {
if let bots = bots {
for bot in bots {
let b = Bot(bot: bot as? [String: AnyObject])
self.bots[b!.id!] = b
}
}
}
internal func enumerateSubteams(subteams: [String: AnyObject]?) {
if let subteams = subteams {
if let all = subteams["all"] as? [[String: AnyObject]] {
for item in all {
let u = UserGroup(userGroup: item)
self.userGroups[u!.id!] = u
}
}
if let auth = subteams["self"] as? [String] {
for item in auth {
authenticatedUser?.userGroups = [String: String]()
authenticatedUser?.userGroups![item] = item
}
}
}
}
// MARK: - WebSocketDelegate
public func websocketDidConnect(socket: WebSocket) {}
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
connected = false
authenticated = false
webSocket = nil
if let delegate = slackEventsDelegate {
delegate.clientDisconnected()
}
}
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
guard let data = text.dataUsingEncoding(NSUTF8StringEncoding) else {
return
}
do {
try dispatcher?.dispatch(NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as! [String: AnyObject])
}
catch _ {
}
}
public func websocketDidReceiveData(socket: WebSocket, data: NSData) {}
}
-85
View File
@@ -1,85 +0,0 @@
//
// ClientExtensions.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 Foundation
extension Client {
//MARK: - User & Channel
public func getChannelOrUserIdByName(name: String) -> String? {
if (name[name.startIndex] == "@") {
return getUserIdByName(name)
} else if (name[name.startIndex] == "C") {
return getChannelIDByName(name)
}
return nil
}
public func getChannelIDByName(name: String) -> String? {
return channels.filter{$0.1.name == stripString(name)}.first?.0
}
public func getUserIdByName(name: String) -> String? {
return users.filter{$0.1.name == stripString(name)}.first?.0
}
public func getImIDForUserWithID(id: String, success: (imID: String?)->Void, failure: (error: 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)
} else {
webAPI.openIM(id, success: success, failure: failure)
}
}
//MARK: - Utilities
internal func stripString(var string: String) -> String {
if string[string.startIndex] == "@" {
string = string.substringFromIndex(string.startIndex.advancedBy(1))
} else if string[string.startIndex] == "#" {
string = string.substringFromIndex(string.startIndex.advancedBy(1))
}
return string
}
}
internal extension String {
func slackFormatEscaping() -> String {
var escapedString = stringByReplacingOccurrencesOfString("&", withString: "&amp;")
escapedString = stringByReplacingOccurrencesOfString("<", withString: "&lt;")
escapedString = stringByReplacingOccurrencesOfString(">", withString: "&gt;")
return escapedString
}
}
public extension NSDate {
func slackTimestamp() -> String {
return NSNumber(double: timeIntervalSince1970).stringValue
}
}
-218
View File
@@ -1,218 +0,0 @@
//
// Message.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.
internal enum EventType: String {
case Hello = "hello"
case Message = "message"
case UserTyping = "user_typing"
case ChannelMarked = "channel_marked"
case ChannelCreated = "channel_created"
case ChannelJoined = "channel_joined"
case ChannelLeft = "channel_left"
case ChannelDeleted = "channel_deleted"
case ChannelRenamed = "channel_rename"
case ChannelArchive = "channel_archive"
case ChannelUnarchive = "channel_unarchive"
case ChannelHistoryChanged = "channel_history_changed"
case DNDUpdated = "dnd_updated"
case DNDUpatedUser = "dnd_updated_user"
case IMCreated = "im_created"
case IMOpen = "im_open"
case IMClose = "im_close"
case IMMarked = "im_marked"
case IMHistoryChanged = "im_history_changed"
case GroupJoined = "group_joined"
case GroupLeft = "group_left"
case GroupOpen = "group_open"
case GroupClose = "group_close"
case GroupArchive = "group_archive"
case GroupUnarchive = "group_unarchive"
case GroupRename = "group_rename"
case GroupMarked = "group_marked"
case GroupHistoryChanged = "group_history_changed"
case FileCreated = "file_created"
case FileShared = "file_shared"
case FileUnshared = "file_unshared"
case FilePublic = "file_public"
case FilePrivate = "file_private"
case FileChanged = "file_change"
case FileDeleted = "file_deleted"
case FileCommentAdded = "file_comment_added"
case FileCommentEdited = "file_comment_edited"
case FileCommentDeleted = "file_comment_deleted"
case PinAdded = "pin_added"
case PinRemoved = "pin_removed"
case PresenceChange = "presence_change"
case ManualPresenceChange = "manual_presence_change"
case PrefChange = "pref_change"
case UserChange = "user_change"
case TeamJoin = "team_join"
case StarAdded = "star_added"
case StarRemoved = "star_removed"
case ReactionAdded = "reaction_added"
case ReactionRemoved = "reaction_removed"
case EmojiChanged = "emoji_changed"
case CommandsChanged = "commands_changed"
case TeamPlanChange = "team_plan_change"
case TeamPrefChange = "team_pref_change"
case TeamRename = "team_rename"
case TeamDomainChange = "team_domain_change"
case EmailDomainChange = "email_domain_change"
case BotAdded = "bot_added"
case BotChanged = "bot_changed"
case AccountsChanged = "accounts_changed"
case TeamMigrationStarted = "team_migration_started"
case SubteamCreated = "subteam_created"
case SubteamUpdated = "subteam_updated"
case SubteamSelfAdded = "subteam_self_added"
case SubteamSelfRemoved = "subteam_self_removed"
case Ok = "ok"
case Error = "error"
}
internal enum MessageSubtype: String {
case BotMessage = "bot_message"
case MeMessage = "me_message"
case MessageChanged = "message_changed"
case MessageDeleted = "message_deleted"
case ChannelJoin = "channel_join"
case ChannelLeave = "channel_leave"
case ChannelTopic = "channel_topic"
case ChannelPurpose = "channel_purpose"
case ChannelName = "channel_name"
case ChannelArchive = "channel_archive"
case ChannelUnarchive = "channel_unarchive"
case GroupJoin = "group_join"
case GroupLeave = "group_leave"
case GroupTopic = "group_topic"
case GroupPurpose = "group_purpose"
case GroupName = "group_name"
case GroupArchive = "group_archive"
case GroupUnarchive = "group_unarchive"
case FileShare = "file_share"
case FileComment = "file_comment"
case FileMention = "file_mention"
case PinnedItem = "pinned_item"
case UnpinnedItem = "unpinned_item"
}
internal struct Event {
let type: EventType?
let ts: String?
let subtype: String?
let channelID: String?
let text: String?
let eventTs: String?
let latest: String?
let hidden: Bool?
let isStarred: Bool?
let hasPins: Bool?
let pinnedTo: [String]?
let fileID: String?
let presence: String?
let name: String?
let value: AnyObject?
let plan: String?
let url: String?
let domain: String?
let emailDomain: String?
let reaction: String?
let replyTo: Double?
let reactions: [[String: AnyObject]]?
let edited: Edited?
let bot: Bot?
let channel: Channel?
let comment: Comment?
let user: User?
let file: File?
let message: Message?
let nestedMessage: Message?
let item: Item?
let dndStatus: DoNotDisturbStatus?
let subteam: UserGroup?
let subteamID: String?
init(event:[String: AnyObject]) {
if let eventType = event["type"] as? String {
type = EventType(rawValue:eventType)
} else {
type = EventType(rawValue: "ok")
}
ts = event["ts"] as? String
subtype = event["subtype"] as? String
channelID = event["channel_id"] as? String
text = event["text"] as? String
eventTs = event["event_ts"] as? String
latest = event["latest"] as? String
hidden = event["hidden"] as? Bool
isStarred = event["is_starred"] as? Bool
hasPins = event["has_pins"] as? Bool
pinnedTo = event["pinned_top"] as? [String]
fileID = event["file_id"] as? String
presence = event["presence"] as? String
name = event["name"] as? String
value = event["value"]
plan = event["plan"] as? String
url = event["url"] as? String
domain = event["domain"] as? String
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])
item = Item(item: event["item"] as? [String: AnyObject])
subteam = UserGroup(userGroup: event["subteam"] as? [String: AnyObject])
subteamID = event["subteam_id"] as? String
message = Message(message: event)
nestedMessage = Message(message: event["message"] as? [String: AnyObject])
// Comment, Channel, User, and File can come across as Strings or Dictionaries
if (Comment(comment: event["comment"] as? [String: AnyObject])?.id == nil) {
comment = Comment(id: event["comment"] as? String)
} else {
comment = Comment(comment: event["comment"] as? [String: AnyObject])
}
if (User(user: event["user"] as? [String: AnyObject])?.id == nil) {
user = User(id: event["user"] as? String)
} else {
user = User(user: event["user"] as? [String: AnyObject])
}
if (File(file: event["file"] as? [String: AnyObject])?.id == nil) {
file = File(id: event["file"] as? String)
} else {
file = File(file: event["file"] as? [String: AnyObject])
}
if (Channel(channel: event["channel"] as? [String: AnyObject])?.id == nil) {
channel = Channel(id: event["channel"] as? String)
} else {
channel = Channel(channel: event["channel"] as? [String: AnyObject])
}
}
}
-101
View File
@@ -1,101 +0,0 @@
//
// EventDelegate.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 Foundation
public protocol SlackEventsDelegate {
func clientConnected()
func clientDisconnected()
func preferenceChanged(preference: String, value: AnyObject)
func userChanged(user: User)
func presenceChanged(user: User?, presence: String?)
func manualPresenceChanged(user: User?, presence: String?)
func botEvent(bot: Bot)
}
public protocol MessageEventsDelegate {
func messageSent(message: Message)
func messageReceived(message: Message)
func messageChanged(message: Message)
func messageDeleted(message: Message?)
}
public protocol ChannelEventsDelegate {
func userTyping(channel: Channel?, user: User?)
func channelMarked(channel: Channel, timestamp: String?)
func channelCreated(channel: Channel)
func channelDeleted(channel: Channel)
func channelRenamed(channel: Channel)
func channelArchived(channel: Channel)
func channelHistoryChanged(channel: Channel)
func channelJoined(channel: Channel)
func channelLeft(channel: Channel)
}
public protocol DoNotDisturbEventsDelegate {
func doNotDisturbUpdated(dndStatus: DoNotDisturbStatus)
func doNotDisturbUserUpdated(dndStatus: DoNotDisturbStatus, user: User?)
}
public protocol GroupEventsDelegate {
func groupOpened(group: Channel)
}
public protocol FileEventsDelegate {
func fileProcessed(file: File)
func fileMadePrivate(file: File)
func fileDeleted(file: File)
func fileCommentAdded(file: File, comment: Comment)
func fileCommentEdited(file: File, comment: Comment)
func fileCommentDeleted(file: File, comment: Comment)
}
public protocol PinEventsDelegate {
func itemPinned(item: Item?, channel: Channel?)
func itemUnpinned(item: Item?, channel: Channel?)
}
public protocol StarEventsDelegate {
func itemStarred(item: Item, star: Bool)
}
public protocol ReactionEventsDelegate {
func reactionAdded(reaction: String?, item: Item?)
func reactionRemoved(reaction: String?, item: Item?)
}
public protocol TeamEventsDelegate {
func teamJoined(user: User)
func teamPlanChanged(plan: String)
func teamPreferencesChanged(preference: String, value: AnyObject)
func teamNameChanged(name: String)
func teamDomainChanged(domain: String)
func teamEmailDomainChanged(domain: String)
func teamEmojiChanged()
}
public protocol SubteamEventsDelegate {
func subteamEvent(userGroup: UserGroup)
func subteamSelfAdded(subteamID: String)
func subteamSelfRemoved(subteamID: String)
}
-166
View File
@@ -1,166 +0,0 @@
//
// EventDispatcher.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.
internal class EventDispatcher {
let client: Client
let handler: EventHandler
required init(client: Client) {
self.client = client
handler = EventHandler(client: client)
}
func dispatch(event: [String: AnyObject]) {
let event = Event(event: event)
if let type = event.type {
switch type {
case .Hello:
handler.connected()
case .Ok:
handler.messageSent(event)
case .Message:
if (event.subtype != nil) {
messageDispatcher(event)
} else {
handler.messageReceived(event)
}
case .UserTyping:
handler.userTyping(event)
case .ChannelMarked, .IMMarked, .GroupMarked:
handler.channelMarked(event)
case .ChannelCreated, .IMCreated:
handler.channelCreated(event)
case .ChannelJoined, .GroupJoined:
handler.channelJoined(event)
case .ChannelLeft, .GroupLeft:
handler.channelLeft(event)
case .ChannelDeleted:
handler.channelDeleted(event)
case .ChannelRenamed, .GroupRename:
handler.channelRenamed(event)
case .ChannelArchive, .GroupArchive:
handler.channelArchived(event, archived: true)
case .ChannelUnarchive, .GroupUnarchive:
handler.channelArchived(event, archived: false)
case .ChannelHistoryChanged, .IMHistoryChanged, .GroupHistoryChanged:
handler.channelHistoryChanged(event)
case .DNDUpdated:
handler.doNotDisturbUpdated(event)
case .DNDUpatedUser:
handler.doNotDisturbUserUpdated(event)
case .IMOpen, .GroupOpen:
handler.open(event, open: true)
case .IMClose, .GroupClose:
handler.open(event, open: false)
case .FileCreated:
handler.processFile(event)
case .FileShared:
handler.processFile(event)
case .FileUnshared:
handler.processFile(event)
case .FilePublic:
handler.processFile(event)
case .FilePrivate:
handler.filePrivate(event)
case .FileChanged:
handler.processFile(event)
case .FileDeleted:
handler.deleteFile(event)
case .FileCommentAdded:
handler.fileCommentAdded(event)
case .FileCommentEdited:
handler.fileCommentEdited(event)
case .FileCommentDeleted:
handler.fileCommentDeleted(event)
case .PinAdded:
handler.pinAdded(event)
case .PinRemoved:
handler.pinRemoved(event)
case .PresenceChange:
handler.presenceChange(event)
case .ManualPresenceChange:
handler.manualPresenceChange(event)
case .PrefChange:
handler.changePreference(event)
case .UserChange:
handler.userChange(event)
case .TeamJoin:
handler.teamJoin(event)
case .StarAdded:
handler.itemStarred(event, star: true)
case .StarRemoved:
handler.itemStarred(event, star: false)
case .ReactionAdded:
handler.addedReaction(event)
case .ReactionRemoved:
handler.removedReaction(event)
case .EmojiChanged:
handler.emojiChanged(event)
case .CommandsChanged:
// Not implemented per Slack documentation.
break
case .TeamPlanChange:
handler.teamPlanChange(event)
case .TeamPrefChange:
handler.teamPreferenceChange(event)
case .TeamRename:
handler.teamNameChange(event)
case .TeamDomainChange:
handler.teamDomainChange(event)
case .EmailDomainChange:
handler.emailDomainChange(event)
case .BotAdded:
handler.bot(event)
case .BotChanged:
handler.bot(event)
case .AccountsChanged:
// Not implemented per Slack documentation.
break
case .TeamMigrationStarted:
client.connect()
case .SubteamCreated, .SubteamUpdated:
handler.subteam(event)
case .SubteamSelfAdded:
handler.subteamAddedSelf(event)
case.SubteamSelfRemoved:
handler.subteamRemovedSelf(event)
case .Error:
print("Error: \(event)")
break
}
}
}
func messageDispatcher(event:Event) {
let subtype = MessageSubtype(rawValue: event.subtype!)!
switch subtype {
case .MessageChanged:
handler.messageChanged(event)
case .MessageDeleted:
handler.messageDeleted(event)
default:
handler.messageReceived(event)
}
}
}
-604
View File
@@ -1,604 +0,0 @@
//
// EventHandler.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 Foundation
internal class EventHandler {
let client: Client
required init(client: Client) {
self.client = client
}
//MARK: - Initial connection
func connected() {
client.connected = true
if let delegate = client.slackEventsDelegate {
delegate.clientConnected()
}
}
//MARK: - Messages
func messageSent(event: Event) {
if let reply = event.replyTo, message = client.sentMessages[NSNumber(double: reply).stringValue], channel = message.channel, ts = message.ts {
message.ts = event.ts
message.text = event.text
client.channels[channel]?.messages[ts] = message
if let delegate = client.messageEventsDelegate {
delegate.messageSent(message)
}
}
}
func messageReceived(event: Event) {
if let channel = event.channel, message = event.message, id = channel.id, ts = message.ts {
client.channels[id]?.messages[ts] = message
if let delegate = client.messageEventsDelegate {
delegate.messageReceived(message)
}
}
}
func messageChanged(event: Event) {
if let id = event.channel?.id, nested = event.nestedMessage, ts = nested.ts {
client.channels[id]?.messages[ts] = nested
if let delegate = client.messageEventsDelegate {
delegate.messageChanged(nested)
}
}
}
func messageDeleted(event: Event) {
if let id = event.channel?.id, key = event.message?.deletedTs {
let message = client.channels[id]?.messages[key]
client.channels[id]?.messages.removeValueForKey(key)
if let delegate = client.messageEventsDelegate {
delegate.messageDeleted(message)
}
}
}
//MARK: - Channels
func userTyping(event: Event) {
if let channelID = event.channel?.id, userID = event.user?.id {
if let _ = client.channels[channelID] {
if (!client.channels[channelID]!.usersTyping.contains(userID)) {
client.channels[channelID]?.usersTyping.append(userID)
if let delegate = client.channelEventsDelegate {
delegate.userTyping(event.channel, user: event.user)
}
}
}
let timeout = dispatch_time(DISPATCH_TIME_NOW, Int64(5.0 * Double(NSEC_PER_SEC)))
dispatch_after(timeout, dispatch_get_main_queue()) {
if let index = self.client.channels[channelID]?.usersTyping.indexOf(userID) {
self.client.channels[channelID]?.usersTyping.removeAtIndex(index)
}
}
}
}
func channelMarked(event: Event) {
if let channel = event.channel, id = channel.id {
client.channels[id]?.lastRead = event.ts
if let delegate = client.channelEventsDelegate {
delegate.channelMarked(channel, timestamp: event.ts)
}
}
//TODO: Recalculate unreads
}
func channelCreated(event: Event) {
if let channel = event.channel, id = channel.id {
client.channels[id] = channel
if let delegate = client.channelEventsDelegate {
delegate.channelCreated(channel)
}
}
}
func channelDeleted(event: Event) {
if let channel = event.channel, id = channel.id {
client.channels.removeValueForKey(id)
if let delegate = client.channelEventsDelegate {
delegate.channelDeleted(channel)
}
}
}
func channelJoined(event: Event) {
if let channel = event.channel, id = channel.id {
client.channels[id] = event.channel
if let delegate = client.channelEventsDelegate {
delegate.channelJoined(channel)
}
}
}
func channelLeft(event: Event) {
if let channel = event.channel, id = channel.id, userID = client.authenticatedUser?.id {
if let index = client.channels[id]?.members.indexOf(userID) {
client.channels[id]?.members.removeAtIndex(index)
if let delegate = client.channelEventsDelegate {
delegate.channelLeft(channel)
}
}
}
}
func channelRenamed(event: Event) {
if let channel = event.channel, id = channel.id {
client.channels[id]?.name = channel.name
if let delegate = client.channelEventsDelegate {
delegate.channelRenamed(channel)
}
}
}
func channelArchived(event: Event, archived: Bool) {
if let channel = event.channel, id = channel.id {
client.channels[id]?.isArchived = archived
if let delegate = client.channelEventsDelegate {
delegate.channelArchived(channel)
}
}
}
func channelHistoryChanged(event: Event) {
if let channel = event.channel {
//TODO: Reload chat history if there are any cached messages before latest
if let delegate = client.channelEventsDelegate {
delegate.channelHistoryChanged(channel)
}
}
}
//MARK: - Do Not Disturb
func doNotDisturbUpdated(event: Event) {
if let dndStatus = event.dndStatus {
client.authenticatedUser?.doNotDisturbStatus = dndStatus
if let delegate = client.doNotDisturbEventsDelegate {
delegate.doNotDisturbUpdated(dndStatus)
}
}
}
func doNotDisturbUserUpdated(event: Event) {
if let dndStatus = event.dndStatus, user = event.user, id = user.id {
client.users[id]?.doNotDisturbStatus = dndStatus
if let delegate = client.doNotDisturbEventsDelegate {
delegate.doNotDisturbUserUpdated(dndStatus, user: user)
}
}
}
//MARK: - IM & Group Open/Close
func open(event: Event, open: Bool) {
if let channel = event.channel, id = channel.id {
client.channels[id]?.isOpen = open
if let delegate = client.groupEventsDelegate {
delegate.groupOpened(channel)
}
}
}
//MARK: - Files
func processFile(event: Event) {
if let file = event.file, id = file.id {
if let comment = file.initialComment, commentID = comment.id {
if client.files[id]?.comments[commentID] == nil {
client.files[id]?.comments[commentID] = comment
}
}
client.files[id] = file
if let delegate = client.fileEventsDelegate {
delegate.fileProcessed(file)
}
}
}
func filePrivate(event: Event) {
if let file = event.file, id = file.id {
client.files[id]?.isPublic = false
if let delegate = client.fileEventsDelegate {
delegate.fileMadePrivate(file)
}
}
}
func deleteFile(event: Event) {
if let file = event.file, id = file.id {
if client.files[id] != nil {
client.files.removeValueForKey(id)
}
if let delegate = client.fileEventsDelegate {
delegate.fileDeleted(file)
}
}
}
func fileCommentAdded(event: Event) {
if let file = event.file, id = file.id, comment = event.comment, commentID = comment.id {
client.files[id]?.comments[commentID] = comment
if let delegate = client.fileEventsDelegate {
delegate.fileCommentAdded(file, comment: comment)
}
}
}
func fileCommentEdited(event: Event) {
if let file = event.file, id = file.id, comment = event.comment, commentID = comment.id {
client.files[id]?.comments[commentID]?.comment = comment.comment
if let delegate = client.fileEventsDelegate {
delegate.fileCommentEdited(file, comment: comment)
}
}
}
func fileCommentDeleted(event: Event) {
if let file = event.file, id = file.id, comment = event.comment, commentID = comment.id {
client.files[id]?.comments.removeValueForKey(commentID)
if let delegate = client.fileEventsDelegate {
delegate.fileCommentDeleted(file, comment: comment)
}
}
}
//MARK: - Pins
func pinAdded(event: Event) {
if let id = event.channelID, item = event.item {
client.channels[id]?.pinnedItems.append(item)
if let delegate = client.pinEventsDelegate {
delegate.itemPinned(item, channel: client.channels[id])
}
}
}
func pinRemoved(event: Event) {
if let id = event.channelID {
if let pins = client.channels[id]?.pinnedItems.filter({$0 != event.item}) {
client.channels[id]?.pinnedItems = pins
}
if let delegate = client.pinEventsDelegate {
delegate.itemUnpinned(event.item, channel: client.channels[id])
}
}
}
//MARK: - Stars
func itemStarred(event: Event, star: Bool) {
if let item = event.item, type = item.type {
switch type {
case "message":
starMessage(item, star: star)
case "file":
starFile(item, star: star)
case "file_comment":
starComment(item)
default:
break
}
if let delegate = client.starEventsDelegate {
delegate.itemStarred(item, star: star)
}
}
}
func starMessage(item: Item, star: Bool) {
if let message = item.message, ts = message.ts, channel = item.channel {
if let _ = client.channels[channel]?.messages[ts] {
client.channels[channel]?.messages[ts]?.isStarred = star
}
}
}
func starFile(item: Item, star: Bool) {
if let file = item.file, id = file.id {
client.files[id]?.isStarred = star
if let stars = client.files[id]?.stars {
if star == true {
client.files[id]?.stars = stars + 1
} else {
if stars > 0 {
client.files[id]?.stars = stars - 1
}
}
}
}
}
func starComment(item: Item) {
if let file = item.file, id = file.id, comment = item.comment, commentID = comment.id {
client.files[id]?.comments[commentID] = comment
}
}
//MARK: - Reactions
func addedReaction(event: Event) {
if let item = event.item, type = item.type, key = event.reaction, userID = event.user?.id {
switch type {
case "message":
if let channel = item.channel, ts = item.ts {
if let message = client.channels[channel]?.messages[ts] {
if (message.reactions[key]) == nil {
message.reactions[key] = Reaction(name: event.reaction, user: userID)
} else {
message.reactions[key]?.users[userID] = userID
}
}
}
case "file":
if let id = item.file?.id, file = client.files[id] {
if file.reactions[key] == nil {
client.files[id]?.reactions[key] = Reaction(name: event.reaction, user: userID)
} else {
client.files[id]?.reactions[key]?.users[userID] = userID
}
}
case "file_comment":
if let id = item.file?.id, file = client.files[id], commentID = item.fileCommentID {
if file.comments[commentID]?.reactions[key] == nil {
client.files[id]?.comments[commentID]?.reactions[key] = Reaction(name: event.reaction, user: userID)
} else {
client.files[id]?.comments[commentID]?.reactions[key]?.users[userID] = userID
}
}
break
default:
break
}
if let delegate = client.reactionEventsDelegate {
delegate.reactionAdded(event.reaction, item: event.item)
}
}
}
func removedReaction(event: Event) {
if let item = event.item, type = item.type, key = event.reaction, userID = event.user?.id {
switch type {
case "message":
if let channel = item.channel, ts = item.ts {
if let message = client.channels[channel]?.messages[ts] {
if (message.reactions[key]) != nil {
message.reactions[key]?.users.removeValueForKey(userID)
}
if (message.reactions[key]?.users.count == 0) {
message.reactions.removeValueForKey(key)
}
}
}
case "file":
if let itemFile = item.file, id = itemFile.id, file = client.files[id] {
if file.reactions[key] != nil {
client.files[id]?.reactions[key]?.users.removeValueForKey(userID)
}
if client.files[id]?.reactions[key]?.users.count == 0 {
client.files[id]?.reactions.removeValueForKey(key)
}
}
case "file_comment":
if let id = item.file?.id, file = client.files[id], commentID = item.fileCommentID {
if file.comments[commentID]?.reactions[key] != nil {
client.files[id]?.comments[commentID]?.reactions[key]?.users.removeValueForKey(userID)
}
if client.files[id]?.comments[commentID]?.reactions[key]?.users.count == 0 {
client.files[id]?.comments[commentID]?.reactions.removeValueForKey(key)
}
}
break
default:
break
}
if let delegate = client.reactionEventsDelegate {
delegate.reactionAdded(event.reaction, item: event.item)
}
}
}
//MARK: - Preferences
func changePreference(event: Event) {
if let name = event.name {
client.authenticatedUser?.preferences?[name] = event.value
if let delegate = client.slackEventsDelegate, value = event.value {
delegate.preferenceChanged(name, value: value)
}
}
}
//Mark: - User Change
func userChange(event: Event) {
if let user = event.user, id = user.id {
let preferences = client.users[id]?.preferences
client.users[id] = user
client.users[id]?.preferences = preferences
if let delegate = client.slackEventsDelegate {
delegate.userChanged(user)
}
}
}
//MARK: - User Presence
func presenceChange(event: Event) {
if let user = event.user, id = user.id {
client.users[id]?.presence = event.presence
if let delegate = client.slackEventsDelegate {
delegate.presenceChanged(user, presence: event.presence)
}
}
}
//MARK: - Team
func teamJoin(event: Event) {
if let user = event.user, id = user.id {
client.users[id] = user
if let delegate = client.teamEventsDelegate {
delegate.teamJoined(user)
}
}
}
func teamPlanChange(event: Event) {
if let plan = event.plan {
client.team?.plan = plan
if let delegate = client.teamEventsDelegate {
delegate.teamPlanChanged(plan)
}
}
}
func teamPreferenceChange(event: Event) {
if let name = event.name {
client.team?.prefs?[name] = event.value
if let delegate = client.teamEventsDelegate, value = event.value {
delegate.teamPreferencesChanged(name, value: value)
}
}
}
func teamNameChange(event: Event) {
if let name = event.name {
client.team?.name = name
if let delegate = client.teamEventsDelegate {
delegate.teamNameChanged(name)
}
}
}
func teamDomainChange(event: Event) {
if let domain = event.domain {
client.team?.domain = domain
if let delegate = client.teamEventsDelegate {
delegate.teamDomainChanged(domain)
}
}
}
func emailDomainChange(event: Event) {
if let domain = event.emailDomain {
client.team?.emailDomain = domain
if let delegate = client.teamEventsDelegate {
delegate.teamEmailDomainChanged(domain)
}
}
}
func emojiChanged(event: Event) {
//TODO: Call emoji.list here
if let delegate = client.teamEventsDelegate {
delegate.teamEmojiChanged()
}
}
//MARK: - Bots
func bot(event: Event) {
if let bot = event.bot, id = bot.id {
client.bots[id] = bot
if let delegate = client.slackEventsDelegate {
delegate.botEvent(bot)
}
}
}
//MARK: - Subteams
func subteam(event: Event) {
if let subteam = event.subteam, id = subteam.id {
client.userGroups[id] = subteam
if let delegate = client.subteamEventsDelegate {
delegate.subteamEvent(subteam)
}
}
}
func subteamAddedSelf(event: Event) {
if let subteamID = event.subteamID, _ = client.authenticatedUser?.userGroups {
client.authenticatedUser?.userGroups![subteamID] = subteamID
if let delegate = client.subteamEventsDelegate {
delegate.subteamSelfAdded(subteamID)
}
}
}
func subteamRemovedSelf(event: Event) {
if let subteamID = event.subteamID {
client.authenticatedUser?.userGroups?.removeValueForKey(subteamID)
if let delegate = client.subteamEventsDelegate {
delegate.subteamSelfRemoved(subteamID)
}
}
}
//MARK: - Authenticated User
func manualPresenceChange(event: Event) {
client.authenticatedUser?.presence = event.presence
if let delegate = client.slackEventsDelegate {
delegate.manualPresenceChanged(client.authenticatedUser, presence: event.presence)
}
}
}
-144
View File
@@ -1,144 +0,0 @@
//
// File.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.
public struct File {
public let id: String?
public let created: Int?
public let name: String?
public let title: String?
public let mimeType: String?
public let fileType: String?
public let prettyType: String?
public let user: String?
public let mode: String?
internal(set) public var editable: Bool?
public let isExternal: Bool?
public let externalType: String?
public let size: Int?
public let urlPrivate: String?
public let urlPrivateDownload: String?
public let thumb64: String?
public let thumb80: String?
public let thumb360: String?
public let thumb360gif: String?
public let thumb360w: String?
public let thumb360h: String?
public let permalink: String?
public let editLink: String?
public let preview: String?
public let previewHighlight: String?
public let lines: Int?
public let linesMore: Int?
internal(set) public var isPublic: Bool?
internal(set) public var publicSharedURL: Bool?
internal(set) public var channels: [String]?
internal(set) public var groups: [String]?
internal(set) public var ims: [String]?
public let initialComment: Comment?
internal(set) public var stars: Int?
internal(set) public var isStarred: Bool?
internal(set) public var pinnedTo: [String]?
internal(set) public var comments = [String: Comment]()
internal(set) public var reactions = [String: Reaction]()
init?(file:[String: AnyObject]?) {
id = file?["id"] as? String
created = file?["created"] as? Int
name = file?["name"] as? String
title = file?["title"] as? String
mimeType = file?["mimetype"] as? String
fileType = file?["filetype"] as? String
prettyType = file?["pretty_type"] as? String
user = file?["user"] as? String
mode = file?["mode"] as? String
editable = file?["editable"] as? Bool
isExternal = file?["is_external"] as? Bool
externalType = file?["external_type"] as? String
size = file?["size"] as? Int
urlPrivate = file?["url_private"] as? String
urlPrivateDownload = file?["url_private_download"] as? String
thumb64 = file?["thumb_64"] as? String
thumb80 = file?["thumb_80"] as? String
thumb360 = file?["thumb_360"] as? String
thumb360gif = file?["thumb_360_gif"] as? String
thumb360w = file?["thumb_360_w"] as? String
thumb360h = file?["thumb_360_h"] as? String
permalink = file?["permalink"] as? String
editLink = file?["edit_link"] as? String
preview = file?["preview"] as? String
previewHighlight = file?["preview_highlight"] as? String
lines = file?["lines"] as? Int
linesMore = file?["lines_more"] as? Int
isPublic = file?["is_public"] as? Bool
publicSharedURL = file?["public_url_shared"] as? Bool
channels = file?["channels"] as? [String]
groups = file?["groups"] as? [String]
ims = file?["ims"] as? [String]
initialComment = Comment(comment: file?["initial_comment"] as? [String: AnyObject])
stars = file?["num_stars"] as? Int
isStarred = file?["is_starred"] as? Bool
pinnedTo = file?["pinned_to"] as? [String]
if let reactions = file?["reactions"] as? [[String: AnyObject]] {
self.reactions = Reaction.reactionsFromArray(reactions)
}
}
init?(id:String?) {
self.id = id
created = nil
name = nil
title = nil
mimeType = nil
fileType = nil
prettyType = nil
user = nil
mode = nil
isExternal = nil
externalType = nil
size = nil
urlPrivate = nil
urlPrivateDownload = nil
thumb64 = nil
thumb80 = nil
thumb360 = nil
thumb360gif = nil
thumb360w = nil
thumb360h = nil
permalink = nil
editLink = nil
preview = nil
previewHighlight = nil
lines = nil
linesMore = nil
initialComment = nil
}
}
extension File: Equatable {}
public func ==(lhs: File, rhs: File) -> Bool {
return lhs.id == rhs.id
}
-92
View File
@@ -1,92 +0,0 @@
//
// Message.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.
public enum ItemType: String {
case ChannelMessage = "C"
case PrivateGroupMessage = "G"
case File = "F"
case FileComments = "Fc"
}
public class Message {
public let type = "message"
public let subtype: String?
internal(set) public var ts: String?
public let user: String?
public let channel: String?
internal(set) public var hidden: Bool?
internal(set) public var text: String?
public let botID: String?
public let username: String?
public let icons: [String: AnyObject]?
public let deletedTs: String?
internal(set) var purpose: String?
internal(set) var topic: String?
internal(set) var name: String?
internal(set) var members: [String]?
internal(set) var oldName: String?
public let upload: Bool?
public let itemType: String?
internal(set) public var isStarred: Bool?
internal(set) var pinnedTo: [String]?
public let comment: Comment?
public let file: File?
internal(set) public var reactions = [String: Reaction]()
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])
if let messageReactions = message?["reactions"] as? [[String: AnyObject]] {
for react in messageReactions {
let reaction = Reaction(reaction: react)
self.reactions[reaction!.name!] = reaction
}
}
}
}
extension Message: Equatable {}
public func ==(lhs: Message, rhs: Message) -> Bool {
return lhs.ts == rhs.ts && lhs.user == rhs.user && lhs.text == rhs.text
}
-129
View File
@@ -1,129 +0,0 @@
//
// NetworkInterface.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 Foundation
internal struct NetworkInterface {
private let apiUrl = "https://slack.com/api/"
internal func request(endpoint: SlackAPIEndpoint, token: String, parameters: [String: AnyObject]?, successClosure: ([String: AnyObject])->Void, errorClosure: (SlackError)->Void) {
var requestString = "\(apiUrl)\(endpoint.rawValue)?token=\(token)"
if let params = parameters {
requestString = requestString + requestStringFromParameters(params)
}
let request = NSURLRequest(URL: NSURL(string: requestString)!)
NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, internalError) -> Void in
guard let data = data else {
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: AnyObject]
if (result["ok"] as! Bool == true) {
successClosure(result)
} else {
if let errorString = result["error"] as? String {
throw ErrorDispatcher.dispatch(errorString)
} else {
throw SlackError.UnknownError
}
}
} catch let error {
if let slackError = error as? SlackError {
errorClosure(slackError)
} else {
errorClosure(SlackError.UnknownError)
}
}
}.resume()
}
internal func uploadRequest(token: String, data: NSData, parameters: [String: AnyObject]?, successClosure: ([String: AnyObject])->Void, errorClosure: (SlackError)->Void) {
var requestString = "\(apiUrl)\(SlackAPIEndpoint.FilesUpload.rawValue)?token=\(token)"
if let params = parameters {
requestString = requestString + requestStringFromParameters(params)
}
let request = NSMutableURLRequest(URL: NSURL(string: requestString)!)
request.HTTPMethod = "POST"
let boundaryConstant = randomBoundary()
let contentType = "multipart/form-data; boundary=" + boundaryConstant
let boundaryStart = "--\(boundaryConstant)\r\n"
let boundaryEnd = "--\(boundaryConstant)--\r\n"
let contentDispositionString = "Content-Disposition: form-data; name=\"file\"; filename=\"\(parameters!["filename"])\"\r\n"
let contentTypeString = "Content-Type: \(parameters!["filetype"])\r\n\r\n"
let requestBodyData : NSMutableData = NSMutableData()
requestBodyData.appendData(boundaryStart.dataUsingEncoding(NSUTF8StringEncoding)!)
requestBodyData.appendData(contentDispositionString.dataUsingEncoding(NSUTF8StringEncoding)!)
requestBodyData.appendData(contentTypeString.dataUsingEncoding(NSUTF8StringEncoding)!)
requestBodyData.appendData(data)
requestBodyData.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
requestBodyData.appendData(boundaryEnd.dataUsingEncoding(NSUTF8StringEncoding)!)
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
request.HTTPBody = requestBodyData
NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, internalError) -> Void in
guard let data = data else {
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: AnyObject]
if (result["ok"] as! Bool == true) {
successClosure(result)
} else {
if let errorString = result["error"] as? String {
throw ErrorDispatcher.dispatch(errorString)
} else {
throw SlackError.UnknownError
}
}
} catch let error {
if let slackError = error as? SlackError {
errorClosure(slackError)
} else {
errorClosure(SlackError.UnknownError)
}
}
}.resume()
}
private func randomBoundary() -> String {
return String(format: "slackkit.boundary.%08x%08x", arc4random(), arc4random())
}
private func requestStringFromParameters(parameters: [String: AnyObject]) -> String {
var requestString = ""
for key in parameters.keys {
if let value = parameters[key] as? String, encodedValue = value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet()) {
requestString = requestString + "&"+key+"="+encodedValue
}
}
return requestString
}
}
-636
View File
@@ -1,636 +0,0 @@
//
// SlackWebAPI.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 Foundation
internal enum SlackAPIEndpoint: String {
case APITest = "api.test"
case AuthTest = "auth.test"
case ChannelsHistory = "channels.history"
case ChannelsInfo = "channels.info"
case ChannelsList = "channels.list"
case ChannelsMark = "channels.mark"
case ChannelsSetPurpose = "channels.setPurpose"
case ChannelsSetTopic = "channels.setTopic"
case ChatDelete = "chat.delete"
case ChatPostMessage = "chat.postMessage"
case ChatUpdate = "chat.update"
case EmojiList = "emoji.list"
case FilesDelete = "files.delete"
case FilesUpload = "files.upload"
case GroupsClose = "groups.close"
case GroupsHistory = "groups.history"
case GroupsInfo = "groups.info"
case GroupsList = "groups.list"
case GroupsMark = "groups.mark"
case GroupsOpen = "groups.open"
case GroupsSetPurpose = "groups.setPurpose"
case GroupsSetTopic = "groups.setTopic"
case IMClose = "im.close"
case IMHistory = "im.history"
case IMList = "im.list"
case IMMark = "im.mark"
case IMOpen = "im.open"
case MPIMClose = "mpim.close"
case MPIMHistory = "mpim.history"
case MPIMList = "mpim.list"
case MPIMMark = "mpim.mark"
case MPIMOpen = "mpim.open"
case PinsAdd = "pins.add"
case PinsRemove = "pins.remove"
case ReactionsAdd = "reactions.add"
case ReactionsGet = "reactions.get"
case ReactionsList = "reactions.list"
case ReactionsRemove = "reactions.remove"
case RTMStart = "rtm.start"
case StarsAdd = "stars.add"
case StarsRemove = "stars.remove"
case TeamInfo = "team.info"
case UsersGetPresence = "users.getPresence"
case UsersInfo = "users.info"
case UsersList = "users.list"
case UsersSetActive = "users.setActive"
case UsersSetPresence = "users.setPresence"
}
public class SlackWebAPI {
public typealias FailureClosure = (error: SlackError)->Void
public enum InfoType: String {
case Purpose = "purpose"
case Topic = "topic"
}
public enum ParseMode: String {
case Full = "full"
case None = "none"
}
public enum Presence: String {
case Auto = "auto"
case Away = "away"
}
private enum ChannelType: String {
case Channel = "channel"
case Group = "group"
case IM = "im"
}
private let client: Client
required public init(client: Client) {
self.client = client
}
//MARK: - RTM
public func rtmStart(success success: ((response: [String: AnyObject])->Void)?, failure: FailureClosure?) {
client.api.request(.RTMStart, token: client.token, parameters: nil, successClosure: {
(response) -> Void in
success?(response: response)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Auth Test
public func authenticationTest(success: ((authenticated: Bool)->Void)?, failure: FailureClosure?) {
client.api.request(.AuthTest, token: client.token, parameters: nil, successClosure: {
(response) -> Void in
success?(authenticated: true)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Channels
public func channelHistory(id: String, latest: String = "\(NSDate().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
history(.ChannelsHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history:history)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) { (error) -> Void in
failure?(error: error)
}
}
public func channelsList(excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
list(.ChannelsList, type:ChannelType.Channel, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) { (error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Messaging
public func deleteMessage(channel: String, ts: String, success: ((deleted: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": channel, "ts": ts]
client.api.request(.ChatDelete, token: client.token, parameters: parameters, successClosure: { (response) -> Void in
success?(deleted: true)
}) {(error) -> Void in
failure?(error: error)
}
}
public func sendMessage(channel: String, text: String, username: String? = nil, asUser: Bool = false, parse: ParseMode = .Full, linkNames: Bool = false, attachments: [[String: AnyObject]]? = nil, unfurlLinks: Bool = false, unfurlMedia: Bool = false, 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":attachments, "icon_url":iconURL, "icon_emoji":iconEmoji]
client.api.request(.ChatPostMessage, token: client.token, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?((ts: response["ts"] as? String, response["channel"] as? String))
}) {(error) -> Void in
failure?(error: error)
}
}
public func updateMessage(channel: String, ts: String, message: String, attachments: [[String: AnyObject]]? = 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":attachments]
client.api.request(.ChatUpdate, token: client.token, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(updated: true)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Emoji
public func emojiList(success: ((emojiList: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
client.api.request(.EmojiList, token: client.token, parameters: nil, successClosure: {
(response) -> Void in
success?(emojiList: response["emoji"] as? [String: AnyObject])
}) { (error) -> Void in
failure?(error: error)
}
}
//MARK: - Files
public func deleteFile(fileID: String, success: ((deleted: Bool)->Void)?, failure: FailureClosure?) {
let parameters = ["file":fileID]
client.api.request(.FilesDelete, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(deleted: true)
}) {(error) -> Void in
failure?(error: error)
}
}
public func uploadFile(file: NSData, 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?.joinWithSeparator(",")]
client.api.uploadRequest(client.token, data: file, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(file: File(file: response["file"] as? [String: AnyObject]))
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Groups
public func closeGroup(groupID: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
close(.GroupsClose, channelID: groupID, success: {
(closed) -> Void in
success?(closed:closed)
}) {(error) -> Void in
failure?(error:error)
}
}
public func groupHistory(id: String, latest: String = "\(NSDate().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
history(.GroupsHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history: history)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
public func groupsList(excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
list(.GroupsList, type:ChannelType.Group, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
public func openGroup(channel: String, success: ((opened: Bool)->Void)?, failure: FailureClosure?) {
let parameters = ["channel":channel]
client.api.request(.GroupsOpen, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(opened: true)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - IM
public func closeIM(channel: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
close(.IMClose, channelID: channel, success: {
(closed) -> Void in
success?(closed: closed)
}) {(error) -> Void in
failure?(error: error)
}
}
public func imHistory(id: String, latest: String = "\(NSDate().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
history(.IMHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history: history)
}) {(error) -> Void in
failure?(error: error)
}
}
public func imsList(excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
list(.IMList, type:ChannelType.IM, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
public func openIM(userID: String, success: ((imID: String?)->Void)?, failure: FailureClosure?) {
let parameters = ["user":userID]
client.api.request(.IMOpen, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
let group = response["channel"] as? [String: AnyObject]
success?(imID: group?["id"] as? String)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - MPIM
public func closeMPIM(channel: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
close(.MPIMClose, channelID: channel, success: {
(closed) -> Void in
success?(closed: closed)
}) {(error) -> Void in
failure?(error: error)
}
}
public func mpimHistory(id: String, latest: String = "\(NSDate().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
history(.MPIMHistory, id: id, latest: latest, oldest: oldest, inclusive: inclusive, count: count, unreads: unreads, success: {
(history) -> Void in
success?(history: history)
}) {(error) -> Void in
failure?(error: error)
}
}
public func mpimsList(excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
list(.MPIMList, type:ChannelType.Group, excludeArchived: excludeArchived, success: {
(channels) -> Void in
success?(channels: channels)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
public func openMPIM(userIDs: [String], success: ((mpimID: String?)->Void)?, failure: FailureClosure?) {
let parameters = ["users":userIDs.joinWithSeparator(",")]
client.api.request(.MPIMOpen, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
let group = response["group"] as? [String: AnyObject]
success?(mpimID: group?["id"] as? String)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Pins
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)
}) {(error) -> Void in
failure?(error: error)
}
}
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)
}) {(error) -> Void in
failure?(error: error)
}
}
private func pin(endpoint: SlackAPIEndpoint, 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]
client.api.request(endpoint, token: client.token, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(ok: true)
}){(error) -> Void in
failure?(error: 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?) {
react(.ReactionsAdd, name: name, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(reacted: ok)
}) {(error) -> Void in
failure?(error: 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?) {
react(.ReactionsRemove, name: name, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(unreacted: ok)
}) {(error) -> Void in
failure?(error: error)
}
}
private func react(endpoint: SlackAPIEndpoint, 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]
client.api.request(endpoint, token: client.token, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(ok: true)
}) {(error) -> Void in
failure?(error: 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?) {
star(.StarsAdd, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(starred: ok)
}) {(error) -> Void in
failure?(error: 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?) {
star(.StarsRemove, file: file, fileComment: fileComment, channel: channel, timestamp: timestamp, success: {
(ok) -> Void in
success?(unstarred: ok)
}) {(error) -> Void in
failure?(error: error)
}
}
private func star(endpoint: SlackAPIEndpoint, 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]
client.api.request(endpoint, token: client.token, parameters: filterNilParameters(parameters), successClosure: {
(response) -> Void in
success?(ok: true)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Team
public func teamInfo(success: ((info: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
client.api.request(.TeamInfo, token: client.token, parameters: nil, successClosure: {
(response) -> Void in
success?(info: response["team"] as? [String: AnyObject])
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Users
public func userPresence(user: String, success: ((presence: String?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["user":user]
client.api.request(.UsersGetPresence, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(presence: response["presence"] as? String)
}){(error) -> Void in
failure?(error: error)
}
}
public func userInfo(id: String, success: ((user: User?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["user":id]
client.api.request(.UsersInfo, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(user: User(user: response["user"] as? [String: AnyObject]))
}) {(error) -> Void in
failure?(error: error)
}
}
public func usersList(includePresence: Bool = false, success: ((userList: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["presence":includePresence]
client.api.request(.UsersList, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(userList: response["members"] as? [[String: AnyObject]])
}){(error) -> Void in
failure?(error: error)
}
}
public func setUserActive(success: ((success: Bool)->Void)?, failure: FailureClosure?) {
client.api.request(.UsersSetActive, token: client.token, parameters: nil, successClosure: {
(response) -> Void in
success?(success: true)
}) {(error) -> Void in
failure?(error: error)
}
}
public func setUserPresence(presence: Presence, success: ((success: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["presence":presence.rawValue]
client.api.request(.UsersSetPresence, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(success:true)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Channel Utilities
private func close(endpoint: SlackAPIEndpoint, channelID: String, success: ((closed: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel":channelID]
client.api.request(endpoint, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(closed: true)
}) {(error) -> Void in
failure?(error: error)
}
}
private func history(endpoint: SlackAPIEndpoint, id: String, latest: String = "\(NSDate().timeIntervalSince1970)", oldest: String = "0", inclusive: Bool = false, count: Int = 100, unreads: Bool = false, success: ((history: [String: AnyObject]?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": id, "latest": latest, "oldest": oldest, "inclusive":inclusive, "count":count, "unreads":unreads]
client.api.request(endpoint, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(history: response)
}) {(error) -> Void in
failure?(error: error)
}
}
private func info(endpoint: SlackAPIEndpoint, type: ChannelType, id: String, success: ((channel: Channel?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": id]
client.api.request(endpoint, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(channel: Channel(channel: response[type.rawValue] as? [String: AnyObject]))
}) {(error) -> Void in
failure?(error: error)
}
}
private func list(endpoint: SlackAPIEndpoint, type: ChannelType, excludeArchived: Bool = false, success: ((channels: [[String: AnyObject]]?)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["exclude_archived": excludeArchived]
client.api.request(endpoint, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(channels: response[type.rawValue+"s"] as? [[String: AnyObject]])
}) {(error) -> Void in
failure?(error: error)
}
}
private func mark(endpoint: SlackAPIEndpoint, channel: String, timestamp: String, success: ((ts: String)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": channel, "ts": timestamp]
client.api.request(endpoint, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(ts: timestamp)
}) {(error) -> Void in
failure?(error: error)
}
}
private func setInfo(endpoint: SlackAPIEndpoint, type: InfoType, channel: String, text: String, success: ((success: Bool)->Void)?, failure: FailureClosure?) {
let parameters: [String: AnyObject] = ["channel": channel, type.rawValue: text]
client.api.request(endpoint, token: client.token, parameters: parameters, successClosure: {
(response) -> Void in
success?(success: true)
}) {(error) -> Void in
failure?(error: error)
}
}
//MARK: - Filter Nil Parameters
private func filterNilParameters(parameters: [String: AnyObject?]) -> [String: AnyObject] {
var finalParameters = [String: AnyObject]()
for key in parameters.keys {
if parameters[key] != nil {
finalParameters[key] = parameters[key]!
}
}
return finalParameters
}
}
@@ -1,284 +0,0 @@
//
// SlackWebAPIErrorHandling.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 Foundation
public enum SlackError: ErrorType {
case AccountInactive
case AlreadyArchived
case AlreadyInChannel
case AlreadyPinned
case AlreadyReacted
case AlreadyStarred
case BadClientSecret
case BadRedirectURI
case BadTimeStamp
case CantArchiveGeneral
case CantDeleteFile
case CantDeleteMessage
case CantInvite
case CantInviteSelf
case CantKickFromGeneral
case CantKickFromLastChannel
case CantKickSelf
case CantLeaveGeneral
case CantLeaveLastChannel
case CantUpdateMessage
case ChannelNotFound
case ComplianceExportsPreventDeletion
case EditWindowClosed
case FileCommentNotFound
case FileDeleted
case FileNotFound
case FileNotShared
case GroupContainsOthers
case InvalidArrayArg
case InvalidAuth
case InvalidChannel
case InvalidCharSet
case InvalidClientID
case InvalidCode
case InvalidFormData
case InvalidName
case InvalidPostType
case InvalidPresence
case InvalidTS
case InvalidTSLatest
case InvalidTSOldest
case IsArchived
case LastMember
case LastRAChannel
case MessageNotFound
case MessageTooLong
case MigrationInProgress
case MissingDuration
case MissingPostType
case NameTaken
case NoChannel
case NoItemSpecified
case NoReaction
case NoText
case NotArchived
case NotAuthed
case NotEnoughUsers
case NotInChannel
case NotInGroup
case NotPinned
case NotStarred
case OverPaginationLimit
case PaidOnly
case PermissionDenied
case PostingToGeneralChannelDenied
case RateLimited
case RequestTimeout
case RestrictedAction
case SnoozeEndFailed
case SnoozeFailed
case SnoozeNotActive
case TooLong
case TooManyEmoji
case TooManyReactions
case TooManyUsers
case UnknownError
case UnknownType
case UserDisabled
case UserDoesNotOwnChannel
case UserIsBot
case UserIsRestricted
case UserIsUltraRestricted
case UserListNotSupplied
case UserNotFound
case UserNotVisible
}
internal struct ErrorDispatcher {
static func dispatch(error: String) -> SlackError {
switch error {
case "account_inactive":
return .AccountInactive
case "already_in_channel":
return .AlreadyInChannel
case "already_pinned":
return .AlreadyPinned
case "already_reacted":
return .AlreadyReacted
case "already_starred":
return .AlreadyStarred
case "bad_client_secret":
return .BadClientSecret
case "bad_redirect_uri":
return .BadRedirectURI
case "bad_timestamp":
return .BadTimeStamp
case "cant_delete_file":
return .CantDeleteFile
case "cant_delete_message":
return .CantDeleteMessage
case "cant_invite":
return .CantInvite
case "cant_invite_self":
return .CantInviteSelf
case "cant_kick_from_general":
return .CantKickFromGeneral
case "cant_kick_from_last_channel":
return .CantKickFromLastChannel
case "cant_kick_self":
return .CantKickSelf
case "cant_leave_general":
return .CantLeaveGeneral
case "cant_leave_last_channel":
return .CantLeaveLastChannel
case "cant_update_message":
return .CantUpdateMessage
case "compliance_exports_prevent_deletion":
return .ComplianceExportsPreventDeletion
case "channel_not_found":
return .ChannelNotFound
case "edit_window_closed":
return .EditWindowClosed
case "file_comment_not_found":
return .FileCommentNotFound
case "file_deleted":
return .FileDeleted
case "file_not_found":
return .FileNotFound
case "file_not_shared":
return .FileNotShared
case "group_contains_others":
return .GroupContainsOthers
case "invalid_array_arg":
return .InvalidArrayArg
case "invalid_auth":
return .InvalidAuth
case "invalid_channel":
return .InvalidChannel
case "invalid_charset":
return .InvalidCharSet
case "invalid_client_id":
return .InvalidClientID
case "invalid_code":
return .InvalidCode
case "invalid_form_data":
return .InvalidFormData
case "invalid_name":
return .InvalidName
case "invalid_post_type":
return .InvalidPostType
case "invalid_presence":
return .InvalidPresence
case "invalid_timestamp":
return .InvalidTS
case "invalid_ts_latest":
return .InvalidTSLatest
case "invalid_ts_oldest":
return .InvalidTSOldest
case "is_archived":
return .IsArchived
case "last_member":
return .LastMember
case "last_ra_channel":
return .LastRAChannel
case "message_not_found":
return .MessageNotFound
case "msg_too_long":
return .MessageTooLong
case "migration_in_progress":
return .MigrationInProgress
case "missing_duration":
return .MissingDuration
case "missing_post_type":
return .MissingPostType
case "name_taken":
return .NameTaken
case "no_channel":
return .NoChannel
case "no_reaction":
return .NoReaction
case "no_item_specified":
return .NoItemSpecified
case "no_text":
return .NoText
case "not_archived":
return .NotArchived
case "not_authed":
return .NotAuthed
case "not_enough_users":
return .NotEnoughUsers
case "not_in_channel":
return .NotInChannel
case "not_in_group":
return .NotInGroup
case "not_pinned":
return .NotPinned
case "not_starred":
return .NotStarred
case "over_pagination_limit":
return .OverPaginationLimit
case "paid_only":
return .PaidOnly
case "perimssion_denied":
return .PermissionDenied
case "posting_to_general_channel_denied":
return .PostingToGeneralChannelDenied
case "rate_limited":
return .RateLimited
case "request_timeout":
return .RequestTimeout
case "snooze_end_failed":
return .SnoozeEndFailed
case "snooze_failed":
return .SnoozeFailed
case "snooze_not_active":
return .SnoozeNotActive
case "too_long":
return .TooLong
case "too_many_emoji":
return .TooManyEmoji
case "too_many_reactions":
return .TooManyReactions
case "too_many_users":
return .TooManyUsers
case "unknown_type":
return .UnknownType
case "user_disabled":
return .UserDisabled
case "user_does_not_own_channel":
return .UserDoesNotOwnChannel
case "user_is_bot":
return .UserIsBot
case "user_is_restricted":
return .UserIsRestricted
case "user_is_ultra_restricted":
return .UserIsUltraRestricted
case "user_list_not_supplied":
return .UserListNotSupplied
case "user_not_found":
return .UserNotFound
case "user_not_visible":
return .UserNotVisible
default:
return .UnknownError
}
}
}
-45
View File
@@ -1,45 +0,0 @@
//
// Team.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.
public struct Team {
public let id: String
internal(set) public var name: String?
internal(set) public var emailDomain: String?
internal(set) public var domain: String?
internal(set) public var messageEditWindowMinutes: Int?
internal(set) public var overStorageLimit: Bool?
internal(set) public var prefs: [String: AnyObject]?
internal(set) public var plan: String?
internal init?(team: [String: AnyObject]?) {
id = team?["id"] as! String
name = team?["id"] as? String
emailDomain = team?["email_domain"] as? String
domain = team?["domain"] as? String
messageEditWindowMinutes = team?["mesg_edit_window_mins"] as? Int
overStorageLimit = team?["over_storage_limit"] as? Bool
prefs = team?["prefs"] as? [String: AnyObject]
plan = team?["plan"] as? String
}
}
-177
View File
@@ -1,177 +0,0 @@
//
// Types.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.
// MARK: - Edited
public struct Edited {
public let user: String?
public let ts: String?
internal init?(edited:[String: AnyObject]?) {
user = edited?["user"] as? String
ts = edited?["ts"] as? String
}
}
// MARK: - Reaction
public struct Reaction {
public let name: String?
internal(set) public var users = [String: String]()
internal init?(reaction:[String: AnyObject]?) {
name = reaction?["name"] as? String
}
internal init?(name: String?, user: String) {
self.name = name
users[user] = user
}
internal init?(name: String?, users: [String: String]) {
self.name = name
self.users = users
}
static func reactionsFromArray(array: [[String: AnyObject]]) -> [String: Reaction] {
var reactions = [String: Reaction]()
var userDictionary = [String: String]()
for reaction in array {
if let users = reaction["users"] as? [String] {
for user in users {
userDictionary[user] = user
}
}
if let name = reaction["name"] as? String {
reactions[name] = Reaction(name: name, users: userDictionary)
}
}
return reactions
}
}
extension Reaction: Equatable {}
public func ==(lhs: Reaction, rhs: Reaction) -> Bool {
return lhs.name == rhs.name
}
// MARK: - Comment
public struct Comment {
public let id: String?
public let user: String?
internal(set) public var created: Int?
internal(set) public var comment: String?
internal(set) public var starred: Bool?
internal(set) public var stars: Int?
internal(set) public var reactions = [String: Reaction]()
internal init?(comment:[String: AnyObject]?) {
id = comment?["id"] as? String
created = comment?["created"] as? Int
user = comment?["user"] as? String
starred = comment?["is_starred"] as? Bool
stars = comment?["num_stars"] as? Int
self.comment = comment?["comment"] as? String
}
internal init?(id: String?) {
self.id = id
self.user = nil
}
}
extension Comment: Equatable {}
public func ==(lhs: Comment, rhs: Comment) -> Bool {
return lhs.id == rhs.id
}
// MARK: - Item
public struct Item {
public let type: String?
public let ts: String?
public let channel: String?
public let message: Message?
public let file: File?
public let comment: Comment?
public let fileCommentID: String?
internal init?(item:[String: AnyObject]?) {
type = item?["type"] as? String
ts = item?["ts"] as? String
channel = item?["channel"] as? String
message = Message(message: item?["message"] as? [String: AnyObject])
// Comment and File can come across as Strings or Dictionaries
if (Comment(comment: item?["comment"] as? [String: AnyObject])?.id == nil) {
comment = Comment(id: item?["comment"] as? String)
} else {
comment = Comment(comment: item?["comment"] as? [String: AnyObject])
}
if (File(file: item?["file"] as? [String: AnyObject])?.id == nil) {
file = File(id: item?["file"] as? String)
} else {
file = File(file: item?["file"] as? [String: AnyObject])
}
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
}
// MARK: - Topic
public struct Topic {
public let value: String?
public let creator: String?
public let lastSet: Int?
internal init?(topic: [String: AnyObject]?) {
value = topic?["value"] as? String
creator = topic?["creator"] as? String
lastSet = topic?["last_set"] as? Int
}
}
// MARK: - Do Not Disturb Status
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]?) {
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
}
}
-103
View File
@@ -1,103 +0,0 @@
//
// User.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.
public struct User {
public struct Profile {
internal(set) public var firstName: String?
internal(set) public var lastName: String?
internal(set) public var realName: String?
internal(set) public var email: String?
internal(set) public var skype: String?
internal(set) public var phone: String?
internal(set) public var image24: String?
internal(set) public var image32: String?
internal(set) public var image48: String?
internal(set) public var image72: String?
internal(set) public var image192: String?
internal init?(profile: [String: AnyObject]?) {
firstName = profile?["first_name"] as? String
lastName = profile?["last_name"] as? String
realName = profile?["real_name"] as? String
email = profile?["email"] as? String
skype = profile?["skype"] as? String
phone = profile?["phone"] as? String
image24 = profile?["image_24"] as? String
image32 = profile?["image_32"] as? String
image48 = profile?["image_48"] as? String
image72 = profile?["image_72"] as? String
image192 = profile?["image_192"] as? String
}
}
public let id: String?
internal(set) public var name: String?
internal(set) public var deleted: Bool?
internal(set) public var profile: Profile?
internal(set) public var doNotDisturbStatus: DoNotDisturbStatus?
internal(set) public var presence: String?
internal(set) public var color: String?
public let isBot: Bool?
internal(set) public var isAdmin: Bool?
internal(set) public var isOwner: Bool?
internal(set) public var isPrimaryOwner: Bool?
internal(set) public var isRestricted: Bool?
internal(set) public var isUltraRestricted: Bool?
internal(set) public var has2fa: Bool?
internal(set) public var hasFiles: Bool?
internal(set) public var status: String?
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]?
// Client properties
internal(set) public var userGroups: [String: String]?
internal init?(user: [String: AnyObject]?) {
id = user?["id"] as? String
name = user?["name"] as? String
deleted = user?["deleted"] as? Bool
profile = Profile(profile: user?["profile"] as? [String: AnyObject])
color = user?["color"] as? String
isAdmin = user?["is_admin"] as? Bool
isOwner = user?["is_owner"] as? Bool
isPrimaryOwner = user?["is_primary_owner"] as? Bool
isRestricted = user?["is_restricted"] as? Bool
isUltraRestricted = user?["is_ultra_restricted"] as? Bool
has2fa = user?["has_2fa"] as? Bool
hasFiles = user?["has_files"] as? Bool
isBot = user?["is_bot"] as? Bool
presence = user?["presence"] as? String
status = user?["status"] as? String
timeZone = user?["tz"] as? String
timeZoneLabel = user?["tz_label"] as? String
timeZoneOffSet = user?["tz_offset"] as? Int
preferences = user?["prefs"] as? [String: AnyObject]
}
internal init?(id: String?) {
self.id = id
self.isBot = nil
}
}
-68
View File
@@ -1,68 +0,0 @@
//
// UserGroup.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.
public struct UserGroup {
public let id: String?
internal(set) public var teamID: String?
public let isUserGroup: Bool?
internal(set) public var name: String?
internal(set) public var description: String?
internal(set) public var handle: String?
internal(set) public var isExternal: Bool?
public let dateCreated: Int?
internal(set) public var dateUpdated: Int?
internal(set) public var dateDeleted: Int?
internal(set) public var autoType: String?
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 users: [String]?
internal(set) public var userCount: Int?
internal init?(userGroup: [String: AnyObject]?) {
id = userGroup?["id"] as? String
teamID = userGroup?["team_id"] as? String
isUserGroup = userGroup?["is_usergroup"] as? Bool
name = userGroup?["name"] as? String
description = userGroup?["description"] as? String
handle = userGroup?["handle"] as? String
isExternal = userGroup?["is_external"] as? Bool
dateCreated = userGroup?["date_create"] as? Int
dateUpdated = userGroup?["date_update"] as? Int
dateDeleted = userGroup?["date_delete"] as? Int
autoType = userGroup?["auto_type"] as? String
createdBy = userGroup?["created_by"] as? String
updatedBy = userGroup?["updated_by"] as? String
deletedBy = userGroup?["deleted_by"] as? String
preferences = userGroup?["prefs"] as? [String: AnyObject]
users = userGroup?["users"] as? [String]
if let count = userGroup?["user_count"] as? String {
userCount = Int(count)
}
}
}
+104
View File
@@ -0,0 +1,104 @@
//
// SlackKit.swift
//
// Copyright © 2017 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 Foundation
@_exported import SKClient
@_exported import SKCore
@_exported import SKRTMAPI
@_exported import SKServer
@_exported import SKWebAPI
public final class SlackKit: RTMAdapter {
public typealias EventClosure = (Event, Client?) -> Void
internal typealias TypedEvent = (EventType, EventClosure)
internal var callbacks = [TypedEvent]()
internal(set) public var rtm: SKRTMAPI?
internal(set) public var server: SKServer?
internal(set) public var webAPI: WebAPI?
internal(set) public var clients: [String: Client] = [:]
public init() {}
public func addWebAPIAccessWithToken(_ token: String) {
self.webAPI = WebAPI(token: token)
}
public func addRTMBotWithAPIToken(_ token: String, client: Client? = Client(), options: RTMOptions = RTMOptions(), rtm: RTMWebSocket? = nil) {
self.rtm = SKRTMAPI(withAPIToken: token, options: options, rtm: rtm)
self.rtm?.adapter = self
clients[token] = client
self.rtm?.connect()
}
public func addServer(_ server: SlackKitServer? = nil, responder: SlackKitResponder? = nil, oauth: OAuthConfig? = nil) {
var responder: SlackKitResponder = responder ?? SlackKitResponder(routes: [])
if let oauth = oauth {
responder.routes.append(oauthRequestRoute(config: oauth))
}
self.server = SKServer(server: server, responder: responder)
self.server?.start()
}
private func oauthRequestRoute(config: OAuthConfig) -> RequestRoute {
let oauth = OAuthMiddleware(config: config) { authorization in
// User
if let token = authorization.accessToken {
self.webAPI = WebAPI(token: token)
}
// Bot User
if let token = authorization.bot?.botToken {
self.webAPI = WebAPI(token: token)
self.rtm = SKRTMAPI(withAPIToken: token, options: RTMOptions(), rtm: nil)
self.rtm?.adapter = self
self.clients[token] = Client()
self.rtm?.connect()
}
}
return RequestRoute(path: "/oauth", middleware: oauth)
}
//MARK: - RTM Adapter
public func initialSetup(json: [String: Any], instance: SKRTMAPI) {
clients[instance.token]?.initialSetup(JSON: json)
}
public func notificationForEvent(_ event: Event, type: EventType, instance: SKRTMAPI) {
let client = clients[instance.token]
client?.notificationForEvent(event, type: type)
executeCallbackForEvent(event, type: type, client: client)
}
//MARK: - Callbacks
public func notificationForEvent(_ type: EventType, event: @escaping EventClosure) {
callbacks.append((type, event))
}
private func executeCallbackForEvent(_ event: Event, type: EventType, client: Client?) {
let cbs = callbacks.filter {$0.0 == type}
for callback in cbs {
callback.1(event, client)
}
}
}
@@ -15,13 +15,11 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.9.8</string>
<key>CFBundleSignature</key>
<string>????</string>
<string>4.0.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Peter Zignego. All rights reserved.</string>
<string>Copyright © 2017 Peter Zignego. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>