slack-ruby-client 2.6.0 → 3.0.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/.github/workflows/test.yml +4 -10
- data/.github/workflows/update_api.yml +1 -1
- data/.rubocop_todo.yml +58 -71
- data/CHANGELOG.md +15 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +0 -9
- data/LICENSE.md +1 -1
- data/README.md +31 -220
- data/Rakefile +0 -1
- data/UPGRADING.md +4 -0
- data/bin/commands/admin_analytics.rb +1 -1
- data/bin/commands/admin_apps.rb +4 -4
- data/bin/commands/admin_apps_activities.rb +7 -7
- data/bin/commands/admin_apps_approved.rb +4 -4
- data/bin/commands/admin_apps_config.rb +3 -1
- data/bin/commands/admin_apps_requests.rb +5 -5
- data/bin/commands/admin_apps_restricted.rb +4 -4
- data/bin/commands/admin_audit_anomaly_allow.rb +6 -6
- data/bin/commands/admin_auth_policy.rb +5 -5
- data/bin/commands/admin_barriers.rb +3 -3
- data/bin/commands/admin_conversations.rb +15 -15
- data/bin/commands/admin_conversations_ekm.rb +2 -2
- data/bin/commands/admin_conversations_restrictAccess.rb +5 -5
- data/bin/commands/admin_emoji.rb +5 -5
- data/bin/commands/admin_functions.rb +1 -1
- data/bin/commands/admin_inviteRequests.rb +3 -3
- data/bin/commands/admin_inviteRequests_approved.rb +1 -1
- data/bin/commands/admin_inviteRequests_denied.rb +1 -1
- data/bin/commands/admin_roles.rb +3 -3
- data/bin/commands/admin_teams.rb +3 -3
- data/bin/commands/admin_teams_admins.rb +2 -2
- data/bin/commands/admin_teams_owners.rb +2 -2
- data/bin/commands/admin_teams_settings.rb +5 -5
- data/bin/commands/admin_usergroups.rb +4 -4
- data/bin/commands/admin_users.rb +12 -11
- data/bin/commands/admin_users_session.rb +6 -5
- data/bin/commands/admin_users_unsupportedVersions.rb +1 -1
- data/bin/commands/admin_workflows.rb +6 -6
- data/bin/commands/admin_workflows_collaborators.rb +2 -2
- data/bin/commands/apps_activities.rb +7 -7
- data/bin/commands/apps_auth_external.rb +1 -1
- data/bin/commands/apps_datastore.rb +12 -12
- data/bin/commands/apps_event_authorizations.rb +3 -3
- data/bin/commands/apps_manifest.rb +1 -1
- data/bin/commands/assistant_search.rb +18 -2
- data/bin/commands/assistant_threads.rb +2 -2
- data/bin/commands/auth.rb +1 -1
- data/bin/commands/auth_teams.rb +1 -1
- data/bin/commands/bookmarks.rb +6 -6
- data/bin/commands/calls.rb +5 -5
- data/bin/commands/canvases.rb +2 -2
- data/bin/commands/canvases_access.rb +1 -1
- data/bin/commands/chat.rb +23 -24
- data/bin/commands/conversations.rb +8 -8
- data/bin/commands/conversations_canvases.rb +1 -1
- data/bin/commands/conversations_externalInvitePermissions.rb +1 -1
- data/bin/commands/conversations_requestSharedInvite.rb +4 -4
- data/bin/commands/dnd.rb +1 -1
- data/bin/commands/files.rb +5 -5
- data/bin/commands/files_remote.rb +1 -1
- data/bin/commands/functions.rb +1 -1
- data/bin/commands/functions_distributions_permissions.rb +15 -15
- data/bin/commands/functions_workflows_steps.rb +2 -2
- data/bin/commands/functions_workflows_steps_responses.rb +2 -2
- data/bin/commands/migration.rb +2 -2
- data/bin/commands/oauth_v2.rb +1 -1
- data/bin/commands/openid_connect.rb +1 -1
- data/bin/commands/reactions.rb +3 -3
- data/bin/commands/reminders.rb +2 -2
- data/bin/commands/rtm.rb +15 -0
- data/bin/commands/search.rb +4 -4
- data/bin/commands/slackLists.rb +37 -0
- data/bin/commands/slackLists_access.rb +34 -0
- data/bin/commands/slackLists_download.rb +31 -0
- data/bin/commands/slackLists_items.rb +76 -0
- data/bin/commands/team.rb +1 -1
- data/bin/commands/team_externalTeams.rb +4 -4
- data/bin/commands/usergroups.rb +10 -10
- data/bin/commands/usergroups_users.rb +5 -5
- data/bin/commands/users.rb +1 -1
- data/bin/commands/users_discoverableContacts.rb +1 -1
- data/bin/commands/views.rb +4 -4
- data/bin/commands/workflows_featured.rb +50 -0
- data/bin/commands/workflows_triggers_permissions.rb +7 -7
- data/examples/files_upload_v2/files_upload_v2.rb +8 -0
- data/lib/slack/events/request.rb +1 -0
- data/lib/slack/version.rb +1 -1
- data/lib/slack/web/api/endpoints/admin_analytics.rb +2 -2
- data/lib/slack/web/api/endpoints/admin_apps.rb +8 -8
- data/lib/slack/web/api/endpoints/admin_apps_activities.rb +14 -14
- data/lib/slack/web/api/endpoints/admin_apps_approved.rb +5 -7
- data/lib/slack/web/api/endpoints/admin_apps_config.rb +6 -3
- data/lib/slack/web/api/endpoints/admin_apps_requests.rb +7 -9
- data/lib/slack/web/api/endpoints/admin_apps_restricted.rb +5 -7
- data/lib/slack/web/api/endpoints/admin_audit_anomaly_allow.rb +5 -5
- data/lib/slack/web/api/endpoints/admin_auth_policy.rb +14 -14
- data/lib/slack/web/api/endpoints/admin_barriers.rb +8 -8
- data/lib/slack/web/api/endpoints/admin_conversations.rb +27 -28
- data/lib/slack/web/api/endpoints/admin_conversations_ekm.rb +4 -4
- data/lib/slack/web/api/endpoints/admin_conversations_restrictAccess.rb +11 -12
- data/lib/slack/web/api/endpoints/admin_emoji.rb +5 -5
- data/lib/slack/web/api/endpoints/admin_functions.rb +2 -2
- data/lib/slack/web/api/endpoints/admin_inviteRequests.rb +6 -6
- data/lib/slack/web/api/endpoints/admin_inviteRequests_approved.rb +2 -2
- data/lib/slack/web/api/endpoints/admin_inviteRequests_denied.rb +2 -2
- data/lib/slack/web/api/endpoints/admin_roles.rb +8 -8
- data/lib/slack/web/api/endpoints/admin_teams.rb +3 -3
- data/lib/slack/web/api/endpoints/admin_teams_admins.rb +3 -4
- data/lib/slack/web/api/endpoints/admin_teams_owners.rb +2 -3
- data/lib/slack/web/api/endpoints/admin_teams_settings.rb +12 -13
- data/lib/slack/web/api/endpoints/admin_usergroups.rb +11 -11
- data/lib/slack/web/api/endpoints/admin_users.rb +27 -25
- data/lib/slack/web/api/endpoints/admin_users_session.rb +12 -9
- data/lib/slack/web/api/endpoints/admin_users_unsupportedVersions.rb +2 -2
- data/lib/slack/web/api/endpoints/admin_workflows.rb +12 -12
- data/lib/slack/web/api/endpoints/admin_workflows_collaborators.rb +6 -6
- data/lib/slack/web/api/endpoints/apps_activities.rb +14 -14
- data/lib/slack/web/api/endpoints/apps_auth_external.rb +2 -2
- data/lib/slack/web/api/endpoints/apps_datastore.rb +8 -15
- data/lib/slack/web/api/endpoints/apps_event_authorizations.rb +0 -3
- data/lib/slack/web/api/endpoints/apps_manifest.rb +5 -5
- data/lib/slack/web/api/endpoints/assistant_search.rb +28 -3
- data/lib/slack/web/api/endpoints/assistant_threads.rb +6 -6
- data/lib/slack/web/api/endpoints/auth.rb +1 -1
- data/lib/slack/web/api/endpoints/auth_teams.rb +2 -2
- data/lib/slack/web/api/endpoints/bookmarks.rb +14 -14
- data/lib/slack/web/api/endpoints/calls.rb +10 -10
- data/lib/slack/web/api/endpoints/canvases.rb +4 -4
- data/lib/slack/web/api/endpoints/canvases_access.rb +3 -3
- data/lib/slack/web/api/endpoints/chat.rb +53 -55
- data/lib/slack/web/api/endpoints/conversations.rb +16 -16
- data/lib/slack/web/api/endpoints/conversations_canvases.rb +1 -1
- data/lib/slack/web/api/endpoints/conversations_externalInvitePermissions.rb +3 -3
- data/lib/slack/web/api/endpoints/conversations_requestSharedInvite.rb +8 -8
- data/lib/slack/web/api/endpoints/dnd.rb +2 -2
- data/lib/slack/web/api/endpoints/files.rb +11 -11
- data/lib/slack/web/api/endpoints/files_remote.rb +2 -2
- data/lib/slack/web/api/endpoints/functions.rb +3 -3
- data/lib/slack/web/api/endpoints/functions_distributions_permissions.rb +24 -24
- data/lib/slack/web/api/endpoints/functions_workflows_steps.rb +4 -4
- data/lib/slack/web/api/endpoints/functions_workflows_steps_responses.rb +4 -4
- data/lib/slack/web/api/endpoints/migration.rb +1 -1
- data/lib/slack/web/api/endpoints/oauth_v2.rb +2 -2
- data/lib/slack/web/api/endpoints/openid_connect.rb +2 -2
- data/lib/slack/web/api/endpoints/reactions.rb +6 -6
- data/lib/slack/web/api/endpoints/reminders.rb +4 -4
- data/lib/slack/web/api/endpoints/rtm.rb +23 -0
- data/lib/slack/web/api/endpoints/search.rb +8 -8
- data/lib/slack/web/api/endpoints/slackLists.rb +52 -0
- data/lib/slack/web/api/endpoints/slackLists_access.rb +47 -0
- data/lib/slack/web/api/endpoints/slackLists_download.rb +40 -0
- data/lib/slack/web/api/endpoints/slackLists_items.rb +116 -0
- data/lib/slack/web/api/endpoints/team.rb +3 -3
- data/lib/slack/web/api/endpoints/team_externalTeams.rb +8 -8
- data/lib/slack/web/api/endpoints/usergroups.rb +18 -18
- data/lib/slack/web/api/endpoints/usergroups_users.rb +8 -8
- data/lib/slack/web/api/endpoints/users.rb +2 -2
- data/lib/slack/web/api/endpoints/users_discoverableContacts.rb +0 -1
- data/lib/slack/web/api/endpoints/views.rb +9 -9
- data/lib/slack/web/api/endpoints/workflows_featured.rb +69 -0
- data/lib/slack/web/api/endpoints/workflows_triggers_permissions.rb +15 -15
- data/lib/slack/web/api/endpoints.rb +10 -2
- data/lib/slack/web/api/errors.rb +88 -46
- data/lib/slack/web/api/helpers/files.rb +32 -22
- data/lib/slack/web/api/mixins/conversations.id.rb +14 -3
- data/lib/slack/web/api/mixins/users.id.rb +7 -3
- data/lib/slack/web/faraday/response/raise_error.rb +20 -2
- data/lib/slack-ruby-client.rb +0 -12
- data/lib/tasks/update.rake +0 -1
- data/lib/tasks/web.rake +0 -4
- data/slack-ruby-client.gemspec +1 -1
- metadata +19 -38
- data/.github/workflows/integration_test.yml +0 -45
- data/bin/commands/workflows.rb +0 -44
- data/examples/hi_real_time_and_web/Gemfile +0 -6
- data/examples/hi_real_time_and_web/hi.gif +0 -0
- data/examples/hi_real_time_and_web/hi.rb +0 -28
- data/examples/hi_real_time_async_async/Gemfile +0 -7
- data/examples/hi_real_time_async_async/Procfile +0 -2
- data/examples/hi_real_time_async_async/hi.rb +0 -41
- data/lib/slack/real_time/api/message.rb +0 -23
- data/lib/slack/real_time/api/message_id.rb +0 -15
- data/lib/slack/real_time/api/ping.rb +0 -19
- data/lib/slack/real_time/api/schema/event.json +0 -23
- data/lib/slack/real_time/api/templates/event_handler.erb +0 -8
- data/lib/slack/real_time/api/typing.rb +0 -20
- data/lib/slack/real_time/client.rb +0 -271
- data/lib/slack/real_time/concurrency/async.rb +0 -142
- data/lib/slack/real_time/concurrency.rb +0 -8
- data/lib/slack/real_time/config.rb +0 -62
- data/lib/slack/real_time/models/base.rb +0 -11
- data/lib/slack/real_time/models/bot.rb +0 -9
- data/lib/slack/real_time/models/channel.rb +0 -13
- data/lib/slack/real_time/models/im.rb +0 -9
- data/lib/slack/real_time/models/mpim.rb +0 -9
- data/lib/slack/real_time/models/team.rb +0 -9
- data/lib/slack/real_time/models/user.rb +0 -9
- data/lib/slack/real_time/models.rb +0 -9
- data/lib/slack/real_time/socket.rb +0 -118
- data/lib/slack/real_time/stores/base.rb +0 -47
- data/lib/slack/real_time/stores/starter.rb +0 -449
- data/lib/slack/real_time/stores/store.rb +0 -624
- data/lib/slack/real_time/stores.rb +0 -5
- data/lib/slack/web/api/endpoints/workflows.rb +0 -63
- data/lib/tasks/real_time.rake +0 -81
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Slack
|
3
|
-
module RealTime
|
4
|
-
module Api
|
5
|
-
module Typing
|
6
|
-
#
|
7
|
-
# Send a typing indicator to indicate that the user is currently writing a message.
|
8
|
-
#
|
9
|
-
# @option options [channel] :channel
|
10
|
-
# Channel to send message to. Can be a public channel, private group or IM channel.
|
11
|
-
# Can be an encoded ID, or a name.
|
12
|
-
def typing(options = {})
|
13
|
-
raise ArgumentError, 'Required arguments :channel missing' if options[:channel].nil?
|
14
|
-
|
15
|
-
send_json({ type: 'typing', id: next_id }.merge(options))
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,271 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Slack
|
3
|
-
module RealTime
|
4
|
-
class Client
|
5
|
-
class ClientNotStartedError < StandardError; end
|
6
|
-
|
7
|
-
class ClientAlreadyStartedError < StandardError; end
|
8
|
-
|
9
|
-
include Api::MessageId
|
10
|
-
include Api::Ping
|
11
|
-
include Api::Message
|
12
|
-
include Api::Typing
|
13
|
-
|
14
|
-
attr_accessor :web_client, :store, :url, *Config::ATTRIBUTES
|
15
|
-
|
16
|
-
protected :store_class, :store_class=, :store_options, :store_options=
|
17
|
-
|
18
|
-
def initialize(options = {})
|
19
|
-
@callbacks = Hash.new { |h, k| h[k] = [] }
|
20
|
-
Slack::RealTime::Config::ATTRIBUTES.each do |key|
|
21
|
-
send("#{key}=", options.key?(key) ? options[key] : Slack::RealTime.config.send(key))
|
22
|
-
end
|
23
|
-
@token ||= Slack.config.token
|
24
|
-
@logger ||= (Slack::Config.logger || Slack::Logger.default)
|
25
|
-
@web_client = Slack::Web::Client.new(token: token, logger: logger)
|
26
|
-
end
|
27
|
-
|
28
|
-
[:self, :team, *Stores::Base::CACHES].each do |store_method|
|
29
|
-
define_method store_method do
|
30
|
-
store&.send(store_method)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def on(type, &block)
|
35
|
-
type = type.to_s
|
36
|
-
callbacks[type] << block
|
37
|
-
end
|
38
|
-
|
39
|
-
# Start RealTime client and block until it disconnects.
|
40
|
-
def start!(&block)
|
41
|
-
@callback = block if block
|
42
|
-
build_socket
|
43
|
-
@socket.start_sync(self)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Start RealTime client and return immediately.
|
47
|
-
# The RealTime::Client will run in the background.
|
48
|
-
def start_async(&block)
|
49
|
-
@callback = block if block
|
50
|
-
build_socket
|
51
|
-
@socket.start_async(self)
|
52
|
-
end
|
53
|
-
|
54
|
-
def stop!
|
55
|
-
raise ClientNotStartedError unless started?
|
56
|
-
|
57
|
-
@socket&.disconnect!
|
58
|
-
end
|
59
|
-
|
60
|
-
def started?
|
61
|
-
@socket&.connected?
|
62
|
-
end
|
63
|
-
|
64
|
-
class << self
|
65
|
-
def configure
|
66
|
-
block_given? ? yield(config) : config
|
67
|
-
end
|
68
|
-
|
69
|
-
def config
|
70
|
-
Config
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def run_loop
|
75
|
-
@socket.connect! do |driver|
|
76
|
-
driver.on :open do |event|
|
77
|
-
logger.debug("#{self}##{__method__}") { event.class.name }
|
78
|
-
open_event(event)
|
79
|
-
callback(event, :open)
|
80
|
-
end
|
81
|
-
|
82
|
-
driver.on :message do |event|
|
83
|
-
logger.debug("#{self}##{__method__}") { "#{event.class}, #{event.data}" }
|
84
|
-
dispatch(event)
|
85
|
-
end
|
86
|
-
|
87
|
-
driver.on :close do |event|
|
88
|
-
logger.debug("#{self}##{__method__}") { event.class.name }
|
89
|
-
callback(event, :close)
|
90
|
-
close(event)
|
91
|
-
callback(event, :closed)
|
92
|
-
end
|
93
|
-
|
94
|
-
# This must be called last to ensure any events are registered before invoking user code.
|
95
|
-
@callback&.call(driver)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Ensure the server is running, and ping the remote server if no other messages were sent.
|
100
|
-
def keep_alive?
|
101
|
-
# We can't ping the remote server if we aren't connected.
|
102
|
-
return false if @socket.nil? || !@socket.connected?
|
103
|
-
|
104
|
-
time_since_last_message = @socket.time_since_last_message
|
105
|
-
|
106
|
-
# If the server responded within the specified time, we are okay:
|
107
|
-
return true if time_since_last_message < websocket_ping
|
108
|
-
|
109
|
-
# If the server has not responded for a while:
|
110
|
-
return false if time_since_last_message > (websocket_ping * 2)
|
111
|
-
|
112
|
-
# Kick off the next ping message:
|
113
|
-
ping
|
114
|
-
|
115
|
-
true
|
116
|
-
end
|
117
|
-
|
118
|
-
# Check if the remote server is responsive, and if not, restart the connection.
|
119
|
-
def run_ping!
|
120
|
-
return if keep_alive?
|
121
|
-
|
122
|
-
logger.warn(to_s) { 'is offline' }
|
123
|
-
|
124
|
-
restart_async
|
125
|
-
rescue Slack::Web::Api::Errors::SlackError => e
|
126
|
-
# stop pinging if bot was uninstalled
|
127
|
-
case e.message
|
128
|
-
when 'account_inactive', 'invalid_auth'
|
129
|
-
logger.warn(to_s) { e.message }
|
130
|
-
raise e
|
131
|
-
end
|
132
|
-
logger.debug("#{self}##{__method__}") { e }
|
133
|
-
rescue StandardError => e
|
134
|
-
# disregard all ping worker failures, keep pinging
|
135
|
-
logger.debug("#{self}##{__method__}") { e }
|
136
|
-
end
|
137
|
-
|
138
|
-
def run_ping?
|
139
|
-
!websocket_ping.nil? && websocket_ping.positive?
|
140
|
-
end
|
141
|
-
|
142
|
-
def websocket_ping_timer
|
143
|
-
websocket_ping / 2
|
144
|
-
end
|
145
|
-
|
146
|
-
def to_s
|
147
|
-
if store&.team
|
148
|
-
"id=#{store.team.id}, name=#{store.team.name}, domain=#{store.team.domain}"
|
149
|
-
else
|
150
|
-
super
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
protected
|
155
|
-
|
156
|
-
def restart_async
|
157
|
-
logger.debug("#{self}##{__method__}")
|
158
|
-
@socket.close
|
159
|
-
start = web_client.rtm_connect(start_options)
|
160
|
-
data = Slack::Messages::Message.new(start)
|
161
|
-
@url = data.url
|
162
|
-
@store = store_class.new(data, store_options.to_h) if store_class
|
163
|
-
@socket.restart_async(self, @url)
|
164
|
-
end
|
165
|
-
|
166
|
-
# @return [Slack::RealTime::Socket]
|
167
|
-
def build_socket
|
168
|
-
raise ClientAlreadyStartedError if started?
|
169
|
-
|
170
|
-
start = web_client.rtm_connect(start_options)
|
171
|
-
data = Slack::Messages::Message.new(start)
|
172
|
-
@url = data.url
|
173
|
-
@store = store_class.new(data, store_options.to_h) if store_class
|
174
|
-
@socket = socket_class.new(@url, socket_options)
|
175
|
-
end
|
176
|
-
|
177
|
-
def socket_options
|
178
|
-
socket_options = {}
|
179
|
-
socket_options[:ping] = websocket_ping if websocket_ping
|
180
|
-
socket_options[:proxy] = websocket_proxy if websocket_proxy
|
181
|
-
socket_options[:logger] = logger
|
182
|
-
socket_options
|
183
|
-
end
|
184
|
-
|
185
|
-
attr_reader :callbacks
|
186
|
-
|
187
|
-
def socket_class
|
188
|
-
concurrency::Socket
|
189
|
-
end
|
190
|
-
|
191
|
-
def send_json(data)
|
192
|
-
raise ClientNotStartedError unless started?
|
193
|
-
|
194
|
-
logger.debug("#{self}##{__method__}") { data }
|
195
|
-
@socket.send_data(data.to_json)
|
196
|
-
end
|
197
|
-
|
198
|
-
def open_event(_event); end
|
199
|
-
|
200
|
-
def close(_event)
|
201
|
-
[@socket, socket_class].each do |s|
|
202
|
-
s.close if s.respond_to?(:close)
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def callback(event, type)
|
207
|
-
callbacks = self.callbacks[type.to_s]
|
208
|
-
return false unless callbacks
|
209
|
-
|
210
|
-
callbacks.each do |c|
|
211
|
-
c.call(event)
|
212
|
-
end
|
213
|
-
true
|
214
|
-
rescue StandardError => e
|
215
|
-
logger.error("#{self}##{__method__}") { e }
|
216
|
-
false
|
217
|
-
end
|
218
|
-
|
219
|
-
def dispatch(event)
|
220
|
-
return false unless event.data
|
221
|
-
|
222
|
-
data = Slack::Messages::Message.new(JSON.parse(event.data))
|
223
|
-
type = data.type
|
224
|
-
return false unless type
|
225
|
-
|
226
|
-
type = type.to_s
|
227
|
-
logger.debug("#{self}##{__method__}") { data.to_s }
|
228
|
-
run_handlers(type, data) if @store
|
229
|
-
run_callbacks(type, data)
|
230
|
-
rescue StandardError => e
|
231
|
-
logger.error("#{self}##{__method__}") { e }
|
232
|
-
false
|
233
|
-
end
|
234
|
-
|
235
|
-
def run_handlers(type, data)
|
236
|
-
handlers = store.class.events[type.to_s]
|
237
|
-
case async_handlers
|
238
|
-
when :all
|
239
|
-
@socket.run_async { handlers_loop(handlers, data) }
|
240
|
-
when :none
|
241
|
-
handlers_loop(handlers, data)
|
242
|
-
else
|
243
|
-
raise Config::InvalidAsyncHandlersError,
|
244
|
-
"Invalid value '#{async_handlers.inspect}' for config#async_handlers, must be :all or :none."
|
245
|
-
end
|
246
|
-
rescue StandardError => e
|
247
|
-
logger.error("#{self}##{__method__}") { e }
|
248
|
-
false
|
249
|
-
end
|
250
|
-
|
251
|
-
def handlers_loop(handlers, data)
|
252
|
-
handlers.each do |handler|
|
253
|
-
store.instance_exec(data, self, &handler)
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def run_callbacks(type, data)
|
258
|
-
callbacks = self.callbacks[type]
|
259
|
-
return false unless callbacks
|
260
|
-
|
261
|
-
callbacks.each do |c|
|
262
|
-
c.call(data)
|
263
|
-
end
|
264
|
-
true
|
265
|
-
rescue StandardError => e
|
266
|
-
logger.error("#{self}##{__method__}") { e }
|
267
|
-
false
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'async/websocket'
|
3
|
-
require 'async/notification'
|
4
|
-
require 'async/clock'
|
5
|
-
|
6
|
-
module Slack
|
7
|
-
module RealTime
|
8
|
-
module Concurrency
|
9
|
-
module Async
|
10
|
-
class Client < ::Async::WebSocket::Client
|
11
|
-
extend ::Forwardable
|
12
|
-
def_delegators :@driver, :on, :text, :binary, :emit
|
13
|
-
end
|
14
|
-
|
15
|
-
class Socket < Slack::RealTime::Socket
|
16
|
-
attr_reader :client
|
17
|
-
|
18
|
-
def start_sync(client)
|
19
|
-
start_reactor(client).wait
|
20
|
-
end
|
21
|
-
|
22
|
-
def start_async(client)
|
23
|
-
Thread.new do
|
24
|
-
start_reactor(client)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def start_reactor(client)
|
29
|
-
Async do |task|
|
30
|
-
@restart = ::Async::Notification.new
|
31
|
-
|
32
|
-
if client.run_ping?
|
33
|
-
@ping_task = task.async do |subtask|
|
34
|
-
subtask.annotate "#{client} keep-alive"
|
35
|
-
|
36
|
-
# The timer task will naturally exit after the driver is set to nil.
|
37
|
-
while @restart
|
38
|
-
subtask.sleep client.websocket_ping_timer
|
39
|
-
client.run_ping! if @restart
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
while @restart
|
45
|
-
@client_task&.stop
|
46
|
-
|
47
|
-
@client_task = task.async do |subtask|
|
48
|
-
subtask.annotate "#{client} run-loop"
|
49
|
-
client.run_loop
|
50
|
-
rescue ::Async::Wrapper::Cancelled => e
|
51
|
-
# Will get restarted by ping worker.
|
52
|
-
rescue StandardError => e
|
53
|
-
client.logger.error(subtask.to_s) { e.message }
|
54
|
-
end
|
55
|
-
|
56
|
-
@restart.wait
|
57
|
-
end
|
58
|
-
|
59
|
-
@ping_task&.stop
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def restart_async(_client, new_url)
|
64
|
-
@url = new_url
|
65
|
-
@last_message_at = current_time
|
66
|
-
|
67
|
-
@restart&.signal
|
68
|
-
end
|
69
|
-
|
70
|
-
def run_async(&block)
|
71
|
-
::Async.run(&block)
|
72
|
-
end
|
73
|
-
|
74
|
-
def current_time
|
75
|
-
::Async::Clock.now
|
76
|
-
end
|
77
|
-
|
78
|
-
def connect!
|
79
|
-
super
|
80
|
-
run_loop
|
81
|
-
end
|
82
|
-
|
83
|
-
# Kill the restart/ping loop.
|
84
|
-
def disconnect!
|
85
|
-
super
|
86
|
-
ensure
|
87
|
-
if (restart = @restart)
|
88
|
-
@restart = nil
|
89
|
-
restart.signal
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Close the socket.
|
94
|
-
def close
|
95
|
-
super
|
96
|
-
ensure
|
97
|
-
if @socket
|
98
|
-
@socket.close
|
99
|
-
@socket = nil
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def run_loop
|
104
|
-
while @driver&.next_event
|
105
|
-
# $stderr.puts event.inspect
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
protected
|
110
|
-
|
111
|
-
def build_ssl_context
|
112
|
-
OpenSSL::SSL::SSLContext.new(:TLSv1_2_client).tap do |ctx|
|
113
|
-
ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def build_endpoint
|
118
|
-
endpoint = ::Async::IO::Endpoint.tcp(addr, port)
|
119
|
-
endpoint = ::Async::IO::SSLEndpoint.new(endpoint, ssl_context: build_ssl_context) if secure?
|
120
|
-
endpoint
|
121
|
-
end
|
122
|
-
|
123
|
-
def connect_socket
|
124
|
-
build_endpoint.connect
|
125
|
-
end
|
126
|
-
|
127
|
-
def connect
|
128
|
-
@socket = connect_socket
|
129
|
-
@driver = Client.new(@socket, url)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
if Gem::Version.new(Async::WebSocket::VERSION) >= Gem::Version.new('0.9.0')
|
138
|
-
raise(
|
139
|
-
"Incompatible version of async-websocket, #{Async::WebSocket::VERSION}, " \
|
140
|
-
"use \"gem 'async-websocket', '~> 0.8.0'\"."
|
141
|
-
)
|
142
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Slack
|
3
|
-
module RealTime
|
4
|
-
module Config
|
5
|
-
class NoConcurrencyError < StandardError; end
|
6
|
-
class InvalidAsyncHandlersError < StandardError; end
|
7
|
-
|
8
|
-
extend self
|
9
|
-
|
10
|
-
ATTRIBUTES = %i[
|
11
|
-
token
|
12
|
-
websocket_ping
|
13
|
-
websocket_proxy
|
14
|
-
concurrency
|
15
|
-
start_options
|
16
|
-
store_class
|
17
|
-
store_options
|
18
|
-
logger
|
19
|
-
async_handlers
|
20
|
-
].freeze
|
21
|
-
|
22
|
-
attr_accessor(*Config::ATTRIBUTES - [:concurrency])
|
23
|
-
attr_writer :concurrency
|
24
|
-
|
25
|
-
def reset
|
26
|
-
self.websocket_ping = 30
|
27
|
-
self.websocket_proxy = nil
|
28
|
-
self.token = nil
|
29
|
-
self.concurrency = method(:detect_concurrency)
|
30
|
-
self.start_options = { request: { timeout: 180 } }
|
31
|
-
self.store_class = Slack::RealTime::Stores::Starter
|
32
|
-
self.store_options = {}
|
33
|
-
self.logger = nil
|
34
|
-
self.async_handlers = :none
|
35
|
-
end
|
36
|
-
|
37
|
-
def concurrency
|
38
|
-
(val = @concurrency).respond_to?(:call) ? val.call : val
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def detect_concurrency
|
44
|
-
Slack::RealTime::Concurrency.const_get(:Async)
|
45
|
-
rescue LoadError, NameError
|
46
|
-
raise NoConcurrencyError, 'Missing concurrency. Add async-websocket to your Gemfile.'
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class << self
|
51
|
-
def configure
|
52
|
-
block_given? ? yield(Config) : Config
|
53
|
-
end
|
54
|
-
|
55
|
-
def config
|
56
|
-
Config
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
Slack::RealTime::Config.reset
|