slack-ruby-bot 0.10.2 → 0.10.3

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 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.