A library that enables you to write a complete Slack bot service with Slack button integration, in Ruby.
Build a complete Slack bot service with Slack button integration, in Ruby.
A library that contains a web server and a RESTful Grape API serving a Slack bot to multiple teams. Use in conjunction with slack-ruby-bot-server-events to build a complete Slack bot service, or slack-ruby-bot-server-rtm to build a (legacy) Classic RealTime Slack bot. Your customers can use a Slack button to install the bot.
You're reading the documentation for the next release of slack-ruby-bot-server. Please see the documentation for the last stable release, v1.2.0 unless you're integrating with HEAD. See UPGRADING when upgrading from an older version. See MIGRATING for help with migrating Legacy Slack Apps to Granular Scopes.
This library alone will only register a new bot, but will not include any bot functionality. To make something useful, we recommend you get started from either slack-ruby-bot-server-events-app-mentions-sample (handles a single kind of event), or slack-ruby-bot-server-events-sample (handles all kinds of events) to bootstrap your project.
A database is required to store teams.
Use MongoDB with Mongoid as ODM. Configure the database connection in
mongoid.yml. Add the
mongoidgem in your Gemfile.
gem 'mongoid' gem 'kaminari-mongoid' gem 'mongoid-scroll' gem 'slack-ruby-bot-server'
Use ActiveRecord with, for example, PostgreSQL via pg. Add the
activerecord,
pg,
otr-activerecordand
cursor_paginationgems to your Gemfile.
gem 'pg' gem 'activerecord', require: 'active_record' gem 'slack-ruby-bot-server' gem 'otr-activerecord' gem 'cursor_pagination'
Configure the database connection in
config/postgresql.yml.
default: &default adapter: postgresql pool: 10 timeout: 5000 encoding: unicodedevelopment: <<: database: bot_development test: bot_test production: bot>
Establish a connection in your startup code.
ActiveRecord::Base.establish_connection( YAML.safe_load( ERB.new( File.read('config/postgresql.yml') ).result, [], [], true )[ENV['RACK_ENV']] )OAuth Version and Scopes
Configure your app's OAuth version and scopes as needed by your application.
SlackRubyBotServer.configure do |config| config.oauth_version = :v2 config.oauth_scope = ['channels:read', 'chat:write'] endThe "Add to Slack" button uses the standard OAuth code grant flow as described in the Slack docs. Once clicked, the user is taken through the authorization process at Slack's site. Upon successful completion, a callback containing a temporary code is sent to the redirect URL you specified. The endpoint at that URL contains code that persists the bot token each time a Slack client is instantiated for the specific team.
Slack App
Create a new Slack App here.
Follow Slack's instructions, note the app client ID and secret, give the bot a default name, etc.
Within your application, edit your
.envfile and addSLACK_CLIENT_ID=...andSLACK_CLIENT_SECRET=...in it.Run
bundle installandforeman startto boot the app.$ foreman start 07:44:47 web.1 | started with pid 59258 07:44:50 web.1 | * Listening on tcp://0.0.0.0:5000Set the redirect URL in "OAuth & Permissions" be the location of your app. Since you cannot receive notifications on localhost from Slack use a public tunneling service such as ngrok to expose local port 9292 for testing.
$ ngrok http 5000 Forwarding https://ddfd97f80615.ngrok.io -> http://localhost:5000Navigate to either localhost:9292 or the ngrok URL above. You should see an "Add to Slack" button. Use it to install the app into your own Slack team.
API
This library implements an app, SlackRubyBotServer::App and a service manager, SlackRubyBotServer::Service. It also provides default HTML templates and JS scripts for Slack integration.
App
The app instance checks for a working database connection, ensures indexes, performs migrations, sets up bot aliases and log levels. You can introduce custom behavior into the app lifecycle by subclassing
SlackRubyBotServer::Appand creating an instance of the child class inconfig.ru.class MyApp < SlackRubyBotServer::App def prepare! super deactivate_sleepy_teams! endprivate
def deactivate_sleepy_teams! Team.active.each do |team| next unless team.sleepy? team.deactivate! end end end
MyApp.instance.prepare!Service Manager
Lifecycle Callbacks
You can introduce custom behavior into the service lifecycle via callbacks. This can be useful when new team has been registered via the API or a team has been deactivated from Slack.
instance = SlackRubyBotServer::Service.instanceinstance.on :started, :stopped do |team|
team has been started or stopped
end
instance.on :created do |team, error, options|
a new team has been registered
end
instance.on :deactivated do |team, error, options|
an existing team has been deactivated in Slack
end
instance.on :error do |team, error, options|
an error has occurred
end
The following callbacks are supported. All callbacks receive a
team, excepterror, which receives aStandardErrorobject.| callback | description | |:--------------:|:-----------------------------------------------------------------| | error | an error has occurred | | creating | a new team is being registered | | created | a new team has been registered | | booting | the service is starting and is connecting a team to Slack | | booted | the service is starting and has connected a team to Slack | | stopping | the service is about to disconnect a team from Slack | | stopped | the service has disconnected a team from Slack | | starting | the service is (re)connecting a team to Slack | | started | the service has (re)connected a team to Slack | | deactivating | a team is being deactivated | | deactivated | a team has been deactivated |
The Add to Slack button also allows for an optional
stateparameter that will be returned on completion of the request. Thecreatingandcreatedcallbacks include an options hash where this value can be accessed (to check for forgery attacks for instance).ruby auth = OpenSSL::HMAC.hexdigest("SHA256", "key", "data")html ...ruby instance = SlackRubyBotServer::Service.instance instance.on :creating do |team, error, options| raise "Unauthorized response" unless options[:state] == auth endService Timers
You can introduce custom behavior into the service lifecycle on a timer. For example, check whether a team's trial has expired, or periodically cleanup data.
Note that unlike callbacks, timers are global for the entire service.
instance = SlackRubyBotServer::Service.instanceinstance.every :hour do Team.each do |team| begin # do something with every team once an hour rescue StandardError end end end
instance.every :minute do
called every minute
end
instance.every :second do
called every second
end
instance.every 30 do
called every 30 seconds
end
Extensions
A number of extensions use service manager callbacks and service timers to implement useful functionality.
You can override the service class to handle additional methods.
class MyService < SlackRubyBotServer::Service def url 'https://www.example.com' end endSlackRubyBotServer.configure do |config| config.service_class = MyService end
SlackRubyBotServer::Service.instance # MyService SlackRubyBotServer::Service.instance.url # https://www.example.com
This library provides a default HTML template and JS scripts that implement the "Add to Slack" button workflow. Customize your pages by adding a
publicdirectory in your application and starting with a index.html.erb template. The application's
viewsand
publicfolders are loaded by default.
You can add to or override template paths as follows.
SlackRubyBotServer.configure do |config| config.view_paths << File.expand_path(File.join(__dir__, 'public')) end
By default the implementation of Team stores the value of the token with all the requested OAuth scopes in both
tokenand
activated_user_access_token(for backwards compatibility), along with
oauth_versionand
oauth_scope. If a legacy Slack bot integration
bot_access_tokenis present, it is stored as
token, and
activated_user_access_tokenis the token that has all the requested OAuth scopes.
Copyright Daniel Doubrovkine and Contributors, 2015-2020