slack-ruby-bot 0.10.2 → 0.10.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15ac681a340b2b17bc5a4148c0b55dd7295fc1f2
4
- data.tar.gz: 04d0018c8acf732715f5992af917a69fcaa6d337
3
+ metadata.gz: 88982b31e113e853ff4c707a7718f0739ccf260e
4
+ data.tar.gz: 9f818712b6659e1281a89b0a144b922f9b66e61d
5
5
  SHA512:
6
- metadata.gz: 9f04ac47c686f1acd671d691826e7192d24da2b73c30fcdfda5a553f0906fa37439b5d4b4c2690148fd8fee7dd58cb9c6b2074e141b4d9670dbe5ceaa05e2e75
7
- data.tar.gz: 9e65685bc89a791ac36000bfd955daef01ef230f1010e31ff71b2133d82ee241c6f81dd6660ff81488d7d20a5e0b3f6eab5b79ba22323e5a3794e7e93b22349f
6
+ metadata.gz: 537ee07e13e6500c453b71cbfffa1b9eeda032baaf86319af4c298a6e65b3adc51de771694e6cc5107e4858d3344633bfaca7b70f23025afc6c5a1eb8bb23580
7
+ data.tar.gz: 6e2f758c616871af780b376613ef9eac7c0bfe6438f65e5950b035e4e450da31d207674b558b9e3726ca3287f0e468adda333988fa3c2a53b7fe0ac50757b660
@@ -1,3 +1,8 @@
1
+ ### 0.10.3 (06/15/2017)
2
+
3
+ * [#145](https://github.com/slack-ruby/slack-ruby-bot/pull/145): Map multiple command strings to same controller method - [@chuckremes](https://github.com/chuckremes).
4
+ * [#144](https://github.com/slack-ruby/slack-ruby-bot/pull/144): Support usage of commands with embedded spaces when using Controller methods - [@chuckremes](https://github.com/chuckremes).
5
+
1
6
  ### 0.10.2 (06/03/2017)
2
7
 
3
8
  * [#137](https://github.com/slack-ruby/slack-ruby-bot/pull/137): Add Model-View-Controller classes to allow for more explicit control over how `command`s are designed - [@chuckremes](https://github.com/chuckremes).
data/README.md CHANGED
@@ -364,10 +364,11 @@ Consider the following `Agent` class which is the simplest default approach to t
364
364
 
365
365
  ```ruby
366
366
  class Agent < SlackRubyBot::Bot
367
- command 'sayhello' do |client, data, match|
367
+ command 'sayhello', 'alternate way to call hello' do |client, data, match|
368
368
  client.say(channel: data.channel, text: "Received command #{match[:command]} with args #{match[:expression]}")
369
369
  end
370
370
  end
371
+ ```
371
372
 
372
373
  Using the MVC functionality, we would create a controller instead to encapsulate this function.
373
374
  ```ruby
@@ -375,6 +376,7 @@ class MyController < SlackRubyBot::MVC::Controller::Base
375
376
  def sayhello
376
377
  client.say(channel: data.channel, text: "Received command #{match[:command]} with args #{match[:expression]}")
377
378
  end
379
+ alternate_name :sayhello, :alternate_way_to_call_hello
378
380
  end
379
381
  MyController.new(MyModel.new, MyView.new)
380
382
  ```
@@ -384,6 +386,8 @@ However, the Controller anticipates that the model and view objects should conta
384
386
 
385
387
  A Controller may need helper methods for certain work. To prevent the helper method from creating a route that the bot will respond to directly, the instance method name should begin with an underscore (e.g. `_my_helper_method`). When building the bot routes, these methods will be skipped.
386
388
 
389
+ Calling `alternate_name` after the method definition allows for method aliases similar to the regular `command` structure. When commands can be triggered by multiple text strings it's useful to have that ability map to the controller methods too.
390
+
387
391
  Lastly, the Controller class includes `ActiveSupport::Callbacks` which allows for full flexibility in creating `before`, `after`, and `around` hooks for all methods. Again, see the [inventory example](examples/inventory/inventorybot.rb) for more information.
388
392
 
389
393
  #### Model
@@ -404,18 +408,18 @@ class MyModel < SlackRubyBot::MVC::Model::Base
404
408
 
405
409
  def read(resource)
406
410
  self._resource = resource
407
- run_callbacks :sanitize do
408
- @db.select(:column1 => resource)
409
- # ... do some expensive work
410
- end
411
+ run_callbacks :sanitize do
412
+ @db.select(:column1 => resource)
413
+ # ... do some expensive work
414
+ end
411
415
  end
412
416
 
413
417
  private
414
418
 
415
419
  def sanitize_resource
416
420
  self._resource.downcase
417
- result = yield
418
- puts "After read, result is #{result.inspect}"
421
+ result = yield
422
+ puts "After read, result is #{result.inspect}"
419
423
  end
420
424
  end
421
425
  ```
@@ -435,37 +439,37 @@ class MyView < SlackRubyBot::MVC::View::Base
435
439
 
436
440
  def initialize
437
441
  @mailer = setup_mailer
438
- @ftp = setup_ftp_handler
442
+ @ftp = setup_ftp_handler
439
443
  end
440
444
 
441
445
  def email_admin(message)
442
446
  run_callbacks :logit do
443
- @mailer.send(:administrator, message)
444
- end
447
+ @mailer.send(:administrator, message)
448
+ end
445
449
  end
446
450
 
447
451
  def react_thumbsup
448
- client.web_client.reactions_add(
449
- name: :thumbs_up,
450
- channel: data.channel,
451
- timestamp: data.ts,
452
- as_user: true)
452
+ client.web_client.reactions_add(
453
+ name: :thumbs_up,
454
+ channel: data.channel,
455
+ timestamp: data.ts,
456
+ as_user: true)
453
457
  end
454
458
 
455
459
  def react_thumbsdown
456
- client.web_client.reactions_remove(
457
- name: :thumbs_up,
458
- channel: data.channel,
459
- timestamp: data.ts,
460
- as_user: true)
460
+ client.web_client.reactions_remove(
461
+ name: :thumbs_up,
462
+ channel: data.channel,
463
+ timestamp: data.ts,
464
+ as_user: true)
461
465
  end
462
466
 
463
467
  private
464
468
 
465
469
  def audit_trail
466
470
  Logger.audit("Sending email at [#{Time.now}]")
467
- yield
468
- Logger.audit("Email sent by [#{Time.now}]")
471
+ yield
472
+ Logger.audit("Email sent by [#{Time.now}]")
469
473
  end
470
474
  end
471
475
  ```
@@ -7,6 +7,7 @@ There're no particular rules about when to release slack-ruby-bot. Release bug f
7
7
  Run tests, check that all tests succeed locally.
8
8
 
9
9
  ```
10
+ export CONCURRENCY=celluloid-io
10
11
  bundle install
11
12
  rake
12
13
  ```
@@ -16,6 +16,10 @@ module SlackRubyBot
16
16
  Base.instance_variable_get(:@command_class)
17
17
  end
18
18
 
19
+ def aliases
20
+ Base.instance_variable_get(:@aliases)
21
+ end
22
+
19
23
  def reset!
20
24
  # Remove any earlier anonymous classes from prior calls so we don't leak them
21
25
  Commands::Base.command_classes.delete(Controller::Base.command_class) if Base.command_class
@@ -43,6 +47,7 @@ module SlackRubyBot
43
47
  def register_controller(controller)
44
48
  # Only used to keep a reference around so the instance object doesn't get garbage collected
45
49
  Base.instance_variable_set(:@controllers, []) unless controllers
50
+ Base.instance_variable_set(:@aliases, Hash.new { |h, k| h[k] = [] }) unless aliases
46
51
  controller_ary = Base.instance_variable_get(:@controllers)
47
52
  controller_ary << controller
48
53
  klass = controller.class
@@ -53,14 +58,18 @@ module SlackRubyBot
53
58
  # Be sure to include shadowed public instance methods of this class
54
59
  klass.public_instance_methods(false)).uniq.map(&:to_s)
55
60
 
56
- methods.each do |meth_name|
57
- next if meth_name[0] == '_'
58
-
59
- # sprinkle a little syntactic sugar on top of existing `command` infrastructure
60
- command_class.class_eval do
61
- command meth_name.to_s do |client, data, match|
62
- controller.use_args(client, data, match)
63
- controller.call_command
61
+ methods.each do |name|
62
+ next if name[0] == '_'
63
+ commands = lookup_command_name(name)
64
+
65
+ # Generates a command for each controller method *and* its aliases
66
+ commands.each do |command_string|
67
+ # sprinkle a little syntactic sugar on top of existing `command` infrastructure
68
+ command_class.class_eval do
69
+ command command_string do |client, data, match|
70
+ controller.use_args(client, data, match)
71
+ controller.call_command
72
+ end
64
73
  end
65
74
  end
66
75
  end
@@ -76,6 +85,47 @@ module SlackRubyBot
76
85
  controller = controller.superclass until controller.abstract?
77
86
  controller.public_instance_methods(true)
78
87
  end
88
+
89
+ # Maps a controller method name to an alternate command name. Used in cases where
90
+ # a command can be called via multiple text strings.
91
+ #
92
+ # Call this method *after* defining the original method.
93
+ #
94
+ # Class.new(SlackRubyBot::MVC::Controller::Base) do
95
+ # def quxo_foo_bar
96
+ # client.say(channel: data.channel, text: "quxo foo bar: #{match[:expression]}")
97
+ # end
98
+ # # setup alias name after original method definition
99
+ # alternate_name :quxo_foo_bar, :another_text_string
100
+ # end
101
+ #
102
+ # This is equivalent to:
103
+ #
104
+ # e.g.
105
+ # command 'quxo foo bar', 'another text string' do |*args|
106
+ # ..
107
+ # end
108
+ def alternate_name(original_name, *alias_names)
109
+ command_name = convert_method_name_to_command_string(original_name)
110
+ command_aliases = alias_names.map do |name|
111
+ convert_method_name_to_command_string(name)
112
+ end
113
+
114
+ aliases[command_name] += command_aliases
115
+
116
+ alias_names.each { |alias_name| alias_method(alias_name, original_name) }
117
+ end
118
+
119
+ private
120
+
121
+ def lookup_command_name(name)
122
+ name = convert_method_name_to_command_string(name)
123
+ [name] + aliases[name]
124
+ end
125
+
126
+ def convert_method_name_to_command_string(name)
127
+ name.to_s.tr('_', ' ')
128
+ end
79
129
  end
80
130
 
81
131
  abstract!
@@ -102,9 +152,15 @@ module SlackRubyBot
102
152
  # Determine the command issued and call the corresponding instance method
103
153
  def call_command
104
154
  verb = match.captures[match.names.index('command')]
105
- verb = verb.downcase if verb
155
+ verb = normalize_command_string(verb)
106
156
  public_send(verb)
107
157
  end
158
+
159
+ private
160
+
161
+ def normalize_command_string(string)
162
+ string.downcase.tr(' ', '_')
163
+ end
108
164
  end
109
165
  end
110
166
  end
@@ -1,3 +1,3 @@
1
1
  module SlackRubyBot
2
- VERSION = '0.10.2'.freeze
2
+ VERSION = '0.10.3'.freeze
3
3
  end
@@ -95,3 +95,56 @@ describe SlackRubyBot::MVC::Controller::Base, 'execution' do
95
95
  expect(instance.__flag).to be_truthy
96
96
  end
97
97
  end
98
+
99
+ describe SlackRubyBot::MVC::Controller::Base, 'command text conversion' do
100
+ let(:controller) do
101
+ Class.new(SlackRubyBot::MVC::Controller::Base) do
102
+ def quxo_foo_bar
103
+ client.say(channel: data.channel, text: "#{match[:command].downcase}: #{match[:expression]}")
104
+ end
105
+ end
106
+ end
107
+
108
+ after(:each) { controller.reset! }
109
+
110
+ it 'converts a command with spaces into a controller method with underscores separating the tokens' do
111
+ model = SlackRubyBot::MVC::Model::Base.new
112
+ view = SlackRubyBot::MVC::View::Base.new
113
+ controller.new(model, view)
114
+ expect(message: " #{SlackRubyBot.config.user} quxo foo bar red").to respond_with_slack_message('quxo foo bar: red')
115
+ end
116
+
117
+ it 'converts a command with upper case letters into a lower case method call' do
118
+ model = SlackRubyBot::MVC::Model::Base.new
119
+ view = SlackRubyBot::MVC::View::Base.new
120
+ controller.new(model, view)
121
+ expect(message: " #{SlackRubyBot.config.user} Quxo Foo Bar red").to respond_with_slack_message('quxo foo bar: red')
122
+ end
123
+ end
124
+
125
+ describe SlackRubyBot::MVC::Controller::Base, 'alternate command text conversion' do
126
+ let(:controller) do
127
+ Class.new(SlackRubyBot::MVC::Controller::Base) do
128
+ def quxo_foo_bar
129
+ client.say(channel: data.channel, text: "quxo foo bar: #{match[:expression]}")
130
+ end
131
+ alternate_name :quxo_foo_bar, :another_text_string, :third_text_string
132
+ end
133
+ end
134
+
135
+ after(:each) { controller.reset! }
136
+
137
+ it 'aliases another valid command string to the controller method' do
138
+ model = SlackRubyBot::MVC::Model::Base.new
139
+ view = SlackRubyBot::MVC::View::Base.new
140
+ controller.new(model, view)
141
+ expect(message: " #{SlackRubyBot.config.user} another text string red").to respond_with_slack_message('quxo foo bar: red')
142
+ end
143
+
144
+ it 'allows for aliasing multiple names in a single call' do
145
+ model = SlackRubyBot::MVC::Model::Base.new
146
+ view = SlackRubyBot::MVC::View::Base.new
147
+ controller.new(model, view)
148
+ expect(message: " #{SlackRubyBot.config.user} third text string red").to respond_with_slack_message('quxo foo bar: red')
149
+ end
150
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slack-ruby-bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.10.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Doubrovkine
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-03 00:00:00.000000000 Z
11
+ date: 2017-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -266,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
266
  version: 1.3.6
267
267
  requirements: []
268
268
  rubyforge_project:
269
- rubygems_version: 2.6.11
269
+ rubygems_version: 2.6.8
270
270
  signing_key:
271
271
  specification_version: 4
272
272
  summary: The easiest way to write a Slack bot in Ruby.