slack-ruby-bot 0.10.5 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +52 -16
- data/CHANGELOG.md +8 -0
- data/Gemfile +3 -0
- data/README.md +92 -5
- data/Rakefile +1 -1
- data/examples/inventory/Gemfile +1 -1
- data/examples/market/Gemfile +1 -1
- data/examples/market/marketbot.rb +1 -1
- data/examples/minimal/Gemfile +1 -1
- data/examples/weather/Gemfile +1 -1
- data/lib/slack-ruby-bot.rb +0 -1
- data/lib/slack-ruby-bot/app.rb +10 -8
- data/lib/slack-ruby-bot/client.rb +8 -6
- data/lib/slack-ruby-bot/commands/base.rb +41 -8
- data/lib/slack-ruby-bot/commands/help.rb +4 -4
- data/lib/slack-ruby-bot/commands/{help → support}/attrs.rb +1 -1
- data/lib/slack-ruby-bot/commands/support/help.rb +80 -0
- data/lib/slack-ruby-bot/commands/support/match.rb +22 -0
- data/lib/slack-ruby-bot/config.rb +1 -1
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/not_respond.rb +5 -3
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_error.rb +5 -3
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_slack_message.rb +2 -2
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_slack_messages.rb +2 -2
- data/lib/slack-ruby-bot/rspec/support/spec_helpers.rb +3 -1
- data/lib/slack-ruby-bot/server.rb +1 -1
- data/lib/slack-ruby-bot/version.rb +1 -1
- data/slack-ruby-bot.gemspec +2 -2
- data/spec/slack-ruby-bot/commands/attachment_spec.rb +102 -0
- data/spec/slack-ruby-bot/commands/bot_message_spec.rb +1 -1
- data/spec/slack-ruby-bot/commands/commands_regexp_escape_spec.rb +6 -0
- data/spec/slack-ruby-bot/commands/{help → support}/attrs_spec.rb +1 -1
- data/spec/slack-ruby-bot/{support/commands_helper_spec.rb → commands/support/help_spec.rb} +23 -9
- data/spec/slack-ruby-bot/commands/support/match_spec.rb +54 -0
- data/spec/slack-ruby-bot/hooks/hook_support_spec.rb +1 -1
- data/spec/slack-ruby-bot/hooks/message_spec.rb +1 -1
- data/spec/slack-ruby-bot/mvc/controller/controller_to_command_spec.rb +2 -2
- data/spec/slack-ruby-bot/rspec/respond_with_error_spec.rb +8 -3
- data/spec/slack-ruby-bot/rspec/respond_with_slack_message_spec.rb +11 -0
- data/spec/slack-ruby-bot/rspec/respond_with_slack_messages_spec.rb +15 -0
- data/spec/slack-ruby-bot/server_spec.rb +2 -2
- metadata +28 -23
- data/lib/slack-ruby-bot/support/commands_helper.rb +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9478d61ec600a816259bd73d8aab8120a1d76ed2
|
4
|
+
data.tar.gz: c1d005b0e9c308af61dbe3d8ec112f3a8e72b62a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce48f28806019da9be29699e48d7aa292d70b462df75d6e5eccf0f5a7c40dde8eab1f99b3465779c55ec4c14d64c5a91f2cbbb1b370d4e570f4185701ab22720
|
7
|
+
data.tar.gz: 6d13d2fe47144b8cbec5740b6598aa3b7e0f8bdf1010b27ffb41d313eb33f3d67da6e745cffc54221bdede92584a183f48decb3b5a1daeec84ecf866ec423887
|
data/.rubocop_todo.yml
CHANGED
@@ -1,11 +1,25 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2018-03-29 16:47:34 +0200 using RuboCop version 0.51.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
+
# Offense count: 2
|
10
|
+
# Cop supports --auto-correct.
|
11
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
12
|
+
# SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
|
13
|
+
Layout/IndentHeredoc:
|
14
|
+
Exclude:
|
15
|
+
- 'lib/slack-ruby-bot/commands/help.rb'
|
16
|
+
- 'spec/slack-ruby-bot/commands/help_spec.rb'
|
17
|
+
|
18
|
+
# Offense count: 1
|
19
|
+
Lint/DuplicateMethods:
|
20
|
+
Exclude:
|
21
|
+
- 'lib/slack-ruby-bot/hooks/set.rb'
|
22
|
+
|
9
23
|
# Offense count: 1
|
10
24
|
Lint/HandleExceptions:
|
11
25
|
Exclude:
|
@@ -15,31 +29,57 @@ Lint/HandleExceptions:
|
|
15
29
|
Metrics/AbcSize:
|
16
30
|
Max: 40
|
17
31
|
|
32
|
+
# Offense count: 30
|
33
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
34
|
+
Metrics/BlockLength:
|
35
|
+
Max: 131
|
36
|
+
|
18
37
|
# Offense count: 1
|
19
38
|
# Configuration parameters: CountComments.
|
20
39
|
Metrics/ClassLength:
|
21
|
-
Max:
|
40
|
+
Max: 131
|
22
41
|
|
23
42
|
# Offense count: 2
|
24
43
|
Metrics/CyclomaticComplexity:
|
25
|
-
Max:
|
44
|
+
Max: 16
|
26
45
|
|
27
|
-
# Offense count:
|
28
|
-
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
|
46
|
+
# Offense count: 249
|
47
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
29
48
|
# URISchemes: http, https
|
30
49
|
Metrics/LineLength:
|
31
|
-
Max:
|
50
|
+
Max: 151
|
32
51
|
|
33
|
-
# Offense count:
|
52
|
+
# Offense count: 11
|
34
53
|
# Configuration parameters: CountComments.
|
35
54
|
Metrics/MethodLength:
|
36
|
-
Max:
|
55
|
+
Max: 27
|
37
56
|
|
38
57
|
# Offense count: 2
|
39
58
|
Metrics/PerceivedComplexity:
|
40
|
-
Max:
|
59
|
+
Max: 14
|
60
|
+
|
61
|
+
# Offense count: 1
|
62
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
63
|
+
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
64
|
+
Naming/FileName:
|
65
|
+
Exclude:
|
66
|
+
- 'lib/slack-ruby-bot.rb'
|
41
67
|
|
42
|
-
# Offense count:
|
68
|
+
# Offense count: 2
|
69
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
70
|
+
# SupportedStyles: snake_case, normalcase, non_integer
|
71
|
+
Naming/VariableNumber:
|
72
|
+
Exclude:
|
73
|
+
- 'spec/slack-ruby-bot/hooks/set_spec.rb'
|
74
|
+
|
75
|
+
# Offense count: 1
|
76
|
+
# Cop supports --auto-correct.
|
77
|
+
# Configuration parameters: AutoCorrect.
|
78
|
+
Performance/HashEachMethods:
|
79
|
+
Exclude:
|
80
|
+
- 'lib/slack-ruby-bot/hooks/set.rb'
|
81
|
+
|
82
|
+
# Offense count: 32
|
43
83
|
Style/Documentation:
|
44
84
|
Enabled: false
|
45
85
|
|
@@ -49,12 +89,8 @@ Style/DoubleNegation:
|
|
49
89
|
- 'lib/slack-ruby-bot/commands/base.rb'
|
50
90
|
|
51
91
|
# Offense count: 1
|
52
|
-
# Configuration parameters:
|
53
|
-
|
54
|
-
Exclude:
|
55
|
-
- 'lib/slack-ruby-bot.rb'
|
56
|
-
|
57
|
-
# Offense count: 1
|
92
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
93
|
+
# SupportedStyles: module_function, extend_self
|
58
94
|
Style/ModuleFunction:
|
59
95
|
Exclude:
|
60
96
|
- 'lib/slack-ruby-bot/config.rb'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
### 0.11.0 (04/02/2018)
|
2
|
+
|
3
|
+
* [#182](https://github.com/slack-ruby/slack-ruby-bot/pull/182): Refactor CommandsHelper class and Help module - [@mdudzinski](https://github.com/mdudzinski).
|
4
|
+
* [#180](https://github.com/slack-ruby/slack-ruby-bot/pull/180): Allow to respond to text in attachments #177 - [@mdudzinski](https://github.com/mdudzinski).
|
5
|
+
* [#173](https://github.com/slack-ruby/slack-ruby-bot/pull/173): Exposing SlackRubyBot::CommandsHelper.find_command_help_attrs - [@alexagranov](https://github.com/alexagranov).
|
6
|
+
* [#179](https://github.com/slack-ruby/slack-ruby-bot/pull/179): Allow multiline expression - [@tiagotex](https://github.com/tiagotex).
|
7
|
+
* [#183](https://github.com/slack-ruby/slack-ruby-bot/pull/183): Add missing test dependency to readme.md - [@hoshinotsuyoshi](https://github.com/hoshinotsuyoshi).
|
8
|
+
|
1
9
|
### 0.10.5 (10/15/2017)
|
2
10
|
|
3
11
|
* Refactored `SlackRubyBot::MVC::Controller::Base`, consolidated ivar handling, centralized object allocations and DRYed up the code - [@chuckremes](https://github.com/chuckremes).
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -19,7 +19,9 @@ If you are not familiar with Slack bots or Slack API concepts, you might want to
|
|
19
19
|
|
20
20
|
## Stable Release
|
21
21
|
|
22
|
-
You're reading the documentation for the **next** release of slack-ruby-bot.
|
22
|
+
You're reading the documentation for the **next** release of slack-ruby-bot.
|
23
|
+
Please see the documentation for the [last stable release, v0.10.5](https://github.com/slack-ruby/slack-ruby-bot/tree/v0.10.5) unless you're integrating with HEAD.
|
24
|
+
See [CHANGELOG](CHANGELOG.md) for a history of changes and [UPGRADING](UPGRADING.md) for how to upgrade to more recent versions.
|
23
25
|
|
24
26
|
## Usage
|
25
27
|
|
@@ -104,6 +106,28 @@ end
|
|
104
106
|
|
105
107
|
Operator match data includes `match['operator']` and `match['expression']`. The `bot` match always checks against the `SlackRubyBot::Config.user` setting.
|
106
108
|
|
109
|
+
### Threaded Messages
|
110
|
+
|
111
|
+
To reply to a message in a thread you must provide a reference to the first message that initiated the thread, which is available as either `data.ts` if no threaded messages have been sent, or `data.thread_ts` if the message being replied to is already in a thread. See [message-threading](https://api.slack.com/docs/message-threading) for more information.
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
command 'reply in thread' do |client, data, match|
|
115
|
+
client.say(
|
116
|
+
channel: data.channel,
|
117
|
+
text: "let's avoid spamming everyone, I will tell you what you need in this thread",
|
118
|
+
thread_ts: data.thread_ts || data.ts
|
119
|
+
)
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
_Note that sending a message using only `thread_ts: data.ts` can cause some permanent issues where Slack will keep reporting inaccessible messages as unread. At the time of writing the slack team is still having problems clearing those notifications. As recommended by the slack documentation ..._
|
124
|
+
|
125
|
+
> A true parent's thread_ts should be used when replying. Providing a child's message ID will result in a new, detached thread breaking all context and sense.
|
126
|
+
|
127
|
+
_... the replies to a thread should always be sent to the message `ts` that started the thread, available as `thread_ts` for subsequent messages. Hence `data.thread_ts || data.ts`._
|
128
|
+
|
129
|
+
For additional options, including broadcasting, see [slack-ruby-client#chat_postMessage](https://github.com/slack-ruby/slack-ruby-client/blob/41539c647ac877400f20aa338aa42d2ebfd2866b/lib/slack/web/api/endpoints/chat.rb#L105).
|
130
|
+
|
107
131
|
### Bot Aliases
|
108
132
|
|
109
133
|
A bot will always respond to its name (eg. `rubybot`) and Slack ID (eg. `@rubybot`), but you can specify multiple aliases via the `SLACK_RUBY_BOT_ALIASES` environment variable or via an explicit configuration.
|
@@ -154,6 +178,46 @@ end
|
|
154
178
|
|
155
179
|
See [examples/market](examples/market/marketbot.rb) for a working example.
|
156
180
|
|
181
|
+
### Matching text in message attachments
|
182
|
+
|
183
|
+
You can respond to text in [attachments](https://api.slack.com/docs/message-attachments) with
|
184
|
+
`attachment`. It will scan `text`, `pretext` and `title` fields in each attachment until a first
|
185
|
+
match is found.
|
186
|
+
|
187
|
+
For example you can match [this example attachment](http://goo.gl/K0cLkH)
|
188
|
+
by its `title` with the following bot:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
class Attachment < SlackRubyBot::Bot
|
192
|
+
attachment 'Slack API Documentation' do |client, data, match|
|
193
|
+
client.say(channel: data.channel, text: "Matched by #{match.attachment_field}.")
|
194
|
+
client.say(channel: data.channel, text: "The attachment's text: #{match.attachment.text}.")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
```
|
198
|
+
|
199
|
+
You can also define which fields in attachment object should be scanned.
|
200
|
+
|
201
|
+
Scan only a single field:
|
202
|
+
|
203
|
+
```ruby
|
204
|
+
class Attachment < SlackRubyBot::Bot
|
205
|
+
attachment 'Slack API Documentation', :title do |client, data, match|
|
206
|
+
# implementation details
|
207
|
+
end
|
208
|
+
end
|
209
|
+
```
|
210
|
+
|
211
|
+
Scan multiple fields:
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
class Attachment < SlackRubyBot::Bot
|
215
|
+
attachment 'Slack API Documentation', %i[text pretext author_name] do |client, data, match|
|
216
|
+
# implementation details
|
217
|
+
end
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
157
221
|
### Providing description for your bot and commands
|
158
222
|
|
159
223
|
You can specify help information for bot or commands with `help` block, for example:
|
@@ -195,6 +259,22 @@ class Deploy < SlackRubyBot::Commands::Base
|
|
195
259
|
end
|
196
260
|
```
|
197
261
|
|
262
|
+
### Customize your command help output
|
263
|
+
|
264
|
+
If you've used the `help` block described above to document your
|
265
|
+
commands, you can provide your own implementation of outputting help
|
266
|
+
for commands like so:
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
class Market < SlackRubyBot::Bot
|
270
|
+
command 'help' do |client, data, match|
|
271
|
+
user_command = match[:expression]
|
272
|
+
help_attrs = SlackRubyBot::Commands::Support::Help.instance.find_command_help_attrs(user_command)
|
273
|
+
client.say(channel: data.channel, text: "#{help_attrs.command_desc}\n\n#{help_attrs.command_long_desc}"
|
274
|
+
end
|
275
|
+
end
|
276
|
+
```
|
277
|
+
|
198
278
|
### SlackRubyBot::Commands::Base
|
199
279
|
|
200
280
|
The `SlackRubyBot::Bot` class is DSL sugar deriving from `SlackRubyBot::Commands::Base`. For more involved bots you can organize the bot implementation into subclasses of `SlackRubyBot::Commands::Base` manually. By default a command class responds, case-insensitively, to its name. A class called `Phone` that inherits from `SlackRubyBot::Commands::Base` responds to `phone` and `Phone` and calls the `call` method when implemented.
|
@@ -290,8 +370,8 @@ Hooks are event handlers and respond to Slack RTM API [events](https://api.slack
|
|
290
370
|
|
291
371
|
A Hook Handler is any object that respond to a `call` message, like a proc, instance of an object, class with a `call` class method, etc.
|
292
372
|
|
293
|
-
Hooks can be registered using different methods based on user preference / use case.
|
294
|
-
Currently someone can use one of the following methods:
|
373
|
+
Hooks can be registered using different methods based on user preference / use case.
|
374
|
+
Currently someone can use one of the following methods:
|
295
375
|
|
296
376
|
* Pass `hooks` in `SlackRubyBot::Server` initialization.
|
297
377
|
* Register `hooks` on `SlackRubyBot::Server` using `on` class method.
|
@@ -350,8 +430,8 @@ module MyBot
|
|
350
430
|
# data['user']['id'] contains the user ID
|
351
431
|
# data['user']['name'] contains the new user name
|
352
432
|
end
|
353
|
-
|
354
|
-
on 'user_change', ->(client, data) {
|
433
|
+
|
434
|
+
on 'user_change', ->(client, data) {
|
355
435
|
# data['user']['id'] contains the user ID
|
356
436
|
# data['user']['name'] contains the new user name
|
357
437
|
}
|
@@ -420,6 +500,12 @@ end
|
|
420
500
|
|
421
501
|
For an example of advanced integration that supports multiple teams, see [slack-gamebot](https://github.com/dblock/slack-gamebot) and [playplay.io](http://playplay.io) that is built on top of it.
|
422
502
|
|
503
|
+
### Proxy Configuration
|
504
|
+
|
505
|
+
There are [several proxy options](https://github.com/slack-ruby/slack-ruby-client#web-client-options) that can be configured on `Slack::Web::Client`. 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).
|
506
|
+
|
507
|
+
Note that Docker on OSX seems to incorrectly set the proxy, [causing `Faraday::ConnectionFailed`](https://github.com/slack-ruby/slack-ruby-bot/issues/155), `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`.
|
508
|
+
|
423
509
|
### Model-View-Controller Design
|
424
510
|
|
425
511
|
The `command` method is essentially a controller method that receives input from the outside and acts upon it. Complex behaviors could lead to a long and difficult-to-understand `command` block. A complex `command` block is a candidate for separation into classes conforming to the Model-View-Controller pattern popularized by Rails.
|
@@ -564,6 +650,7 @@ Require `slack-ruby-bot/rspec` in your `spec_helper.rb` along with the following
|
|
564
650
|
|
565
651
|
```ruby
|
566
652
|
group :development, :test do
|
653
|
+
gem 'rack-test'
|
567
654
|
gem 'rspec'
|
568
655
|
gem 'vcr'
|
569
656
|
gem 'webmock'
|
data/Rakefile
CHANGED
data/examples/inventory/Gemfile
CHANGED
data/examples/market/Gemfile
CHANGED
@@ -5,7 +5,7 @@ SlackRubyBot::Client.logger.level = Logger::WARN
|
|
5
5
|
|
6
6
|
class MarketBot < SlackRubyBot::Bot
|
7
7
|
scan(/([A-Z]{2,5}+)/) do |client, data, stocks|
|
8
|
-
YahooFinance::Client.new.quotes(stocks, [
|
8
|
+
YahooFinance::Client.new.quotes(stocks, %i[name symbol last_trade_price change change_in_percent]).each do |quote|
|
9
9
|
next if quote.symbol == 'N/A'
|
10
10
|
client.web_client.chat_postMessage(
|
11
11
|
channel: data.channel,
|
data/examples/minimal/Gemfile
CHANGED
data/examples/weather/Gemfile
CHANGED
data/lib/slack-ruby-bot.rb
CHANGED
data/lib/slack-ruby-bot/app.rb
CHANGED
@@ -22,14 +22,16 @@ module SlackRubyBot
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def hello(client, _data)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
if client.team && client.self
|
26
|
+
SlackRubyBot.configure do |config|
|
27
|
+
config.url = "https://#{client.team.domain}.slack.com"
|
28
|
+
config.team = client.team.name
|
29
|
+
config.team_id = client.team.id
|
30
|
+
config.user = client.self.name
|
31
|
+
config.user_id = client.self.id
|
32
|
+
logger.info "Welcome #{config.user} to the #{config.team} team."
|
33
|
+
end
|
34
|
+
end
|
33
35
|
super
|
34
36
|
end
|
35
37
|
|
@@ -48,12 +48,14 @@ module SlackRubyBot
|
|
48
48
|
keywords = options.delete(:gif)
|
49
49
|
# text
|
50
50
|
text = options.delete(:text)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
if keywords && send_gifs?
|
52
|
+
gif = begin
|
53
|
+
Giphy.random(keywords)
|
54
|
+
rescue StandardError => e
|
55
|
+
logger.warn "Giphy.random: #{e.message}"
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
57
59
|
text = [text, gif && gif.image_url.to_s].compact.join("\n")
|
58
60
|
message({ text: text }.merge(options))
|
59
61
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
require_relative 'support/match'
|
2
|
+
require_relative 'support/help'
|
3
|
+
|
1
4
|
module SlackRubyBot
|
2
5
|
module Commands
|
3
6
|
class Base
|
4
7
|
include Loggable
|
5
|
-
class_attribute :routes
|
6
8
|
|
7
9
|
class << self
|
8
10
|
attr_accessor :command_classes
|
@@ -32,7 +34,7 @@ module SlackRubyBot
|
|
32
34
|
end
|
33
35
|
|
34
36
|
def help(&block)
|
35
|
-
|
37
|
+
Support::Help.instance.capture_help(self, &block)
|
36
38
|
end
|
37
39
|
|
38
40
|
def command_name_from_class
|
@@ -46,24 +48,32 @@ module SlackRubyBot
|
|
46
48
|
|
47
49
|
def command(*values, &block)
|
48
50
|
values = values.map { |value| value.is_a?(Regexp) ? value.source : Regexp.escape(value) }.join('|')
|
49
|
-
match Regexp.new("^#{bot_matcher}[\\s]+(?<command>#{values})([\\s]+(?<expression>.*)|)$", Regexp::IGNORECASE), &block
|
51
|
+
match Regexp.new("^#{bot_matcher}[\\s]+(?<command>#{values})([\\s]+(?<expression>.*)|)$", Regexp::IGNORECASE | Regexp::MULTILINE), &block
|
50
52
|
end
|
51
53
|
|
52
54
|
def invoke(client, data)
|
53
55
|
finalize_routes!
|
54
56
|
expression, text = parse(client, data)
|
55
|
-
return false unless expression
|
57
|
+
return false unless expression || data.attachments
|
56
58
|
routes.each_pair do |route, options|
|
57
59
|
match_method = options[:match_method]
|
58
60
|
case match_method
|
59
61
|
when :match
|
62
|
+
next unless expression
|
60
63
|
match = route.match(expression)
|
61
64
|
match ||= route.match(text) if text
|
62
65
|
next unless match
|
63
66
|
next if match.names.include?('bot') && !client.name?(match['bot'])
|
67
|
+
match = Support::Match.new(match)
|
64
68
|
when :scan
|
69
|
+
next unless expression
|
65
70
|
match = expression.scan(route)
|
66
71
|
next unless match.any?
|
72
|
+
when :attachment
|
73
|
+
next unless data.attachments && !data.attachments.empty?
|
74
|
+
match, attachment, field = match_attachments(data, route, options[:fields_to_scan])
|
75
|
+
next unless match
|
76
|
+
match = Support::Match.new(match, attachment, field)
|
67
77
|
end
|
68
78
|
call_command(client, data, match, options[:block])
|
69
79
|
return true
|
@@ -72,19 +82,30 @@ module SlackRubyBot
|
|
72
82
|
end
|
73
83
|
|
74
84
|
def match(match, &block)
|
75
|
-
|
76
|
-
self.routes[match] = { match_method: :match, block: block }
|
85
|
+
routes[match] = { match_method: :match, block: block }
|
77
86
|
end
|
78
87
|
|
79
88
|
def scan(match, &block)
|
80
|
-
|
81
|
-
|
89
|
+
routes[match] = { match_method: :scan, block: block }
|
90
|
+
end
|
91
|
+
|
92
|
+
def attachment(match, fields_to_scan = nil, &block)
|
93
|
+
fields_to_scan = [fields_to_scan] unless fields_to_scan.nil? || fields_to_scan.is_a?(Array)
|
94
|
+
routes[match] = {
|
95
|
+
match_method: :attachment,
|
96
|
+
block: block,
|
97
|
+
fields_to_scan: fields_to_scan
|
98
|
+
}
|
82
99
|
end
|
83
100
|
|
84
101
|
def bot_matcher
|
85
102
|
'(?<bot>\S*)'
|
86
103
|
end
|
87
104
|
|
105
|
+
def routes
|
106
|
+
@routes ||= ActiveSupport::OrderedHash.new
|
107
|
+
end
|
108
|
+
|
88
109
|
private
|
89
110
|
|
90
111
|
def call_command(client, data, match, block)
|
@@ -122,6 +143,18 @@ module SlackRubyBot
|
|
122
143
|
command command_name_from_class
|
123
144
|
end
|
124
145
|
|
146
|
+
def match_attachments(data, route, fields_to_scan = nil)
|
147
|
+
fields_to_scan ||= %i[pretext text title]
|
148
|
+
data.attachments.each do |attachment|
|
149
|
+
fields_to_scan.each do |field|
|
150
|
+
next unless attachment[field]
|
151
|
+
match = route.match(attachment[field])
|
152
|
+
return match, attachment, field if match
|
153
|
+
end
|
154
|
+
end
|
155
|
+
false
|
156
|
+
end
|
157
|
+
|
125
158
|
# Intended to be overridden by subclasses to hook in an
|
126
159
|
# authorization mechanism.
|
127
160
|
def permitted?(_client, _data, _match)
|