slack-ruby-client 0.11.0 → 2.7.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 +5 -5
- data/.coveralls.yml +2 -0
- data/.github/FUNDING.yml +2 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/integration_test.yml +45 -0
- data/.github/workflows/lint.yml +14 -0
- data/.github/workflows/pr_lint.yml +21 -0
- data/.github/workflows/test.yml +56 -0
- data/.github/workflows/update_api.yml +81 -0
- data/.gitignore +7 -3
- data/.rubocop.yml +40 -2
- data/.rubocop_todo.yml +209 -55
- data/.ruby-version +1 -0
- data/CHANGELOG.md +257 -30
- data/CONTRIBUTING.md +44 -29
- data/Dangerfile +2 -0
- data/Gemfile +28 -6
- data/Gemfile.danger +6 -0
- data/LICENSE.md +1 -1
- data/README.md +473 -134
- data/RELEASING.md +2 -2
- data/Rakefile +2 -1
- data/SECURITY.md +9 -0
- data/UPGRADING.md +117 -3
- data/bin/commands/admin_analytics.rb +22 -0
- data/bin/commands/admin_apps.rb +57 -0
- data/bin/commands/admin_apps_activities.rb +32 -0
- data/bin/commands/admin_apps_approved.rb +24 -0
- data/bin/commands/admin_apps_config.rb +31 -0
- data/bin/commands/admin_apps_requests.rb +35 -0
- data/bin/commands/admin_apps_restricted.rb +24 -0
- data/bin/commands/admin_audit_anomaly_allow.rb +29 -0
- data/bin/commands/admin_auth_policy.rb +45 -0
- data/bin/commands/admin_barriers.rb +53 -0
- data/bin/commands/admin_conversations.rb +260 -0
- data/bin/commands/admin_conversations_ekm.rb +23 -0
- data/bin/commands/admin_conversations_restrictAccess.rb +43 -0
- data/bin/commands/admin_emoji.rb +60 -0
- data/bin/commands/admin_functions.rb +23 -0
- data/bin/commands/admin_functions_permissions.rb +31 -0
- data/bin/commands/admin_inviteRequests.rb +42 -0
- data/bin/commands/admin_inviteRequests_approved.rb +22 -0
- data/bin/commands/admin_inviteRequests_denied.rb +22 -0
- data/bin/commands/admin_roles.rb +46 -0
- data/bin/commands/admin_teams.rb +33 -0
- data/bin/commands/admin_teams_admins.rb +22 -0
- data/bin/commands/admin_teams_owners.rb +22 -0
- data/bin/commands/admin_teams_settings.rb +70 -0
- data/bin/commands/admin_usergroups.rb +54 -0
- data/bin/commands/admin_users.rb +106 -0
- data/bin/commands/admin_users_session.rb +84 -0
- data/bin/commands/admin_users_unsupportedVersions.rb +21 -0
- data/bin/commands/admin_workflows.rb +42 -0
- data/bin/commands/admin_workflows_collaborators.rb +31 -0
- data/bin/commands/admin_workflows_permissions.rb +21 -0
- data/bin/commands/admin_workflows_triggers_types_permissions.rb +31 -0
- data/bin/commands/api.rb +15 -9
- data/bin/commands/apps.rb +21 -0
- data/bin/commands/apps_activities.rb +32 -0
- data/bin/commands/apps_auth_external.rb +32 -0
- data/bin/commands/apps_connections.rb +19 -0
- data/bin/commands/apps_datastore.rb +116 -0
- data/bin/commands/apps_event_authorizations.rb +22 -0
- data/bin/commands/apps_manifest.rb +58 -0
- data/bin/commands/assistant_search.rb +27 -0
- data/bin/commands/assistant_threads.rb +45 -0
- data/bin/commands/auth.rb +22 -15
- data/bin/commands/auth_teams.rb +22 -0
- data/bin/commands/bookmarks.rb +60 -0
- data/bin/commands/bots.rb +16 -8
- data/bin/commands/calls.rb +58 -0
- data/bin/commands/calls_participants.rb +31 -0
- data/bin/commands/canvases.rb +41 -0
- data/bin/commands/canvases_access.rb +34 -0
- data/bin/commands/canvases_sections.rb +21 -0
- data/bin/commands/chat.rb +158 -99
- data/bin/commands/chat_scheduledMessages.rb +25 -0
- data/bin/commands/conversations.rb +241 -157
- data/bin/commands/conversations_canvases.rb +22 -0
- data/bin/commands/conversations_externalInvitePermissions.rb +22 -0
- data/bin/commands/conversations_requestSharedInvite.rb +48 -0
- data/bin/commands/dialog.rb +16 -9
- data/bin/commands/dnd.rb +47 -38
- data/bin/commands/emoji.rb +15 -7
- data/bin/commands/files.rb +113 -87
- data/bin/commands/files_comments.rb +16 -30
- data/bin/commands/files_remote.rb +84 -0
- data/bin/commands/functions.rb +31 -0
- data/bin/commands/functions_distributions_permissions.rb +61 -0
- data/bin/commands/functions_workflows_steps.rb +23 -0
- data/bin/commands/functions_workflows_steps_responses.rb +23 -0
- data/bin/commands/migration.rb +17 -9
- data/bin/commands/oauth.rb +19 -24
- data/bin/commands/oauth_v2.rb +35 -0
- data/bin/commands/openid_connect.rb +33 -0
- data/bin/commands/pins.rb +33 -30
- data/bin/commands/reactions.rb +53 -45
- data/bin/commands/reminders.rb +54 -41
- data/bin/commands/rtm.rb +16 -22
- data/bin/commands/search.rb +44 -33
- data/bin/commands/stars.rb +39 -29
- data/bin/commands/team.rb +50 -34
- data/bin/commands/team_billing.rb +19 -0
- data/bin/commands/team_externalTeams.rb +35 -0
- data/bin/commands/team_preferences.rb +19 -0
- data/bin/commands/team_profile.rb +15 -8
- data/bin/commands/tooling_tokens.rb +20 -0
- data/bin/commands/usergroups.rb +69 -53
- data/bin/commands/usergroups_users.rb +30 -19
- data/bin/commands/users.rb +114 -84
- data/bin/commands/users_admin.rb +29 -22
- data/bin/commands/users_discoverableContacts.rb +20 -0
- data/bin/commands/users_prefs.rb +14 -7
- data/bin/commands/users_profile.rb +27 -20
- data/bin/commands/views.rb +56 -0
- data/bin/commands/workflows.rb +44 -0
- data/bin/commands/workflows_triggers_permissions.rb +60 -0
- data/bin/slack +50 -46
- data/examples/files_upload_v2/.env.example +1 -0
- data/examples/{hi_real_time → files_upload_v2}/Gemfile +2 -2
- data/examples/files_upload_v2/README.md +13 -0
- data/examples/files_upload_v2/files_upload_v2.rb +45 -0
- 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_eventmachine → hi_real_time_async_async}/Gemfile +2 -1
- data/examples/{hi_real_time_async_eventmachine → hi_real_time_async_async}/hi.rb +12 -7
- 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/examples/oauth_v2/.env.example +4 -0
- data/examples/oauth_v2/Gemfile +7 -0
- data/examples/oauth_v2/README.md +33 -0
- data/examples/oauth_v2/oauth_v2.rb +60 -0
- data/lib/slack/config.rb +2 -2
- data/lib/slack/events/config.rb +32 -0
- data/lib/slack/events/request.rb +76 -0
- data/lib/slack/logger.rb +6 -5
- data/lib/slack/messages/formatting.rb +66 -1
- data/lib/slack/messages/message.rb +1 -4
- data/lib/slack/real_time/api/message.rb +6 -3
- 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 +5 -1
- data/lib/slack/real_time/api/typing.rb +5 -2
- data/lib/slack/real_time/client.rb +117 -54
- data/lib/slack/real_time/concurrency/async.rb +142 -0
- data/lib/slack/real_time/concurrency.rb +2 -2
- data/lib/slack/real_time/config.rb +12 -13
- data/lib/slack/real_time/models/base.rb +1 -4
- data/lib/slack/real_time/models/bot.rb +1 -0
- data/lib/slack/real_time/models/channel.rb +5 -0
- data/lib/slack/real_time/models/im.rb +1 -0
- data/lib/slack/real_time/models/{group.rb → mpim.rb} +2 -1
- 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/models.rb +3 -1
- data/lib/slack/real_time/socket.rb +49 -17
- data/lib/slack/real_time/stores/base.rb +28 -14
- data/lib/slack/real_time/stores/starter.rb +325 -287
- data/lib/slack/real_time/stores/store.rb +271 -186
- data/lib/slack/real_time/stores.rb +2 -7
- data/lib/slack/utils/security.rb +44 -0
- data/lib/slack/version.rb +2 -1
- data/lib/slack/web/api/endpoints/admin_analytics.rb +28 -0
- data/lib/slack/web/api/endpoints/admin_apps.rb +78 -0
- data/lib/slack/web/api/endpoints/admin_apps_activities.rb +53 -0
- data/lib/slack/web/api/endpoints/admin_apps_approved.rb +37 -0
- data/lib/slack/web/api/endpoints/admin_apps_config.rb +40 -0
- data/lib/slack/web/api/endpoints/admin_apps_requests.rb +53 -0
- data/lib/slack/web/api/endpoints/admin_apps_restricted.rb +37 -0
- data/lib/slack/web/api/endpoints/admin_audit_anomaly_allow.rb +34 -0
- data/lib/slack/web/api/endpoints/admin_auth_policy.rb +72 -0
- data/lib/slack/web/api/endpoints/admin_barriers.rb +82 -0
- data/lib/slack/web/api/endpoints/admin_conversations.rb +397 -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_emoji.rb +88 -0
- data/lib/slack/web/api/endpoints/admin_functions.rb +36 -0
- data/lib/slack/web/api/endpoints/admin_functions_permissions.rb +41 -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_roles.rb +73 -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 +167 -0
- data/lib/slack/web/api/endpoints/admin_users_session.rb +121 -0
- data/lib/slack/web/api/endpoints/admin_users_unsupportedVersions.rb +25 -0
- data/lib/slack/web/api/endpoints/admin_workflows.rb +67 -0
- data/lib/slack/web/api/endpoints/admin_workflows_collaborators.rb +42 -0
- data/lib/slack/web/api/endpoints/admin_workflows_permissions.rb +26 -0
- data/lib/slack/web/api/endpoints/admin_workflows_triggers_types_permissions.rb +41 -0
- data/lib/slack/web/api/endpoints/api.rb +2 -3
- data/lib/slack/web/api/endpoints/apps.rb +27 -0
- data/lib/slack/web/api/endpoints/apps_activities.rb +54 -0
- data/lib/slack/web/api/endpoints/apps_auth_external.rb +41 -0
- data/lib/slack/web/api/endpoints/apps_connections.rb +21 -0
- data/lib/slack/web/api/endpoints/apps_datastore.rb +181 -0
- data/lib/slack/web/api/endpoints/apps_event_authorizations.rb +34 -0
- data/lib/slack/web/api/endpoints/apps_manifest.rb +79 -0
- data/lib/slack/web/api/endpoints/assistant_search.rb +44 -0
- data/lib/slack/web/api/endpoints/assistant_threads.rb +68 -0
- data/lib/slack/web/api/endpoints/auth.rb +2 -1
- data/lib/slack/web/api/endpoints/auth_teams.rb +33 -0
- data/lib/slack/web/api/endpoints/bookmarks.rb +90 -0
- data/lib/slack/web/api/endpoints/bots.rb +4 -1
- 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/canvases.rb +54 -0
- data/lib/slack/web/api/endpoints/canvases_access.rb +47 -0
- data/lib/slack/web/api/endpoints/canvases_sections.rb +27 -0
- data/lib/slack/web/api/endpoints/chat.rb +172 -87
- data/lib/slack/web/api/endpoints/chat_scheduledMessages.rb +40 -0
- data/lib/slack/web/api/endpoints/conversations.rb +190 -64
- data/lib/slack/web/api/endpoints/conversations_canvases.rb +28 -0
- data/lib/slack/web/api/endpoints/conversations_externalInvitePermissions.rb +31 -0
- data/lib/slack/web/api/endpoints/conversations_requestSharedInvite.rb +73 -0
- data/lib/slack/web/api/endpoints/dialog.rb +6 -10
- data/lib/slack/web/api/endpoints/dnd.rb +11 -5
- data/lib/slack/web/api/endpoints/emoji.rb +3 -0
- data/lib/slack/web/api/endpoints/files.rb +85 -36
- data/lib/slack/web/api/endpoints/files_comments.rb +4 -36
- data/lib/slack/web/api/endpoints/files_remote.rb +127 -0
- data/lib/slack/web/api/endpoints/functions.rb +43 -0
- data/lib/slack/web/api/endpoints/functions_distributions_permissions.rb +84 -0
- data/lib/slack/web/api/endpoints/functions_workflows_steps.rb +30 -0
- data/lib/slack/web/api/endpoints/functions_workflows_steps_responses.rb +30 -0
- data/lib/slack/web/api/endpoints/migration.rb +6 -3
- data/lib/slack/web/api/endpoints/oauth.rb +10 -32
- data/lib/slack/web/api/endpoints/oauth_v2.rb +48 -0
- data/lib/slack/web/api/endpoints/openid_connect.rb +42 -0
- data/lib/slack/web/api/endpoints/pins.rb +11 -18
- data/lib/slack/web/api/endpoints/reactions.rb +31 -20
- data/lib/slack/web/api/endpoints/reminders.rb +25 -12
- data/lib/slack/web/api/endpoints/rtm.rb +4 -22
- data/lib/slack/web/api/endpoints/search.rb +33 -18
- data/lib/slack/web/api/endpoints/stars.rb +23 -10
- data/lib/slack/web/api/endpoints/team.rb +38 -7
- data/lib/slack/web/api/endpoints/team_billing.rb +21 -0
- data/lib/slack/web/api/endpoints/team_externalTeams.rb +53 -0
- data/lib/slack/web/api/endpoints/team_preferences.rb +21 -0
- data/lib/slack/web/api/endpoints/team_profile.rb +2 -1
- data/lib/slack/web/api/endpoints/tooling_tokens.rb +24 -0
- data/lib/slack/web/api/endpoints/usergroups.rb +44 -25
- data/lib/slack/web/api/endpoints/usergroups_users.rb +23 -14
- data/lib/slack/web/api/endpoints/users.rb +57 -18
- data/lib/slack/web/api/endpoints/users_admin.rb +5 -2
- data/lib/slack/web/api/endpoints/users_discoverableContacts.rb +24 -0
- data/lib/slack/web/api/endpoints/users_prefs.rb +2 -0
- data/lib/slack/web/api/endpoints/users_profile.rb +11 -9
- data/lib/slack/web/api/endpoints/views.rb +86 -0
- data/lib/slack/web/api/endpoints/workflows.rb +63 -0
- data/lib/slack/web/api/endpoints/workflows_triggers_permissions.rb +87 -0
- data/lib/slack/web/api/endpoints.rb +136 -12
- data/lib/slack/web/api/error.rb +1 -0
- data/lib/slack/web/api/errors/server_error.rb +37 -0
- data/lib/slack/web/api/errors/slack_error.rb +14 -1
- data/lib/slack/web/api/errors/too_many_requests_error.rb +2 -4
- data/lib/slack/web/api/errors.rb +1396 -0
- data/lib/slack/web/api/helpers/files.rb +97 -0
- data/lib/slack/web/api/helpers.rb +13 -0
- data/lib/slack/web/api/mixins/conversations.id.rb +47 -0
- data/lib/slack/web/api/mixins/ids.id.rb +4 -3
- data/lib/slack/web/api/mixins/users.id.rb +18 -4
- data/lib/slack/web/api/mixins/users.search.rb +3 -1
- data/lib/slack/web/api/mixins.rb +2 -2
- data/lib/slack/web/api/options.rb +26 -0
- data/lib/slack/web/api/patches/.gitkeep +0 -0
- data/lib/slack/web/api/templates/command.erb +19 -12
- data/lib/slack/web/api/templates/endpoints.erb +2 -2
- data/lib/slack/web/api/templates/errors.erb +20 -0
- data/lib/slack/web/api/templates/method.erb +23 -3
- data/lib/slack/web/api/templates/method_spec.erb +40 -3
- data/lib/slack/web/client.rb +4 -1
- data/lib/slack/web/config.rb +9 -2
- data/lib/slack/web/faraday/connection.rb +11 -20
- data/lib/slack/web/faraday/options.rb +24 -0
- data/lib/slack/web/faraday/request.rb +6 -1
- data/lib/slack/web/faraday/response/raise_error.rb +14 -8
- data/lib/slack/web/faraday/response/wrap_error.rb +24 -0
- data/lib/slack/web/pagination/cursor.rb +7 -7
- data/lib/slack-ruby-client.rb +18 -6
- data/lib/slack.rb +1 -0
- data/lib/slack_ruby_client.rb +1 -0
- data/lib/tasks/git.rake +1 -0
- data/lib/tasks/real_time.rake +51 -21
- data/lib/tasks/update.rake +1 -0
- data/lib/tasks/web.rake +43 -17
- data/slack-ruby-client.gemspec +10 -14
- metadata +191 -307
- data/.travis.yml +0 -30
- data/bin/commands/apps_permissions.rb +0 -22
- data/bin/commands/channels.rb +0 -175
- data/bin/commands/groups.rb +0 -172
- data/bin/commands/im.rb +0 -67
- data/bin/commands/mpim.rb +0 -63
- data/bin/commands.rb +0 -33
- 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_celluloid/hi.rb +0 -36
- data/examples/hi_real_time_async_eventmachine/Procfile +0 -2
- data/lib/slack/real_time/concurrency/celluloid.rb +0 -117
- data/lib/slack/real_time/concurrency/eventmachine.rb +0 -60
- data/lib/slack/web/api/endpoints/apps_permissions.rb +0 -35
- data/lib/slack/web/api/endpoints/channels.rb +0 -265
- data/lib/slack/web/api/endpoints/groups.rb +0 -255
- data/lib/slack/web/api/endpoints/im.rb +0 -113
- data/lib/slack/web/api/endpoints/mpim.rb +0 -98
- data/lib/slack/web/api/endpoints/presence.rb +0 -23
- data/lib/slack/web/api/mixins/channels.id.json +0 -20
- data/lib/slack/web/api/mixins/channels.id.rb +0 -26
- data/lib/slack/web/api/mixins/groups.id.json +0 -20
- data/lib/slack/web/api/mixins/groups.id.rb +0 -26
- 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 -21
- data/lib/slack/web/api/patches/chat.4.postEphemeral-attachments-support.patch +0 -17
- data/lib/slack/web/api/patches/dialog.1.open-json-support.patch +0 -17
- data/lib/slack/web/api/templates/commands.erb +0 -5
- data/screenshots/register-bot.png +0 -0
- data/spec/fixtures/slack/web/429_error.yml +0 -85
- data/spec/fixtures/slack/web/auth_test_error.yml +0 -48
- data/spec/fixtures/slack/web/auth_test_success.yml +0 -57
- data/spec/fixtures/slack/web/channels_info.yml +0 -46
- data/spec/fixtures/slack/web/groups_info.yml +0 -43
- data/spec/fixtures/slack/web/paginated_users_list.yml +0 -181
- data/spec/fixtures/slack/web/rtm_connect.yml +0 -70
- data/spec/fixtures/slack/web/rtm_start.yml +0 -104
- data/spec/fixtures/slack/web/users_info.yml +0 -130
- data/spec/fixtures/slack/web/users_list.yml +0 -72
- data/spec/integration/integration_spec.rb +0 -139
- data/spec/slack/config_spec.rb +0 -14
- data/spec/slack/messages/formatting_spec.rb +0 -43
- data/spec/slack/real_time/api/message_spec.rb +0 -15
- data/spec/slack/real_time/api/ping_spec.rb +0 -15
- data/spec/slack/real_time/api/typing_spec.rb +0 -15
- data/spec/slack/real_time/client_spec.rb +0 -425
- data/spec/slack/real_time/concurrency/celluloid_spec.rb +0 -62
- data/spec/slack/real_time/concurrency/eventmachine_spec.rb +0 -47
- data/spec/slack/real_time/concurrency/it_behaves_like_a_realtime_socket.rb +0 -19
- data/spec/slack/real_time/event_handlers/bot_spec.rb +0 -44
- data/spec/slack/real_time/event_handlers/channel_spec.rb +0 -116
- data/spec/slack/real_time/event_handlers/event_handlers_spec.rb +0 -15
- data/spec/slack/real_time/event_handlers/group_spec.rb +0 -90
- data/spec/slack/real_time/event_handlers/im_spec.rb +0 -47
- data/spec/slack/real_time/event_handlers/team_spec.rb +0 -62
- data/spec/slack/real_time/event_handlers/user_spec.rb +0 -63
- data/spec/slack/real_time/rtm_connect_spec.rb +0 -13
- data/spec/slack/real_time/rtm_start_spec.rb +0 -13
- data/spec/slack/real_time/store_spec.rb +0 -11
- data/spec/slack/slack_spec.rb +0 -58
- data/spec/slack/version_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/api_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/apps_permissions_spec.rb +0 -15
- data/spec/slack/web/api/endpoints/bots_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/conversations_spec.rb +0 -100
- data/spec/slack/web/api/endpoints/custom_specs/auth_spec.rb +0 -25
- data/spec/slack/web/api/endpoints/custom_specs/channels_spec.rb +0 -11
- data/spec/slack/web/api/endpoints/custom_specs/chat_spec.rb +0 -105
- data/spec/slack/web/api/endpoints/custom_specs/dialog_spec.rb +0 -28
- data/spec/slack/web/api/endpoints/custom_specs/groups_spec.rb +0 -11
- data/spec/slack/web/api/endpoints/custom_specs/users_spec.rb +0 -33
- data/spec/slack/web/api/endpoints/dnd_spec.rb +0 -12
- data/spec/slack/web/api/endpoints/emoji_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/files_comments_spec.rb +0 -34
- data/spec/slack/web/api/endpoints/files_spec.rb +0 -43
- data/spec/slack/web/api/endpoints/im_spec.rb +0 -38
- data/spec/slack/web/api/endpoints/migration_spec.rb +0 -12
- data/spec/slack/web/api/endpoints/mpim_spec.rb +0 -38
- data/spec/slack/web/api/endpoints/oauth_spec.rb +0 -29
- data/spec/slack/web/api/endpoints/pins_spec.rb +0 -22
- data/spec/slack/web/api/endpoints/reactions_spec.rb +0 -17
- data/spec/slack/web/api/endpoints/reminders_spec.rb +0 -30
- data/spec/slack/web/api/endpoints/rtm_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/search_spec.rb +0 -22
- data/spec/slack/web/api/endpoints/stars_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/team_profile_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/team_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/usergroups_spec.rb +0 -27
- data/spec/slack/web/api/endpoints/usergroups_users_spec.rb +0 -20
- data/spec/slack/web/api/endpoints/users_admin_spec.rb +0 -17
- data/spec/slack/web/api/endpoints/users_prefs_spec.rb +0 -7
- data/spec/slack/web/api/endpoints/users_profile_spec.rb +0 -7
- data/spec/slack/web/api/error_spec.rb +0 -14
- data/spec/slack/web/api/errors/slack_error_spec.rb +0 -14
- data/spec/slack/web/api/mixins/channels_spec.rb +0 -31
- data/spec/slack/web/api/mixins/groups_spec.rb +0 -31
- data/spec/slack/web/api/mixins/users_spec.rb +0 -39
- data/spec/slack/web/api/pagination/cursor_spec.rb +0 -70
- data/spec/slack/web/client_spec.rb +0 -174
- data/spec/spec_helper.rb +0 -14
- data/spec/support/queue_with_timeout.rb +0 -34
- data/spec/support/real_time/concurrency/mock.rb +0 -30
- data/spec/support/real_time/connected_client.rb +0 -21
- data/spec/support/real_time/event.rb +0 -11
- data/spec/support/token.rb +0 -10
- data/spec/support/vcr.rb +0 -9
- /data/examples/{hi_real_time_async_celluloid → hi_real_time_async_async}/Procfile +0 -0
data/README.md
CHANGED
@@ -2,23 +2,86 @@ Slack Ruby Client
|
|
2
2
|
=================
|
3
3
|
|
4
4
|
[](http://badge.fury.io/rb/slack-ruby-client)
|
5
|
-
[](https://github.com/slack-ruby/slack-ruby-client/actions/workflows/integration_test.yml)
|
6
|
+
[](https://github.com/slack-ruby/slack-ruby-client/actions/workflows/test.yml)
|
7
|
+
[](https://coveralls.io/github/slack-ruby/slack-ruby-client?branch=master)
|
7
8
|
|
8
|
-
A Ruby client for the Slack [Web](https://api.slack.com/web)
|
9
|
+
A Ruby client for the Slack [Web](https://api.slack.com/web), [RealTime Messaging](https://api.slack.com/rtm) and [Events](https://api.slack.com/events-api) APIs. Comes with a handy command-line client, too. If you are not familiar with these concepts, you might want to watch [this video](http://code.dblock.org/2016/03/11/your-first-slack-bot-service-video.html).
|
9
10
|
|
10
11
|

|
11
12
|
|
13
|
+
# Table of Contents
|
14
|
+
|
15
|
+
- [Useful to Me?](#useful-to-me)
|
16
|
+
- [Stable Release](#stable-release)
|
17
|
+
- [Installation](#installation)
|
18
|
+
- [Usage](#usage)
|
19
|
+
- [Create a New Bot Integration](#create-a-new-bot-integration)
|
20
|
+
- [OAuth Code Grant](#oauth-code-grant)
|
21
|
+
- [Using an API Token](#using-an-api-token)
|
22
|
+
- [Global Settings](#global-settings)
|
23
|
+
- [Web Client](#web-client)
|
24
|
+
- [Web Client Examples](#web-client-examples)
|
25
|
+
- [Test Auth](#test-auth)
|
26
|
+
- [Send Messages](#send-messages)
|
27
|
+
- [List Channels](#list-channels)
|
28
|
+
- [Upload a File](#upload-a-file)
|
29
|
+
- [Get Channel Info](#get-channel-info)
|
30
|
+
- [Get User Info](#get-user-info)
|
31
|
+
- [Search for a User](#search-for-a-user)
|
32
|
+
- [Other](#other)
|
33
|
+
- [JSON Arguments](#json-arguments)
|
34
|
+
- [Web Client Options](#web-client-options)
|
35
|
+
- [Pagination Support](#pagination-support)
|
36
|
+
- [Character Encoding](#character-encoding)
|
37
|
+
- [Error Handling](#error-handling)
|
38
|
+
- [Slack Errors](#slack-errors)
|
39
|
+
- [Rate Limiting](#rate-limiting)
|
40
|
+
- [Other Errors](#other-errors)
|
41
|
+
- [RealTime Client](#realtime-client)
|
42
|
+
- [Configuring Slack::RealTime::Client](#configuring-slackrealtimeclient)
|
43
|
+
- [Caveats](#caveats)
|
44
|
+
- [websocket_ping](#websocket_ping)
|
45
|
+
- [RealTime Store](#realtime-store)
|
46
|
+
- [Slack::RealTime::Stores::Starter](#slackrealtimestoresstarter)
|
47
|
+
- [Slack::RealTime::Stores::Store](#slackrealtimestoresstore)
|
48
|
+
- [Combining RealTime and Web Clients](#combining-realtime-and-web-clients)
|
49
|
+
- [Concurrency](#concurrency)
|
50
|
+
- [Async](#async)
|
51
|
+
- [Events API](#events-api)
|
52
|
+
- [Configuring Slack::Events](#configuring-slackevents)
|
53
|
+
- [Verifying the Request Signature](#verifying-the-request-signature)
|
54
|
+
- [Message Handling](#message-handling)
|
55
|
+
- [Formatting Messages](#formatting-messages)
|
56
|
+
- [Date and Time Formatting](#date-and-time-formatting)
|
57
|
+
- [Channel ID Formatting](#channel-id-formatting)
|
58
|
+
- [User ID Formatting](#user-id-formatting)
|
59
|
+
- [Group ID Formatting](#group-id-formatting)
|
60
|
+
- [URL Formatting](#url-formatting)
|
61
|
+
- [Markdown Formatting](#markdown-formatting)
|
62
|
+
- [Parsing Messages](#parsing-messages)
|
63
|
+
- [Unescaping Message Content](#unescaping-message-content)
|
64
|
+
- [Escaping Message Content](#escaping-message-content)
|
65
|
+
- [Command-Line Client](#command-line-client)
|
66
|
+
- [Authenticate with Slack](#authenticate-with-slack)
|
67
|
+
- [Send a Message](#send-a-message)
|
68
|
+
- [Get Channel Info](#get-channel-info-1)
|
69
|
+
- [List Users](#list-users)
|
70
|
+
- [Enterprise Support](#enterprise-support)
|
71
|
+
- [History](#history)
|
72
|
+
- [Security](#security)
|
73
|
+
- [Contributing](#contributing)
|
74
|
+
- [Copyright and License](#copyright-and-license)
|
75
|
+
|
12
76
|
## Useful to Me?
|
13
77
|
|
14
|
-
* This
|
15
|
-
*
|
16
|
-
*
|
17
|
-
* If you're trying to roll out a full service with Slack button integration to multiple teams, check out [slack-ruby-bot-server](https://github.com/dblock/slack-ruby-bot-server), which is built on top of slack-ruby-bot, which uses this library.
|
78
|
+
* This library lets you send messages to Slack via the Web API, send and receive messages via the Real Time Messaging API, and facilitates integration with the Events API.
|
79
|
+
* To write a complete bot for Slack you need more than this library, and it's much easier to start with [slack-ruby-bot-server-events](https://github.com/slack-ruby/slack-ruby-bot-server-events).
|
80
|
+
* To respond to slash commands, interactive components, or events at the lowest level, implement a web application using your favorite web framework, and use this library to call the Slack Web API, and to verify that events are coming from Slack.
|
18
81
|
|
19
82
|
## Stable Release
|
20
83
|
|
21
|
-
You're reading the documentation for the **stable** release of slack-ruby-client
|
84
|
+
You're reading the documentation for the **stable** release of slack-ruby-client 2.7.0. See [UPGRADING](UPGRADING.md) when upgrading from an older version.
|
22
85
|
|
23
86
|
## Installation
|
24
87
|
|
@@ -28,11 +91,10 @@ Add to Gemfile.
|
|
28
91
|
gem 'slack-ruby-client'
|
29
92
|
```
|
30
93
|
|
31
|
-
If you're going to be using the RealTime client, add
|
94
|
+
If you're going to be using the RealTime client, add `async-websocket`. See below for more information about concurrency.
|
32
95
|
|
33
96
|
```
|
34
|
-
gem '
|
35
|
-
gem 'faye-websocket'
|
97
|
+
gem 'async-websocket', '~> 0.8.0'
|
36
98
|
```
|
37
99
|
|
38
100
|
Run `bundle install`.
|
@@ -41,11 +103,15 @@ Run `bundle install`.
|
|
41
103
|
|
42
104
|
### Create a New Bot Integration
|
43
105
|
|
44
|
-
|
106
|
+
To integrate your bot with Slack, you must first create a new [Slack App](https://api.slack.com/apps).
|
107
|
+
|
108
|
+
### OAuth Code Grant
|
109
|
+
|
110
|
+
Once created, go to the app's Basic Info tab and grab the Client ID and Client Secret. You'll need these in order complete an [OAuth Workflow](https://api.slack.com/authentication/oauth-v2). A working sample that starts a local web server and obtains a bot or a user token for your app using OAuth v2 is available in [examples/oauth_v2](examples/oauth_v2).
|
45
111
|
|
46
|
-
|
112
|
+
### Using an API Token
|
47
113
|
|
48
|
-
|
114
|
+
Although OAuth is recommended, you can also [generate an API token](https://api.slack.com/tutorials/tracks/getting-a-token) for your app and use it for some interactions.
|
49
115
|
|
50
116
|
```ruby
|
51
117
|
Slack.configure do |config|
|
@@ -68,14 +134,18 @@ logger | An optional logger, defaults to `::Logger.new(STDOUT)` at `Logger
|
|
68
134
|
|
69
135
|
The Slack Web API allows you to build applications that interact with Slack.
|
70
136
|
|
71
|
-
####
|
137
|
+
#### Web Client Examples
|
138
|
+
|
139
|
+
Here are some examples of how to use the web client with the Web API.
|
140
|
+
|
141
|
+
##### Test Auth
|
72
142
|
|
73
143
|
```ruby
|
74
144
|
client = Slack::Web::Client.new
|
75
145
|
client.auth_test
|
76
146
|
```
|
77
147
|
|
78
|
-
|
148
|
+
##### Send Messages
|
79
149
|
|
80
150
|
Send messages with [chat_PostMessage](https://api.slack.com/methods/chat.postMessage).
|
81
151
|
|
@@ -87,44 +157,80 @@ See a fully working example in [examples/hi_web](examples/hi_web/hi.rb).
|
|
87
157
|
|
88
158
|

|
89
159
|
|
90
|
-
|
160
|
+
##### List Channels
|
91
161
|
|
92
|
-
List channels with [
|
162
|
+
List channels with [conversations_list](https://api.slack.com/methods/conversations.list).
|
93
163
|
|
94
164
|
```ruby
|
95
|
-
channels = client.
|
165
|
+
channels = client.conversations_list.channels
|
96
166
|
|
97
167
|
general_channel = channels.detect { |c| c.name == 'general' }
|
98
168
|
```
|
99
169
|
|
100
|
-
|
170
|
+
##### Upload a File
|
101
171
|
|
102
|
-
Upload
|
172
|
+
Upload files with [sequenced API calls](https://api.slack.com/messaging/files#uploading_files).
|
173
|
+
|
174
|
+
This library provides a helper method `files_upload_v2` that wraps the three separate API calls.
|
175
|
+
|
176
|
+
Upload a single file.
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
client.files_upload_v2(
|
180
|
+
# required options
|
181
|
+
filename: 'results.pdf', # this is used for the file title, unless a :title option is provided
|
182
|
+
content: File.read('/users/me/results.pdf'), # the string contents of the file
|
183
|
+
|
184
|
+
# optional options
|
185
|
+
channels: ['C000000', 'C000001'], # channel IDs to share the file in (:channel_id, :channel, or :channels are all supported)
|
186
|
+
initial_comment: 'Sharing the Q1 results :tada:', # the message that is included with the file share thread
|
187
|
+
snippet_type: 'text', # the type of snippet
|
188
|
+
title: 'Q1 Results', # sets the title of the file, overriding the filename
|
189
|
+
thread_ts: '1738331487.481469' # specifies a thread to add this file to
|
190
|
+
)
|
191
|
+
```
|
192
|
+
|
193
|
+
Upload multiple files.
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
client.files_upload_v2(
|
197
|
+
files: [
|
198
|
+
{ filename: 'report.pdf', content: File.read('/users/me/report.pdf'), title: 'Monthly Report' },
|
199
|
+
{ filename: 'data.csv', content: File.read('/users/me/data.csv'), title: 'Raw Data' }
|
200
|
+
],
|
201
|
+
channels: ['#general'],
|
202
|
+
initial_comment: 'Here are the monthly results!'
|
203
|
+
)
|
204
|
+
```
|
205
|
+
|
206
|
+
You can use a channel ID passed as `channel_id`, a single channel as `channel`, an array of channel IDs as `channels`, or a channel name or names (prefixed with `#`) in `files_upload_v2`. Lookup by name is not supported by the Slack API and this method called invokes `conversations_list` in order to locate the channel ID. This invocation can have a cost if you have many Slack channels and is only recommended when you intend to list channels anyway.
|
207
|
+
|
208
|
+
Note: This library includes a `files_upload` method that uses a deprecated endpoint `files.upload` that will [no longer be supported on 3/11/2025](https://api.slack.com/methods/files.upload#markdown).
|
103
209
|
|
104
210
|
```ruby
|
105
211
|
client.files_upload(
|
106
212
|
channels: '#general',
|
107
213
|
as_user: true,
|
108
|
-
file: Faraday::
|
214
|
+
file: Faraday::Multipart::FilePart.new('/path/to/avatar.jpg', 'image/jpeg'),
|
109
215
|
title: 'My Avatar',
|
110
216
|
filename: 'avatar.jpg',
|
111
217
|
initial_comment: 'Attached a selfie.'
|
112
218
|
)
|
113
219
|
```
|
114
220
|
|
115
|
-
|
221
|
+
##### Get Channel Info
|
116
222
|
|
117
|
-
You can use a channel ID or name (prefixed with `#`) in all functions that take a `:channel` argument. Lookup by name is not supported by the Slack API and the `channels_id` method called invokes `
|
223
|
+
You can use a channel ID or name (prefixed with `#`) in all functions that take a `:channel` argument. Lookup by name is not supported by the Slack API and the `channels_id` method called invokes `conversations_list` in order to locate the channel ID. This invocation can have a cost if you have many Slack channels. In this scenario, we encourage you to use channel id.
|
118
224
|
|
119
225
|
```ruby
|
120
|
-
client.
|
226
|
+
client.conversations_info(channel: 'C04KB5X4D') # calls conversations_info
|
121
227
|
```
|
122
228
|
|
123
229
|
```ruby
|
124
|
-
client.
|
230
|
+
client.conversations_info(channel: '#general') # calls conversations_list followed by conversations_info
|
125
231
|
```
|
126
232
|
|
127
|
-
|
233
|
+
##### Get User Info
|
128
234
|
|
129
235
|
You can use a user ID or name (prefixed with `@`) in all functions that take a `:user` argument. Lookup by name is not supported by the Slack API and the `users_id` method called invokes `users_list` in order to locate the user ID.
|
130
236
|
|
@@ -136,7 +242,7 @@ client.users_info(user: 'U092BDCLV') # calls users_info
|
|
136
242
|
client.users_info(user: '@dblock') # calls users_list followed by users_info
|
137
243
|
```
|
138
244
|
|
139
|
-
|
245
|
+
##### Search for a User
|
140
246
|
|
141
247
|
Constructs an in-memory index of users and searches it. If you want to use this functionality, add the [picky](https://github.com/floere/picky) gem to your project's Gemfile.
|
142
248
|
|
@@ -144,16 +250,41 @@ Constructs an in-memory index of users and searches it. If you want to use this
|
|
144
250
|
client.users_search(user: 'dblock')
|
145
251
|
```
|
146
252
|
|
147
|
-
|
253
|
+
##### Other
|
148
254
|
|
149
255
|
Refer to the [Slack Web API Method Reference](https://api.slack.com/methods) for the list of all available functions.
|
150
256
|
|
257
|
+
#### JSON Arguments
|
258
|
+
|
259
|
+
The Web API expects certain arguments to be sent as JSON-encoded strings. With the client you can pass these args as ruby hashes or arrays and they will be converted automatically to JSON, or you can provide the JSON directly.
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
# As ruby objects
|
263
|
+
client.chat_postMessage(
|
264
|
+
channel: 'C123456',
|
265
|
+
text: 'Hello World',
|
266
|
+
blocks: [{type: 'section', text: {type: 'mrkdwn', text: 'Hello World'}}]
|
267
|
+
)
|
268
|
+
|
269
|
+
# As a JSON string
|
270
|
+
client.chat_postMessage(
|
271
|
+
channel: 'C123456',
|
272
|
+
text: 'Hello World',
|
273
|
+
blocks: JSON.dump([{type: 'section', text: {type: 'mrkdwn', text: 'Hello World'}}])
|
274
|
+
)
|
275
|
+
client.chat_postMessage(
|
276
|
+
channel: 'C123456',
|
277
|
+
text: 'Hello World',
|
278
|
+
blocks: '[{"type":"section","text":{"type":"mrkdwn","text":"Hello World"}}]'
|
279
|
+
)
|
280
|
+
```
|
281
|
+
|
151
282
|
#### Web Client Options
|
152
283
|
|
153
284
|
You can configure the Web client either globally or via the initializer.
|
154
285
|
|
155
286
|
```ruby
|
156
|
-
Slack::Web::Client.
|
287
|
+
Slack::Web::Client.configure do |config|
|
157
288
|
config.user_agent = 'Slack Ruby Client/1.0'
|
158
289
|
end
|
159
290
|
```
|
@@ -164,26 +295,33 @@ client = Slack::Web::Client.new(user_agent: 'Slack Ruby Client/1.0')
|
|
164
295
|
|
165
296
|
The following settings are supported.
|
166
297
|
|
167
|
-
setting
|
168
|
-
|
169
|
-
token
|
170
|
-
user_agent
|
171
|
-
proxy
|
172
|
-
ca_path
|
173
|
-
ca_file
|
174
|
-
endpoint
|
175
|
-
logger
|
176
|
-
timeout
|
177
|
-
open_timeout
|
178
|
-
default_page_size
|
179
|
-
|
298
|
+
setting | description
|
299
|
+
-----------------------------|-------------------------------------------------------------------------------------------------
|
300
|
+
token | Slack API token.
|
301
|
+
user_agent | User-agent, defaults to _Slack Ruby Client/version_.
|
302
|
+
proxy | Optional HTTP proxy.
|
303
|
+
ca_path | Optional SSL certificates path.
|
304
|
+
ca_file | Optional SSL certificates file.
|
305
|
+
endpoint | Slack endpoint, default is _https://slack.com/api_.
|
306
|
+
logger | Optional `Logger` instance that logs HTTP requests.
|
307
|
+
timeout | Optional open/read timeout in seconds.
|
308
|
+
open_timeout | Optional connection open timeout in seconds.
|
309
|
+
default_page_size | Optional page size for paginated requests, default is _100_.
|
310
|
+
conversations_id_page_size | Optional page size for conversations_list requests made when calculating conversation id from a conversation name, default is _nil_, which will use the default_page_size.
|
311
|
+
users_id_page_size | Optional page size for users_list requests made when calculating user id from a user name, default is _nil_, which will use the default_page_size.
|
312
|
+
default_max_retries | Optional number of retries for paginated requests, default is _100_.
|
313
|
+
adapter | Optional HTTP adapter to use, defaults to `Faraday.default_adapter`.
|
180
314
|
|
181
315
|
You can also pass request options, including `timeout` and `open_timeout` into individual calls.
|
182
316
|
|
183
317
|
```ruby
|
184
|
-
client.
|
318
|
+
client.conversations_list(request: { timeout: 180 })
|
185
319
|
```
|
186
320
|
|
321
|
+
You can also control what proxy options are used by modifying the `http_proxy` environment variable per [Net::HTTP's documentation](https://docs.ruby-lang.org/en/2.0.0/Net/HTTP.html#class-Net::HTTP-label-Proxies).
|
322
|
+
|
323
|
+
Note that Docker on OSX seems to incorrectly set the proxy, causing `Faraday::ConnectionFailed, ERROR -- : Failed to open TCP connection to : (getaddrinfo: Name or service not known)`. You might need to manually unset `http_proxy` in that case, eg. `http_proxy="" bundle exec ruby ./my_bot.rb`.
|
324
|
+
|
187
325
|
#### Pagination Support
|
188
326
|
|
189
327
|
The Web client natively supports [cursor pagination](https://api.slack.com/docs/pagination#cursors) for methods that allow it, such as `users_list`. Supply a block and the client will make repeated requests adjusting the value of `cursor` with every response. The default limit is set to 100 and can be adjusted via `Slack::Web::Client.config.default_page_size` or by passing it directly into the API call.
|
@@ -210,6 +348,60 @@ end
|
|
210
348
|
all_members # many thousands of team members retrieved 10 at a time
|
211
349
|
```
|
212
350
|
|
351
|
+
#### Character Encoding
|
352
|
+
|
353
|
+
Note that Slack expects `text` to be UTF-8 encoded. If your messages appear with text such as `BAD+11` in Slack, check `text.encoding` and `.encode(Encoding::UTF_8)` your messages before sending them to Slack.
|
354
|
+
|
355
|
+
```ruby
|
356
|
+
text = 'characters such as "Ñ", "Á", "É"'
|
357
|
+
text.encoding
|
358
|
+
=> #<Encoding:UTF-8>
|
359
|
+
client.chat_postMessage(channel: '#general', text: text, as_user: true)
|
360
|
+
# renders 'characters such as "Ñ", "Á", "É"' in Slack
|
361
|
+
|
362
|
+
text = text.encode(Encoding::ISO_8859_1)
|
363
|
+
text.encoding
|
364
|
+
# => #<Encoding:ISO-8859-1>
|
365
|
+
client.chat_postMessage(channel: '#general', text: text, as_user: true)
|
366
|
+
# renders 'characters such as "BAD+11", "", "BAD+9"' in Slack
|
367
|
+
```
|
368
|
+
|
369
|
+
#### Error Handling
|
370
|
+
|
371
|
+
##### Slack Errors
|
372
|
+
|
373
|
+
If Slack returns an error for the request, then an error will be raised. The error class is specific to the type of error that Slack returns. For instance if Slack returns `account_inactive` then the error will be `Slack::Web::Api::Errors::AccountInactive`. This allows you to handle certain types of errors as needed:
|
374
|
+
|
375
|
+
```ruby
|
376
|
+
rescue Slack::Web::Api::Errors::AccountInactive => e
|
377
|
+
# deal with inactive account
|
378
|
+
end
|
379
|
+
```
|
380
|
+
|
381
|
+
All of these errors inherit from `Slack::Web::Api::Errors::SlackError`, so you can handle or silence all errors if necessary:
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
rescue Slack::Web::Api::Errors::SlackError => e
|
385
|
+
# capture all Slack errors
|
386
|
+
end
|
387
|
+
```
|
388
|
+
|
389
|
+
If there's a new error type that is not yet known by this library, then it will raise `Slack::Web::Api::Errors::SlackError`. (Update the Web API if you find that errors are missing — see [CONTRIBUTING](CONTRIBUTING.md).)
|
390
|
+
|
391
|
+
In all of these cases the error message contains the error code, which is also accessible with `slack_error.error`. In case of multiple errors, the error message contains the error codes separated by commas, or they are accessible as an array with `slack_error.errors`. The original response is also accessible using the `response` attribute. The `response_metadata` is accessible with `slack_error.response_metadata`.
|
392
|
+
|
393
|
+
##### Rate Limiting
|
394
|
+
|
395
|
+
If you exceed [Slack’s rate limits](https://api.slack.com/docs/rate-limits), a `Slack::Web::Api::Errors::TooManyRequestsError` will be raised instead. (This does not inherit from `Slack::Web::Api::Errors::SlackError`.)
|
396
|
+
|
397
|
+
##### Other Errors
|
398
|
+
|
399
|
+
When Slack is temporarily unavailable a subclass of `Slack::Web::Api::Errors::ServerError` will be raised and the original `Faraday::Error` will be accesible via `exception.cause`. (Starting with 0.18.0 this is no longer a subclass of `Slack::Web::Api::Errors::SlackError`.)
|
400
|
+
|
401
|
+
Specifically `Slack::Web::Api::Errors::ParsingError` will be raised on non-json response (i.e. 200 OK with `Slack unavailable` HTML page) and `Slack::Web::Api::Errors::HttpRequestError` subclasses for connection failures (`Slack::Web::Api::Errors::TimeoutError` for read/open timeouts & `Slack::Web::Api::Errors::UnavailableError` for 5xx HTTP responses).
|
402
|
+
|
403
|
+
In any other case, a `Faraday::ClientError` will be raised.
|
404
|
+
|
213
405
|
### RealTime Client
|
214
406
|
|
215
407
|
The Real Time Messaging API is a WebSocket-based API that allows you to receive events from Slack in real time and send messages as user.
|
@@ -224,9 +416,9 @@ end
|
|
224
416
|
client.on :message do |data|
|
225
417
|
case data.text
|
226
418
|
when 'bot hi' then
|
227
|
-
client.message
|
419
|
+
client.message(channel: data.channel, text: "Hi <@#{data.user}>!")
|
228
420
|
when /^bot/ then
|
229
|
-
client.message
|
421
|
+
client.message(channel: data.channel, text: "Sorry <@#{data.user}>, what?")
|
230
422
|
end
|
231
423
|
end
|
232
424
|
|
@@ -253,37 +445,12 @@ You can send a ping with `ping`.
|
|
253
445
|
client.ping
|
254
446
|
```
|
255
447
|
|
256
|
-
|
257
|
-
|
258
|
-
property | description
|
259
|
-
---------|-------------------------------------------------------------------------------------------------
|
260
|
-
url | A WebSocket Message Server URL.
|
261
|
-
self | The authenticated bot user.
|
262
|
-
team | Details on the authenticated user's team.
|
263
|
-
users | A hash of user objects by user ID.
|
264
|
-
channels | A hash of channel objects, one for every channel visible to the authenticated user.
|
265
|
-
groups | A hash of group objects, one for every group the authenticated user is in.
|
266
|
-
ims | A hash of IM objects, one for every direct message channel visible to the authenticated user.
|
267
|
-
bots | Details of the integrations set up on this team.
|
268
|
-
|
269
|
-
It also tracks changes, such as users being renamed, added or deleted, therefore `client.users` is always up-to-date.
|
270
|
-
|
271
|
-
Tracking with a local store can be disabled with `Slack::RealTime::Client.new(store_class: nil)`. Other stores are also available.
|
272
|
-
|
273
|
-
#### Slack::RealTime::Stores::Store
|
274
|
-
|
275
|
-
The default store that tracks all changes. By default the client will be connected using `rtm_start`.
|
276
|
-
|
277
|
-
#### Slack::RealTime::Stores::Starter
|
278
|
-
|
279
|
-
A smaller store that only stores and tracks information about the bot user, but not channels, users, groups, ims or bots. By default the client will be connected using `rtm_connect`.
|
280
|
-
|
281
|
-
### Configuring Slack::RealTime::Client
|
448
|
+
#### Configuring Slack::RealTime::Client
|
282
449
|
|
283
450
|
You can configure the RealTime client either globally or via the initializer.
|
284
451
|
|
285
452
|
```ruby
|
286
|
-
Slack::RealTime::Client.
|
453
|
+
Slack::RealTime::Client.configure do |config|
|
287
454
|
config.websocket_ping = 42
|
288
455
|
end
|
289
456
|
```
|
@@ -297,29 +464,81 @@ The following settings are supported.
|
|
297
464
|
setting | description
|
298
465
|
----------------|-----------------------------------------------------------------------------------------------------
|
299
466
|
token | Slack API token.
|
300
|
-
websocket_ping |
|
467
|
+
websocket_ping | How long the socket can be idle before sending a ping message to confirm it's still connected, default is 30.
|
301
468
|
websocket_proxy | Connect via proxy, include `:origin` and `:headers`.
|
302
|
-
|
303
|
-
|
304
|
-
|
469
|
+
start_options | Options to pass to `rtm.connect`, default is `{ request: { timeout: 180 } }`.
|
470
|
+
store_class | Local store class, default is an in-memory `Slack::RealTime::Stores::Starter`.
|
471
|
+
store_options | Options to initialize the store, default is `{}`.
|
472
|
+
async_handlers | Option to run handlers asynchronously. Valid options are `:all` or `:none`, default is `:none`.
|
305
473
|
logger | Optional `Logger` instance that logs RealTime requests and socket data.
|
306
474
|
|
307
|
-
Note that the RealTime client uses a Web client to obtain the WebSocket URL via [rtm.
|
475
|
+
Note that the RealTime client uses a Web client to obtain the WebSocket URL via [rtm.connect](https://api.slack.com/methods/rtm.connect). While `token` and `logger` options are passed down from the RealTime client, you may also configure Web client options via `Slack::Web::Client.configure` as described above.
|
476
|
+
|
477
|
+
See a fully working example in [examples/hi_real_time_and_web](examples/hi_real_time_and_web/hi.rb).
|
478
|
+
|
479
|
+

|
480
|
+
|
481
|
+
##### Caveats
|
482
|
+
|
483
|
+
###### `websocket_ping`
|
484
|
+
|
485
|
+
This setting determines how long the socket can be idle before sending a ping message to confirm it's still connected.
|
486
|
+
|
487
|
+
It's important to note that if a ping message was sent and no response was received within the amount of time specified in `websocket_ping` the client will attempt to reestablish it's connection to the message server.
|
488
|
+
|
489
|
+
Note that the ping may take between `websocket_ping` and `websocket_ping * 3/2` seconds to actually trigger when there is no activity on the socket. This is because the timer that checks whether to ping is triggered at every `websocket_ping / 2` interval.
|
490
|
+
|
491
|
+
To disable this feature set `websocket_ping` to 0.
|
492
|
+
|
493
|
+
#### RealTime Store
|
308
494
|
|
309
|
-
|
495
|
+
The RealTime client exposes and maintains a local store upon successful connection.
|
496
|
+
Event hooks keep the store's cached data up-to-date.
|
310
497
|
|
311
|
-
|
498
|
+
Tracking with a local store can be disabled with `Slack::RealTime::Client.new(store_class: nil)`.
|
312
499
|
|
313
|
-
|
500
|
+
##### `Slack::RealTime::Stores::Starter`
|
314
501
|
|
315
|
-
|
502
|
+
A small store that only caches and tracks data returned in the [rtm.connect](https://api.slack.com/methods/rtm.connect#examples) response.
|
503
|
+
This store provides `self` and `team` for accessing the limited data about the authenticated user and its workspace, but does not cache other users or bots, channels, or direct messages.
|
316
504
|
|
505
|
+
##### `Slack::RealTime::Stores::Store`
|
506
|
+
|
507
|
+
A more complete store that tracks most changes visible to the authenticated user.
|
508
|
+
|
509
|
+
You can see all of the cache types in the table below (each is a hash indexed by its objects' `id`).
|
510
|
+
|
511
|
+
Cache | Description
|
512
|
+
-------------------|-------------------------------------------------------------------------------------------------
|
513
|
+
`teams` | Workspaces (teams). Will likely contain only one `team`.
|
514
|
+
`users` | All [user](https://api.slack.com/types/user) objects, including `self`.
|
515
|
+
`bots` | All [bot users](https://api.slack.com/bot-users) (from Slack Apps and legacy custom integrations).
|
516
|
+
`public_channels` | Public [conversation](https://api.slack.com/types/conversation) objects.
|
517
|
+
`private_channels` | Private [conversation](https://api.slack.com/types/conversation) and [group](https://api.slack.com/types/group) objects with the authenticated user as a member.
|
518
|
+
`ims` | Visible [im](https://api.slack.com/types/im) objects, direct message channels with the authenticated user.
|
519
|
+
`mpims` | Visible [mpim](https://api.slack.com/types/mpim) objects, multiparty direct message channels that include the authenticated user.
|
520
|
+
|
521
|
+
By default, none of these caches are initialized with data beyond what is returned from [rtm.connect](https://api.slack.com/methods/rtm.connect#examples), same as [Slack::RealTime::Stores::Starter](#slackrealtimestoresstarter).
|
522
|
+
When configured, this store initializes its caches by making additional calls to Web API methods upon successful connection to the RTM API (i.e. "hello" message).
|
523
|
+
|
524
|
+
Configure by specifying which caches to fetch:
|
317
525
|
```ruby
|
318
|
-
Slack::RealTime::Client.
|
319
|
-
config.
|
526
|
+
Slack::RealTime::Client.configure do |config|
|
527
|
+
config.store_class = Slack::RealTime::Stores::Store
|
528
|
+
config.store_options = { caches: %i[teams users public_channels private_channels ims] }
|
529
|
+
end
|
530
|
+
```
|
531
|
+
or with the `:all` option:
|
532
|
+
```ruby
|
533
|
+
Slack::RealTime::Client.configure do |config|
|
534
|
+
config.store_class = Slack::RealTime::Stores::Store
|
535
|
+
config.store_options = { caches: :all }
|
320
536
|
end
|
321
537
|
```
|
322
538
|
|
539
|
+
Note: For `teams`, this makes a single call to `team.info`, while for `users` and all conversation-like types, this makes paginated calls to `users.list` and `conversations.list` respectively.
|
540
|
+
Only `bots` requires a separate call for every bot user, so may be slow if your workplace has a lot of bot users.
|
541
|
+
|
323
542
|
### Combining RealTime and Web Clients
|
324
543
|
|
325
544
|
Since the Web client is used to obtain the RealTime client's WebSocket URL, you can continue using the Web client in combination with the RealTime client.
|
@@ -330,9 +549,9 @@ client = Slack::RealTime::Client.new
|
|
330
549
|
client.on :message do |data|
|
331
550
|
case data.text
|
332
551
|
when 'bot hi' then
|
333
|
-
client.web_client.chat_postMessage
|
552
|
+
client.web_client.chat_postMessage(channel: data.channel, text: "Hi <@#{data.user}>!")
|
334
553
|
when /^bot/ then
|
335
|
-
client.web_client.chat_postMessage
|
554
|
+
client.web_client.chat_postMessage(channel: data.channel, text: "Sorry <@#{data.user}>, what?")
|
336
555
|
end
|
337
556
|
end
|
338
557
|
|
@@ -343,90 +562,207 @@ See a fully working example in [examples/hi_real_time_and_web](examples/hi_real_
|
|
343
562
|
|
344
563
|

|
345
564
|
|
346
|
-
|
565
|
+
#### Concurrency
|
347
566
|
|
348
|
-
|
567
|
+
`Slack::RealTime::Client` needs help from a concurrency library and supports [Async](https://github.com/socketry/async).
|
349
568
|
|
350
569
|
```ruby
|
351
|
-
Slack::RealTime
|
352
|
-
|
353
|
-
config.start_options[:simple_latest] = true
|
354
|
-
# Skip unread counts for each channel.
|
355
|
-
config.start_options[:no_unreads] = true
|
356
|
-
# Increase request timeout to 6 minutes.
|
357
|
-
config.start_options[:request][:timeout] = 360
|
570
|
+
Slack::RealTime.configure do |config|
|
571
|
+
config.concurrency = Slack::RealTime::Concurrency::Async
|
358
572
|
end
|
359
573
|
```
|
360
574
|
|
361
|
-
|
575
|
+
Use `client.start_async` instead of `client.start!`. A good example of such application is [slack-ruby-bot-server](https://github.com/slack-ruby/slack-ruby-bot-server).
|
362
576
|
|
363
|
-
|
577
|
+
```ruby
|
578
|
+
client = Slack::RealTime::Client.new
|
364
579
|
|
365
|
-
|
580
|
+
client.start_async
|
581
|
+
```
|
582
|
+
|
583
|
+
##### Async
|
584
|
+
|
585
|
+
Add `async-websocket` to your Gemfile.
|
586
|
+
|
587
|
+
```
|
588
|
+
gem 'async-websocket'
|
589
|
+
```
|
590
|
+
|
591
|
+
See a fully working example in [examples/hi_real_time_async_async](examples/hi_real_time_async_async/hi.rb).
|
592
|
+
|
593
|
+
### Events API
|
594
|
+
|
595
|
+
This library provides limited support for the [Slack Events API](https://api.slack.com/events-api).
|
596
|
+
|
597
|
+
#### Configuring Slack::Events
|
598
|
+
|
599
|
+
You can configure Events support globally.
|
366
600
|
|
367
601
|
```ruby
|
368
|
-
Slack::
|
369
|
-
config.
|
602
|
+
Slack::Events.configure do |config|
|
603
|
+
config.signing_secret = 'secret'
|
370
604
|
end
|
371
605
|
```
|
372
606
|
|
373
|
-
|
607
|
+
The following settings are supported.
|
608
|
+
|
609
|
+
setting | description
|
610
|
+
----------------------|---------------------------------------------------------------------------------------------------
|
611
|
+
signing_secret | Slack signing secret, defaults is `ENV['SLACK_SIGNING_SECRET']`.
|
612
|
+
signature_expires_in | Signature expiration window in seconds, default is `300`.
|
613
|
+
|
614
|
+
#### Verifying the Request Signature
|
615
|
+
|
616
|
+
Slack signs its requests using a secret that's unique to your app. Verify incoming HTTP requests as follows.
|
374
617
|
|
375
618
|
```ruby
|
376
|
-
|
619
|
+
slack_request = Slack::Events::Request.new(http_request)
|
620
|
+
slack_request.verify!
|
621
|
+
```
|
377
622
|
|
378
|
-
|
623
|
+
To specify secrets on a per-request basis:
|
624
|
+
```ruby
|
625
|
+
Slack::Events::Request.new(http_request,
|
626
|
+
signing_secret: signing_secret,
|
627
|
+
signature_expires_in: signature_expires_in)
|
379
628
|
```
|
380
629
|
|
381
|
-
|
630
|
+
The `verify!` call may raise `Slack::Events::Request::MissingSigningSecret`, `Slack::Events::Request::InvalidSignature` or `Slack::Events::Request::TimestampExpired` errors.
|
382
631
|
|
383
|
-
|
632
|
+
### Message Handling
|
384
633
|
|
385
|
-
|
386
|
-
|
634
|
+
All text in Slack uses the same [system of formatting and escaping](https://api.slack.com/docs/formatting): chat messages, direct messages, file comments, etc. [Slack::Messages::Formatting](lib/slack/messages/formatting.rb) provides convenience methods to format and parse messages.
|
635
|
+
|
636
|
+
#### Formatting Messages
|
637
|
+
|
638
|
+
`Slack::Messages::Formatting` provides a number of methods for formatting objects that you can then embed in outgoing messages.
|
639
|
+
|
640
|
+
##### Date and Time Formatting
|
641
|
+
|
642
|
+
You can embed a pre-formatted date in a message as a string like any other text, but using Slack's date formatting allows you to display dates based on user preferences for dates and times, incorporating users' local time zones, and optionally using relative values like "yesterday", "today", or "tomorrow" when appropriate.
|
643
|
+
|
644
|
+
```ruby
|
645
|
+
date = Time.now
|
646
|
+
|
647
|
+
# Display date as `YYYY-MM-DD HH:MM:SS`
|
648
|
+
Slack::Messages::Formatting.date(date)
|
649
|
+
# => "<!date^1688150386^{date_num} {time_secs}|2023-06-30 18:39:46 +0000>"
|
650
|
+
|
651
|
+
# Specify a different format
|
652
|
+
# See https://api.slack.com/reference/surfaces/formatting#date-formatting for supported formats
|
653
|
+
Slack::Messages::Formatting.date(date, format: 'date_long_pretty')
|
654
|
+
# => "<!date^1688150386^date_long_pretty|2023-06-30 18:39:46 +0000>"
|
655
|
+
|
656
|
+
# Link your timestamp to a fully qualified URL
|
657
|
+
Slack::Messages::Formatting.date(date, link: 'https://media.giphy.com/media/AcfTF7tyikWyroP0x7/giphy.gif')
|
658
|
+
# => "<!date^1688150386^{date_num} {time_secs}^https://media.giphy.com/media/AcfTF7tyikWyroP0x7/giphy.gif|2023-06-30 18:39:46 +0000>"
|
659
|
+
|
660
|
+
# Specify custom fallback text to use if the client is unable to process the date
|
661
|
+
Slack::Messages::Formatting.date(date, text: 'party time!')
|
662
|
+
# => "<!date^1688150386^{date_num} {time_secs}|party time!>"
|
387
663
|
```
|
388
664
|
|
389
|
-
|
665
|
+
##### Channel ID Formatting
|
390
666
|
|
391
|
-
|
667
|
+
If you already know the channel name you can just embed it in the message as `#some-channel`, but if you only have the ID you can embed it using special syntax which Slack will display as the channel name (while respecting channel visibility).
|
392
668
|
|
393
|
-
|
669
|
+
```ruby
|
670
|
+
channel_id = 'C0000000001'
|
671
|
+
Slack::Messages::Formatting.channel_link(channel_id)
|
672
|
+
# => "<#C0000000001>"
|
673
|
+
```
|
674
|
+
|
675
|
+
##### User ID Formatting
|
394
676
|
|
677
|
+
If you already know the user name you can just embed it in the message as `@some_username`, but if you only have the ID you can embed it using special syntax which Slack will display as the user name.
|
678
|
+
|
679
|
+
```ruby
|
680
|
+
user_id = 'U0000000001'
|
681
|
+
Slack::Messages::Formatting.user_link(user_id)
|
682
|
+
# => "<@U0000000001>"
|
395
683
|
```
|
396
|
-
|
684
|
+
|
685
|
+
##### Group ID Formatting
|
686
|
+
|
687
|
+
If you already know the group name you can just embed it in the message as `@some_group`, but if you only have the ID you can embed it using special syntax which Slack will display as the group name.
|
688
|
+
|
689
|
+
```ruby
|
690
|
+
group_id = 'S0000000001'
|
691
|
+
Slack::Messages::Formatting.group_link(group_id)
|
692
|
+
# => "<!subteam^S0000000001>"
|
397
693
|
```
|
398
694
|
|
399
|
-
|
695
|
+
##### URL Formatting
|
400
696
|
|
401
|
-
|
697
|
+
Slack will automatically parse fully qualified URLs in messages, but you need special formatting to embed a link with different text.
|
402
698
|
|
403
|
-
|
699
|
+
```ruby
|
700
|
+
text = 'party time'
|
701
|
+
url = 'https://media.giphy.com/media/AcfTF7tyikWyroP0x7/giphy.gif'
|
702
|
+
Slack::Messages::Formatting.url_link(text, url)
|
703
|
+
# => "<https://media.giphy.com/media/AcfTF7tyikWyroP0x7/giphy.gif|party time>"
|
704
|
+
```
|
705
|
+
|
706
|
+
##### Markdown Formatting
|
404
707
|
|
405
|
-
|
708
|
+
Slack uses a mishmash of regular markdown formatting with its own syntax. Some features like headings aren't supported and will be left as-is, but others like bold, strikethrough, and links are converted.
|
709
|
+
|
710
|
+
```ruby
|
711
|
+
text = """
|
712
|
+
## A heading
|
713
|
+
**Bold text**
|
714
|
+
~~Strikethrough text~~
|
715
|
+
_Italic text_
|
716
|
+
[A link](https://example.com)
|
717
|
+
`code`
|
718
|
+
"""
|
719
|
+
Slack::Messages::Formatting.markdown(text)
|
720
|
+
# => """
|
721
|
+
# ## A heading
|
722
|
+
# *Bold text*
|
723
|
+
# ~Strikethrough text~
|
724
|
+
# _Italic text_
|
725
|
+
# <https://example.com|A link>
|
726
|
+
# `code`
|
727
|
+
# """
|
728
|
+
```
|
729
|
+
|
730
|
+
#### Parsing Messages
|
731
|
+
|
732
|
+
`Slack::Messages::Formatting` also provides ways to escape or unescape messages. This comes handy, for example, you want to treat all input to a real time bot as plain text.
|
733
|
+
|
734
|
+
##### Unescaping Message Content
|
406
735
|
|
407
736
|
```ruby
|
408
|
-
Slack::Messages::Formatting.unescape('Hello & <world>')
|
737
|
+
Slack::Messages::Formatting.unescape('Hello & <world>')
|
409
738
|
# => 'Hello & <world>'
|
410
|
-
Slack::Messages::Formatting.unescape('Hey <@U024BE7LH|bob>, did you see my file?')
|
739
|
+
Slack::Messages::Formatting.unescape('Hey <@U024BE7LH|bob>, did you see my file?')
|
411
740
|
# => 'Hey @bob, did you see my file?'
|
412
|
-
Slack::Messages::Formatting.unescape('Hey <@U02BEFY4U>')
|
741
|
+
Slack::Messages::Formatting.unescape('Hey <@U02BEFY4U>')
|
413
742
|
# => 'Hey @U02BEFY4U'
|
414
|
-
Slack::Messages::Formatting.unescape('This message contains a URL <http://foo.com/>')
|
743
|
+
Slack::Messages::Formatting.unescape('This message contains a URL <http://foo.com/>')
|
415
744
|
# => 'This message contains a URL http://foo.com/'
|
416
|
-
Slack::Messages::Formatting.unescape('So does this one: <http://www.foo.com|www.foo.com>')
|
745
|
+
Slack::Messages::Formatting.unescape('So does this one: <http://www.foo.com|www.foo.com>')
|
417
746
|
# => 'So does this one: www.foo.com'
|
418
|
-
Slack::Messages::Formatting.unescape('<mailto:bob@example.com|Bob>')
|
747
|
+
Slack::Messages::Formatting.unescape('<mailto:bob@example.com|Bob>')
|
419
748
|
# => 'Bob'
|
420
|
-
Slack::Messages::Formatting.unescape('Hello <@U123|bob>, say hi to <!everyone> in <#C1234|general>')
|
749
|
+
Slack::Messages::Formatting.unescape('Hello <@U123|bob>, say hi to <!everyone> in <#C1234|general>')
|
421
750
|
# => 'Hello @bob, say hi to @everyone in #general'
|
422
|
-
Slack::Messages::Formatting.unescape('Hello <@U123|bob> > file.txt')
|
751
|
+
Slack::Messages::Formatting.unescape('Hello <@U123|bob> > file.txt')
|
423
752
|
# => 'Hello @bob > file.txt'
|
424
|
-
Slack::Messages::Formatting.unescape('“hello”')
|
753
|
+
Slack::Messages::Formatting.unescape('“hello”')
|
425
754
|
# => '"hello"'
|
426
|
-
Slack::Messages::Formatting.unescape('‘hello’')
|
755
|
+
Slack::Messages::Formatting.unescape('‘hello’')
|
427
756
|
# => "'hello'"
|
428
757
|
```
|
429
758
|
|
759
|
+
##### Escaping Message Content
|
760
|
+
|
761
|
+
```ruby
|
762
|
+
Slack::Messages::Formatting.escape('Hello & <world>')
|
763
|
+
# => 'Hello & <world>'
|
764
|
+
```
|
765
|
+
|
430
766
|
### Command-Line Client
|
431
767
|
|
432
768
|
The slack command-line client returns JSON data from the Slack API.
|
@@ -446,17 +782,10 @@ $ slack chat postMessage --text="hello world" --channel="#general"
|
|
446
782
|
{"ok":true,"channel":"...","ts":"...","message":{"text":"hello world","username":"bot","type":"message","subtype":"bot_message","ts":"..."}}
|
447
783
|
```
|
448
784
|
|
449
|
-
#### Get Channel Id
|
450
|
-
|
451
|
-
```
|
452
|
-
$ slack channels id --channel=#general
|
453
|
-
{"ok":true,"channel":{"id":"C04KB5X4D"}}
|
454
|
-
```
|
455
|
-
|
456
785
|
#### Get Channel Info
|
457
786
|
|
458
787
|
```
|
459
|
-
$ slack
|
788
|
+
$ slack conversations info --channel=#general
|
460
789
|
{"ok":true,"channel":{"id":"C04KB5X4D","name":"general", ...}}
|
461
790
|
```
|
462
791
|
|
@@ -478,16 +807,26 @@ $ slack users list | jq '.members | map({(.id): .name})'
|
|
478
807
|
|
479
808
|
See `slack help` for a complete command-line reference.
|
480
809
|
|
810
|
+
## Enterprise Support
|
811
|
+
|
812
|
+
Available as part of the Tidelift Subscription.
|
813
|
+
|
814
|
+
The maintainers of slack-ruby-client are working with Tidelift to deliver commercial support and maintenance. Save time, reduce risk, and improve code health, while paying the maintainers of slack-ruby-client. Click [here](https://tidelift.com/subscription/request-a-demo?utm_source=rubygems-slack-ruby-client&utm_medium=referral&utm_campaign=enterprise) for more details.
|
815
|
+
|
481
816
|
## History
|
482
817
|
|
483
818
|
This gem is based on [slack-ruby-gem](https://github.com/aki017/slack-ruby-gem), but it more clearly separates the Web and RTM APIs, is more thoroughly tested and is in active development.
|
484
819
|
|
820
|
+
## Security
|
821
|
+
|
822
|
+
See [SECURITY](SECURITY.md).
|
823
|
+
|
485
824
|
## Contributing
|
486
825
|
|
487
826
|
See [CONTRIBUTING](CONTRIBUTING.md).
|
488
827
|
|
489
828
|
## Copyright and License
|
490
829
|
|
491
|
-
Copyright (c) 2015-
|
830
|
+
Copyright (c) 2015-2021, [Daniel Doubrovkine](https://twitter.com/dblockdotorg), [Artsy](https://www.artsy.net) and [Contributors](CHANGELOG.md).
|
492
831
|
|
493
832
|
This project is licensed under the [MIT License](LICENSE.md).
|