slack-ruby-client 0.4.0 → 0.5.0
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 +4 -4
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +23 -6
- data/.travis.yml +3 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +2 -0
- data/README.md +89 -1
- data/RELEASING.md +3 -1
- data/UPGRADING.md +26 -0
- data/bin/commands.rb +20 -0
- data/bin/commands/api.rb +14 -0
- data/bin/commands/auth.rb +12 -0
- data/bin/commands/channels.rb +140 -0
- data/bin/commands/chat.rb +47 -0
- data/bin/commands/emoji.rb +12 -0
- data/bin/commands/files.rb +61 -0
- data/bin/commands/groups.rb +158 -0
- data/bin/commands/im.rb +53 -0
- data/bin/commands/mpim.rb +53 -0
- data/bin/commands/oauth.rb +16 -0
- data/bin/commands/pins.rb +37 -0
- data/bin/commands/reactions.rb +53 -0
- data/bin/commands/rtm.rb +15 -0
- data/bin/commands/search.rb +40 -0
- data/bin/commands/stars.rb +37 -0
- data/bin/commands/team.rb +32 -0
- data/bin/commands/usergroups.rb +73 -0
- data/bin/commands/users.rb +48 -0
- data/bin/slack +50 -0
- data/examples/hi_real_time/Gemfile +2 -0
- data/examples/hi_real_time_and_web/Gemfile +2 -0
- data/examples/hi_real_time_async/Gemfile +5 -0
- data/examples/hi_real_time_async/hi.rb +29 -0
- data/lib/slack-ruby-client.rb +2 -2
- data/lib/slack/real_time/client.rb +72 -30
- data/lib/slack/real_time/concurrency.rb +8 -0
- data/lib/slack/real_time/concurrency/celluloid.rb +92 -0
- data/lib/slack/real_time/concurrency/eventmachine.rb +39 -0
- data/lib/slack/real_time/config.rb +23 -1
- data/lib/slack/real_time/socket.rb +50 -12
- data/lib/slack/version.rb +1 -1
- data/lib/slack/web/api/endpoints.rb +2 -0
- data/lib/slack/web/api/endpoints/groups.rb +1 -1
- data/lib/slack/web/api/endpoints/team.rb +1 -1
- data/lib/slack/web/api/endpoints/usergroups.rb +113 -0
- data/lib/slack/web/api/error.rb +6 -0
- data/lib/slack/web/api/schema/group.json +14 -0
- data/lib/slack/web/api/tasks/generate.rake +19 -3
- data/lib/slack/web/api/templates/command.erb +34 -0
- data/lib/slack/web/api/templates/commands.erb +5 -0
- data/lib/slack/web/config.rb +2 -0
- data/lib/slack/web/faraday/connection.rb +3 -2
- data/lib/slack/web/faraday/response/raise_error.rb +2 -1
- data/slack-ruby-client.gemspec +4 -2
- data/spec/fixtures/slack/web/429_error.yml +83 -0
- data/spec/fixtures/slack/web/rtm_start.yml +1 -1
- data/spec/fixtures/slack/web/users_list.yml +72 -0
- data/spec/integration/integration_spec.rb +88 -0
- data/spec/slack/real_time/client_spec.rb +8 -5
- data/spec/slack/real_time/concurrency/celluloid_spec.rb +58 -0
- data/spec/slack/real_time/concurrency/eventmachine_spec.rb +49 -0
- data/spec/slack/slack_spec.rb +52 -0
- data/spec/slack/web/api/endpoints/auth_spec.rb +6 -1
- data/spec/slack/web/api/endpoints/users_spec.rb +13 -0
- data/spec/slack/web/api/error_spec.rb +14 -0
- data/spec/slack/web/client_spec.rb +16 -0
- data/spec/support/real_time/concurrency/mock.rb +31 -0
- data/spec/support/real_time/connected_client.rb +5 -2
- metadata +55 -8
- data/spec/slack/real_time/socket_spec.rb +0 -46
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'websocket/driver'
|
2
|
+
require 'socket'
|
3
|
+
require 'forwardable'
|
4
|
+
require 'celluloid/io'
|
5
|
+
|
6
|
+
module Slack
|
7
|
+
module RealTime
|
8
|
+
module Concurrency
|
9
|
+
module Celluloid
|
10
|
+
class Socket < Slack::RealTime::Socket
|
11
|
+
include ::Celluloid::IO
|
12
|
+
include ::Celluloid::Logger
|
13
|
+
|
14
|
+
BLOCK_SIZE = 4096
|
15
|
+
|
16
|
+
extend ::Forwardable
|
17
|
+
def_delegator :socket, :write
|
18
|
+
def_delegators :driver, :text, :binary, :close
|
19
|
+
|
20
|
+
attr_reader :socket
|
21
|
+
|
22
|
+
def initialize(*args)
|
23
|
+
super
|
24
|
+
@driver = build_driver
|
25
|
+
end
|
26
|
+
|
27
|
+
# @yieldparam [WebSocket::Driver] driver
|
28
|
+
def connect!
|
29
|
+
super
|
30
|
+
|
31
|
+
driver.start
|
32
|
+
future.run_loop
|
33
|
+
end
|
34
|
+
|
35
|
+
def run_loop
|
36
|
+
loop { read } if socket
|
37
|
+
rescue EOFError
|
38
|
+
# connection closed
|
39
|
+
end
|
40
|
+
|
41
|
+
def read
|
42
|
+
buffer = socket.readpartial(BLOCK_SIZE)
|
43
|
+
driver.parse buffer
|
44
|
+
end
|
45
|
+
|
46
|
+
def start_async
|
47
|
+
future = yield self if block_given?
|
48
|
+
|
49
|
+
Actor.new(future)
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
class Actor
|
55
|
+
attr_reader :future
|
56
|
+
|
57
|
+
def initialize(future)
|
58
|
+
@future = future
|
59
|
+
end
|
60
|
+
|
61
|
+
def join
|
62
|
+
@future.value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def connected?
|
67
|
+
!@connected.nil?
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_socket
|
71
|
+
socket = TCPSocket.new(addr, port)
|
72
|
+
socket = SSLSocket.new(socket, build_ssl_context) if secure?
|
73
|
+
socket
|
74
|
+
end
|
75
|
+
|
76
|
+
def build_ssl_context
|
77
|
+
OpenSSL::SSL::SSLContext.new(:TLSv1_2_client)
|
78
|
+
end
|
79
|
+
|
80
|
+
def build_driver
|
81
|
+
::WebSocket::Driver.client(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
def connect
|
85
|
+
@socket = build_socket
|
86
|
+
@connected = @socket.connect
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'faye/websocket'
|
2
|
+
require 'eventmachine'
|
3
|
+
|
4
|
+
module Slack
|
5
|
+
module RealTime
|
6
|
+
module Concurrency
|
7
|
+
module Eventmachine
|
8
|
+
class Socket < Slack::RealTime::Socket
|
9
|
+
def start_async
|
10
|
+
thread = ensure_reactor_running
|
11
|
+
|
12
|
+
yield self if block_given?
|
13
|
+
|
14
|
+
thread
|
15
|
+
end
|
16
|
+
|
17
|
+
def send_data(message)
|
18
|
+
driver.send(message)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
# @return [Thread]
|
24
|
+
def ensure_reactor_running
|
25
|
+
return if EventMachine.reactor_running?
|
26
|
+
|
27
|
+
reactor = Thread.new { EventMachine.run }
|
28
|
+
Thread.pass until EventMachine.reactor_running?
|
29
|
+
reactor
|
30
|
+
end
|
31
|
+
|
32
|
+
def connect
|
33
|
+
@driver = ::Faye::WebSocket::Client.new(url, nil, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module Slack
|
2
2
|
module RealTime
|
3
3
|
module Config
|
4
|
+
class NoConcurrencyError < StandardError; end
|
5
|
+
|
4
6
|
extend self
|
5
7
|
|
6
8
|
ATTRIBUTES = [
|
7
9
|
:token,
|
8
10
|
:websocket_ping,
|
9
|
-
:websocket_proxy
|
11
|
+
:websocket_proxy,
|
12
|
+
:concurrency
|
10
13
|
]
|
11
14
|
|
12
15
|
attr_accessor(*Config::ATTRIBUTES)
|
@@ -15,6 +18,25 @@ module Slack
|
|
15
18
|
self.websocket_ping = 30
|
16
19
|
self.websocket_proxy = nil
|
17
20
|
self.token = nil
|
21
|
+
self.concurrency = method(:detect_concurrency)
|
22
|
+
end
|
23
|
+
|
24
|
+
def concurrency
|
25
|
+
(val = @concurrency).respond_to?(:call) ? val.call : val
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def detect_concurrency
|
31
|
+
[:Eventmachine, :Celluloid].each do |concurrency|
|
32
|
+
begin
|
33
|
+
return Slack::RealTime::Concurrency.const_get(concurrency)
|
34
|
+
rescue LoadError
|
35
|
+
false # could not be loaded, missing dependencies
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
fail NoConcurrencyError, 'Missing concurrency. Add faye-websocket or celluloid-io to your Gemfile.'
|
18
40
|
end
|
19
41
|
end
|
20
42
|
|
@@ -3,40 +3,78 @@ module Slack
|
|
3
3
|
class Socket
|
4
4
|
attr_accessor :url
|
5
5
|
attr_accessor :options
|
6
|
+
attr_reader :driver
|
6
7
|
|
7
8
|
def initialize(url, options = {})
|
8
9
|
@url = url
|
9
10
|
@options = options
|
11
|
+
@driver = nil
|
10
12
|
end
|
11
13
|
|
12
|
-
def send_data(
|
13
|
-
|
14
|
+
def send_data(message)
|
15
|
+
case message
|
16
|
+
when Numeric then driver.text(message.to_s)
|
17
|
+
when String then driver.text(message)
|
18
|
+
when Array then driver.binary(message)
|
19
|
+
else false
|
20
|
+
end
|
14
21
|
end
|
15
22
|
|
16
|
-
def connect!
|
23
|
+
def connect!
|
17
24
|
return if connected?
|
18
25
|
|
19
|
-
|
20
|
-
|
21
|
-
@ws.on :close do |event|
|
22
|
-
close(event)
|
23
|
-
end
|
26
|
+
connect
|
24
27
|
|
25
|
-
yield
|
28
|
+
yield driver if block_given?
|
26
29
|
end
|
27
30
|
|
28
31
|
def disconnect!
|
29
|
-
|
32
|
+
driver.close
|
30
33
|
end
|
31
34
|
|
32
35
|
def connected?
|
33
|
-
|
36
|
+
!driver.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_sync(&block)
|
40
|
+
thread = start_async(&block)
|
41
|
+
thread.join if thread
|
42
|
+
rescue Interrupt
|
43
|
+
thread.exit if thread
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [#join]
|
47
|
+
def start_async
|
48
|
+
fail NotImplementedError, "Expected #{self.class} to implement #{__method__}."
|
34
49
|
end
|
35
50
|
|
36
51
|
protected
|
37
52
|
|
53
|
+
def addr
|
54
|
+
URI(url).host
|
55
|
+
end
|
56
|
+
|
57
|
+
def secure?
|
58
|
+
port == URI::HTTPS::DEFAULT_PORT
|
59
|
+
end
|
60
|
+
|
61
|
+
def port
|
62
|
+
case (uri = URI(url)).scheme
|
63
|
+
when 'wss'.freeze, 'https'.freeze
|
64
|
+
URI::HTTPS::DEFAULT_PORT
|
65
|
+
when 'ws', 'http'.freeze
|
66
|
+
URI::HTTP::DEFAULT_PORT
|
67
|
+
else
|
68
|
+
uri.port
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def connect
|
73
|
+
fail NotImplementedError, "Expected #{self.class} to implement #{__method__}."
|
74
|
+
end
|
75
|
+
|
38
76
|
def close(_event)
|
39
|
-
@
|
77
|
+
@driver = nil
|
40
78
|
end
|
41
79
|
end
|
42
80
|
end
|
data/lib/slack/version.rb
CHANGED
@@ -16,6 +16,7 @@ require 'slack/web/api/endpoints/rtm'
|
|
16
16
|
require 'slack/web/api/endpoints/search'
|
17
17
|
require 'slack/web/api/endpoints/stars'
|
18
18
|
require 'slack/web/api/endpoints/team'
|
19
|
+
require 'slack/web/api/endpoints/usergroups'
|
19
20
|
require 'slack/web/api/endpoints/users'
|
20
21
|
|
21
22
|
module Slack
|
@@ -38,6 +39,7 @@ module Slack
|
|
38
39
|
include Search
|
39
40
|
include Stars
|
40
41
|
include Team
|
42
|
+
include Usergroups
|
41
43
|
include Users
|
42
44
|
end
|
43
45
|
end
|
@@ -21,7 +21,7 @@ module Slack
|
|
21
21
|
# This method closes a private group.
|
22
22
|
#
|
23
23
|
# @option options [group] :channel
|
24
|
-
# Group to
|
24
|
+
# Group to close.
|
25
25
|
# @see https://api.slack.com/methods/groups.close
|
26
26
|
# @see https://github.com/dblock/slack-api-ref/blob/master/methods/groups.close.json
|
27
27
|
def groups_close(options = {})
|
@@ -31,7 +31,7 @@ module Slack
|
|
31
31
|
# @option options [Object] :app_id
|
32
32
|
# Filter logs to this API application. Defaults to all logs.
|
33
33
|
# @option options [user] :user
|
34
|
-
# Filter logs generated by this user
|
34
|
+
# Filter logs generated by this user's actions. Defaults to all logs.
|
35
35
|
# @option options [Object] :change_type
|
36
36
|
# Filter logs with this change type. Defaults to all logs.
|
37
37
|
# @see https://api.slack.com/methods/team.integrationLogs
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# This file was auto-generated by lib/slack/web/api/tasks/generate.rake
|
2
|
+
|
3
|
+
module Slack
|
4
|
+
module Web
|
5
|
+
module Api
|
6
|
+
module Endpoints
|
7
|
+
module Usergroups
|
8
|
+
#
|
9
|
+
# This method is used to create a user group.
|
10
|
+
#
|
11
|
+
# @option options [Object] :name
|
12
|
+
# A name for the user group. Must be unique among user groups.
|
13
|
+
# @option options [Object] :handle
|
14
|
+
# A mention handle. Must be unique among channels, users and user groups.
|
15
|
+
# @option options [Object] :description
|
16
|
+
# A short description of the user group.
|
17
|
+
# @option options [Object] :channels
|
18
|
+
# A comma separated string of encoded channel IDs for which the user group uses as a default.
|
19
|
+
# @option options [Object] :include_count
|
20
|
+
# Include the number of users in each user group.
|
21
|
+
# @see https://api.slack.com/methods/usergroups.create
|
22
|
+
# @see https://github.com/dblock/slack-api-ref/blob/master/methods/usergroups.create.json
|
23
|
+
def usergroups_create(options = {})
|
24
|
+
throw ArgumentError.new('Required arguments :name missing') if options[:name].nil?
|
25
|
+
post('usergroups.create', options)
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# This method disables an existing user group.
|
30
|
+
#
|
31
|
+
# @option options [Object] :usergroup
|
32
|
+
# The encoded ID of the user group to disable.
|
33
|
+
# @option options [Object] :include_count
|
34
|
+
# Include the number of users in the user group.
|
35
|
+
# @see https://api.slack.com/methods/usergroups.disable
|
36
|
+
# @see https://github.com/dblock/slack-api-ref/blob/master/methods/usergroups.disable.json
|
37
|
+
def usergroups_disable(options = {})
|
38
|
+
throw ArgumentError.new('Required arguments :usergroup missing') if options[:usergroup].nil?
|
39
|
+
post('usergroups.disable', options)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# This method enables a user group which was previously disabled.
|
44
|
+
#
|
45
|
+
# @option options [Object] :usergroup
|
46
|
+
# The encoded ID of the user group to enable.
|
47
|
+
# @option options [Object] :include_count
|
48
|
+
# Include the number of users in the user group.
|
49
|
+
# @see https://api.slack.com/methods/usergroups.enable
|
50
|
+
# @see https://github.com/dblock/slack-api-ref/blob/master/methods/usergroups.enable.json
|
51
|
+
def usergroups_enable(options = {})
|
52
|
+
throw ArgumentError.new('Required arguments :usergroup missing') if options[:usergroup].nil?
|
53
|
+
post('usergroups.enable', options)
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# This method returns a list of all user groups in the team. This can optionally include disabled user groups.
|
58
|
+
#
|
59
|
+
# @option options [Object] :include_disabled
|
60
|
+
# Include disabled user groups.
|
61
|
+
# @option options [Object] :include_count
|
62
|
+
# Include the number of users in each user group.
|
63
|
+
# @option options [Object] :include_users
|
64
|
+
# Include the list of users for each user group.
|
65
|
+
# @see https://api.slack.com/methods/usergroups.list
|
66
|
+
# @see https://github.com/dblock/slack-api-ref/blob/master/methods/usergroups.list.json
|
67
|
+
def usergroups_list(options = {})
|
68
|
+
post('usergroups.list', options)
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# This method updates the properties of an existing user group.
|
73
|
+
#
|
74
|
+
# @option options [Object] :usergroup
|
75
|
+
# The encoded ID of the user group to update.
|
76
|
+
# @option options [Object] :name
|
77
|
+
# A name for the user group. Must be unique among user groups.
|
78
|
+
# @option options [Object] :handle
|
79
|
+
# A mention handle. Must be unique among channels, users and user groups.
|
80
|
+
# @option options [Object] :description
|
81
|
+
# A short description of the user group.
|
82
|
+
# @option options [Object] :channels
|
83
|
+
# A comma separated string of encoded channel IDs for which the user group uses as a default.
|
84
|
+
# @option options [Object] :include_count
|
85
|
+
# Include the number of users in the user group.
|
86
|
+
# @see https://api.slack.com/methods/usergroups.update
|
87
|
+
# @see https://github.com/dblock/slack-api-ref/blob/master/methods/usergroups.update.json
|
88
|
+
def usergroups_update(options = {})
|
89
|
+
throw ArgumentError.new('Required arguments :usergroup missing') if options[:usergroup].nil?
|
90
|
+
post('usergroups.update', options)
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# This method updates the list of users that belong to a user group. This method replaces all users in a user group with the list of users provided in the users parameter.
|
95
|
+
#
|
96
|
+
# @option options [Object] :usergroup
|
97
|
+
# The encoded ID of the user group to update.
|
98
|
+
# @option options [Object] :users
|
99
|
+
# A comma separated string of encoded user IDs that represent the entire list of users for the user group.
|
100
|
+
# @option options [Object] :include_count
|
101
|
+
# Include the number of users in the user group.
|
102
|
+
# @see https://api.slack.com/methods/usergroups.users
|
103
|
+
# @see https://github.com/dblock/slack-api-ref/blob/master/methods/usergroups.users.json
|
104
|
+
def usergroups_users(options = {})
|
105
|
+
throw ArgumentError.new('Required arguments :usergroup missing') if options[:usergroup].nil?
|
106
|
+
throw ArgumentError.new('Required arguments :users missing') if options[:users].nil?
|
107
|
+
post('usergroups.users', options)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/slack/web/api/error.rb
CHANGED