slack-ruby-client 0.12.0 → 0.14.6
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/.gitignore +1 -0
- data/.rubocop.yml +21 -9
- data/.rubocop_todo.yml +64 -56
- data/.travis.yml +5 -3
- data/CHANGELOG.md +90 -32
- data/Dangerfile +2 -0
- data/Gemfile +10 -4
- data/LICENSE.md +1 -1
- data/README.md +176 -32
- data/Rakefile +2 -1
- data/UPGRADING.md +27 -1
- data/bin/commands.rb +21 -0
- data/bin/commands/admin_apps.rb +27 -0
- data/bin/commands/admin_apps_approved.rb +17 -0
- data/bin/commands/admin_apps_requests.rb +16 -0
- data/bin/commands/admin_apps_restricted.rb +17 -0
- data/bin/commands/admin_conversations.rb +17 -0
- data/bin/commands/admin_emoji.rb +54 -0
- data/bin/commands/admin_inviteRequests.rb +36 -0
- data/bin/commands/admin_inviteRequests_approved.rb +16 -0
- data/bin/commands/admin_inviteRequests_denied.rb +16 -0
- data/bin/commands/admin_teams.rb +27 -0
- data/bin/commands/admin_teams_admins.rb +16 -0
- data/bin/commands/admin_teams_owners.rb +16 -0
- data/bin/commands/admin_teams_settings.rb +64 -0
- data/bin/commands/admin_users.rb +97 -0
- data/bin/commands/admin_users_session.rb +16 -0
- data/bin/commands/api.rb +1 -0
- data/bin/commands/apps.rb +15 -0
- data/bin/commands/apps_permissions.rb +1 -0
- data/bin/commands/apps_permissions_resources.rb +1 -0
- data/bin/commands/apps_permissions_scopes.rb +1 -0
- data/bin/commands/apps_permissions_users.rb +1 -0
- data/bin/commands/auth.rb +1 -0
- data/bin/commands/bots.rb +1 -0
- data/bin/commands/channels.rb +3 -1
- data/bin/commands/chat.rb +48 -9
- data/bin/commands/chat_scheduledMessages.rb +18 -0
- data/bin/commands/conversations.rb +4 -2
- data/bin/commands/dialog.rb +1 -0
- data/bin/commands/dnd.rb +4 -3
- data/bin/commands/emoji.rb +1 -0
- data/bin/commands/files.rb +4 -14
- data/bin/commands/files_comments.rb +1 -21
- data/bin/commands/files_remote.rb +78 -0
- data/bin/commands/groups.rb +2 -1
- data/bin/commands/im.rb +2 -1
- data/bin/commands/migration.rb +1 -0
- data/bin/commands/mpim.rb +2 -1
- data/bin/commands/oauth.rb +2 -1
- data/bin/commands/oauth_v2.rb +17 -0
- data/bin/commands/pins.rb +1 -2
- data/bin/commands/reactions.rb +2 -3
- data/bin/commands/reminders.rb +1 -0
- data/bin/commands/rtm.rb +1 -0
- data/bin/commands/search.rb +2 -1
- data/bin/commands/stars.rb +1 -0
- data/bin/commands/team.rb +2 -0
- data/bin/commands/team_profile.rb +1 -0
- data/bin/commands/usergroups.rb +2 -1
- data/bin/commands/usergroups_users.rb +1 -0
- data/bin/commands/users.rb +2 -2
- data/bin/commands/users_admin.rb +1 -0
- data/bin/commands/users_prefs.rb +1 -0
- data/bin/commands/users_profile.rb +1 -0
- data/bin/commands/views.rb +48 -0
- data/bin/slack +2 -3
- data/examples/hi_real_time/Gemfile +1 -0
- data/examples/hi_real_time/hi.rb +7 -3
- data/examples/hi_real_time_and_web/Gemfile +1 -0
- data/examples/hi_real_time_and_web/hi.rb +7 -3
- data/examples/hi_real_time_async_async/Gemfile +7 -0
- data/examples/hi_real_time_async_async/Procfile +2 -0
- data/examples/hi_real_time_async_async/hi.rb +41 -0
- data/examples/hi_real_time_async_celluloid/Gemfile +1 -0
- data/examples/hi_real_time_async_celluloid/hi.rb +7 -3
- data/examples/hi_real_time_async_eventmachine/Gemfile +1 -0
- data/examples/hi_real_time_async_eventmachine/hi.rb +7 -3
- data/examples/hi_web/Gemfile +1 -0
- data/examples/hi_web/hi.rb +1 -0
- data/examples/new_ticket/Gemfile +1 -0
- data/examples/new_ticket/new_ticket.rb +1 -0
- data/lib/slack-ruby-client.rb +8 -2
- data/lib/slack.rb +1 -0
- data/lib/slack/config.rb +1 -0
- data/lib/slack/events/config.rb +32 -0
- data/lib/slack/events/request.rb +66 -0
- data/lib/slack/logger.rb +6 -5
- data/lib/slack/messages/formatting.rb +1 -0
- data/lib/slack/messages/message.rb +1 -0
- data/lib/slack/real_time/api/message.rb +3 -1
- data/lib/slack/real_time/api/message_id.rb +1 -0
- data/lib/slack/real_time/api/ping.rb +5 -2
- data/lib/slack/real_time/api/typing.rb +3 -1
- data/lib/slack/real_time/client.rb +97 -28
- data/lib/slack/real_time/concurrency.rb +2 -0
- data/lib/slack/real_time/concurrency/async.rb +142 -0
- data/lib/slack/real_time/concurrency/celluloid.rb +33 -9
- data/lib/slack/real_time/concurrency/eventmachine.rb +32 -7
- data/lib/slack/real_time/config.rb +7 -2
- data/lib/slack/real_time/models.rb +1 -0
- data/lib/slack/real_time/models/base.rb +1 -0
- data/lib/slack/real_time/models/bot.rb +1 -0
- data/lib/slack/real_time/models/channel.rb +1 -0
- data/lib/slack/real_time/models/group.rb +1 -0
- data/lib/slack/real_time/models/im.rb +1 -0
- data/lib/slack/real_time/models/team.rb +1 -0
- data/lib/slack/real_time/models/user.rb +1 -0
- data/lib/slack/real_time/socket.rb +42 -13
- data/lib/slack/real_time/stores.rb +1 -0
- data/lib/slack/real_time/stores/base.rb +1 -0
- data/lib/slack/real_time/stores/starter.rb +11 -0
- data/lib/slack/real_time/stores/store.rb +28 -25
- data/lib/slack/version.rb +2 -1
- data/lib/slack/web/api/endpoints.rb +41 -0
- data/lib/slack/web/api/endpoints/admin_apps.rb +42 -0
- data/lib/slack/web/api/endpoints/admin_apps_approved.rb +35 -0
- data/lib/slack/web/api/endpoints/admin_apps_requests.rb +33 -0
- data/lib/slack/web/api/endpoints/admin_apps_restricted.rb +35 -0
- data/lib/slack/web/api/endpoints/admin_conversations.rb +30 -0
- data/lib/slack/web/api/endpoints/admin_emoji.rb +88 -0
- data/lib/slack/web/api/endpoints/admin_inviteRequests.rb +61 -0
- data/lib/slack/web/api/endpoints/admin_inviteRequests_approved.rb +33 -0
- data/lib/slack/web/api/endpoints/admin_inviteRequests_denied.rb +33 -0
- data/lib/slack/web/api/endpoints/admin_teams.rb +50 -0
- data/lib/slack/web/api/endpoints/admin_teams_admins.rb +34 -0
- data/lib/slack/web/api/endpoints/admin_teams_owners.rb +34 -0
- data/lib/slack/web/api/endpoints/admin_teams_settings.rb +99 -0
- data/lib/slack/web/api/endpoints/admin_users.rb +163 -0
- data/lib/slack/web/api/endpoints/admin_users_session.rb +28 -0
- data/lib/slack/web/api/endpoints/api.rb +1 -0
- data/lib/slack/web/api/endpoints/apps.rb +27 -0
- data/lib/slack/web/api/endpoints/apps_permissions.rb +1 -0
- data/lib/slack/web/api/endpoints/apps_permissions_resources.rb +1 -0
- data/lib/slack/web/api/endpoints/apps_permissions_scopes.rb +1 -0
- data/lib/slack/web/api/endpoints/apps_permissions_users.rb +1 -0
- data/lib/slack/web/api/endpoints/auth.rb +1 -0
- data/lib/slack/web/api/endpoints/bots.rb +1 -0
- data/lib/slack/web/api/endpoints/channels.rb +3 -0
- data/lib/slack/web/api/endpoints/chat.rb +99 -12
- data/lib/slack/web/api/endpoints/chat_scheduledMessages.rb +38 -0
- data/lib/slack/web/api/endpoints/conversations.rb +4 -1
- data/lib/slack/web/api/endpoints/dialog.rb +1 -0
- data/lib/slack/web/api/endpoints/dnd.rb +3 -1
- data/lib/slack/web/api/endpoints/emoji.rb +1 -0
- data/lib/slack/web/api/endpoints/files.rb +4 -13
- data/lib/slack/web/api/endpoints/files_comments.rb +1 -33
- data/lib/slack/web/api/endpoints/files_remote.rb +127 -0
- data/lib/slack/web/api/endpoints/groups.rb +1 -0
- data/lib/slack/web/api/endpoints/im.rb +1 -0
- data/lib/slack/web/api/endpoints/migration.rb +1 -0
- data/lib/slack/web/api/endpoints/mpim.rb +1 -0
- data/lib/slack/web/api/endpoints/oauth.rb +2 -1
- data/lib/slack/web/api/endpoints/oauth_v2.rb +30 -0
- data/lib/slack/web/api/endpoints/pins.rb +2 -4
- data/lib/slack/web/api/endpoints/reactions.rb +5 -6
- data/lib/slack/web/api/endpoints/reminders.rb +1 -0
- data/lib/slack/web/api/endpoints/rtm.rb +1 -0
- data/lib/slack/web/api/endpoints/search.rb +1 -0
- data/lib/slack/web/api/endpoints/stars.rb +1 -0
- data/lib/slack/web/api/endpoints/team.rb +3 -0
- data/lib/slack/web/api/endpoints/team_profile.rb +1 -0
- data/lib/slack/web/api/endpoints/usergroups.rb +1 -0
- data/lib/slack/web/api/endpoints/usergroups_users.rb +1 -0
- data/lib/slack/web/api/endpoints/users.rb +1 -2
- data/lib/slack/web/api/endpoints/users_admin.rb +1 -0
- data/lib/slack/web/api/endpoints/users_prefs.rb +1 -0
- data/lib/slack/web/api/endpoints/users_profile.rb +1 -0
- data/lib/slack/web/api/endpoints/views.rb +97 -0
- data/lib/slack/web/api/error.rb +1 -0
- data/lib/slack/web/api/errors.rb +566 -0
- data/lib/slack/web/api/errors/slack_error.rb +14 -1
- data/lib/slack/web/api/errors/too_many_requests_error.rb +1 -0
- data/lib/slack/web/api/mixins.rb +1 -0
- data/lib/slack/web/api/mixins/channels.id.rb +1 -0
- data/lib/slack/web/api/mixins/groups.id.rb +1 -0
- data/lib/slack/web/api/mixins/ids.id.rb +4 -1
- data/lib/slack/web/api/mixins/users.id.rb +1 -0
- data/lib/slack/web/api/mixins/users.search.rb +1 -0
- data/lib/slack/web/api/patches/chat.5.postEphemeral-text-or-attachments.patch +5 -3
- data/lib/slack/web/api/patches/chat.6.block-kit-support.patch +69 -0
- data/lib/slack/web/api/patches/views.1.view-json.patch +40 -0
- data/lib/slack/web/api/patches/views.1.views-published.patch +16 -0
- data/lib/slack/web/api/templates/command.erb +1 -0
- data/lib/slack/web/api/templates/commands.erb +1 -0
- data/lib/slack/web/api/templates/endpoints.erb +1 -0
- data/lib/slack/web/api/templates/errors.erb +20 -0
- data/lib/slack/web/api/templates/method.erb +1 -0
- data/lib/slack/web/api/templates/method_spec.erb +1 -0
- data/lib/slack/web/client.rb +2 -1
- data/lib/slack/web/config.rb +1 -0
- data/lib/slack/web/faraday/connection.rb +1 -0
- data/lib/slack/web/faraday/request.rb +1 -0
- data/lib/slack/web/faraday/response/raise_error.rb +10 -6
- data/lib/slack/web/pagination/cursor.rb +4 -0
- data/lib/slack_ruby_client.rb +1 -0
- data/lib/tasks/git.rake +1 -0
- data/lib/tasks/real_time.rake +15 -5
- data/lib/tasks/update.rake +1 -0
- data/lib/tasks/web.rake +28 -7
- data/screenshots/create-app.png +0 -0
- data/slack-ruby-client.gemspec +6 -2
- data/spec/fixtures/slack/web/views_open_error.yml +76 -0
- data/spec/integration/integration_spec.rb +116 -48
- data/spec/slack/config_spec.rb +2 -0
- data/spec/slack/events/config_spec.rb +33 -0
- data/spec/slack/events/request_spec.rb +179 -0
- data/spec/slack/messages/formatting_spec.rb +25 -13
- data/spec/slack/real_time/api/message_spec.rb +6 -1
- data/spec/slack/real_time/api/ping_spec.rb +2 -0
- data/spec/slack/real_time/api/typing_spec.rb +5 -1
- data/spec/slack/real_time/client_spec.rb +212 -31
- data/spec/slack/real_time/concurrency/celluloid_spec.rb +15 -5
- data/spec/slack/real_time/concurrency/eventmachine_spec.rb +11 -1
- data/spec/slack/real_time/concurrency/it_behaves_like_a_realtime_socket.rb +2 -0
- data/spec/slack/real_time/event_handlers/bot_spec.rb +2 -1
- data/spec/slack/real_time/event_handlers/channel_spec.rb +9 -6
- data/spec/slack/real_time/event_handlers/event_handlers_spec.rb +2 -1
- data/spec/slack/real_time/event_handlers/group_spec.rb +5 -4
- data/spec/slack/real_time/event_handlers/im_spec.rb +4 -3
- data/spec/slack/real_time/event_handlers/team_spec.rb +3 -1
- data/spec/slack/real_time/event_handlers/user_spec.rb +1 -0
- data/spec/slack/real_time/rtm_connect_spec.rb +1 -0
- data/spec/slack/real_time/rtm_start_spec.rb +1 -0
- data/spec/slack/real_time/store_spec.rb +2 -1
- data/spec/slack/slack_spec.rb +37 -5
- data/spec/slack/version_spec.rb +2 -1
- data/spec/slack/web/api/endpoints/admin_apps_approved_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/admin_apps_requests_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/admin_apps_restricted_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/admin_apps_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/admin_conversations_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/admin_emoji_spec.rb +37 -0
- data/spec/slack/web/api/endpoints/admin_inviteRequests_approved_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/admin_inviteRequests_denied_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/admin_inviteRequests_spec.rb +18 -0
- data/spec/slack/web/api/endpoints/admin_teams_admins_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/admin_teams_owners_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/admin_teams_settings_spec.rb +53 -0
- data/spec/slack/web/api/endpoints/admin_teams_spec.rb +16 -0
- data/spec/slack/web/api/endpoints/admin_users_session_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/admin_users_spec.rb +75 -0
- data/spec/slack/web/api/endpoints/api_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/apps_permissions_resources_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/apps_permissions_scopes_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/apps_permissions_spec.rb +3 -2
- data/spec/slack/web/api/endpoints/apps_permissions_users_spec.rb +4 -3
- data/spec/slack/web/api/endpoints/apps_spec.rb +16 -0
- data/spec/slack/web/api/endpoints/bots_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/chat_scheduledMessages_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/conversations_spec.rb +2 -1
- data/spec/slack/web/api/endpoints/custom_specs/auth_spec.rb +5 -1
- data/spec/slack/web/api/endpoints/custom_specs/channels_spec.rb +2 -0
- data/spec/slack/web/api/endpoints/custom_specs/chat_spec.rb +112 -36
- data/spec/slack/web/api/endpoints/custom_specs/dialog_spec.rb +12 -4
- data/spec/slack/web/api/endpoints/custom_specs/groups_spec.rb +2 -0
- data/spec/slack/web/api/endpoints/custom_specs/users_spec.rb +6 -1
- data/spec/slack/web/api/endpoints/custom_specs/views_spec.rb +95 -0
- data/spec/slack/web/api/endpoints/dnd_spec.rb +6 -0
- data/spec/slack/web/api/endpoints/emoji_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/files_comments_spec.rb +1 -19
- data/spec/slack/web/api/endpoints/files_remote_spec.rb +24 -0
- data/spec/slack/web/api/endpoints/files_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/im_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/migration_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/mpim_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/oauth_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/oauth_v2_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/pins_spec.rb +5 -1
- data/spec/slack/web/api/endpoints/reactions_spec.rb +8 -1
- data/spec/slack/web/api/endpoints/reminders_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/rtm_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/search_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/stars_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/team_profile_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/team_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/usergroups_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/usergroups_users_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/users_admin_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/users_prefs_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/users_profile_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/views_spec.rb +29 -0
- data/spec/slack/web/api/error_spec.rb +4 -2
- data/spec/slack/web/api/errors/service_unavailable_spec.rb +6 -3
- data/spec/slack/web/api/errors/slack_error_spec.rb +26 -2
- data/spec/slack/web/api/mixins/channels_spec.rb +17 -7
- data/spec/slack/web/api/mixins/groups_spec.rb +17 -7
- data/spec/slack/web/api/mixins/users_spec.rb +17 -8
- data/spec/slack/web/api/pagination/cursor_spec.rb +40 -10
- data/spec/slack/web/client_spec.rb +45 -18
- data/spec/slack/web/faraday/response/raise_error_spec.rb +41 -7
- data/spec/spec_helper.rb +8 -1
- data/spec/support/queue_with_timeout.rb +5 -4
- data/spec/support/real_time/concurrency/mock.rb +1 -0
- data/spec/support/real_time/connected_client.rb +9 -3
- data/spec/support/real_time/event.rb +1 -0
- data/spec/support/token.rb +1 -0
- data/spec/support/vcr.rb +1 -0
- metadata +149 -9
- data/screenshots/register-bot.png +0 -0
data/lib/slack-ruby-client.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require_relative 'slack/version'
|
|
2
3
|
require_relative 'slack/logger'
|
|
3
4
|
require_relative 'slack/config'
|
|
@@ -14,18 +15,19 @@ require 'json'
|
|
|
14
15
|
require 'logger'
|
|
15
16
|
begin
|
|
16
17
|
require 'picky'
|
|
17
|
-
rescue LoadError
|
|
18
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
|
18
19
|
# ignore, only used in users_search
|
|
19
20
|
end
|
|
20
21
|
begin
|
|
21
22
|
require 'openssl'
|
|
22
|
-
rescue LoadError
|
|
23
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
|
23
24
|
# Used in slack/web/config
|
|
24
25
|
end
|
|
25
26
|
require_relative 'slack/web/config'
|
|
26
27
|
require_relative 'slack/web/api/errors/slack_error'
|
|
27
28
|
require_relative 'slack/web/api/errors/too_many_requests_error'
|
|
28
29
|
require_relative 'slack/web/api/error'
|
|
30
|
+
require_relative 'slack/web/api/errors'
|
|
29
31
|
require_relative 'slack/web/faraday/response/raise_error'
|
|
30
32
|
require_relative 'slack/web/faraday/connection'
|
|
31
33
|
require_relative 'slack/web/faraday/request'
|
|
@@ -47,3 +49,7 @@ require_relative 'slack/real_time/models'
|
|
|
47
49
|
require_relative 'slack/real_time/stores'
|
|
48
50
|
require_relative 'slack/real_time/config'
|
|
49
51
|
require_relative 'slack/real_time/client'
|
|
52
|
+
|
|
53
|
+
# Events API
|
|
54
|
+
require_relative 'slack/events/config'
|
|
55
|
+
require_relative 'slack/events/request'
|
data/lib/slack.rb
CHANGED
data/lib/slack/config.rb
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Slack
|
|
3
|
+
module Events
|
|
4
|
+
module Config
|
|
5
|
+
extend self
|
|
6
|
+
|
|
7
|
+
ATTRIBUTES = %i[
|
|
8
|
+
signing_secret
|
|
9
|
+
signature_expires_in
|
|
10
|
+
].freeze
|
|
11
|
+
|
|
12
|
+
attr_accessor(*Config::ATTRIBUTES)
|
|
13
|
+
|
|
14
|
+
def reset
|
|
15
|
+
self.signing_secret = ENV['SLACK_SIGNING_SECRET']
|
|
16
|
+
self.signature_expires_in = 5 * 60
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def configure
|
|
22
|
+
block_given? ? yield(Config) : Config
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def config
|
|
26
|
+
Config
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Slack::Events::Config.reset
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Slack
|
|
3
|
+
module Events
|
|
4
|
+
class Request
|
|
5
|
+
class MissingSigningSecret < StandardError; end
|
|
6
|
+
class TimestampExpired < StandardError; end
|
|
7
|
+
class InvalidSignature < StandardError; end
|
|
8
|
+
|
|
9
|
+
attr_reader :http_request,
|
|
10
|
+
:signing_secret,
|
|
11
|
+
:signature_expires_in
|
|
12
|
+
|
|
13
|
+
def initialize(http_request, options = {})
|
|
14
|
+
@http_request = http_request
|
|
15
|
+
@signing_secret = options[:signing_secret] || Slack::Events.config.signing_secret
|
|
16
|
+
@signature_expires_in =
|
|
17
|
+
options[:signature_expires_in] || Slack::Events.config.signature_expires_in
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Request timestamp.
|
|
21
|
+
def timestamp
|
|
22
|
+
@timestamp ||= http_request.headers['X-Slack-Request-Timestamp']
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# The signature is created by combining the signing secret with the body of the request
|
|
26
|
+
# Slack is sending using a standard HMAC-SHA256 keyed hash.
|
|
27
|
+
def signature
|
|
28
|
+
@signature ||= http_request.headers['X-Slack-Signature']
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Signature version.
|
|
32
|
+
def version
|
|
33
|
+
'v0'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Request body.
|
|
37
|
+
def body
|
|
38
|
+
@body ||= http_request.body.read
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns true if the signature coming from Slack has expired.
|
|
42
|
+
def expired?
|
|
43
|
+
timestamp.nil? || (Time.now.to_i - timestamp.to_i).abs > signature_expires_in
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns true if the signature coming from Slack is valid.
|
|
47
|
+
def valid?
|
|
48
|
+
raise MissingSigningSecret unless signing_secret
|
|
49
|
+
|
|
50
|
+
digest = OpenSSL::Digest::SHA256.new
|
|
51
|
+
signature_basestring = [version, timestamp, body].join(':')
|
|
52
|
+
hex_hash = OpenSSL::HMAC.hexdigest(digest, signing_secret, signature_basestring)
|
|
53
|
+
computed_signature = [version, hex_hash].join('=')
|
|
54
|
+
computed_signature == signature
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Validates the request signature and its expiration.
|
|
58
|
+
def verify!
|
|
59
|
+
raise TimestampExpired if expired?
|
|
60
|
+
raise InvalidSignature unless valid?
|
|
61
|
+
|
|
62
|
+
true
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/slack/logger.rb
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'logger'
|
|
2
3
|
|
|
3
4
|
module Slack
|
|
4
5
|
class Logger < ::Logger
|
|
5
6
|
def self.default
|
|
6
|
-
@
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
return @default if @default
|
|
8
|
+
|
|
9
|
+
logger = new STDOUT
|
|
10
|
+
logger.level = Logger::WARN
|
|
11
|
+
@default = logger
|
|
11
12
|
end
|
|
12
13
|
end
|
|
13
14
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Slack
|
|
2
3
|
module RealTime
|
|
3
4
|
module Api
|
|
@@ -6,7 +7,8 @@ module Slack
|
|
|
6
7
|
# Sends a message to a channel.
|
|
7
8
|
#
|
|
8
9
|
# @option options [channel] :channel
|
|
9
|
-
# Channel to send message to. Can be a public channel, private group or IM 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.
|
|
10
12
|
# @option options [Object] :text
|
|
11
13
|
# Text of the message to send. See below for an explanation of formatting.
|
|
12
14
|
def message(options = {})
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Slack
|
|
2
3
|
module RealTime
|
|
3
4
|
module Api
|
|
4
5
|
module Ping
|
|
5
6
|
#
|
|
6
|
-
# Clients should try to quickly detect disconnections, even in idle periods, so that users
|
|
7
|
-
#
|
|
7
|
+
# Clients should try to quickly detect disconnections, even in idle periods, so that users
|
|
8
|
+
# can easily tell the
|
|
9
|
+
# difference between being disconnected and everyone being quiet. Not all web browsers
|
|
10
|
+
# support the WebSocket
|
|
8
11
|
# ping spec, so the RTM protocol also supports ping/pong messages.
|
|
9
12
|
#
|
|
10
13
|
def ping(options = {})
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Slack
|
|
2
3
|
module RealTime
|
|
3
4
|
module Api
|
|
@@ -6,7 +7,8 @@ module Slack
|
|
|
6
7
|
# Send a typing indicator to indicate that the user is currently writing a message.
|
|
7
8
|
#
|
|
8
9
|
# @option options [channel] :channel
|
|
9
|
-
# Channel to send message to. Can be a public channel, private group or IM 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.
|
|
10
12
|
def typing(options = {})
|
|
11
13
|
throw ArgumentError.new('Required arguments :channel missing') if options[:channel].nil?
|
|
12
14
|
send_json({ type: 'typing', id: next_id }.merge(options))
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Slack
|
|
2
3
|
module RealTime
|
|
3
4
|
class Client
|
|
@@ -19,8 +20,8 @@ module Slack
|
|
|
19
20
|
attr_accessor :store
|
|
20
21
|
attr_accessor :url
|
|
21
22
|
attr_accessor(*Config::ATTRIBUTES)
|
|
23
|
+
attr_accessor :logger
|
|
22
24
|
|
|
23
|
-
protected :logger, :logger=
|
|
24
25
|
protected :store_class, :store_class=
|
|
25
26
|
|
|
26
27
|
def initialize(options = {})
|
|
@@ -35,7 +36,7 @@ module Slack
|
|
|
35
36
|
|
|
36
37
|
%i[users self channels team teams groups ims bots].each do |store_method|
|
|
37
38
|
define_method store_method do
|
|
38
|
-
store
|
|
39
|
+
store&.send(store_method)
|
|
39
40
|
end
|
|
40
41
|
end
|
|
41
42
|
|
|
@@ -47,7 +48,7 @@ module Slack
|
|
|
47
48
|
# Start RealTime client and block until it disconnects.
|
|
48
49
|
def start!(&block)
|
|
49
50
|
@callback = block if block_given?
|
|
50
|
-
|
|
51
|
+
build_socket
|
|
51
52
|
@socket.start_sync(self)
|
|
52
53
|
end
|
|
53
54
|
|
|
@@ -55,17 +56,18 @@ module Slack
|
|
|
55
56
|
# The RealTime::Client will run in the background.
|
|
56
57
|
def start_async(&block)
|
|
57
58
|
@callback = block if block_given?
|
|
58
|
-
|
|
59
|
+
build_socket
|
|
59
60
|
@socket.start_async(self)
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
def stop!
|
|
63
64
|
raise ClientNotStartedError unless started?
|
|
64
|
-
|
|
65
|
+
|
|
66
|
+
@socket&.disconnect!
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
def started?
|
|
68
|
-
@socket
|
|
70
|
+
@socket&.connected?
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
class << self
|
|
@@ -80,38 +82,105 @@ module Slack
|
|
|
80
82
|
|
|
81
83
|
def run_loop
|
|
82
84
|
@socket.connect! do |driver|
|
|
83
|
-
@callback.call(driver) if @callback
|
|
84
|
-
|
|
85
85
|
driver.on :open do |event|
|
|
86
|
-
logger.debug("#{self
|
|
87
|
-
|
|
86
|
+
logger.debug("#{self}##{__method__}") { event.class.name }
|
|
87
|
+
open_event(event)
|
|
88
88
|
callback(event, :open)
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
driver.on :message do |event|
|
|
92
|
-
logger.debug("#{self
|
|
92
|
+
logger.debug("#{self}##{__method__}") { "#{event.class}, #{event.data}" }
|
|
93
93
|
dispatch(event)
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
driver.on :close do |event|
|
|
97
|
-
logger.debug("#{self
|
|
97
|
+
logger.debug("#{self}##{__method__}") { event.class.name }
|
|
98
98
|
callback(event, :close)
|
|
99
99
|
close(event)
|
|
100
100
|
callback(event, :closed)
|
|
101
101
|
end
|
|
102
|
+
|
|
103
|
+
# This must be called last to ensure any events are registered before invoking user code.
|
|
104
|
+
@callback&.call(driver)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Ensure the server is running, and ping the remote server if no other messages were sent.
|
|
109
|
+
def keep_alive?
|
|
110
|
+
# We can't ping the remote server if we aren't connected.
|
|
111
|
+
return false if @socket.nil? || !@socket.connected?
|
|
112
|
+
|
|
113
|
+
time_since_last_message = @socket.time_since_last_message
|
|
114
|
+
|
|
115
|
+
# If the server responded within the specified time, we are okay:
|
|
116
|
+
return true if time_since_last_message < websocket_ping
|
|
117
|
+
|
|
118
|
+
# If the server has not responded for a while:
|
|
119
|
+
return false if time_since_last_message > (websocket_ping * 2)
|
|
120
|
+
|
|
121
|
+
# Kick off the next ping message:
|
|
122
|
+
ping
|
|
123
|
+
|
|
124
|
+
true
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Check if the remote server is responsive, and if not, restart the connection.
|
|
128
|
+
def run_ping!
|
|
129
|
+
return if keep_alive?
|
|
130
|
+
|
|
131
|
+
logger.warn(to_s) { 'is offline' }
|
|
132
|
+
|
|
133
|
+
restart_async
|
|
134
|
+
rescue Slack::Web::Api::Errors::SlackError => e
|
|
135
|
+
# stop pinging if bot was uninstalled
|
|
136
|
+
case e.message
|
|
137
|
+
when 'account_inactive', 'invalid_auth' then
|
|
138
|
+
logger.warn(to_s) { e.message }
|
|
139
|
+
raise e
|
|
140
|
+
end
|
|
141
|
+
logger.debug("#{self}##{__method__}") { e }
|
|
142
|
+
rescue StandardError => e
|
|
143
|
+
# disregard all ping worker failures, keep pinging
|
|
144
|
+
logger.debug("#{self}##{__method__}") { e }
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def run_ping?
|
|
148
|
+
!websocket_ping.nil? && websocket_ping.positive?
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def websocket_ping_timer
|
|
152
|
+
websocket_ping / 2
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def to_s
|
|
156
|
+
if store&.team
|
|
157
|
+
"id=#{store.team.id}, name=#{store.team.name}, domain=#{store.team.domain}"
|
|
158
|
+
else
|
|
159
|
+
super
|
|
102
160
|
end
|
|
103
161
|
end
|
|
104
162
|
|
|
105
163
|
protected
|
|
106
164
|
|
|
165
|
+
def restart_async
|
|
166
|
+
logger.debug("#{self}##{__method__}")
|
|
167
|
+
@socket.close
|
|
168
|
+
start = web_client.send(rtm_start_method, start_options)
|
|
169
|
+
data = Slack::Messages::Message.new(start)
|
|
170
|
+
@url = data.url
|
|
171
|
+
@store = @store_class.new(data) if @store_class
|
|
172
|
+
@socket.restart_async(self, @url)
|
|
173
|
+
end
|
|
174
|
+
|
|
107
175
|
# @return [Slack::RealTime::Socket]
|
|
108
176
|
def build_socket
|
|
109
177
|
raise ClientAlreadyStartedError if started?
|
|
178
|
+
|
|
110
179
|
start = web_client.send(rtm_start_method, start_options)
|
|
111
180
|
data = Slack::Messages::Message.new(start)
|
|
112
181
|
@url = data.url
|
|
113
182
|
@store = @store_class.new(data) if @store_class
|
|
114
|
-
socket_class.new(@url, socket_options)
|
|
183
|
+
@socket = socket_class.new(@url, socket_options)
|
|
115
184
|
end
|
|
116
185
|
|
|
117
186
|
def rtm_start_method
|
|
@@ -139,17 +208,15 @@ module Slack
|
|
|
139
208
|
|
|
140
209
|
def send_json(data)
|
|
141
210
|
raise ClientNotStartedError unless started?
|
|
142
|
-
|
|
211
|
+
|
|
212
|
+
logger.debug("#{self}##{__method__}") { data }
|
|
143
213
|
@socket.send_data(data.to_json)
|
|
144
214
|
end
|
|
145
215
|
|
|
146
|
-
def
|
|
216
|
+
def open_event(_event); end
|
|
147
217
|
|
|
148
218
|
def close(_event)
|
|
149
|
-
socket
|
|
150
|
-
@socket = nil
|
|
151
|
-
|
|
152
|
-
[socket, socket_class].each do |s|
|
|
219
|
+
[@socket, socket_class].each do |s|
|
|
153
220
|
s.close if s.respond_to?(:close)
|
|
154
221
|
end
|
|
155
222
|
end
|
|
@@ -157,50 +224,52 @@ module Slack
|
|
|
157
224
|
def callback(event, type)
|
|
158
225
|
callbacks = self.callbacks[type.to_s]
|
|
159
226
|
return false unless callbacks
|
|
227
|
+
|
|
160
228
|
callbacks.each do |c|
|
|
161
229
|
c.call(event)
|
|
162
230
|
end
|
|
163
231
|
true
|
|
164
232
|
rescue StandardError => e
|
|
165
|
-
logger.error e
|
|
233
|
+
logger.error("#{self}##{__method__}") { e }
|
|
166
234
|
false
|
|
167
235
|
end
|
|
168
236
|
|
|
169
237
|
def dispatch(event)
|
|
170
238
|
return false unless event.data
|
|
239
|
+
|
|
171
240
|
data = Slack::Messages::Message.new(JSON.parse(event.data))
|
|
172
241
|
type = data.type
|
|
173
242
|
return false unless type
|
|
243
|
+
|
|
174
244
|
type = type.to_s
|
|
175
|
-
logger.debug("#{self
|
|
245
|
+
logger.debug("#{self}##{__method__}") { data.to_s }
|
|
176
246
|
run_handlers(type, data) if @store
|
|
177
247
|
run_callbacks(type, data)
|
|
178
248
|
rescue StandardError => e
|
|
179
|
-
logger.error e
|
|
249
|
+
logger.error("#{self}##{__method__}") { e }
|
|
180
250
|
false
|
|
181
251
|
end
|
|
182
252
|
|
|
183
253
|
def run_handlers(type, data)
|
|
184
254
|
handlers = store.class.events[type.to_s]
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
store.instance_exec(data, &handler)
|
|
188
|
-
end
|
|
255
|
+
handlers&.each do |handler|
|
|
256
|
+
store.instance_exec(data, &handler)
|
|
189
257
|
end
|
|
190
258
|
rescue StandardError => e
|
|
191
|
-
logger.error e
|
|
259
|
+
logger.error("#{self}##{__method__}") { e }
|
|
192
260
|
false
|
|
193
261
|
end
|
|
194
262
|
|
|
195
263
|
def run_callbacks(type, data)
|
|
196
264
|
callbacks = self.callbacks[type]
|
|
197
265
|
return false unless callbacks
|
|
266
|
+
|
|
198
267
|
callbacks.each do |c|
|
|
199
268
|
c.call(data)
|
|
200
269
|
end
|
|
201
270
|
true
|
|
202
271
|
rescue StandardError => e
|
|
203
|
-
logger.error e
|
|
272
|
+
logger.error("#{self}##{__method__}") { e }
|
|
204
273
|
false
|
|
205
274
|
end
|
|
206
275
|
end
|