slack-api-wrapper 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c18b521343ae2907134d7af29d23616e0990ec2
4
+ data.tar.gz: a8fc73773601ce072195cf08bde1bf0247b7e3db
5
+ SHA512:
6
+ metadata.gz: 1b4e7a04162651cbf861fd47928ce96735666cb5f942b2d51d3f103f6d948c8e2871606e37e0f758c4bba02617a100aaa4766c26922514262bcbeb5ec402fd57
7
+ data.tar.gz: d667a8f1236fa4cf4bb5c337c1a8a0ae460e11741b48fa1020bdc9f9f03b6bcf796e16a37bf513080469a5e60b7e54ef166a22e37f77cdf2c4d128a7004337fc
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in slack.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Gustavo Bazan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ Slack API Wrapper [![Build Status](https://travis-ci.org/gssbzn/slack-api-wrapper.svg)](https://travis-ci.org/gssbzn/slack-api-wrapper)
2
+ =========================
3
+
4
+ A library that provides a plain function-call interface to the Slack API web endpoints.
5
+
6
+ This a work in progress, many API endpoint implementations are still missing,
7
+ I expect to add them as soon as possible or you can help by making a pull request.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'slack-api-wrapper'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install slack-api-wrapper
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ You can see a demo here [slack-web-test](https://github.com/gssbzn/slack-web-test)
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/gssbzn/slack-api-wrapper/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
36
+
37
+
38
+ ## License
39
+
40
+ MIT License. Copyright 2015 Gustavo Bazan. http://gustavobazan.com
41
+
42
+ This software is not created by, affiliated with, or supported by Slack Technologies, Inc.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
@@ -0,0 +1,87 @@
1
+ require 'net/https'
2
+ require 'cgi'
3
+ require 'json'
4
+
5
+ require_relative "slack/version"
6
+ require_relative "slack/error"
7
+ require_relative "slack/session"
8
+ require_relative "slack/oauth2"
9
+ require_relative "slack/client"
10
+
11
+ module Slack # :nodoc:
12
+ WEB_SERVER = 'slack.com'
13
+ API_SERVER = "#{WEB_SERVER}/api"
14
+
15
+ #
16
+ def self.clean_params(params)
17
+ r = {}
18
+ params.each do |k,v|
19
+ r[k] = v.to_s unless v.nil?
20
+ end
21
+ r
22
+ end
23
+
24
+ #
25
+ def self.make_query_string(params)
26
+ clean_params(params).collect {|k,v|
27
+ CGI.escape(k) + "=" + CGI.escape(v)
28
+ }.join("&")
29
+ end
30
+
31
+ #
32
+ def self.do_http(uri, request) # :nodoc:
33
+
34
+ http = Net::HTTP.new(uri.host, uri.port)
35
+
36
+ http.use_ssl = true
37
+
38
+ # Let then know about us
39
+ request['User-Agent'] = "SlackRubyAPIWrapper"
40
+
41
+ begin
42
+ http.request(request)
43
+ rescue OpenSSL::SSL::SSLError => e
44
+ raise SlackError.new("SSL error connecting to Slack.")
45
+ end
46
+ end
47
+
48
+ # Parse response. You probably shouldn't be calling this directly. This takes responses from the server
49
+ # and parses them. It also checks for errors and raises exceptions with the appropriate messages.
50
+ def self.parse_response(response, raw=false) # :nodoc:
51
+ if response.kind_of?(Net::HTTPServerError)
52
+ raise Slack.new("Slack Server Error: #{response} - #{response.body}", response)
53
+ elsif response.kind_of?(Net::HTTPUnauthorized)
54
+ raise SlackAuthError.new("User is not authenticated.", response)
55
+ elsif !response.kind_of?(Net::HTTPSuccess)
56
+ begin
57
+ d = JSON.parse(response.body)
58
+ rescue
59
+ raise SlackError.new("Slack Server Error: body=#{response.body}", response)
60
+ end
61
+ if d['error']
62
+ raise SlackError.new(d['error'], response)
63
+ else
64
+ raise SlackError.new(response.body, response)
65
+ end
66
+ end
67
+
68
+ return response.body if raw
69
+
70
+ begin
71
+ return JSON.parse(response.body)
72
+ rescue JSON::ParserError
73
+ raise SlackError.new("Unable to parse JSON response: #{response.body}", response)
74
+ end
75
+ end
76
+
77
+ # A string comparison function that is resistant to timing attacks. If you're comparing a
78
+ # string you got from the outside world with a string that is supposed to be a secret, use
79
+ # this function to check equality.
80
+ def self.safe_string_equals(a, b)
81
+ if a.length != b.length
82
+ false
83
+ else
84
+ a.chars.zip(b.chars).map {|ac,bc| ac == bc}.all?
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'session'
2
+ require_relative 'web'
3
+
4
+ module Slack
5
+ # Use this class to make Slack API calls. You'll need to obtain an OAuth 2 access token
6
+ # first; you can get one using either SlackOAuth2Flow.
7
+ class Client
8
+ include Web
9
+
10
+ # Args:
11
+ # * +oauth2_access_token+: Obtained via Slack::OAuth2::Flow or Slack::OAuth2::FlowNoRedirect.
12
+ def initialize(oauth2_access_token)
13
+ if oauth2_access_token.is_a?(String)
14
+ @session = OAuth2Session.new(oauth2_access_token)
15
+ else
16
+ raise ArgumentError.new("oauth2_access_token doesn't have a valid type")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # This is the usual error raised on any Slack related Errors
2
+ module Slack
3
+ class Error < RuntimeError
4
+ attr_accessor :http_response, :error
5
+ def initialize(error, http_response=nil)
6
+ @error = error
7
+ @http_response = http_response
8
+ end
9
+
10
+ def to_s
11
+ "#{error}"
12
+ end
13
+ end
14
+
15
+ # This is the error raised on Authentication failures. Usually this means
16
+ # one of three things
17
+ # * Your user failed to go to the authorize url and approve your application
18
+ # * You set an invalid or expired token and secret on your Session
19
+ # * Your user deauthorized the application after you stored a valid token and secret
20
+ class AuthError < Error; end
21
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'oauth2/flow_base'
2
+ require_relative 'oauth2/flow'
3
+ module Slack
4
+ module Oauth2
5
+ end
6
+ end
@@ -0,0 +1,155 @@
1
+ require 'securerandom'
2
+
3
+ require_relative 'flow_base'
4
+
5
+ module Slack
6
+ module OAuth2
7
+ # The standard OAuth 2 authorization helper. Use this if you're writing a web app.
8
+ class Flow < FlowBase
9
+
10
+ # * consumer_key: Your Slack API app's "app key"
11
+ # * consumer_secret: Your Slack API app's "app secret"
12
+ # * redirect_uri: The URI that the Slack server will redirect the user to after the user
13
+ # finishes authorizing your app. This URI must be HTTPs-based and pre-registered with
14
+ # the Slack servers.
15
+ # * session: A hash that represents the current web app session (will be used to save the CSRF
16
+ # token)
17
+ # * csrf_token_key: The key to use when storing the CSRF token in the session (for example,
18
+ # :slack_auth_csrf_token)
19
+ def initialize(consumer_key, consumer_secret, redirect_uri, scope, team, session, csrf_token_session_key)
20
+ super(consumer_key, consumer_secret, scope, team)
21
+ unless redirect_uri.is_a?(String)
22
+ raise ArgumentError, "redirect_uri must be a String, got #{consumer_secret.inspect}"
23
+ end
24
+ @redirect_uri = redirect_uri
25
+ @session = session
26
+ @csrf_token_session_key = csrf_token_session_key
27
+ end
28
+
29
+ # Starts the OAuth 2 authorizaton process, which involves redirecting the user to
30
+ # the returned "authorization URL" (a URL on the Slack website). When the user then
31
+ # either approves or denies your app access, Slack will redirect them to the
32
+ # redirect_uri you provided to the constructor, at which point you should call finish()
33
+ # to complete the process.
34
+ #
35
+ # This function will also save a CSRF token to the session and csrf_token_session_key
36
+ # you provided to the constructor. This CSRF token will be checked on finish() to prevent
37
+ # request forgery.
38
+ #
39
+ # * url_state: Any data you would like to keep in the URL through the authorization
40
+ # process. This exact value will be returned to you by finish().
41
+ #
42
+ # Returns the URL to redirect the user to.
43
+ def start(url_state=nil)
44
+ unless url_state.nil? or url_state.is_a?(String)
45
+ raise ArgumentError, "url_state must be a String"
46
+ end
47
+
48
+ csrf_token = SecureRandom.base64(16)
49
+ state = csrf_token
50
+ unless url_state.nil?
51
+ state += "|" + url_state
52
+ end
53
+ @session[@csrf_token_session_key] = csrf_token
54
+ _get_authorize_url(@redirect_uri, state)
55
+ end
56
+
57
+ # Call this after the user has visited the authorize URL (see: start()), approved your app,
58
+ # and was redirected to your redirect URI.
59
+ #
60
+ # * query_params: The query params on the GET request to your redirect URI.
61
+ #
62
+ # Returns a tuple of (access_token, scope, url_state). access_token can be used to
63
+ # construct a SlackClient. scpe is the Slack scope the user that jsut approved
64
+ # your app. url_state is the value you originally passed in to start().
65
+ #
66
+ # Can throw BadRequestError, BadStateError, CsrfError, NotApprovedError,
67
+ # ProviderError.
68
+ def finish(query_params)
69
+ csrf_token_from_session = @session[@csrf_token_session_key]
70
+
71
+ # Check well-formedness of request.
72
+
73
+ # Check well-formedness of request.
74
+
75
+ state = query_params['state']
76
+ if state.nil?
77
+ raise BadRequestError.new("Missing query parameter 'state'.")
78
+ end
79
+ code = query_params['code']
80
+
81
+ error = query_params['error']
82
+
83
+ unless (error.nil? || code.nil?)
84
+ raise BadRequestError.new("Query parameters 'code' and 'error' are both set;" +
85
+ " only one must be set.")
86
+ end
87
+ if error.nil? and code.nil?
88
+ raise BadRequestError.new("Neither query parameter 'code' or 'error' is set.")
89
+ end
90
+
91
+ # Check CSRF token
92
+
93
+ if csrf_token_from_session.nil?
94
+ raise BadStateError.new("Missing CSRF token in session.");
95
+ end
96
+ unless csrf_token_from_session.length > 20
97
+ raise RuntimeError.new("CSRF token unexpectedly short: #{csrf_token_from_session.inspect}")
98
+ end
99
+
100
+ split_pos = state.index('|')
101
+ if split_pos.nil?
102
+ given_csrf_token = state
103
+ url_state = nil
104
+ else
105
+ given_csrf_token, url_state = state.split('|', 2)
106
+ end
107
+ unless Slack::safe_string_equals(csrf_token_from_session, given_csrf_token)
108
+ raise CsrfError.new("Expected #{csrf_token_from_session.inspect}, " +
109
+ "got #{given_csrf_token.inspect}.")
110
+ end
111
+ @session.delete(@csrf_token_session_key)
112
+
113
+ # Check for error identifier
114
+
115
+ unless error.nil?
116
+ if error == 'access_denied'
117
+ # The user clicked "Deny"
118
+ raise NotApprovedError.new("No additional description from Slack.")
119
+ else
120
+ raise ProviderError.new(error)
121
+ end
122
+ end
123
+
124
+ # If everything went ok, make the network call to get an access token.
125
+
126
+ access_token, scope = _finish(code, @redirect_uri)
127
+ return access_token, scope, url_state
128
+ end
129
+
130
+ # Thrown if the redirect URL was missing parameters or if the given parameters were not valid.
131
+ #
132
+ # The recommended action is to show an HTTP 400 error page.
133
+ class BadRequestError < Exception; end
134
+
135
+ # Thrown if all the parameters are correct, but there's no CSRF token in the session. This
136
+ # probably means that the session expired.
137
+ #
138
+ # The recommended action is to redirect the user's browser to try the approval process again.
139
+ class BadStateError < Exception; end
140
+
141
+ # The user chose not to approve your app.
142
+ class NotApprovedError < Exception; end
143
+
144
+ # Thrown if the given 'state' parameter doesn't contain the CSRF token from the user's session.
145
+ # This is blocked to prevent CSRF attacks.
146
+ #
147
+ # The recommended action is to respond with an HTTP 403 error page.
148
+ class CsrfError < Exception; end
149
+
150
+ # Slack redirected to your redirect URI with some unexpected error identifier and error
151
+ # message.
152
+ class ProviderError < Exception; end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,78 @@
1
+ require 'uri'
2
+
3
+ module Slack
4
+ module OAuth2
5
+ # Base class for the OAuth 2 authorization helpers.
6
+ class FlowBase # :nodoc:
7
+ def initialize(consumer_key, consumer_secret, scope, team)
8
+ unless consumer_key.is_a?(String)
9
+ raise ArgumentError, "consumer_key must be a String, got #{consumer_key.inspect}"
10
+ end
11
+ unless consumer_secret.is_a?(String)
12
+ raise ArgumentError, "consumer_secret must be a String, got #{consumer_secret.inspect}"
13
+ end
14
+ unless scope.is_a?(String)
15
+ raise ArgumentError, "scope must be a String, got #{scope.inspect}"
16
+ end
17
+
18
+ @consumer_key = consumer_key
19
+ @consumer_secret = consumer_secret
20
+ @scope = scope
21
+ @team = team
22
+ end
23
+
24
+ protected
25
+
26
+ def _get_authorize_url(redirect_uri, state)
27
+ params = {
28
+ "client_id" => @consumer_key,
29
+ "redirect_uri" => redirect_uri,
30
+ "scope" => @scope,
31
+ "state" => state,
32
+ "team" => @team
33
+ }
34
+
35
+ host = Slack::WEB_SERVER
36
+ path = "/oauth/authorize"
37
+
38
+ target = URI::Generic.new("https", nil, host, nil, nil, path, nil, nil, nil)
39
+ target.query = Slack::make_query_string(params)
40
+
41
+ target.to_s
42
+ end
43
+
44
+ # Finish the OAuth 2 authorization process. If you used a redirect_uri, pass that in.
45
+ # Will return an access token string that you can use with SlackClient.
46
+ def _finish(code, original_redirect_uri)
47
+
48
+ raise ArgumentError, "code must be a String" unless code.is_a?(String)
49
+
50
+ uri = URI.parse("https://#{Slack::API_SERVER}/oauth.access")
51
+ request = Net::HTTP::Post.new(uri.request_uri)
52
+
53
+ params = {
54
+ "client_id" => @consumer_key,
55
+ "client_secret" => @consumer_secret,
56
+ "code" => code,
57
+ "redirect_uri" => original_redirect_uri
58
+ }
59
+
60
+ request.set_form_data(Slack::clean_params(params))
61
+
62
+ response = Slack::do_http(uri, request)
63
+
64
+ j = Slack::parse_response(response)
65
+ ["access_token", "scope"].each do |k|
66
+ unless j.has_key?(k)
67
+ raise Slack::Error.new("Bad response from /token: missing \"#{k}\".")
68
+ end
69
+ unless j[k].is_a?(String)
70
+ raise Slack::Error.new("Bad response from /token: field \"#{k}\" is not a string.")
71
+ end
72
+ end
73
+
74
+ return j['access_token'], j['scope']
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,77 @@
1
+ module Slack
2
+
3
+ class OAuth2Session # :nodoc:
4
+
5
+ def initialize(oauth2_access_token)
6
+ unless oauth2_access_token.is_a?(String)
7
+ raise "bad type for oauth2_access_token (expecting String)"
8
+ end
9
+ @access_token = oauth2_access_token
10
+ end
11
+
12
+ private
13
+
14
+ def build_url(path)
15
+ host = Slack::WEB_SERVER
16
+ full_path = "/api/#{path}"
17
+ URI::HTTPS.build({host: host, path: full_path})
18
+ end
19
+
20
+ def build_url_with_params(path, params) # :nodoc:
21
+ target = build_url(path)
22
+ target.query = Slack::make_query_string(params)
23
+ target
24
+ end
25
+
26
+ protected
27
+
28
+ def do_http(uri, request) # :nodoc:
29
+ Slack::do_http(uri, request)
30
+ end
31
+
32
+ public
33
+
34
+ def do_get(path, params=nil, headers=nil) # :nodoc:
35
+ params ||= {}
36
+ params["token"] = @access_token
37
+ uri = build_url_with_params(path, params)
38
+ do_http(uri, Net::HTTP::Get.new(uri.request_uri))
39
+ end
40
+
41
+ def do_http_with_body(uri, request, body)
42
+ if body != nil
43
+ if body.is_a?(Hash)
44
+ request.set_form_data(Slack::clean_params(body))
45
+ elsif body.respond_to?(:read)
46
+ if body.respond_to?(:length)
47
+ request["Content-Length"] = body.length.to_s
48
+ elsif body.respond_to?(:stat) && body.stat.respond_to?(:size)
49
+ request["Content-Length"] = body.stat.size.to_s
50
+ else
51
+ raise ArgumentError, "Don't know how to handle 'body' (responds to 'read' but not to 'length' or 'stat.size')."
52
+ end
53
+ request.body_stream = body
54
+ else
55
+ s = body.to_s
56
+ request["Content-Length"] = s.length
57
+ request.body = s
58
+ end
59
+ end
60
+ do_http(uri, request)
61
+ end
62
+
63
+ def do_post(path, params=nil, headers=nil) # :nodoc:
64
+ params ||= {}
65
+ params["token"] = @access_token
66
+ uri = build_url(path)
67
+ do_http_with_body(uri, Net::HTTP::Post.new(uri.request_uri, headers), params)
68
+ end
69
+
70
+ def do_put(path, params=nil, headers=nil, body=nil) # :nodoc:
71
+ params ||= {}
72
+ params["token"] = @access_token
73
+ uri = build_url_with_params(path, params)
74
+ do_http_with_body(uri, Net::HTTP::Put.new(uri.request_uri, headers), body)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module Slack
2
+ VERSION = "0.0.2"
3
+ end
data/lib/slack/web.rb ADDED
@@ -0,0 +1,28 @@
1
+ require_relative 'web/auth'
2
+ require_relative 'web/channels'
3
+ require_relative 'web/chat'
4
+ require_relative 'web/emoji'
5
+ require_relative 'web/files'
6
+ require_relative 'web/groups'
7
+ require_relative 'web/im'
8
+ require_relative 'web/search'
9
+ require_relative 'web/stars'
10
+ require_relative 'web/users'
11
+ require_relative 'error'
12
+
13
+ module Slack
14
+ module Web
15
+ include Auth
16
+ include Channels
17
+ include Chat
18
+ include Emoji
19
+ include Files
20
+ include Groups
21
+ include Im
22
+ include Stars
23
+ include Search
24
+ include Users
25
+
26
+ class NotImplementedError < Exception; end
27
+ end
28
+ end
@@ -0,0 +1,10 @@
1
+ module Slack
2
+ module Web
3
+ module Auth
4
+ def auth_test
5
+ response = @session.do_get "auth.test"
6
+ Slack::parse_response(response)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,82 @@
1
+ module Slack
2
+ module Web
3
+ module Channels
4
+ SCOPE = "channels"
5
+
6
+ # Archives a channel.
7
+ def channels_archive(channel)
8
+ response = @session.do_get "#{SCOPE}.archive", "channel" => channel
9
+ Slack::parse_response(response)
10
+ end
11
+
12
+ # Creates a channel.
13
+ def channels_create(name)
14
+ response = @session.do_get "#{SCOPE}.create", "name" => name
15
+ Slack::parse_response(response)
16
+ end
17
+
18
+ # Fetches history of messages and events from a channel.
19
+ def channels_history(channel, latest, oldest, inclusive, count)
20
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
21
+ end
22
+
23
+ # Gets information about a channel.
24
+ def channels_info(channel)
25
+ response = @session.do_get "#{SCOPE}.info", "channel" => channel
26
+ Slack::parse_response(response)
27
+ end
28
+
29
+ # Invites a user to a channel.
30
+ def channels_invite(channel, user)
31
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
32
+ end
33
+
34
+ # Joins a channel, creating it if needed.
35
+ def channels_join(name)
36
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
37
+ end
38
+
39
+ # Removes a user from a channel.
40
+ def channels_kick(channel, user)
41
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
42
+ end
43
+
44
+ # Leaves a channel.
45
+ def channels_leave(channel)
46
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
47
+ end
48
+
49
+ # Lists all channels in a Slack team.
50
+ def channels_list(exclude_archived=0)
51
+ response = @session.do_get "#{SCOPE}.list", "exclude_archived" => exclude_archived
52
+ Slack::parse_response(response)
53
+ end
54
+
55
+ # Sets the read cursor in a channel.
56
+ def channels_mark(channel, ts)
57
+ raise Slack::Error("Not yet implemented, feel free to make a pull request")
58
+ end
59
+
60
+ # Renames a channel.
61
+ def channels_rename(channel, name)
62
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
63
+ end
64
+
65
+ # Sets the purpose for a channel.
66
+ def channels_set_purpose(channel, purpose)
67
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
68
+ end
69
+
70
+ # Sets the topic for a channel.
71
+ def channels_set_topic(channel, topic)
72
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
73
+ end
74
+
75
+ # Unarchives a channel.
76
+ def channels_unarchive(channel)
77
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,44 @@
1
+ module Slack
2
+ module Web
3
+ module Chat
4
+ SCOPE = "chat"
5
+
6
+ # Deletes a message.
7
+ def chat_delete(ts, channel)
8
+ param = {
9
+ "ts" => ts,
10
+ "channel" => channel
11
+ }
12
+ response = @session.do_get "#{SCOPE}.delete", param
13
+ Slack::parse_response(response)
14
+ end
15
+
16
+ # Sends a message to a channel.
17
+ def chat_post_message(channel, text, username, as_user= false, parse, link_names, attachments)
18
+ param = {
19
+ "channel" => channel,
20
+ "text" => text,
21
+ "username" => username,
22
+ "as_user" => as_user,
23
+ "parse" => parse,
24
+ "link_names" => link_names,
25
+ "attachments" => attachments
26
+ }
27
+ response = @session.do_get "#{SCOPE}.postMessage", param
28
+ Slack::parse_response(response)
29
+ end
30
+
31
+ # Updates a message.
32
+ def chat_update(ts, channel, text)
33
+ param = {
34
+ "ts" => ts,
35
+ "channel" => channel,
36
+ "text" => text
37
+ }
38
+ response = @session.do_get "#{SCOPE}.update", param
39
+ Slack::parse_response(response)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,13 @@
1
+ module Slack
2
+ module Web
3
+ module Emoji
4
+ SCOPE = "emoji"
5
+
6
+ # Lists custom emoji for a team.
7
+ def emoji_list
8
+ response = @session.do_get "#{SCOPE}.list"
9
+ Slack::parse_response(response)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,53 @@
1
+ module Slack
2
+ module Web
3
+ module Files
4
+ SCOPE = "files"
5
+
6
+ #Deletes a file.
7
+ def files_delete(file)
8
+ response = @session.do_get "#{SCOPE}.delete", "file" => file
9
+ Slack::parse_response(response)
10
+ end
11
+
12
+ # Gets information about a team file.
13
+ def files_info(file, count=100, page=1)
14
+ param = {
15
+ "file" => file,
16
+ "count" => count,
17
+ "page" => page
18
+ }
19
+ response = @session.do_get "#{SCOPE}.info", param
20
+ Slack::parse_response(response)
21
+ end
22
+
23
+ # Lists & filters team files.
24
+ def files_list(user, ts_from=0, ts_to=Time.now, types="all", count=100, page=1)
25
+ param = {
26
+ "user" => user,
27
+ "ts_from" => ts_from,
28
+ "ts_to" => ts_to,
29
+ "types" => types,
30
+ "count" => count,
31
+ "page" => page
32
+ }
33
+ response = @session.do_get "#{SCOPE}.list", param
34
+ Slack::parse_response(response)
35
+ end
36
+
37
+ # Uploads or creates a file.
38
+ def files_upload(file, content, filetype, filename, title, initial_comment, channels)
39
+ param = {
40
+ "file" => file,
41
+ "content" => content,
42
+ "filetype" => filetype,
43
+ "filename" => filename,
44
+ "title" => title,
45
+ "initial_comment" => initial_comment,
46
+ "channels" => channels
47
+ }
48
+ response = @session.do_get "#{SCOPE}.upload", param
49
+ Slack::parse_response(response)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,88 @@
1
+ module Slack
2
+ module Web
3
+ module Groups
4
+ SCOPE = "groups"
5
+
6
+ # Archives a private group.
7
+ def groups_archive(channel)
8
+ response = @session.do_get "#{SCOPE}.archive", "channel" => channel
9
+ Slack::parse_response(response)
10
+ end
11
+
12
+ # Closes a private group.
13
+ def groups_close(channel)
14
+ response = @session.do_get "#{SCOPE}.close", "channel" => channel
15
+ Slack::parse_response(response)
16
+ end
17
+
18
+ # Creates a private group.
19
+ def groups_create(name)
20
+ response = @session.do_get "#{SCOPE}.create", "name" => name
21
+ Slack::parse_response(response)
22
+ end
23
+
24
+ # Clones and archives a private group.
25
+ def groups_create_child(channel)
26
+ response = @session.do_get "#{SCOPE}.createChild", "channel" => channel
27
+ Slack::parse_response(response)
28
+ end
29
+
30
+ # Fetches history of messages and events from a private group.
31
+ def groups_history(channel, latest, oldest, inclusive, count)
32
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
33
+ end
34
+
35
+ # Invites a user to a private group.
36
+ def groups_invite(channel, user)
37
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
38
+ end
39
+
40
+ # Removes a user from a private group.
41
+ def groups_kick(channel, user)
42
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
43
+ end
44
+
45
+ # Leaves a private group.
46
+ def groups_leave(channel)
47
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
48
+ end
49
+
50
+ # Lists private groups that the calling user has access to..
51
+ def groups_list(exclude_archived=0)
52
+ response = @session.do_get "#{SCOPE}.list", "exclude_archived" => exclude_archived
53
+ Slack::parse_response(response)
54
+ end
55
+
56
+ # Sets the read cursor in a private group.
57
+ def groups_mark(channel, ts)
58
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
59
+ end
60
+
61
+ # Opens a private group.
62
+ def groups_open(channel)
63
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
64
+ end
65
+
66
+ # Renames a private group.
67
+ def groups_rename(channel, name)
68
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
69
+ end
70
+
71
+ # Sets the purpose for a private group.
72
+ def groups_set_purpose(channel, purpose)
73
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
74
+ end
75
+
76
+ # Sets the topic for a private group.
77
+ def groups_set_topic(channel, topic)
78
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
79
+ end
80
+
81
+ # Unarchives a private group.
82
+ def groups_unarchive(channel)
83
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,34 @@
1
+ module Slack
2
+ module Web
3
+ module Im
4
+ SCOPE = "im"
5
+
6
+ # Close a direct message channel.
7
+ def im_close(channel)
8
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
9
+ end
10
+
11
+ # Fetches history of messages and events from direct message channel.
12
+ def im_history(channel, latest, oldest, inclusive, count)
13
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
14
+ end
15
+
16
+ # Lists direct message channels for the calling user.
17
+ def im_list
18
+ response = @session.do_get "#{SCOPE}.list"
19
+ Slack::parse_response(response)
20
+ end
21
+
22
+ # Sets the read cursor in a direct message channel.
23
+ def im_mark(channel, ts)
24
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
25
+ end
26
+
27
+ # Opens a direct message channel.
28
+ def im_open(user)
29
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ module Slack
2
+ module Web
3
+ module Search
4
+ SCOPE = "search"
5
+
6
+ # Searches for messages and files matching a query.
7
+ def search_all(query, sort, sort_dir, highlight, count, page)
8
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
9
+ end
10
+
11
+ # Searches for files matching a query.
12
+ def search_files(query, sort, sort_dir, highlight, count, page)
13
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
14
+ end
15
+
16
+ # Searches for messages matching a query.
17
+ def search_messages(query, sort, sort_dir, highlight, count, page)
18
+ raise NotImplementedError.new("Not yet implemented, feel free to make a pull request")
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module Slack
2
+ module Web
3
+ module Stars
4
+ SCOPE = "users"
5
+
6
+ # Lists stars for a user.
7
+ def stars_list(user, count, page)
8
+ raise Slack::Error("Not yet implemented, feel free to make a pull request")
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ module Slack
2
+ module Web
3
+ module Users
4
+ SCOPE = "users"
5
+
6
+ # Gets user presence information.
7
+ def users_get_presence(user)
8
+ response = @session.do_get "#{SCOPE}.getPresence", "user" => user
9
+ Slack::parse_response(response)
10
+ end
11
+
12
+ # Gets information about a user.
13
+ def users_info(user)
14
+ response = @session.do_get "#{SCOPE}.info", "user" => user
15
+ Slack::parse_response(response)
16
+ end
17
+
18
+ # Lists all users in a Slack team.
19
+ def users_list
20
+ response = @session.do_get "#{SCOPE}.list"
21
+ Slack::parse_response(response)
22
+ end
23
+
24
+ # Marks a user as active.
25
+ def users_set_active
26
+ response = @session.do_get "#{SCOPE}.setActive"
27
+ Slack::parse_response(response)
28
+ end
29
+
30
+ # Manually sets user presence.
31
+ def users_set_presence(presence)
32
+ response = @session.do_get "#{SCOPE}.setPresence", "presence" => presence
33
+ Slack::parse_response(response)
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'slack/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "slack-api-wrapper"
8
+ spec.version = Slack::VERSION
9
+ spec.authors = ["Gustavo Bazan"]
10
+ spec.email = ["contacto@gustavobazan.com"]
11
+ spec.summary = "Slack API Wrapper"
12
+ spec.description = <<-EOF
13
+ A library that provides a plain function-call interface to the
14
+ Slack API web endpoints.
15
+ EOF
16
+ spec.homepage = ""
17
+ spec.license = "MIT"
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake", '~> 0'
26
+ spec.add_development_dependency "rspec", '~> 3.2', '>= 3.2.0'
27
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slack::Client do
4
+ it 'Initialize' do
5
+ client = Slack::Client.new("")
6
+ expect(client).not_to be nil
7
+ end
8
+ it 'Validates token is string' do
9
+ expect{Slack::Client.new(1)}.to raise_error(ArgumentError)
10
+ end
11
+ it 'Validates unimplemented methods' do
12
+ client = Slack::Client.new("")
13
+ expect{client.groups_open("")}.to raise_error(Slack::Web::NotImplementedError)
14
+ end
15
+ end
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slack::Oauth2 do
4
+ it 'do something' do
5
+ skip
6
+ end
7
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slack do
4
+ it 'has a version number' do
5
+ expect(Slack::VERSION).not_to be nil
6
+ end
7
+
8
+ it 'has web server domain' do
9
+ expect(Slack::WEB_SERVER).to eq('slack.com')
10
+ end
11
+
12
+ it 'has api uri' do
13
+ expect(Slack::API_SERVER).to eq('slack.com/api')
14
+ end
15
+
16
+ describe '::clean_params' do
17
+ let(:params){ {"test_1"=>"test", "test_2" => nil} }
18
+ it 'removes nil params' do
19
+ expect(Slack::clean_params(params)).to eq({"test_1"=>"test"})
20
+ end
21
+ end
22
+
23
+ describe '::make_query_string' do
24
+ let(:params){ {"test_1"=>"test", "test_2" => "test"} }
25
+ it 'transform params to query string' do
26
+ expect(Slack::make_query_string(params)).to eq("test_1=test&test_2=test")
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'slack-api-wrapper'
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slack-api-wrapper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Gustavo Bazan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 3.2.0
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '3.2'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 3.2.0
61
+ description: |2
62
+ A library that provides a plain function-call interface to the
63
+ Slack API web endpoints.
64
+ email:
65
+ - contacto@gustavobazan.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - ".gitignore"
71
+ - ".rspec"
72
+ - ".travis.yml"
73
+ - Gemfile
74
+ - LICENSE.txt
75
+ - README.md
76
+ - Rakefile
77
+ - lib/slack-api-wrapper.rb
78
+ - lib/slack/client.rb
79
+ - lib/slack/error.rb
80
+ - lib/slack/oauth2.rb
81
+ - lib/slack/oauth2/flow.rb
82
+ - lib/slack/oauth2/flow_base.rb
83
+ - lib/slack/session.rb
84
+ - lib/slack/version.rb
85
+ - lib/slack/web.rb
86
+ - lib/slack/web/auth.rb
87
+ - lib/slack/web/channels.rb
88
+ - lib/slack/web/chat.rb
89
+ - lib/slack/web/emoji.rb
90
+ - lib/slack/web/files.rb
91
+ - lib/slack/web/groups.rb
92
+ - lib/slack/web/im.rb
93
+ - lib/slack/web/search.rb
94
+ - lib/slack/web/stars.rb
95
+ - lib/slack/web/users.rb
96
+ - slack-api-wrapper.gemspec
97
+ - spec/slack/client_spec.rb
98
+ - spec/slack/oauth2/flow_base_spec.rb
99
+ - spec/slack/oauth2/flow_spec.rb
100
+ - spec/slack/oauth2_spec.rb
101
+ - spec/slack_spec.rb
102
+ - spec/spec_helper.rb
103
+ homepage: ''
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.4.4
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Slack API Wrapper
127
+ test_files:
128
+ - spec/slack/client_spec.rb
129
+ - spec/slack/oauth2/flow_base_spec.rb
130
+ - spec/slack/oauth2/flow_spec.rb
131
+ - spec/slack/oauth2_spec.rb
132
+ - spec/slack_spec.rb
133
+ - spec/spec_helper.rb