slack-ruby-bot 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -2
- data/.rubocop.yml +14 -1
- data/.rubocop_todo.yml +13 -36
- data/.travis.yml +7 -5
- data/CHANGELOG.md +9 -0
- data/DEPLOYMENT.md +61 -5
- data/Dangerfile +2 -0
- data/Gemfile +10 -3
- data/LICENSE.md +1 -1
- data/README.md +78 -10
- data/Rakefile +2 -0
- data/TUTORIAL.md +23 -0
- data/UPGRADING.md +8 -0
- data/examples/inventory/Gemfile +2 -0
- data/examples/inventory/inventorybot.rb +5 -1
- data/examples/market/Gemfile +4 -3
- data/examples/market/marketbot.rb +22 -15
- data/examples/minimal/Gemfile +2 -0
- data/examples/minimal/pongbot.rb +2 -0
- data/examples/weather/Gemfile +2 -0
- data/examples/weather/weatherbot.rb +2 -0
- data/lib/config/application.rb +4 -2
- data/lib/config/boot.rb +2 -0
- data/lib/config/environment.rb +3 -1
- data/lib/initializers/giphy.rb +2 -0
- data/lib/initializers/giphy_client.rb +2 -0
- data/lib/slack-ruby-bot.rb +3 -1
- data/lib/slack-ruby-bot/about.rb +3 -1
- data/lib/slack-ruby-bot/app.rb +2 -0
- data/lib/slack-ruby-bot/bot.rb +2 -0
- data/lib/slack-ruby-bot/client.rb +7 -4
- data/lib/slack-ruby-bot/commands.rb +2 -0
- data/lib/slack-ruby-bot/commands/about.rb +2 -0
- data/lib/slack-ruby-bot/commands/base.rb +12 -1
- data/lib/slack-ruby-bot/commands/help.rb +9 -7
- data/lib/slack-ruby-bot/commands/hi.rb +2 -0
- data/lib/slack-ruby-bot/commands/support/attrs.rb +2 -0
- data/lib/slack-ruby-bot/commands/support/help.rb +4 -0
- data/lib/slack-ruby-bot/commands/support/match.rb +4 -3
- data/lib/slack-ruby-bot/commands/unknown.rb +2 -0
- data/lib/slack-ruby-bot/config.rb +3 -0
- data/lib/slack-ruby-bot/hooks.rb +2 -0
- data/lib/slack-ruby-bot/hooks/hello.rb +22 -3
- data/lib/slack-ruby-bot/hooks/hook_support.rb +2 -0
- data/lib/slack-ruby-bot/hooks/message.rb +5 -2
- data/lib/slack-ruby-bot/hooks/set.rb +3 -1
- data/lib/slack-ruby-bot/mvc.rb +2 -0
- data/lib/slack-ruby-bot/mvc/controller/base.rb +4 -3
- data/lib/slack-ruby-bot/mvc/model/base.rb +2 -0
- data/lib/slack-ruby-bot/mvc/mvc.rb +2 -0
- data/lib/slack-ruby-bot/mvc/view/base.rb +2 -0
- data/lib/slack-ruby-bot/rspec.rb +3 -1
- data/lib/slack-ruby-bot/rspec/support/bots_for_tests.rb +2 -0
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/it_behaves_like_a_slack_bot.rb +2 -0
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/not_respond.rb +3 -5
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_error.rb +3 -5
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_slack_message.rb +16 -13
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_slack_messages.rb +27 -18
- data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/start_typing.rb +32 -0
- data/lib/slack-ruby-bot/rspec/support/slack_api_key.rb +2 -0
- data/lib/slack-ruby-bot/rspec/support/slack_ruby_bot_configure.rb +2 -0
- data/lib/slack-ruby-bot/rspec/support/spec_helpers.rb +2 -0
- data/lib/slack-ruby-bot/rspec/support/vcr.rb +2 -0
- data/lib/slack-ruby-bot/server.rb +2 -0
- data/lib/slack-ruby-bot/support/loggable.rb +2 -0
- data/lib/slack-ruby-bot/version.rb +3 -1
- data/lib/slack_ruby_bot.rb +2 -0
- data/screenshots/create-app.png +0 -0
- data/slack-ruby-bot.gemspec +5 -2
- data/spec/slack-ruby-bot/app_spec.rb +2 -0
- data/spec/slack-ruby-bot/client_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/about_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/aliases_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/attachment_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/bot_message_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/bot_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_command_classes_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_permitted_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_precedence_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_regexp_escape_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_regexp_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_spaces_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_with_block_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/commands_with_expression_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/direct_messages_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/empty_text_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/help_spec.rb +15 -13
- data/spec/slack-ruby-bot/commands/hi_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/match_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/message_loop_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/nil_message_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/not_implemented_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/operators_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/operators_with_block_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/scan_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/send_gif_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/send_message_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/send_message_with_gif_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/support/attrs_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/support/help_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/support/match_spec.rb +2 -0
- data/spec/slack-ruby-bot/commands/unknown_spec.rb +2 -0
- data/spec/slack-ruby-bot/config_spec.rb +2 -0
- data/spec/slack-ruby-bot/hooks/hello_spec.rb +51 -0
- data/spec/slack-ruby-bot/hooks/hook_support_spec.rb +2 -0
- data/spec/slack-ruby-bot/hooks/message_spec.rb +3 -1
- data/spec/slack-ruby-bot/hooks/set_spec.rb +2 -0
- data/spec/slack-ruby-bot/initializers/giphy_client_spec.rb +2 -0
- data/spec/slack-ruby-bot/initializers/giphy_spec.rb +2 -0
- data/spec/slack-ruby-bot/mvc/controller/controller_to_command_spec.rb +2 -0
- data/spec/slack-ruby-bot/rspec/respond_with_error_spec.rb +2 -0
- data/spec/slack-ruby-bot/rspec/respond_with_slack_message_spec.rb +20 -0
- data/spec/slack-ruby-bot/rspec/respond_with_slack_messages_spec.rb +36 -0
- data/spec/slack-ruby-bot/rspec/start_typing_spec.rb +36 -0
- data/spec/slack-ruby-bot/server_spec.rb +2 -0
- data/spec/slack-ruby-bot/support/loggable_spec.rb +2 -0
- data/spec/slack-ruby-bot/version_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -0
- metadata +12 -8
- data/screenshots/register-bot.png +0 -0
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SlackRubyBot
|
2
4
|
module Config
|
3
5
|
extend self
|
@@ -11,6 +13,7 @@ module SlackRubyBot
|
|
11
13
|
|
12
14
|
def send_gifs?
|
13
15
|
return false unless defined?(Giphy)
|
16
|
+
|
14
17
|
v = boolean_from_env('SLACK_RUBY_BOT_SEND_GIFS')
|
15
18
|
send_gifs.nil? ? (v.nil? || v) : send_gifs
|
16
19
|
end
|
data/lib/slack-ruby-bot/hooks.rb
CHANGED
@@ -1,15 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SlackRubyBot
|
2
4
|
module Hooks
|
3
5
|
class Hello
|
4
|
-
attr_accessor :logger
|
6
|
+
attr_accessor :logger, :connected_at
|
5
7
|
|
6
8
|
def initialize(logger)
|
7
9
|
self.logger = logger
|
8
10
|
end
|
9
11
|
|
10
12
|
def call(client, _data)
|
11
|
-
return unless client
|
12
|
-
|
13
|
+
return unless client&.team
|
14
|
+
|
15
|
+
new_connected_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
16
|
+
log = [
|
17
|
+
'Successfully',
|
18
|
+
connected_at ? 'reconnected' : 'connected',
|
19
|
+
"team #{client.team.name} (#{client.team.id}) to https://#{client.team.domain}.slack.com",
|
20
|
+
connected_at ? "after #{last_connection_till(new_connected_at)}s" : nil
|
21
|
+
].compact.join(' ') + '.'
|
22
|
+
|
23
|
+
logger.info log
|
24
|
+
|
25
|
+
self.connected_at = new_connected_at
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def last_connection_till(time)
|
31
|
+
(time - connected_at).round(2)
|
13
32
|
end
|
14
33
|
end
|
15
34
|
end
|
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SlackRubyBot
|
2
4
|
module Hooks
|
3
5
|
class Message
|
4
6
|
def call(client, data)
|
5
7
|
return if message_to_self_not_allowed? && message_to_self?(client, data)
|
8
|
+
|
6
9
|
data.text = data.text.strip if data.text
|
7
10
|
result = child_command_classes.detect { |d| d.invoke(client, data) }
|
8
11
|
result ||= built_in_command_classes.detect { |d| d.invoke(client, data) }
|
@@ -36,7 +39,7 @@ module SlackRubyBot
|
|
36
39
|
#
|
37
40
|
def child_command_classes
|
38
41
|
command_classes.reject do |k|
|
39
|
-
k.name
|
42
|
+
k.name&.starts_with?('SlackRubyBot::Commands::')
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
@@ -47,7 +50,7 @@ module SlackRubyBot
|
|
47
50
|
#
|
48
51
|
def built_in_command_classes
|
49
52
|
command_classes.select do |k|
|
50
|
-
k.name
|
53
|
+
k.name&.starts_with?('SlackRubyBot::Commands::') && k != SlackRubyBot::Commands::Unknown
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SlackRubyBot
|
2
4
|
module Hooks
|
3
5
|
class Set
|
@@ -36,7 +38,7 @@ module SlackRubyBot
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def flush_handlers
|
39
|
-
handlers.
|
41
|
+
handlers.each_key { |hook| register_callback(hook) }
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
data/lib/slack-ruby-bot/mvc.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SlackRubyBot
|
2
4
|
module MVC
|
3
5
|
module Controller
|
@@ -45,9 +47,7 @@ module SlackRubyBot
|
|
45
47
|
def inherited(klass) # :nodoc:
|
46
48
|
# Define the abstract ivar on subclasses so that we don't get
|
47
49
|
# uninitialized ivar warnings
|
48
|
-
unless klass.instance_variable_defined?(:@abstract)
|
49
|
-
klass.instance_variable_set(:@abstract, false)
|
50
|
-
end
|
50
|
+
klass.instance_variable_set(:@abstract, false) unless klass.instance_variable_defined?(:@abstract)
|
51
51
|
super
|
52
52
|
end
|
53
53
|
|
@@ -64,6 +64,7 @@ module SlackRubyBot
|
|
64
64
|
|
65
65
|
methods.each do |name|
|
66
66
|
next if name[0] == '_'
|
67
|
+
|
67
68
|
commands = lookup_command_name(name)
|
68
69
|
|
69
70
|
# Generates a command for each controller method *and* its aliases
|
data/lib/slack-ruby-bot/rspec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
2
4
|
|
3
5
|
require 'rubygems'
|
@@ -7,6 +9,6 @@ require 'rack/test'
|
|
7
9
|
require 'config/environment'
|
8
10
|
require 'slack-ruby-bot'
|
9
11
|
|
10
|
-
Dir[File.join(File.dirname(__FILE__), 'rspec/support', '**/*.rb')].each do |file|
|
12
|
+
Dir[File.join(File.dirname(__FILE__), 'rspec/support', '**/*.rb')].sort.each do |file|
|
11
13
|
require file
|
12
14
|
end
|
@@ -1,12 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec/expectations'
|
2
4
|
|
3
5
|
RSpec::Matchers.define :not_respond do
|
4
6
|
match do |actual|
|
5
|
-
client =
|
6
|
-
send(:client)
|
7
|
-
else
|
8
|
-
SlackRubyBot::Client.new
|
9
|
-
end
|
7
|
+
client = respond_to?(:client) ? send(:client) : SlackRubyBot::Client.new
|
10
8
|
|
11
9
|
message_command = SlackRubyBot::Hooks::Message.new
|
12
10
|
channel, user, message, attachments = parse(actual)
|
@@ -1,12 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec/expectations'
|
2
4
|
|
3
5
|
RSpec::Matchers.define :respond_with_error do |error, error_message|
|
4
6
|
match do |actual|
|
5
|
-
client =
|
6
|
-
send(:client)
|
7
|
-
else
|
8
|
-
SlackRubyBot::Client.new
|
9
|
-
end
|
7
|
+
client = respond_to?(:client) ? send(:client) : SlackRubyBot::Client.new
|
10
8
|
|
11
9
|
message_command = SlackRubyBot::Hooks::Message.new
|
12
10
|
channel, user, message, attachments = parse(actual)
|
@@ -1,33 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec/expectations'
|
4
|
+
|
2
5
|
RSpec::Matchers.define :respond_with_slack_message do |expected|
|
3
6
|
include SlackRubyBot::SpecHelpers
|
7
|
+
|
4
8
|
match do |actual|
|
5
9
|
client = respond_to?(:client) ? send(:client) : SlackRubyBot::Client.new
|
6
|
-
def client.test_messages
|
7
|
-
@test_received_messages
|
8
|
-
end
|
9
|
-
|
10
|
-
def client.say(options = {})
|
11
|
-
super
|
12
|
-
@test_received_messages = @test_received_messages.nil? ? [] : @test_received_messages
|
13
|
-
@test_received_messages.push options
|
14
|
-
end
|
15
10
|
|
16
11
|
message_command = SlackRubyBot::Hooks::Message.new
|
17
12
|
channel, user, message, attachments = parse(actual)
|
18
13
|
|
19
14
|
allow(Giphy).to receive(:random) if defined?(Giphy)
|
20
15
|
|
21
|
-
allow(client).to receive(:message)
|
16
|
+
allow(client).to receive(:message) do |options|
|
17
|
+
@messages ||= []
|
18
|
+
@messages.push options
|
19
|
+
end
|
20
|
+
|
22
21
|
message_command.call(client, Hashie::Mash.new(text: message, channel: channel, user: user, attachments: attachments))
|
23
|
-
|
24
|
-
|
22
|
+
|
23
|
+
matcher = have_received(:message).once
|
24
|
+
matcher = matcher.with(hash_including(channel: channel, text: expected)) if channel && expected
|
25
|
+
|
26
|
+
expect(client).to matcher
|
27
|
+
|
25
28
|
true
|
26
29
|
end
|
27
30
|
|
28
31
|
failure_message do |_actual|
|
29
32
|
message = "expected to receive message with text: #{expected} once,\n received:"
|
30
|
-
message += @messages
|
33
|
+
message += @messages&.any? ? @messages.inspect : 'none'
|
31
34
|
message
|
32
35
|
end
|
33
36
|
end
|
@@ -1,38 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec/expectations'
|
4
|
+
|
2
5
|
RSpec::Matchers.define :respond_with_slack_messages do |expected|
|
3
6
|
include SlackRubyBot::SpecHelpers
|
7
|
+
|
4
8
|
match do |actual|
|
5
|
-
raise ArgumentError, 'respond_with_slack_messages expects an array of ordered responses'
|
6
|
-
client = respond_to?(:client) ? send(:client) : SlackRubyBot::Client.new
|
7
|
-
def client.test_messages
|
8
|
-
@test_received_messages
|
9
|
-
end
|
9
|
+
raise ArgumentError, 'respond_with_slack_messages expects an array of ordered responses' if expected && !expected.respond_to?(:each)
|
10
10
|
|
11
|
-
|
12
|
-
super
|
13
|
-
@test_received_messages = @test_received_messages.nil? ? [] : @test_received_messages
|
14
|
-
@test_received_messages.push options
|
15
|
-
end
|
11
|
+
client = respond_to?(:client) ? send(:client) : SlackRubyBot::Client.new
|
16
12
|
|
17
13
|
message_command = SlackRubyBot::Hooks::Message.new
|
18
14
|
channel, user, message, attachments = parse(actual)
|
19
15
|
|
20
16
|
allow(Giphy).to receive(:random) if defined?(Giphy)
|
21
17
|
|
22
|
-
|
18
|
+
@messages ||= []
|
19
|
+
allow(client).to receive(:message) do |options|
|
20
|
+
@messages.push options
|
21
|
+
end
|
22
|
+
|
23
23
|
message_command.call(client, Hashie::Mash.new(text: message, channel: channel, user: user, attachments: attachments))
|
24
|
-
|
24
|
+
|
25
25
|
@responses = []
|
26
|
-
|
27
|
-
|
26
|
+
|
27
|
+
if expected&.any?
|
28
|
+
expected.each do |exp|
|
29
|
+
@responses.push(expect(client).to(have_received(:message).with(hash_including(channel: channel, text: exp)).once))
|
30
|
+
end
|
31
|
+
else
|
32
|
+
expect(@messages.size).to be > 1
|
28
33
|
end
|
34
|
+
|
29
35
|
true
|
30
36
|
end
|
37
|
+
|
31
38
|
failure_message do |_actual|
|
32
|
-
|
33
|
-
|
34
|
-
|
39
|
+
if expected&.any?
|
40
|
+
expected.map do |exp|
|
41
|
+
"Expected text: #{exp}, got #{@messages[expected.index(exp)] || 'none'}" unless @responses[expected.index(exp)]
|
42
|
+
end.compact.join("\n")
|
43
|
+
else
|
44
|
+
"Expected to receive multiple messages, got #{@messages.any? ? @messages.size : 'none'}"
|
35
45
|
end
|
36
|
-
message
|
37
46
|
end
|
38
47
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec/expectations'
|
4
|
+
|
5
|
+
RSpec::Matchers.define :start_typing do |expected|
|
6
|
+
include SlackRubyBot::SpecHelpers
|
7
|
+
|
8
|
+
match do |actual|
|
9
|
+
client = respond_to?(:client) ? send(:client) : SlackRubyBot::Client.new
|
10
|
+
|
11
|
+
message_command = SlackRubyBot::Hooks::Message.new
|
12
|
+
|
13
|
+
allow(client).to receive(:typing) do |options|
|
14
|
+
@test_options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
channel, user, message, attachments = parse(actual)
|
18
|
+
message_command.call(client, Hashie::Mash.new(text: message, channel: channel, user: user, attachments: attachments))
|
19
|
+
|
20
|
+
matcher = have_received(:typing).once
|
21
|
+
matcher = matcher.with(expected) if expected&.any?
|
22
|
+
expect(client).to matcher
|
23
|
+
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
failure_message do |_actual|
|
28
|
+
message = "expected to receive typing with: #{expected} once,\n received:"
|
29
|
+
message += @test_options&.any? ? @test_options.inspect : ' none'
|
30
|
+
message
|
31
|
+
end
|
32
|
+
end
|
data/lib/slack_ruby_bot.rb
CHANGED
Binary file
|
data/slack-ruby-bot.gemspec
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
2
4
|
require 'slack-ruby-bot/version'
|
3
5
|
|
4
6
|
Gem::Specification.new do |s|
|
@@ -14,12 +16,13 @@ Gem::Specification.new do |s|
|
|
14
16
|
s.homepage = 'https://github.com/slack-ruby/slack-ruby-bot'
|
15
17
|
s.licenses = ['MIT']
|
16
18
|
s.summary = 'The easiest way to write a Slack bot in Ruby.'
|
19
|
+
s.required_ruby_version = '>= 2.3'
|
17
20
|
s.add_dependency 'hashie'
|
18
21
|
s.add_dependency 'slack-ruby-client', '>= 0.14.0'
|
19
22
|
s.add_development_dependency 'rack-test'
|
20
23
|
s.add_development_dependency 'rake'
|
21
24
|
s.add_development_dependency 'rspec'
|
22
|
-
s.add_development_dependency 'rubocop', '0.
|
25
|
+
s.add_development_dependency 'rubocop', '0.80.1'
|
23
26
|
s.add_development_dependency 'vcr'
|
24
27
|
s.add_development_dependency 'webmock'
|
25
28
|
end
|