slack-ruby-client 0.7.9 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +1 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +32 -1
- data/.rubocop_todo.yml +98 -49
- data/.travis.yml +10 -14
- data/CHANGELOG.md +172 -24
- data/CONTRIBUTING.md +17 -6
- data/Dangerfile +2 -0
- data/Gemfile +10 -4
- data/LICENSE.md +1 -1
- data/README.md +276 -54
- data/RELEASING.md +19 -11
- data/Rakefile +2 -1
- data/UPGRADING.md +84 -2
- data/bin/commands.rb +43 -1
- data/bin/commands/admin_analytics.rb +15 -0
- data/bin/commands/admin_apps.rb +40 -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_barriers.rb +47 -0
- data/bin/commands/admin_conversations.rb +169 -0
- data/bin/commands/admin_conversations_ekm.rb +17 -0
- data/bin/commands/admin_conversations_restrictAccess.rb +37 -0
- data/bin/commands/admin_conversations_whitelist.rb +37 -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_usergroups.rb +48 -0
- data/bin/commands/admin_users.rb +97 -0
- data/bin/commands/admin_users_session.rb +38 -0
- data/bin/commands/api.rb +3 -3
- data/bin/commands/apps.rb +15 -0
- data/bin/commands/apps_connections.rb +13 -0
- data/bin/commands/apps_event_authorizations.rb +16 -0
- data/bin/commands/apps_permissions.rb +23 -0
- data/bin/commands/apps_permissions_resources.rb +15 -0
- data/bin/commands/apps_permissions_scopes.rb +13 -0
- data/bin/commands/apps_permissions_users.rb +26 -0
- data/bin/commands/auth.rb +5 -4
- data/bin/commands/auth_teams.rb +16 -0
- data/bin/commands/bots.rb +4 -2
- data/bin/commands/calls.rb +52 -0
- data/bin/commands/calls_participants.rb +25 -0
- data/bin/commands/channels.rb +64 -43
- data/bin/commands/chat.rb +114 -24
- data/bin/commands/chat_scheduledMessages.rb +19 -0
- data/bin/commands/conversations.rb +196 -0
- data/bin/commands/dialog.rb +15 -0
- data/bin/commands/dnd.rb +9 -8
- data/bin/commands/emoji.rb +3 -2
- data/bin/commands/files.rb +45 -30
- data/bin/commands/files_comments.rb +3 -24
- data/bin/commands/files_remote.rb +78 -0
- data/bin/commands/groups.rb +53 -53
- data/bin/commands/im.rb +17 -13
- data/bin/commands/migration.rb +16 -0
- data/bin/commands/mpim.rb +16 -13
- data/bin/commands/oauth.rb +17 -2
- data/bin/commands/oauth_v2.rb +17 -0
- data/bin/commands/pins.rb +7 -10
- data/bin/commands/reactions.rb +17 -15
- data/bin/commands/reminders.rb +11 -10
- data/bin/commands/rtm.rb +19 -4
- data/bin/commands/search.rb +15 -11
- data/bin/commands/stars.rb +11 -8
- data/bin/commands/team.rb +15 -10
- data/bin/commands/team_profile.rb +3 -2
- data/bin/commands/usergroups.rb +22 -16
- data/bin/commands/usergroups_users.rb +7 -4
- data/bin/commands/users.rb +65 -37
- data/bin/commands/users_admin.rb +29 -0
- data/bin/commands/users_prefs.rb +13 -0
- data/bin/commands/users_profile.rb +8 -7
- data/bin/commands/views.rb +48 -0
- data/bin/commands/workflows.rb +38 -0
- data/bin/slack +3 -4
- data/examples/hi_real_time_and_web/Gemfile +1 -0
- data/examples/hi_real_time_and_web/hi.rb +8 -4
- data/examples/{hi_real_time_async_eventmachine → hi_real_time_async_async}/Gemfile +2 -1
- data/examples/{hi_real_time_async_celluloid → hi_real_time_async_async}/Procfile +0 -0
- data/examples/{hi_real_time_async_celluloid → hi_real_time_async_async}/hi.rb +13 -8
- data/examples/hi_web/Gemfile +1 -0
- data/examples/hi_web/hi.rb +2 -1
- data/examples/new_ticket/Gemfile +1 -0
- data/examples/new_ticket/new_ticket.rb +2 -1
- data/lib/slack-ruby-client.rb +40 -26
- 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 +70 -0
- data/lib/slack/logger.rb +6 -5
- data/lib/slack/messages/formatting.rb +4 -4
- data/lib/slack/messages/message.rb +2 -6
- 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/templates/event_handler.erb +1 -1
- data/lib/slack/real_time/api/typing.rb +3 -1
- data/lib/slack/real_time/client.rb +113 -32
- data/lib/slack/real_time/concurrency.rb +2 -2
- data/lib/slack/real_time/concurrency/async.rb +140 -0
- data/lib/slack/real_time/config.rb +20 -12
- data/lib/slack/real_time/models.rb +8 -7
- data/lib/slack/real_time/models/base.rb +2 -6
- 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 +46 -17
- data/lib/slack/real_time/stores.rb +4 -3
- data/lib/slack/real_time/stores/base.rb +5 -3
- data/lib/slack/real_time/stores/starter.rb +113 -72
- data/lib/slack/real_time/stores/store.rb +131 -88
- data/lib/slack/version.rb +2 -1
- data/lib/slack/web/api/endpoints.rb +110 -26
- data/lib/slack/web/api/endpoints/admin_analytics.rb +26 -0
- data/lib/slack/web/api/endpoints/admin_apps.rb +62 -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_barriers.rb +82 -0
- data/lib/slack/web/api/endpoints/admin_conversations.rb +260 -0
- data/lib/slack/web/api/endpoints/admin_conversations_ekm.rb +35 -0
- data/lib/slack/web/api/endpoints/admin_conversations_restrictAccess.rb +61 -0
- data/lib/slack/web/api/endpoints/admin_conversations_whitelist.rb +64 -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_usergroups.rb +77 -0
- data/lib/slack/web/api/endpoints/admin_users.rb +161 -0
- data/lib/slack/web/api/endpoints/admin_users_session.rb +66 -0
- data/lib/slack/web/api/endpoints/api.rb +3 -4
- data/lib/slack/web/api/endpoints/apps.rb +27 -0
- data/lib/slack/web/api/endpoints/apps_connections.rb +21 -0
- data/lib/slack/web/api/endpoints/apps_event_authorizations.rb +34 -0
- data/lib/slack/web/api/endpoints/apps_permissions.rb +36 -0
- data/lib/slack/web/api/endpoints/apps_permissions_resources.rb +31 -0
- data/lib/slack/web/api/endpoints/apps_permissions_scopes.rb +21 -0
- data/lib/slack/web/api/endpoints/apps_permissions_users.rb +50 -0
- data/lib/slack/web/api/endpoints/auth.rb +5 -4
- data/lib/slack/web/api/endpoints/auth_teams.rb +33 -0
- data/lib/slack/web/api/endpoints/bots.rb +5 -2
- data/lib/slack/web/api/endpoints/calls.rb +83 -0
- data/lib/slack/web/api/endpoints/calls_participants.rb +42 -0
- data/lib/slack/web/api/endpoints/channels.rb +105 -49
- data/lib/slack/web/api/endpoints/chat.rb +221 -40
- data/lib/slack/web/api/endpoints/chat_scheduledMessages.rb +40 -0
- data/lib/slack/web/api/endpoints/conversations.rb +332 -0
- data/lib/slack/web/api/endpoints/dialog.rb +33 -0
- data/lib/slack/web/api/endpoints/dnd.rb +11 -9
- data/lib/slack/web/api/endpoints/emoji.rb +3 -2
- data/lib/slack/web/api/endpoints/files.rb +75 -38
- data/lib/slack/web/api/endpoints/files_comments.rb +3 -38
- data/lib/slack/web/api/endpoints/files_remote.rb +127 -0
- data/lib/slack/web/api/endpoints/groups.rb +76 -53
- data/lib/slack/web/api/endpoints/im.rb +38 -21
- data/lib/slack/web/api/endpoints/migration.rb +28 -0
- data/lib/slack/web/api/endpoints/mpim.rb +37 -22
- data/lib/slack/web/api/endpoints/oauth.rb +25 -4
- data/lib/slack/web/api/endpoints/oauth_v2.rb +30 -0
- data/lib/slack/web/api/endpoints/pins.rb +10 -19
- data/lib/slack/web/api/endpoints/presence.rb +1 -1
- data/lib/slack/web/api/endpoints/reactions.rb +37 -28
- data/lib/slack/web/api/endpoints/reminders.rb +11 -10
- data/lib/slack/web/api/endpoints/rtm.rb +28 -7
- data/lib/slack/web/api/endpoints/search.rb +21 -14
- data/lib/slack/web/api/endpoints/stars.rb +24 -15
- data/lib/slack/web/api/endpoints/team.rb +21 -13
- data/lib/slack/web/api/endpoints/team_profile.rb +3 -2
- data/lib/slack/web/api/endpoints/usergroups.rb +33 -22
- data/lib/slack/web/api/endpoints/usergroups_users.rb +9 -4
- data/lib/slack/web/api/endpoints/users.rb +78 -29
- data/lib/slack/web/api/endpoints/users_admin.rb +49 -0
- data/lib/slack/web/api/endpoints/users_prefs.rb +21 -0
- data/lib/slack/web/api/endpoints/users_profile.rb +11 -10
- data/lib/slack/web/api/endpoints/views.rb +97 -0
- data/lib/slack/web/api/endpoints/workflows.rb +61 -0
- data/lib/slack/web/api/error.rb +2 -8
- data/lib/slack/web/api/errors.rb +850 -0
- data/lib/slack/web/api/errors/internal_error.rb +14 -0
- data/lib/slack/web/api/errors/slack_error.rb +29 -0
- data/lib/slack/web/api/errors/too_many_requests_error.rb +24 -0
- data/lib/slack/web/api/mixins.rb +6 -4
- data/lib/slack/web/api/mixins/channels.id.rb +6 -7
- data/lib/slack/web/api/mixins/conversations.id.rb +25 -0
- data/lib/slack/web/api/mixins/groups.id.rb +6 -7
- data/lib/slack/web/api/mixins/ids.id.rb +24 -0
- data/lib/slack/web/api/mixins/users.id.rb +6 -7
- data/lib/slack/web/api/mixins/users.search.rb +39 -36
- data/lib/slack/web/api/patches/chat.1.patch +72 -0
- data/lib/slack/web/api/patches/dialog.1.open-json-support.patch +17 -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 +5 -3
- data/lib/slack/web/api/templates/commands.erb +2 -1
- data/lib/slack/web/api/templates/endpoints.erb +5 -3
- data/lib/slack/web/api/templates/errors.erb +20 -0
- data/lib/slack/web/api/templates/method.erb +26 -4
- data/lib/slack/web/api/templates/method_spec.erb +3 -2
- data/lib/slack/web/client.rb +2 -1
- data/lib/slack/web/config.rb +21 -10
- data/lib/slack/web/faraday/connection.rb +25 -16
- data/lib/slack/web/faraday/request.rb +2 -0
- data/lib/slack/web/faraday/response/raise_error.rb +23 -1
- data/lib/slack/web/faraday/response/wrap_error.rb +18 -0
- data/lib/slack/web/pagination/cursor.rb +52 -0
- data/lib/slack_ruby_client.rb +1 -0
- data/lib/tasks/git.rake +2 -1
- data/lib/tasks/real_time.rake +16 -6
- data/lib/tasks/update.rake +1 -0
- data/lib/tasks/web.rake +38 -10
- data/screenshots/create-app.png +0 -0
- data/slack-ruby-client.gemspec +9 -6
- data/spec/fixtures/slack/web/429_error.yml +2 -0
- data/spec/fixtures/slack/web/503_error.yml +14 -0
- data/spec/fixtures/slack/web/channels_info.yml +108 -15
- data/spec/fixtures/slack/web/conversations_setTopic.yml +69 -0
- data/spec/fixtures/slack/web/conversations_setTopic_one_page.yml +142 -0
- data/spec/fixtures/slack/web/conversations_setTopic_paginated.yml +208 -0
- data/spec/fixtures/slack/web/paginated_users_list.yml +181 -0
- data/spec/fixtures/slack/web/rtm_connect.yml +70 -0
- data/spec/fixtures/slack/web/rtm_start.yml +1 -1
- 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 +183 -0
- data/spec/slack/messages/formatting_spec.rb +25 -14
- 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 +462 -134
- data/spec/slack/real_time/concurrency/it_behaves_like_a_realtime_socket.rb +3 -1
- data/spec/slack/real_time/event_handlers/bot_spec.rb +6 -3
- data/spec/slack/real_time/event_handlers/channel_spec.rb +9 -6
- data/spec/slack/real_time/event_handlers/event_handlers_spec.rb +3 -2
- 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 +8 -4
- data/spec/slack/real_time/event_handlers/user_spec.rb +5 -2
- data/spec/slack/real_time/rtm_connect_spec.rb +14 -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 +39 -7
- data/spec/slack/version_spec.rb +2 -1
- data/spec/slack/web/api/endpoints/admin_analytics_spec.rb +13 -0
- 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 +13 -0
- data/spec/slack/web/api/endpoints/admin_barriers_spec.rb +38 -0
- data/spec/slack/web/api/endpoints/admin_conversations_ekm_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/admin_conversations_restrictAccess_spec.rb +32 -0
- data/spec/slack/web/api/endpoints/admin_conversations_spec.rb +98 -0
- data/spec/slack/web/api/endpoints/admin_conversations_whitelist_spec.rb +32 -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_usergroups_spec.rb +37 -0
- data/spec/slack/web/api/endpoints/admin_users_session_spec.rb +21 -0
- data/spec/slack/web/api/endpoints/admin_users_spec.rb +67 -0
- data/spec/slack/web/api/endpoints/api_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/apps_connections_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/apps_event_authorizations_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/apps_permissions_resources_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/apps_permissions_scopes_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/apps_permissions_spec.rb +16 -0
- data/spec/slack/web/api/endpoints/apps_permissions_users_spec.rb +19 -0
- data/spec/slack/web/api/endpoints/apps_spec.rb +16 -0
- data/spec/slack/web/api/endpoints/auth_teams_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/bots_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/calls_participants_spec.rb +24 -0
- data/spec/slack/web/api/endpoints/calls_spec.rb +31 -0
- data/spec/slack/web/api/endpoints/chat_scheduledMessages_spec.rb +8 -0
- data/spec/slack/web/api/endpoints/conversations_spec.rb +109 -0
- data/spec/slack/web/api/endpoints/custom_specs/auth_spec.rb +13 -4
- data/spec/slack/web/api/endpoints/custom_specs/channels_spec.rb +5 -3
- data/spec/slack/web/api/endpoints/custom_specs/chat_spec.rb +140 -24
- data/spec/slack/web/api/endpoints/custom_specs/dialog_spec.rb +36 -0
- data/spec/slack/web/api/endpoints/custom_specs/groups_spec.rb +2 -0
- data/spec/slack/web/api/endpoints/custom_specs/users_spec.rb +21 -6
- 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 +3 -21
- data/spec/slack/web/api/endpoints/files_remote_spec.rb +24 -0
- data/spec/slack/web/api/endpoints/files_spec.rb +17 -5
- data/spec/slack/web/api/endpoints/im_spec.rb +5 -4
- data/spec/slack/web/api/endpoints/migration_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/mpim_spec.rb +5 -4
- data/spec/slack/web/api/endpoints/oauth_spec.rb +5 -4
- data/spec/slack/web/api/endpoints/oauth_v2_spec.rb +13 -0
- data/spec/slack/web/api/endpoints/pins_spec.rb +1 -0
- data/spec/slack/web/api/endpoints/reactions_spec.rb +8 -1
- data/spec/slack/web/api/endpoints/reminders_spec.rb +3 -2
- 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 +3 -2
- data/spec/slack/web/api/endpoints/users_admin_spec.rb +18 -0
- data/spec/slack/web/api/endpoints/users_prefs_spec.rb +8 -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/endpoints/workflows_spec.rb +26 -0
- data/spec/slack/web/api/error_spec.rb +5 -3
- data/spec/slack/web/api/errors/slack_error_spec.rb +38 -0
- data/spec/slack/web/api/mixins/channels_spec.rb +24 -12
- data/spec/slack/web/api/mixins/conversations_list_spec.rb +21 -0
- data/spec/slack/web/api/mixins/conversations_spec.rb +43 -0
- data/spec/slack/web/api/mixins/groups_spec.rb +24 -12
- data/spec/slack/web/api/mixins/users_spec.rb +30 -17
- data/spec/slack/web/api/pagination/cursor_spec.rb +100 -0
- data/spec/slack/web/client_spec.rb +215 -14
- data/spec/slack/web/faraday/response/raise_error_spec.rb +85 -0
- data/spec/spec_helper.rb +8 -1
- data/spec/support/queue_with_timeout.rb +6 -5
- data/spec/support/real_time/concurrency/mock.rb +2 -2
- data/spec/support/real_time/connected_client.rb +13 -2
- data/spec/support/real_time/event.rb +1 -0
- data/spec/support/token.rb +1 -0
- data/spec/support/vcr.rb +6 -1
- metadata +280 -55
- data/examples/hi_real_time/Gemfile +0 -5
- data/examples/hi_real_time/hi.gif +0 -0
- data/examples/hi_real_time/hi.rb +0 -37
- data/examples/hi_real_time_async_celluloid/Gemfile +0 -6
- data/examples/hi_real_time_async_eventmachine/Procfile +0 -2
- data/examples/hi_real_time_async_eventmachine/hi.rb +0 -36
- data/lib/slack/real_time/concurrency/celluloid.rb +0 -113
- data/lib/slack/real_time/concurrency/eventmachine.rb +0 -60
- data/lib/slack/web/api/patches/chat.1.text-attachments-required.patch +0 -13
- data/lib/slack/web/api/patches/chat.2.attachments-json.patch +0 -17
- data/lib/slack/web/api/patches/chat.3.update-attachments-support.patch +0 -20
- data/screenshots/register-bot.png +0 -0
- data/spec/slack/real_time/concurrency/celluloid_spec.rb +0 -31
- data/spec/slack/real_time/concurrency/eventmachine_spec.rb +0 -47
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,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
module Slack
|
3
3
|
module Messages
|
4
4
|
module Formatting
|
@@ -10,9 +10,9 @@ module Slack
|
|
10
10
|
def unescape(message)
|
11
11
|
CGI.unescapeHTML(message.gsub(/[“”]/, '"')
|
12
12
|
.gsub(/[‘’]/, "'")
|
13
|
-
.gsub(/<(?<sign>[?@#!]?)(?<dt>.*?)>/) do
|
14
|
-
sign =
|
15
|
-
dt =
|
13
|
+
.gsub(/<(?<sign>[?@#!]?)(?<dt>.*?)>/) do
|
14
|
+
sign = Regexp.last_match[:sign]
|
15
|
+
dt = Regexp.last_match[:dt]
|
16
16
|
rhs = dt.split('|', 2).last
|
17
17
|
case sign
|
18
18
|
when '@', '!'
|
@@ -1,10 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Slack
|
2
3
|
module Messages
|
3
4
|
class Message < Hashie::Mash
|
4
|
-
def presence
|
5
|
-
super['presence']
|
6
|
-
end
|
7
|
-
|
8
5
|
def to_s
|
9
6
|
keys.sort_by(&:to_s).map do |key|
|
10
7
|
"#{key}=#{self[key]}"
|
@@ -14,8 +11,7 @@ module Slack
|
|
14
11
|
private
|
15
12
|
|
16
13
|
# see https://github.com/intridea/hashie/issues/394
|
17
|
-
def log_built_in_message(*)
|
18
|
-
end
|
14
|
+
def log_built_in_message(*); end
|
19
15
|
end
|
20
16
|
end
|
21
17
|
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
|
@@ -20,7 +21,6 @@ module Slack
|
|
20
21
|
attr_accessor :url
|
21
22
|
attr_accessor(*Config::ATTRIBUTES)
|
22
23
|
|
23
|
-
protected :logger, :logger=
|
24
24
|
protected :store_class, :store_class=
|
25
25
|
|
26
26
|
def initialize(options = {})
|
@@ -33,9 +33,9 @@ module Slack
|
|
33
33
|
@web_client = Slack::Web::Client.new(token: token, logger: logger)
|
34
34
|
end
|
35
35
|
|
36
|
-
[
|
36
|
+
%i[users self channels team teams groups ims bots].each do |store_method|
|
37
37
|
define_method store_method do
|
38
|
-
store
|
38
|
+
store&.send(store_method)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -47,7 +47,7 @@ module Slack
|
|
47
47
|
# Start RealTime client and block until it disconnects.
|
48
48
|
def start!(&block)
|
49
49
|
@callback = block if block_given?
|
50
|
-
|
50
|
+
build_socket
|
51
51
|
@socket.start_sync(self)
|
52
52
|
end
|
53
53
|
|
@@ -55,17 +55,18 @@ module Slack
|
|
55
55
|
# The RealTime::Client will run in the background.
|
56
56
|
def start_async(&block)
|
57
57
|
@callback = block if block_given?
|
58
|
-
|
58
|
+
build_socket
|
59
59
|
@socket.start_async(self)
|
60
60
|
end
|
61
61
|
|
62
62
|
def stop!
|
63
|
-
|
64
|
-
|
63
|
+
raise ClientNotStartedError unless started?
|
64
|
+
|
65
|
+
@socket&.disconnect!
|
65
66
|
end
|
66
67
|
|
67
68
|
def started?
|
68
|
-
@socket
|
69
|
+
@socket&.connected?
|
69
70
|
end
|
70
71
|
|
71
72
|
class << self
|
@@ -80,38 +81,115 @@ module Slack
|
|
80
81
|
|
81
82
|
def run_loop
|
82
83
|
@socket.connect! do |driver|
|
83
|
-
@callback.call(driver) if @callback
|
84
|
-
|
85
84
|
driver.on :open do |event|
|
86
|
-
logger.debug("#{self
|
87
|
-
|
85
|
+
logger.debug("#{self}##{__method__}") { event.class.name }
|
86
|
+
open_event(event)
|
88
87
|
callback(event, :open)
|
89
88
|
end
|
90
89
|
|
91
90
|
driver.on :message do |event|
|
92
|
-
logger.debug("#{self
|
91
|
+
logger.debug("#{self}##{__method__}") { "#{event.class}, #{event.data}" }
|
93
92
|
dispatch(event)
|
94
93
|
end
|
95
94
|
|
96
95
|
driver.on :close do |event|
|
97
|
-
logger.debug("#{self
|
96
|
+
logger.debug("#{self}##{__method__}") { event.class.name }
|
98
97
|
callback(event, :close)
|
99
98
|
close(event)
|
100
99
|
callback(event, :closed)
|
101
100
|
end
|
101
|
+
|
102
|
+
# This must be called last to ensure any events are registered before invoking user code.
|
103
|
+
@callback&.call(driver)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Ensure the server is running, and ping the remote server if no other messages were sent.
|
108
|
+
def keep_alive?
|
109
|
+
# We can't ping the remote server if we aren't connected.
|
110
|
+
return false if @socket.nil? || !@socket.connected?
|
111
|
+
|
112
|
+
time_since_last_message = @socket.time_since_last_message
|
113
|
+
|
114
|
+
# If the server responded within the specified time, we are okay:
|
115
|
+
return true if time_since_last_message < websocket_ping
|
116
|
+
|
117
|
+
# If the server has not responded for a while:
|
118
|
+
return false if time_since_last_message > (websocket_ping * 2)
|
119
|
+
|
120
|
+
# Kick off the next ping message:
|
121
|
+
ping
|
122
|
+
|
123
|
+
true
|
124
|
+
end
|
125
|
+
|
126
|
+
# Check if the remote server is responsive, and if not, restart the connection.
|
127
|
+
def run_ping!
|
128
|
+
return if keep_alive?
|
129
|
+
|
130
|
+
logger.warn(to_s) { 'is offline' }
|
131
|
+
|
132
|
+
restart_async
|
133
|
+
rescue Slack::Web::Api::Errors::SlackError => e
|
134
|
+
# stop pinging if bot was uninstalled
|
135
|
+
case e.message
|
136
|
+
when 'account_inactive', 'invalid_auth' then
|
137
|
+
logger.warn(to_s) { e.message }
|
138
|
+
raise e
|
139
|
+
end
|
140
|
+
logger.debug("#{self}##{__method__}") { e }
|
141
|
+
rescue StandardError => e
|
142
|
+
# disregard all ping worker failures, keep pinging
|
143
|
+
logger.debug("#{self}##{__method__}") { e }
|
144
|
+
end
|
145
|
+
|
146
|
+
def run_ping?
|
147
|
+
!websocket_ping.nil? && websocket_ping.positive?
|
148
|
+
end
|
149
|
+
|
150
|
+
def websocket_ping_timer
|
151
|
+
websocket_ping / 2
|
152
|
+
end
|
153
|
+
|
154
|
+
def to_s
|
155
|
+
if store&.team
|
156
|
+
"id=#{store.team.id}, name=#{store.team.name}, domain=#{store.team.domain}"
|
157
|
+
else
|
158
|
+
super
|
102
159
|
end
|
103
160
|
end
|
104
161
|
|
105
162
|
protected
|
106
163
|
|
164
|
+
def restart_async
|
165
|
+
logger.debug("#{self}##{__method__}")
|
166
|
+
@socket.close
|
167
|
+
start = web_client.send(rtm_start_method, start_options)
|
168
|
+
data = Slack::Messages::Message.new(start)
|
169
|
+
@url = data.url
|
170
|
+
@store = @store_class.new(data) if @store_class
|
171
|
+
@socket.restart_async(self, @url)
|
172
|
+
end
|
173
|
+
|
107
174
|
# @return [Slack::RealTime::Socket]
|
108
175
|
def build_socket
|
109
|
-
|
110
|
-
|
176
|
+
raise ClientAlreadyStartedError if started?
|
177
|
+
|
178
|
+
start = web_client.send(rtm_start_method, start_options)
|
111
179
|
data = Slack::Messages::Message.new(start)
|
112
180
|
@url = data.url
|
113
181
|
@store = @store_class.new(data) if @store_class
|
114
|
-
socket_class.new(@url, socket_options)
|
182
|
+
@socket = socket_class.new(@url, socket_options)
|
183
|
+
end
|
184
|
+
|
185
|
+
def rtm_start_method
|
186
|
+
if start_method
|
187
|
+
start_method
|
188
|
+
elsif @store_class && @store_class <= Slack::RealTime::Stores::Store
|
189
|
+
:rtm_start
|
190
|
+
else
|
191
|
+
:rtm_connect
|
192
|
+
end
|
115
193
|
end
|
116
194
|
|
117
195
|
def socket_options
|
@@ -128,19 +206,16 @@ module Slack
|
|
128
206
|
end
|
129
207
|
|
130
208
|
def send_json(data)
|
131
|
-
|
132
|
-
|
209
|
+
raise ClientNotStartedError unless started?
|
210
|
+
|
211
|
+
logger.debug("#{self}##{__method__}") { data }
|
133
212
|
@socket.send_data(data.to_json)
|
134
213
|
end
|
135
214
|
|
136
|
-
def
|
137
|
-
end
|
215
|
+
def open_event(_event); end
|
138
216
|
|
139
217
|
def close(_event)
|
140
|
-
socket
|
141
|
-
@socket = nil
|
142
|
-
|
143
|
-
[socket, socket_class].each do |s|
|
218
|
+
[@socket, socket_class].each do |s|
|
144
219
|
s.close if s.respond_to?(:close)
|
145
220
|
end
|
146
221
|
end
|
@@ -148,48 +223,54 @@ module Slack
|
|
148
223
|
def callback(event, type)
|
149
224
|
callbacks = self.callbacks[type.to_s]
|
150
225
|
return false unless callbacks
|
226
|
+
|
151
227
|
callbacks.each do |c|
|
152
228
|
c.call(event)
|
153
229
|
end
|
154
230
|
true
|
155
231
|
rescue StandardError => e
|
156
|
-
logger.error e
|
232
|
+
logger.error("#{self}##{__method__}") { e }
|
157
233
|
false
|
158
234
|
end
|
159
235
|
|
160
236
|
def dispatch(event)
|
161
237
|
return false unless event.data
|
238
|
+
|
162
239
|
data = Slack::Messages::Message.new(JSON.parse(event.data))
|
163
240
|
type = data.type
|
164
241
|
return false unless type
|
242
|
+
|
165
243
|
type = type.to_s
|
166
|
-
logger.debug("#{self
|
244
|
+
logger.debug("#{self}##{__method__}") { data.to_s }
|
167
245
|
run_handlers(type, data) if @store
|
168
246
|
run_callbacks(type, data)
|
169
247
|
rescue StandardError => e
|
170
|
-
logger.error e
|
248
|
+
logger.error("#{self}##{__method__}") { e }
|
171
249
|
false
|
172
250
|
end
|
173
251
|
|
174
252
|
def run_handlers(type, data)
|
253
|
+
return unless store.class.events
|
254
|
+
|
175
255
|
handlers = store.class.events[type.to_s]
|
176
|
-
handlers
|
256
|
+
handlers&.each do |handler|
|
177
257
|
store.instance_exec(data, &handler)
|
178
|
-
end
|
258
|
+
end
|
179
259
|
rescue StandardError => e
|
180
|
-
logger.error e
|
260
|
+
logger.error("#{self}##{__method__}") { e }
|
181
261
|
false
|
182
262
|
end
|
183
263
|
|
184
264
|
def run_callbacks(type, data)
|
185
265
|
callbacks = self.callbacks[type]
|
186
266
|
return false unless callbacks
|
267
|
+
|
187
268
|
callbacks.each do |c|
|
188
269
|
c.call(data)
|
189
270
|
end
|
190
271
|
true
|
191
272
|
rescue StandardError => e
|
192
|
-
logger.error e
|
273
|
+
logger.error("#{self}##{__method__}") { e }
|
193
274
|
false
|
194
275
|
end
|
195
276
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Slack
|
2
3
|
module RealTime
|
3
4
|
module Concurrency
|
4
|
-
autoload :
|
5
|
-
autoload :Celluloid, 'slack/real_time/concurrency/celluloid'
|
5
|
+
autoload :Async, 'slack/real_time/concurrency/async'
|
6
6
|
end
|
7
7
|
end
|
8
8
|
end
|
@@ -0,0 +1,140 @@
|
|
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
|
+
begin
|
49
|
+
subtask.annotate "#{client} run-loop"
|
50
|
+
client.run_loop
|
51
|
+
rescue ::Async::Wrapper::Cancelled => e
|
52
|
+
# Will get restarted by ping worker.
|
53
|
+
rescue StandardError => e
|
54
|
+
client.logger.error(subtask.to_s) { e.message }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
@restart.wait
|
59
|
+
end
|
60
|
+
|
61
|
+
@ping_task&.stop
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def restart_async(_client, new_url)
|
66
|
+
@url = new_url
|
67
|
+
@last_message_at = current_time
|
68
|
+
|
69
|
+
@restart&.signal
|
70
|
+
end
|
71
|
+
|
72
|
+
def current_time
|
73
|
+
::Async::Clock.now
|
74
|
+
end
|
75
|
+
|
76
|
+
def connect!
|
77
|
+
super
|
78
|
+
run_loop
|
79
|
+
end
|
80
|
+
|
81
|
+
# Kill the restart/ping loop.
|
82
|
+
def disconnect!
|
83
|
+
super
|
84
|
+
ensure
|
85
|
+
if (restart = @restart)
|
86
|
+
@restart = nil
|
87
|
+
restart.signal
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Close the socket.
|
92
|
+
def close
|
93
|
+
super
|
94
|
+
ensure
|
95
|
+
if @socket
|
96
|
+
@socket.close
|
97
|
+
@socket = nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def run_loop
|
102
|
+
while @driver&.next_event
|
103
|
+
# $stderr.puts event.inspect
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
protected
|
108
|
+
|
109
|
+
def build_ssl_context
|
110
|
+
OpenSSL::SSL::SSLContext.new(:TLSv1_2_client).tap do |ctx|
|
111
|
+
ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def build_endpoint
|
116
|
+
endpoint = ::Async::IO::Endpoint.tcp(addr, port)
|
117
|
+
endpoint = ::Async::IO::SSLEndpoint.new(endpoint, ssl_context: build_ssl_context) if secure?
|
118
|
+
endpoint
|
119
|
+
end
|
120
|
+
|
121
|
+
def connect_socket
|
122
|
+
build_endpoint.connect
|
123
|
+
end
|
124
|
+
|
125
|
+
def connect
|
126
|
+
@socket = connect_socket
|
127
|
+
@driver = Client.new(@socket, url)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
if Gem::Version.new(Async::WebSocket::VERSION) >= Gem::Version.new('0.9.0')
|
136
|
+
raise(
|
137
|
+
"Incompatible version of async-websocket, #{Async::WebSocket::VERSION}, " \
|
138
|
+
"use \"gem 'async-websocket', '~> 0.8.0'\"."
|
139
|
+
)
|
140
|
+
end
|