slack-ruby-client-bhe 0.5.4
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 +17 -0
- data/.gitignore +4 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +6 -0
- data/.rubocop_todo.yml +78 -0
- data/.travis.yml +26 -0
- data/CHANGELOG.md +79 -0
- data/CONTRIBUTING.md +157 -0
- data/Gemfile +5 -0
- data/LICENSE.md +22 -0
- data/README.md +385 -0
- data/RELEASING.md +69 -0
- data/Rakefile +19 -0
- data/UPGRADING.md +26 -0
- data/bin/commands.rb +21 -0
- data/bin/commands/api.rb +14 -0
- data/bin/commands/auth.rb +12 -0
- data/bin/commands/channels.rb +149 -0
- data/bin/commands/chat.rb +47 -0
- data/bin/commands/dnd.rb +47 -0
- data/bin/commands/emoji.rb +12 -0
- data/bin/commands/files.rb +72 -0
- data/bin/commands/groups.rb +167 -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 +57 -0
- data/bin/slack +50 -0
- data/examples/hi_real_time/Gemfile +5 -0
- data/examples/hi_real_time/hi.gif +0 -0
- data/examples/hi_real_time/hi.rb +32 -0
- data/examples/hi_real_time_and_web/Gemfile +5 -0
- data/examples/hi_real_time_and_web/hi.gif +0 -0
- data/examples/hi_real_time_and_web/hi.rb +24 -0
- data/examples/hi_real_time_async/Gemfile +5 -0
- data/examples/hi_real_time_async/hi.rb +29 -0
- data/examples/hi_web/Gemfile +3 -0
- data/examples/hi_web/hi.gif +0 -0
- data/examples/hi_web/hi.rb +12 -0
- data/examples/new_ticket/Gemfile +3 -0
- data/examples/new_ticket/new_ticket.rb +25 -0
- data/lib/slack-ruby-client.rb +29 -0
- data/lib/slack.rb +1 -0
- data/lib/slack/config.rb +21 -0
- data/lib/slack/messages/formatting.rb +30 -0
- data/lib/slack/real_time/api/message.rb +20 -0
- data/lib/slack/real_time/api/message_id.rb +14 -0
- data/lib/slack/real_time/api/ping.rb +16 -0
- data/lib/slack/real_time/api/typing.rb +17 -0
- data/lib/slack/real_time/client.rb +152 -0
- data/lib/slack/real_time/concurrency.rb +8 -0
- data/lib/slack/real_time/concurrency/celluloid.rb +93 -0
- data/lib/slack/real_time/concurrency/eventmachine.rb +39 -0
- data/lib/slack/real_time/config.rb +55 -0
- data/lib/slack/real_time/socket.rb +81 -0
- data/lib/slack/version.rb +3 -0
- data/lib/slack/web/api/endpoints.rb +53 -0
- data/lib/slack/web/api/endpoints/api.rb +24 -0
- data/lib/slack/web/api/endpoints/auth.rb +20 -0
- data/lib/slack/web/api/endpoints/channels.rb +220 -0
- data/lib/slack/web/api/endpoints/chat.rb +91 -0
- data/lib/slack/web/api/endpoints/dnd.rb +64 -0
- data/lib/slack/web/api/endpoints/emoji.rb +20 -0
- data/lib/slack/web/api/endpoints/files.rb +108 -0
- data/lib/slack/web/api/endpoints/groups.rb +247 -0
- data/lib/slack/web/api/endpoints/im.rb +85 -0
- data/lib/slack/web/api/endpoints/mpim.rb +84 -0
- data/lib/slack/web/api/endpoints/oauth.rb +32 -0
- data/lib/slack/web/api/endpoints/pins.rb +64 -0
- data/lib/slack/web/api/endpoints/presence.rb +23 -0
- data/lib/slack/web/api/endpoints/reactions.rb +89 -0
- data/lib/slack/web/api/endpoints/rtm.rb +27 -0
- data/lib/slack/web/api/endpoints/search.rb +65 -0
- data/lib/slack/web/api/endpoints/stars.rb +61 -0
- data/lib/slack/web/api/endpoints/team.rb +47 -0
- data/lib/slack/web/api/endpoints/usergroups.rb +113 -0
- data/lib/slack/web/api/endpoints/users.rb +73 -0
- data/lib/slack/web/api/error.rb +14 -0
- data/lib/slack/web/api/mixins.rb +3 -0
- data/lib/slack/web/api/mixins/channels.id.json +20 -0
- data/lib/slack/web/api/mixins/channels.id.rb +26 -0
- data/lib/slack/web/api/mixins/groups.id.json +20 -0
- data/lib/slack/web/api/mixins/groups.id.rb +26 -0
- data/lib/slack/web/api/mixins/users.id.json +20 -0
- data/lib/slack/web/api/mixins/users.id.rb +26 -0
- data/lib/slack/web/api/patches/chat.1.text-attachments-required.patch +13 -0
- data/lib/slack/web/api/patches/chat.2.attachments-json.patch +17 -0
- data/lib/slack/web/api/schema/group.json +14 -0
- data/lib/slack/web/api/schema/method.json +45 -0
- data/lib/slack/web/api/tasks/generate.rake +61 -0
- data/lib/slack/web/api/templates/command.erb +34 -0
- data/lib/slack/web/api/templates/commands.erb +5 -0
- data/lib/slack/web/api/templates/endpoints.erb +21 -0
- data/lib/slack/web/api/templates/method.erb +49 -0
- data/lib/slack/web/client.rb +28 -0
- data/lib/slack/web/config.rb +41 -0
- data/lib/slack/web/faraday/connection.rb +29 -0
- data/lib/slack/web/faraday/request.rb +39 -0
- data/lib/slack/web/faraday/response/raise_error.rb +15 -0
- data/lib/slack_ruby_client.rb +1 -0
- data/screenshots/register-bot.png +0 -0
- data/slack-ruby-client.gemspec +31 -0
- data/slack.png +0 -0
- data/spec/fixtures/slack/web/429_error.yml +83 -0
- data/spec/fixtures/slack/web/auth_test_error.yml +48 -0
- data/spec/fixtures/slack/web/auth_test_success.yml +57 -0
- data/spec/fixtures/slack/web/channels_info.yml +46 -0
- data/spec/fixtures/slack/web/groups_info.yml +43 -0
- data/spec/fixtures/slack/web/rtm_start.yml +73 -0
- data/spec/fixtures/slack/web/users_info.yml +130 -0
- data/spec/fixtures/slack/web/users_list.yml +72 -0
- data/spec/integration/integration_spec.rb +107 -0
- data/spec/slack/config_spec.rb +14 -0
- data/spec/slack/messages/formatting_spec.rb +43 -0
- data/spec/slack/real_time/api/message_spec.rb +15 -0
- data/spec/slack/real_time/api/ping_spec.rb +15 -0
- data/spec/slack/real_time/api/typing_spec.rb +15 -0
- data/spec/slack/real_time/client_spec.rb +198 -0
- 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 +58 -0
- data/spec/slack/version_spec.rb +7 -0
- data/spec/slack/web/api/endpoints/auth_spec.rb +20 -0
- data/spec/slack/web/api/endpoints/channels_spec.rb +11 -0
- data/spec/slack/web/api/endpoints/chat_spec.rb +33 -0
- data/spec/slack/web/api/endpoints/groups_spec.rb +11 -0
- data/spec/slack/web/api/endpoints/users_spec.rb +17 -0
- data/spec/slack/web/api/error_spec.rb +14 -0
- data/spec/slack/web/api/mixins/channels_spec.rb +31 -0
- data/spec/slack/web/api/mixins/groups_spec.rb +31 -0
- data/spec/slack/web/api/mixins/users_spec.rb +31 -0
- data/spec/slack/web/client_spec.rb +134 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/queue_with_timeout.rb +34 -0
- data/spec/support/real_time/concurrency/mock.rb +31 -0
- data/spec/support/real_time/connected_client.rb +16 -0
- data/spec/support/token.rb +10 -0
- data/spec/support/vcr.rb +8 -0
- metadata +392 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Slack
|
|
2
|
+
module RealTime
|
|
3
|
+
module Api
|
|
4
|
+
module Message
|
|
5
|
+
#
|
|
6
|
+
# Sends a message to a channel.
|
|
7
|
+
#
|
|
8
|
+
# @option options [channel] :channel
|
|
9
|
+
# Channel to send message to. Can be a public channel, private group or IM channel. Can be an encoded ID, or a name.
|
|
10
|
+
# @option options [Object] :text
|
|
11
|
+
# Text of the message to send. See below for an explanation of formatting.
|
|
12
|
+
def message(options = {})
|
|
13
|
+
throw ArgumentError.new('Required arguments :channel missing') if options[:channel].nil?
|
|
14
|
+
throw ArgumentError.new('Required arguments :text missing') if options[:text].nil?
|
|
15
|
+
send_json({ type: 'message', id: next_id }.merge(options))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Slack
|
|
2
|
+
module RealTime
|
|
3
|
+
module Api
|
|
4
|
+
module Ping
|
|
5
|
+
#
|
|
6
|
+
# Clients should try to quickly detect disconnections, even in idle periods, so that users can easily tell the
|
|
7
|
+
# difference between being disconnected and everyone being quiet. Not all web browsers support the WebSocket
|
|
8
|
+
# ping spec, so the RTM protocol also supports ping/pong messages.
|
|
9
|
+
#
|
|
10
|
+
def ping(options = {})
|
|
11
|
+
send_json({ type: 'ping', id: next_id }.merge(options))
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Slack
|
|
2
|
+
module RealTime
|
|
3
|
+
module Api
|
|
4
|
+
module Typing
|
|
5
|
+
#
|
|
6
|
+
# Send a typing indicator to indicate that the user is currently writing a message.
|
|
7
|
+
#
|
|
8
|
+
# @option options [channel] :channel
|
|
9
|
+
# Channel to send message to. Can be a public channel, private group or IM channel. Can be an encoded ID, or a name.
|
|
10
|
+
def typing(options = {})
|
|
11
|
+
throw ArgumentError.new('Required arguments :channel missing') if options[:channel].nil?
|
|
12
|
+
send_json({ type: 'typing', id: next_id }.merge(options))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
module Slack
|
|
2
|
+
module RealTime
|
|
3
|
+
class Client
|
|
4
|
+
class ClientNotStartedError < StandardError; end
|
|
5
|
+
class ClientAlreadyStartedError < StandardError; end
|
|
6
|
+
|
|
7
|
+
include Api::MessageId
|
|
8
|
+
include Api::Ping
|
|
9
|
+
include Api::Message
|
|
10
|
+
include Api::Typing
|
|
11
|
+
|
|
12
|
+
attr_accessor :web_client
|
|
13
|
+
attr_accessor(*Config::ATTRIBUTES)
|
|
14
|
+
|
|
15
|
+
def initialize(options = {})
|
|
16
|
+
@callbacks = Hash.new { |h, k| h[k] = [] }
|
|
17
|
+
Slack::RealTime::Config::ATTRIBUTES.each do |key|
|
|
18
|
+
send("#{key}=", options[key] || Slack::RealTime.config.send(key))
|
|
19
|
+
end
|
|
20
|
+
@token ||= Slack.config.token
|
|
21
|
+
@web_client = Slack::Web::Client.new(token: token)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
[:url, :team, :self, :users, :channels, :groups, :ims, :bots].each do |attr|
|
|
25
|
+
define_method attr do
|
|
26
|
+
@options[attr.to_s] if @options
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def on(type, &block)
|
|
31
|
+
type = type.to_s
|
|
32
|
+
callbacks[type] << block
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Start RealTime client and block until it disconnects.
|
|
36
|
+
# @yieldparam [Websocket::Driver] driver
|
|
37
|
+
def start!(&block)
|
|
38
|
+
socket = build_socket
|
|
39
|
+
socket.start_sync { run_loop(socket, &block) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Start RealTime client and return immediately.
|
|
43
|
+
# The RealTime::Client will run in the background.
|
|
44
|
+
# @yieldparam [Websocket::Driver] driver
|
|
45
|
+
def start_async(&block)
|
|
46
|
+
socket = build_socket
|
|
47
|
+
socket.start_async { run_loop(socket, &block) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def stop!
|
|
51
|
+
fail ClientNotStartedError unless started?
|
|
52
|
+
@socket.disconnect! if @socket
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def started?
|
|
56
|
+
@socket && @socket.connected?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class << self
|
|
60
|
+
def configure
|
|
61
|
+
block_given? ? yield(config) : config
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def config
|
|
65
|
+
Config
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
protected
|
|
70
|
+
|
|
71
|
+
# @return [Slack::RealTime::Socket]
|
|
72
|
+
def build_socket
|
|
73
|
+
fail ClientAlreadyStartedError if started?
|
|
74
|
+
@options = web_client.rtm_start
|
|
75
|
+
|
|
76
|
+
socket_class.new(@options.fetch('url'), socket_options)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def socket_options
|
|
80
|
+
socket_options = {}
|
|
81
|
+
socket_options[:ping] = websocket_ping if websocket_ping
|
|
82
|
+
socket_options[:proxy] = websocket_proxy if websocket_proxy
|
|
83
|
+
socket_options
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def run_loop(socket)
|
|
87
|
+
@socket = socket
|
|
88
|
+
|
|
89
|
+
@socket.connect! do |driver|
|
|
90
|
+
yield driver if block_given?
|
|
91
|
+
|
|
92
|
+
driver.on :open do |event|
|
|
93
|
+
open(event)
|
|
94
|
+
callback(event, :open)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
driver.on :message do |event|
|
|
98
|
+
dispatch(event)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
driver.on :close do |event|
|
|
102
|
+
callback(event, :close)
|
|
103
|
+
close(event)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
attr_reader :callbacks
|
|
109
|
+
def socket_class
|
|
110
|
+
concurrency::Socket
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def send_json(data)
|
|
114
|
+
fail ClientNotStartedError unless started?
|
|
115
|
+
@socket.send_data(data.to_json)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def open(_event)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def close(_event)
|
|
122
|
+
socket = @socket
|
|
123
|
+
@socket = nil
|
|
124
|
+
|
|
125
|
+
[socket, socket_class].each do |s|
|
|
126
|
+
s.close if s.respond_to?(:close)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def callback(event, type)
|
|
131
|
+
callbacks = self.callbacks[type.to_s]
|
|
132
|
+
return false unless callbacks
|
|
133
|
+
callbacks.each do |c|
|
|
134
|
+
c.call(event)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def dispatch(event)
|
|
139
|
+
return false unless event.data
|
|
140
|
+
data = JSON.parse(event.data)
|
|
141
|
+
type = data['type']
|
|
142
|
+
return false unless type
|
|
143
|
+
callbacks = self.callbacks[type.to_s]
|
|
144
|
+
return false unless callbacks
|
|
145
|
+
callbacks.each do |c|
|
|
146
|
+
c.call(data)
|
|
147
|
+
end
|
|
148
|
+
true
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require 'websocket/driver'
|
|
2
|
+
require 'socket'
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
require 'celluloid/current'
|
|
5
|
+
require 'celluloid/io'
|
|
6
|
+
|
|
7
|
+
module Slack
|
|
8
|
+
module RealTime
|
|
9
|
+
module Concurrency
|
|
10
|
+
module Celluloid
|
|
11
|
+
class Socket < Slack::RealTime::Socket
|
|
12
|
+
include ::Celluloid::IO
|
|
13
|
+
include ::Celluloid::Internals::Logger
|
|
14
|
+
|
|
15
|
+
BLOCK_SIZE = 4096
|
|
16
|
+
|
|
17
|
+
extend ::Forwardable
|
|
18
|
+
def_delegator :socket, :write
|
|
19
|
+
def_delegators :driver, :text, :binary, :close
|
|
20
|
+
|
|
21
|
+
attr_reader :socket
|
|
22
|
+
|
|
23
|
+
def initialize(*args)
|
|
24
|
+
super
|
|
25
|
+
@driver = build_driver
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @yieldparam [WebSocket::Driver] driver
|
|
29
|
+
def connect!
|
|
30
|
+
super
|
|
31
|
+
|
|
32
|
+
driver.start
|
|
33
|
+
future.run_loop
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def run_loop
|
|
37
|
+
loop { read } if socket
|
|
38
|
+
rescue EOFError
|
|
39
|
+
# connection closed
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def read
|
|
43
|
+
buffer = socket.readpartial(BLOCK_SIZE)
|
|
44
|
+
driver.parse buffer
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def start_async
|
|
48
|
+
future = yield self if block_given?
|
|
49
|
+
|
|
50
|
+
Actor.new(future)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def connected?
|
|
54
|
+
!@connected.nil?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
class Actor
|
|
60
|
+
attr_reader :future
|
|
61
|
+
|
|
62
|
+
def initialize(future)
|
|
63
|
+
@future = future
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def join
|
|
67
|
+
@future.value
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def build_socket
|
|
72
|
+
socket = TCPSocket.new(addr, port)
|
|
73
|
+
socket = SSLSocket.new(socket, build_ssl_context) if secure?
|
|
74
|
+
socket
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def build_ssl_context
|
|
78
|
+
OpenSSL::SSL::SSLContext.new(:TLSv1_2_client)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def build_driver
|
|
82
|
+
::WebSocket::Driver.client(self)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def connect
|
|
86
|
+
@socket = build_socket
|
|
87
|
+
@connected = @socket.connect
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
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
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Slack
|
|
2
|
+
module RealTime
|
|
3
|
+
module Config
|
|
4
|
+
class NoConcurrencyError < StandardError; end
|
|
5
|
+
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
ATTRIBUTES = [
|
|
9
|
+
:token,
|
|
10
|
+
:websocket_ping,
|
|
11
|
+
:websocket_proxy,
|
|
12
|
+
:concurrency
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
attr_accessor(*Config::ATTRIBUTES)
|
|
16
|
+
|
|
17
|
+
def reset
|
|
18
|
+
self.websocket_ping = 30
|
|
19
|
+
self.websocket_proxy = nil
|
|
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, NameError
|
|
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.'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class << self
|
|
44
|
+
def configure
|
|
45
|
+
block_given? ? yield(Config) : Config
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def config
|
|
49
|
+
Config
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Slack::RealTime::Config.reset
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Slack
|
|
2
|
+
module RealTime
|
|
3
|
+
class Socket
|
|
4
|
+
attr_accessor :url
|
|
5
|
+
attr_accessor :options
|
|
6
|
+
attr_reader :driver
|
|
7
|
+
|
|
8
|
+
def initialize(url, options = {})
|
|
9
|
+
@url = url
|
|
10
|
+
@options = options
|
|
11
|
+
@driver = nil
|
|
12
|
+
end
|
|
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
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def connect!
|
|
24
|
+
return if connected?
|
|
25
|
+
|
|
26
|
+
connect
|
|
27
|
+
|
|
28
|
+
yield driver if block_given?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def disconnect!
|
|
32
|
+
driver.close
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def connected?
|
|
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__}."
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def close(_event)
|
|
52
|
+
@driver = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
protected
|
|
56
|
+
|
|
57
|
+
def addr
|
|
58
|
+
URI(url).host
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def secure?
|
|
62
|
+
port == URI::HTTPS::DEFAULT_PORT
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def port
|
|
66
|
+
case (uri = URI(url)).scheme
|
|
67
|
+
when 'wss'.freeze, 'https'.freeze
|
|
68
|
+
URI::HTTPS::DEFAULT_PORT
|
|
69
|
+
when 'ws', 'http'.freeze
|
|
70
|
+
URI::HTTP::DEFAULT_PORT
|
|
71
|
+
else
|
|
72
|
+
uri.port
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def connect
|
|
77
|
+
fail NotImplementedError, "Expected #{self.class} to implement #{__method__}."
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|