slack-ruby-bot-boilerplate 0.1.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 +7 -0
- data/.gitignore +5 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.rubocop_todo.yml +77 -0
- data/.travis.yml +28 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +139 -0
- data/DEPLOYMENT.md +33 -0
- data/Gemfile +9 -0
- data/LICENSE.md +22 -0
- data/README.md +688 -0
- data/Rakefile +19 -0
- data/TUTORIAL.md +218 -0
- data/UPGRADING.md +226 -0
- data/lib/config/application.rb +12 -0
- data/lib/config/boot.rb +6 -0
- data/lib/config/environment.rb +3 -0
- data/lib/slack_respondent.rb +25 -0
- data/lib/slack_respondent/client.rb +61 -0
- data/lib/slack_respondent/commands.rb +5 -0
- data/lib/slack_respondent/commands/about.rb +15 -0
- data/lib/slack_respondent/commands/base.rb +140 -0
- data/lib/slack_respondent/commands/help.rb +42 -0
- data/lib/slack_respondent/commands/hi.rb +14 -0
- data/lib/slack_respondent/commands/support/attrs.rb +34 -0
- data/lib/slack_respondent/commands/support/help.rb +81 -0
- data/lib/slack_respondent/commands/support/match.rb +22 -0
- data/lib/slack_respondent/commands/unknown.rb +13 -0
- data/lib/slack_respondent/config.rb +38 -0
- data/lib/slack_respondent/reactions.rb +38 -0
- data/lib/slack_respondent/support/loggable.rb +23 -0
- data/lib/slack_respondent/version.rb +3 -0
- data/slack-ruby-bot-boilerplate.gemspec +25 -0
- data/slack.png +0 -0
- metadata +189 -0
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
Bundler.setup :default, :development
|
6
|
+
|
7
|
+
unless ENV['RACK_ENV'] == 'production'
|
8
|
+
require 'rspec/core'
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
|
11
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
12
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'rubocop/rake_task'
|
16
|
+
RuboCop::RakeTask.new
|
17
|
+
|
18
|
+
task default: %i[rubocop spec]
|
19
|
+
end
|
data/TUTORIAL.md
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
## Production Bot Tutorial
|
2
|
+
|
3
|
+
In this tutorial we'll implement [slack-mathbot](https://github.com/dblock/slack-mathbot).
|
4
|
+
|
5
|
+
### Introduction
|
6
|
+
|
7
|
+
A typical production Slack bot is a combination of a vanilla web server and a websocket application that talks to the [Slack Real Time Messaging API](https://api.slack.com/rtm). The web server is optional, but most people will run their Slack bots on [Heroku](https://dashboard.heroku.com) in which case a web server is required to prevent Heroku from shutting the bot down. It also makes it convenient to develop a bot and test using `foreman`.
|
8
|
+
|
9
|
+
### Getting Started
|
10
|
+
|
11
|
+
#### Gemfile
|
12
|
+
|
13
|
+
Create a `Gemfile` that uses [slack-ruby-bot](https://github.com/slack-ruby/slack-ruby-bot), [sinatra](https://github.com/sinatra/sinatra) (a web framework) and [puma](https://github.com/puma/puma) (a web server). For development we'll also use [foreman](https://github.com/theforeman/foreman) and write tests with [rspec](https://github.com/rspec/rspec).
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
source 'https://rubygems.org'
|
17
|
+
|
18
|
+
gem 'slack-ruby-bot'
|
19
|
+
gem 'puma'
|
20
|
+
gem 'sinatra'
|
21
|
+
gem 'dotenv'
|
22
|
+
gem 'celluloid-io'
|
23
|
+
|
24
|
+
group :development, :test do
|
25
|
+
gem 'rake'
|
26
|
+
gem 'foreman'
|
27
|
+
end
|
28
|
+
|
29
|
+
group :test do
|
30
|
+
gem 'rspec'
|
31
|
+
gem 'rack-test'
|
32
|
+
gem 'vcr'
|
33
|
+
gem 'webmock'
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
Run `bundle install` to get all the gems.
|
38
|
+
|
39
|
+
#### Application
|
40
|
+
|
41
|
+
Create a folder called `slack-mathbot` and inside of it create `bot.rb`.
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
module SlackMathbot
|
45
|
+
class Bot < SlackRubyBot::Bot
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
#### Commands
|
51
|
+
|
52
|
+
Create a folder called `slack-mathbot/commands` and inside of it create `calculate.rb`. For now this calculator will always return 4.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
module SlackMathbot
|
56
|
+
module Commands
|
57
|
+
class Calculate < SlackRubyBot::Commands::Base
|
58
|
+
command 'calculate' do |client, data, _match|
|
59
|
+
client.say(channel: data.channel, text: '4')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
#### Require Everything
|
67
|
+
|
68
|
+
Create a `slack-mathbot.rb` at the root and require the above files.
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
require 'slack-ruby-bot'
|
72
|
+
require 'slack-mathbot/commands/calculate'
|
73
|
+
require 'slack-mathbot/bot'
|
74
|
+
```
|
75
|
+
|
76
|
+
#### Web Server
|
77
|
+
|
78
|
+
We will need to keep the bot alive on Heroku, so create `web.rb`.
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
require 'sinatra/base'
|
82
|
+
|
83
|
+
module SlackMathbot
|
84
|
+
class Web < Sinatra::Base
|
85
|
+
get '/' do
|
86
|
+
'Math is good for you.'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
#### Config.ru
|
93
|
+
|
94
|
+
Tie all the pieces together in `config.ru` which creates a thread for the bot and runs the web server on the main thread.
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
98
|
+
|
99
|
+
require 'dotenv'
|
100
|
+
Dotenv.load
|
101
|
+
|
102
|
+
require 'slack-mathbot'
|
103
|
+
require 'web'
|
104
|
+
|
105
|
+
Thread.abort_on_exception = true
|
106
|
+
|
107
|
+
Thread.new do
|
108
|
+
begin
|
109
|
+
SlackMathbot::Bot.run
|
110
|
+
rescue Exception => e
|
111
|
+
STDERR.puts "ERROR: #{e}"
|
112
|
+
STDERR.puts e.backtrace
|
113
|
+
raise e
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
run SlackMathbot::Web
|
118
|
+
```
|
119
|
+
|
120
|
+
### Create a Bot User
|
121
|
+
|
122
|
+
In Slack administration create a new Bot Integration under [services/new/bot](http://slack.com/services/new/bot).
|
123
|
+
|
124
|
+

|
125
|
+
|
126
|
+
On the next screen, note the API token.
|
127
|
+
|
128
|
+
#### .env
|
129
|
+
|
130
|
+
Create a `.env` file with the API token from above and make sure to add it to `.gitignore`.
|
131
|
+
|
132
|
+
```
|
133
|
+
SLACK_API_TOKEN=...
|
134
|
+
```
|
135
|
+
|
136
|
+
### Procfile
|
137
|
+
|
138
|
+
Create a `Procfile` which `foreman` will use when you run the `foreman start` command below.
|
139
|
+
|
140
|
+
```
|
141
|
+
web: bundle exec puma -p $PORT
|
142
|
+
```
|
143
|
+
|
144
|
+
### Run the Bot
|
145
|
+
|
146
|
+
Run `foreman start`. Your bot should be running.
|
147
|
+
|
148
|
+
```
|
149
|
+
14:32:32 web.1 | Puma starting in single mode...
|
150
|
+
14:32:32 web.1 | * Version 2.11.3 (ruby 2.1.6-p336), codename: Intrepid Squirrel
|
151
|
+
14:32:32 web.1 | * Min threads: 0, max threads: 16
|
152
|
+
14:32:32 web.1 | * Environment: development
|
153
|
+
14:32:35 web.1 | * Listening on tcp://0.0.0.0:5000
|
154
|
+
14:32:35 web.1 | Use Ctrl-C to stop
|
155
|
+
14:32:36 web.1 | I, [2015-07-10T14:32:36.216663 #98948] INFO -- : Welcome 'mathbot' to the 'xyz' team at https://xyz.slack.com/.
|
156
|
+
14:32:36 web.1 | I, [2015-07-10T14:32:36.766955 #98948] INFO -- : Successfully connected to https://xyz.slack.com/.
|
157
|
+
```
|
158
|
+
|
159
|
+
### Try
|
160
|
+
|
161
|
+
Invite the bot to a channel via `/invite [bot name]` and send it a `calculate` command with `[bot name] calculate 2+2`. It will respond with `4` from the code above.
|
162
|
+
|
163
|
+
### Write Tests
|
164
|
+
|
165
|
+
#### Spec Helper
|
166
|
+
|
167
|
+
Create `spec/spec_helper.rb` that includes the bot files and shared RSpec support from slack-ruby-bot.
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
171
|
+
|
172
|
+
require 'slack-ruby-bot/rspec'
|
173
|
+
require 'slack-mathbot'
|
174
|
+
```
|
175
|
+
|
176
|
+
#### Test the Bot Application
|
177
|
+
|
178
|
+
Create a test for the bot application itself in `spec/slack-mathbot/bot_spec.rb`.
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
require 'spec_helper'
|
182
|
+
|
183
|
+
describe SlackMathbot::Bot do
|
184
|
+
def app
|
185
|
+
SlackMathbot::Bot.instance
|
186
|
+
end
|
187
|
+
|
188
|
+
subject { app }
|
189
|
+
|
190
|
+
it_behaves_like 'a slack ruby bot'
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
#### Test a Command
|
195
|
+
|
196
|
+
Create a test for the `calculate` command in `spec/slack-mathbot/commands/calculate_spec.rb`. The bot is addressed by its user name.
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
require 'spec_helper'
|
200
|
+
|
201
|
+
describe SlackMathbot::Commands::Calculate do
|
202
|
+
def app
|
203
|
+
SlackMathbot::Bot.instance
|
204
|
+
end
|
205
|
+
|
206
|
+
subject { app }
|
207
|
+
|
208
|
+
it 'returns 4' do
|
209
|
+
expect(message: "#{SlackRubyBot.config.user} calculate 2+2", channel: 'channel').to respond_with_slack_message('4')
|
210
|
+
end
|
211
|
+
end
|
212
|
+
```
|
213
|
+
|
214
|
+
See [lib/slack-ruby-bot/rspec/support/slack-ruby-bot](lib/slack-ruby-bot/rspec/support/slack-ruby-bot) for other shared RSpec behaviors.
|
215
|
+
|
216
|
+
### Deploy
|
217
|
+
|
218
|
+
See [DEPLOYMENT](DEPLOYMENT.md) for how to deploy your bot to production.
|
data/UPGRADING.md
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
Upgrading SlackRubyBot
|
2
|
+
======================
|
3
|
+
|
4
|
+
### Upgrading to >= 0.12.0
|
5
|
+
|
6
|
+
#### Remove any references to `SlackRubyBot::Server#restart!`
|
7
|
+
|
8
|
+
We have removed `SlackRubyBot::Server#restart!` since the [`slack-ruby-client`](https://github.com/slack-ruby/slack-ruby-client/blob/master/CHANGELOG.md) now restarts any connection that was not intentionally stopped via `SlackRubyBot::Server#stop!`.
|
9
|
+
|
10
|
+
### Upgrading to >= 0.10.4
|
11
|
+
|
12
|
+
#### Replace `server.hooks.add` with `server.on`
|
13
|
+
|
14
|
+
We have deprecated `SlackRubyBot::Server#hooks` in favor of `SlackRubyBot::Server#on` instance method. All users using `SlackRubyBot::Server#hooks` method should
|
15
|
+
change their codebase and use the new method instead. Method signature is not affected.
|
16
|
+
|
17
|
+
Example:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
# Given server is an instance of SlackRubyBot::Server
|
21
|
+
#
|
22
|
+
# Before
|
23
|
+
server.hooks.add :hello, Greet.new
|
24
|
+
|
25
|
+
# After
|
26
|
+
server.on :hello, Greet.new
|
27
|
+
```
|
28
|
+
|
29
|
+
### Upgrading to >= 0.9.0
|
30
|
+
|
31
|
+
#### Add giphy to your Gemfile for GIF support
|
32
|
+
|
33
|
+
The dependency on the `giphy` gem was dropped and GIFs don't appear by default. If you want GIF support, add `gem 'giphy'` to your **Gemfile**.
|
34
|
+
|
35
|
+
You should not need to make any changes if you had already disabled GIFs for your bot.
|
36
|
+
|
37
|
+
See [#89](https://github.com/slack-ruby/slack-ruby-bot/pull/89) for more information.
|
38
|
+
|
39
|
+
### Upgrading to >= 0.8.0
|
40
|
+
|
41
|
+
#### Require a concurrency library
|
42
|
+
|
43
|
+
The `faye-websocket` library is no longer required by default. Add either `faye-websocket` or `celluiloid-io` to your `Gemfile` depending on which concurrency implementation you'd like to use. We recommend `celluloid-io` moving forward.
|
44
|
+
|
45
|
+
#### Hook::Base was removed, explicitly register any custom hook classes
|
46
|
+
|
47
|
+
Hook classes are now handled differently, namely they are explicitly registered into `SlackRubyBot::Server` via a configuration option (`hook_handlers`) or by passing a similar hash later on through the `add_hook_handlers` method. Including Hook classes directly into the server class is no longer needed.
|
48
|
+
|
49
|
+
A hook is actioned via a `call` message onto the handler object (this can be anything that responds to that), so you'll need to rename your method.
|
50
|
+
|
51
|
+
Finally, you can now register multiple hooks for the same event, so if you had any code to remove default hooks, you'll need to change it so you pass a configuration hash into `Server`
|
52
|
+
|
53
|
+
### Upgrading to >= 0.7.0
|
54
|
+
|
55
|
+
#### Simplify Match Expression Checking
|
56
|
+
|
57
|
+
The regular expression parser for commands will now include a `nil` value for `expression` when an expression is not present. You can therefore no longer rely on checking `match.names.include?('expression')`, instead check `match['expression']`.
|
58
|
+
|
59
|
+
#### Remove any bot.auth! calls
|
60
|
+
|
61
|
+
SlackRubyBot 0.6.x versions invoked a method called `auth!`, which caused a pre-flight authentication via Slack Web API `auth_test` method and collected a number of properties, such as client and team ID or name. This method has been removed in favor of using data available in the `Slack::RealTime::Client` local store introduced in [slack-ruby-client#54](https://github.com/slack-ruby/slack-ruby-client/issues/54). Remove any explicit calls to this method.
|
62
|
+
|
63
|
+
### Upgrading to >= 0.6.0
|
64
|
+
|
65
|
+
While entirely compatible with the 0.5.x series, a number of methods have been deprecated and will be removed in the next release.
|
66
|
+
|
67
|
+
#### Replace SlackRubyBot::Commands::Base#call with command, operator or match
|
68
|
+
|
69
|
+
Prefer `command`, `operator` or `match` with a block instead of implementing a `self.call` method.
|
70
|
+
|
71
|
+
Before:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
require 'slack-ruby-bot'
|
75
|
+
|
76
|
+
class Bot < SlackRubyBot::Bot
|
77
|
+
command 'ping'
|
78
|
+
|
79
|
+
def self.call(client, data, match)
|
80
|
+
...
|
81
|
+
end
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
After:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
require 'slack-ruby-bot'
|
89
|
+
|
90
|
+
class Bot < SlackRubyBot::Bot
|
91
|
+
command 'ping' do |client, data, match|
|
92
|
+
...
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
#### Replace send_message, send_message_with_gif and send_gif with client.say
|
98
|
+
|
99
|
+
Use `client.say` instead of `send_message`, `send_message_with_gif` and `send_gif` in commands.
|
100
|
+
|
101
|
+
Before:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
class Bot < SlackRubyBot::Bot
|
105
|
+
command 'one' do |client, data, match|
|
106
|
+
send_message client, data.channel, 'Text.'
|
107
|
+
end
|
108
|
+
|
109
|
+
command 'two' do |client, data, match|
|
110
|
+
send_message_with_gif client, data.channel, "Text.", 'keyword'
|
111
|
+
end
|
112
|
+
|
113
|
+
command 'three' do |client, data, match|
|
114
|
+
send_gif client, data.channel, 'keyword'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
After:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
class Bot < SlackRubyBot::Bot
|
123
|
+
command 'one' do |client, data, match|
|
124
|
+
client.say(channel: data.channel, text: 'Text.')
|
125
|
+
end
|
126
|
+
|
127
|
+
command 'two' do |client, data, match|
|
128
|
+
client.say(channel: data.channel, text: 'Text.', gif: 'keyword')
|
129
|
+
end
|
130
|
+
|
131
|
+
command 'three' do |client, data, match|
|
132
|
+
client.say(channel: data.channel, gif: 'keyword')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
#### For basic bots replace SlackRubyBot::App with SlackRubyBot::Bot and implement commands inline
|
138
|
+
|
139
|
+
Before:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
module PongBot
|
143
|
+
class App < SlackRubyBot::App
|
144
|
+
end
|
145
|
+
|
146
|
+
class Ping < SlackRubyBot::Commands::Base
|
147
|
+
command 'ping' do |client, data, _match|
|
148
|
+
client.message(text: 'pong', channel: data.channel)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
PongBot::App.instance.run
|
154
|
+
```
|
155
|
+
|
156
|
+
After:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
class Bot < SlackRubyBot::Bot
|
160
|
+
command 'ping' do |client, data, _match|
|
161
|
+
client.say(text: 'pong', channel: data.channel)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
Bot.run
|
166
|
+
```
|
167
|
+
|
168
|
+
### Upgrading to >= 0.4.0
|
169
|
+
|
170
|
+
This version uses [slack-ruby-client](https://github.com/slack-ruby/slack-ruby-client) instead of [slack-ruby-gem](https://github.com/aki017/slack-ruby-gem).
|
171
|
+
|
172
|
+
The command interface now takes a `client` parameter, which is the RealTime Messaging API instance. Add the new parameter to all `call` calls in classes that inherit from `SlackRubyBot::Commands::Base`.
|
173
|
+
|
174
|
+
Before:
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
def self.call(data, match)
|
178
|
+
...
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
182
|
+
After:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
def self.call(client, data, match)
|
186
|
+
...
|
187
|
+
end
|
188
|
+
```
|
189
|
+
|
190
|
+
This also applies to `command`, `operator` and `match` blocks.
|
191
|
+
|
192
|
+
Before:
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
command 'ping' do |data, match|
|
196
|
+
...
|
197
|
+
end
|
198
|
+
```
|
199
|
+
|
200
|
+
After:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
command 'ping' do |client, data, match|
|
204
|
+
...
|
205
|
+
end
|
206
|
+
```
|
207
|
+
|
208
|
+
You can now send messages directly via the RealTime Messaging API.
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
client.message text: 'text', channel: 'channel'
|
212
|
+
```
|
213
|
+
|
214
|
+
Otherwise you must now pass the `client` parameter to `send_message` and `send_message_with_gif`.
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
def self.call(client, data, match)
|
218
|
+
send_message client, data.channel, 'hello'
|
219
|
+
end
|
220
|
+
```
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
def self.call(client, data, match)
|
224
|
+
send_message_with_gif client, data.channel, 'hello', 'hi'
|
225
|
+
end
|
226
|
+
```
|