boty 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +18 -1
- data/README.md +39 -3
- data/Rakefile +1 -1
- data/boty.gemspec +9 -5
- data/lib/boty.rb +2 -1
- data/lib/boty/action.rb +26 -35
- data/lib/boty/action_description.rb +24 -0
- data/lib/boty/bot.rb +36 -25
- data/lib/boty/dsl.rb +3 -3
- data/lib/boty/eventable.rb +4 -3
- data/lib/boty/http.rb +3 -4
- data/lib/boty/locale.rb +12 -13
- data/lib/boty/logger.rb +14 -3
- data/lib/boty/rspec.rb +15 -16
- data/lib/boty/session.rb +7 -8
- data/lib/boty/slack.rb +11 -3
- data/lib/boty/slack/channel.rb +2 -1
- data/lib/boty/slack/chat.rb +5 -1
- data/lib/boty/slack/rtm.rb +1 -1
- data/lib/boty/slack/url.rb +10 -5
- data/lib/boty/slack/user.rb +2 -1
- data/lib/boty/slack/users.rb +1 -1
- data/lib/boty/version.rb +1 -1
- data/script/knows.rb +10 -9
- data/script/pug.rb +5 -1
- data/spec/boty/bot_spec.rb +89 -72
- data/spec/boty/cli_spec.rb +5 -5
- data/spec/boty/dsl_spec.rb +12 -13
- data/spec/boty/rspec_spec.rb +2 -1
- data/spec/boty/script_loader_spec.rb +8 -6
- data/spec/boty/session_spec.rb +2 -2
- data/spec/boty/slack/chat_spec.rb +18 -18
- data/spec/boty/slack/im_spec.rb +4 -4
- data/spec/boty/slack/message_spec.rb +11 -9
- data/spec/boty/slack/rtm_spec.rb +3 -3
- data/spec/boty/slack/url_spec.rb +5 -5
- data/spec/boty/slack/users_spec.rb +23 -23
- data/spec/happy_path_spec.rb +19 -18
- data/spec/script/i18n_spec.rb +18 -10
- data/spec/script/knows_spec.rb +8 -7
- data/spec/script/pug_spec.rb +27 -10
- data/spec/script/remember_spec.rb +27 -21
- data/spec/spec_helper.rb +4 -3
- data/spec/support/em_support.rb +1 -3
- data/spec/support/faraday_support.rb +0 -1
- data/spec/support/faye_support.rb +9 -6
- data/spec/support/file_system_matchers.rb +4 -4
- data/spec/support/logger_support.rb +9 -12
- data/spec/support/session_support.rb +26 -15
- data/spec/support/slack_support.rb +9 -6
- data/spec/support/template_project_support.rb +24 -23
- data/spec/support/thor_support.rb +3 -3
- data/template/project/%bot_name%.rb +4 -1
- data/template/project/spec/spec_helper.rb +4 -2
- metadata +21 -4
data/lib/boty/eventable.rb
CHANGED
@@ -6,7 +6,8 @@ module Boty
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def event(data)
|
9
|
-
|
9
|
+
type = event_type data
|
10
|
+
return unless type
|
10
11
|
|
11
12
|
events[type].each do |action|
|
12
13
|
action.call data
|
@@ -30,9 +31,9 @@ module Boty
|
|
30
31
|
|
31
32
|
def event_type(data)
|
32
33
|
type = data["type"].to_sym
|
33
|
-
logger.debug
|
34
|
+
logger.debug do "event[#{type}] arrived: #{data}" end
|
34
35
|
unless events[type]
|
35
|
-
logger.debug "no action binded to #{type}"
|
36
|
+
logger.debug do "no action binded to #{type}" end
|
36
37
|
return
|
37
38
|
end
|
38
39
|
type
|
data/lib/boty/http.rb
CHANGED
@@ -13,17 +13,16 @@ module Boty
|
|
13
13
|
|
14
14
|
def connection(verb, url, params)
|
15
15
|
uri = URI url
|
16
|
-
Faraday.new(url: "#{uri.scheme}://#{uri.host}") { |builder|
|
16
|
+
faraday = Faraday.new(url: "#{uri.scheme}://#{uri.host}") { |builder|
|
17
17
|
builder.adapter(*Faraday.default_adapter)
|
18
|
-
}.public_send(verb) { |req|
|
19
|
-
req.url uri.path, params
|
20
18
|
}
|
19
|
+
faraday.public_send(verb) { |req| req.url uri.path, params }
|
21
20
|
end
|
22
21
|
|
23
22
|
def handle_response
|
24
23
|
# TODO: use a response parser accordingly to the
|
25
24
|
body = response.body
|
26
|
-
if /
|
25
|
+
if %r{application/json}.match response.headers["Content-Type"]
|
27
26
|
JSON.parse body
|
28
27
|
else
|
29
28
|
body
|
data/lib/boty/locale.rb
CHANGED
@@ -1,24 +1,23 @@
|
|
1
1
|
module Boty
|
2
2
|
class Locale
|
3
|
-
def self.reload(
|
4
|
-
|
5
|
-
I18n.load_path =
|
3
|
+
def self.reload(language = nil)
|
4
|
+
locale = new
|
5
|
+
I18n.load_path = locale.locales_paths.uniq
|
6
6
|
I18n.available_locales = I18n::Backend::Simple.new.available_locales
|
7
|
-
|
7
|
+
locale.locale = language if language
|
8
8
|
end
|
9
9
|
|
10
10
|
def locales_paths
|
11
|
-
|
12
|
-
(
|
13
|
-
|
11
|
+
locale_yaml_files_path = "../../../locale/**/*.yml"
|
12
|
+
default_locales_path = File.expand_path(locale_yaml_files_path, __FILE__)
|
13
|
+
(Dir["locale/**/*.yml"] + Dir[default_locales_path])
|
14
|
+
.map { |file| File.expand_path file }
|
14
15
|
end
|
15
16
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
I18n.locale = :en
|
21
|
-
end
|
17
|
+
def locale=(language)
|
18
|
+
I18n.locale = language
|
19
|
+
rescue I18n::InvalidLocale
|
20
|
+
I18n.locale = :en
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
data/lib/boty/logger.rb
CHANGED
@@ -17,6 +17,16 @@ module Boty
|
|
17
17
|
Logger.adapter
|
18
18
|
end
|
19
19
|
|
20
|
+
def log_error(error, message)
|
21
|
+
logger.error do
|
22
|
+
"#{message}\n#{error.message}"
|
23
|
+
end
|
24
|
+
|
25
|
+
logger.debug do
|
26
|
+
error.backtrace.reduce("") { |a, e| a << "#{e}\n" }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
20
30
|
class Multi < ::Logger
|
21
31
|
def initialize(adapters)
|
22
32
|
@adapters = adapters
|
@@ -38,7 +48,7 @@ module Boty
|
|
38
48
|
class Memory < ::Logger
|
39
49
|
attr_reader :logs
|
40
50
|
|
41
|
-
def initialize(*
|
51
|
+
def initialize(*)
|
42
52
|
@logs = []
|
43
53
|
end
|
44
54
|
|
@@ -52,8 +62,9 @@ module Boty
|
|
52
62
|
end
|
53
63
|
|
54
64
|
class Null < ::Logger
|
55
|
-
def initialize(*
|
56
|
-
|
65
|
+
def initialize(*); end
|
66
|
+
|
67
|
+
def add(*, &block); end
|
57
68
|
end
|
58
69
|
end
|
59
70
|
end
|
data/lib/boty/rspec.rb
CHANGED
@@ -8,23 +8,22 @@ module Boty
|
|
8
8
|
include SlackSupport::Users
|
9
9
|
|
10
10
|
before do
|
11
|
-
@_bot = Boty::Bot.new(
|
12
|
-
|
13
|
-
)
|
14
|
-
|
15
|
-
class << Boty::Slack.chat
|
16
|
-
attr_accessor :messages
|
17
|
-
|
18
|
-
def post_message(message, options)
|
19
|
-
@messages ||= []
|
20
|
-
@messages << { message: message, options: options }
|
21
|
-
end
|
22
|
-
end
|
11
|
+
@_bot = Boty::Bot.new("id" => "1234", "name" => "bot")
|
12
|
+
mock_post_message
|
23
13
|
end
|
24
14
|
|
25
|
-
let(:bot) {
|
26
|
-
|
27
|
-
|
15
|
+
let(:bot) { Boty::DSL.new @_bot }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def mock_post_message
|
20
|
+
class << Boty::Slack.chat
|
21
|
+
attr_accessor :messages
|
22
|
+
|
23
|
+
def post_message(message, options)
|
24
|
+
@messages ||= []
|
25
|
+
@messages << { message: message, options: options }
|
26
|
+
end
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
@@ -39,7 +38,7 @@ module Boty
|
|
39
38
|
|
40
39
|
::RSpec::Matchers.define :have_responded do |expected|
|
41
40
|
# TODO: add proper messages for failures.
|
42
|
-
match do
|
41
|
+
match do
|
43
42
|
last_message = Slack.chat.messages.last
|
44
43
|
expected == last_message[:message]
|
45
44
|
end
|
data/lib/boty/session.rb
CHANGED
@@ -22,38 +22,37 @@ module Boty
|
|
22
22
|
begin
|
23
23
|
on_message event, @bot
|
24
24
|
rescue StandardError => e
|
25
|
-
|
26
|
-
logger.debug e.backtrace.reduce("") { |msg, line| msg << "#{line}\n" }
|
25
|
+
log_error e, "Message #{event} could not be processed."
|
27
26
|
end
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
30
|
def login
|
32
|
-
logger.debug
|
31
|
+
logger.debug do "Logging in against slack right now" end
|
33
32
|
@slack_info = Slack.rtm.start
|
34
|
-
logger.debug
|
33
|
+
logger.debug do "yep! logged in!" end
|
35
34
|
@session_url = @slack_info["url"]
|
36
35
|
end
|
37
36
|
|
38
37
|
def initialize_bot(&block)
|
39
38
|
Bot.new(@slack_info["self"]).tap { |bot|
|
40
39
|
DSL.new(bot).instance_eval(&block) if block_given?
|
41
|
-
logger.debug
|
40
|
+
logger.debug do "Bot is configured and ready to go!" end
|
42
41
|
}
|
43
42
|
end
|
44
43
|
|
45
44
|
def on_message(event, bot)
|
46
|
-
logger.debug
|
45
|
+
logger.debug do "Message arrived. Creating bot event" end
|
47
46
|
bot.event JSON.parse(event.data)
|
48
47
|
end
|
49
48
|
|
50
49
|
def on_close
|
51
50
|
logger.debug { "bye bye" }
|
52
|
-
#
|
51
|
+
# TODO: try to reconnect (stablish_connection) unless is an em interrupt
|
53
52
|
end
|
54
53
|
|
55
54
|
def stablish_connection
|
56
|
-
logger.debug
|
55
|
+
logger.debug do "Starting to listen on #{@session_url}" end
|
57
56
|
ws = Faye::WebSocket::Client.new @session_url
|
58
57
|
ws.on :close do on_close end
|
59
58
|
on_connect ws
|
data/lib/boty/slack.rb
CHANGED
@@ -10,9 +10,17 @@ require "boty/slack/message"
|
|
10
10
|
module Boty
|
11
11
|
module Slack
|
12
12
|
class << self
|
13
|
-
def chat
|
14
|
-
|
15
|
-
|
13
|
+
def chat
|
14
|
+
@chat ||= Chat.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def rtm
|
18
|
+
@rtm ||= RTM.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def users
|
22
|
+
@users ||= Users.new
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
26
|
def User(user_id)
|
data/lib/boty/slack/channel.rb
CHANGED
data/lib/boty/slack/chat.rb
CHANGED
data/lib/boty/slack/rtm.rb
CHANGED
data/lib/boty/slack/url.rb
CHANGED
@@ -2,9 +2,14 @@ module Boty
|
|
2
2
|
module Slack
|
3
3
|
module URL
|
4
4
|
def self.included(base)
|
5
|
+
class << base
|
6
|
+
attr_reader :_url
|
7
|
+
end
|
8
|
+
|
5
9
|
base.instance_eval do
|
6
|
-
def url(url)
|
7
|
-
|
10
|
+
def url(url)
|
11
|
+
@_url = url
|
12
|
+
end
|
8
13
|
end
|
9
14
|
end
|
10
15
|
|
@@ -16,11 +21,11 @@ module Boty
|
|
16
21
|
|
17
22
|
def parameterize(user_parameters, path: nil)
|
18
23
|
url = path ? self.class._url + path : self.class._url
|
19
|
-
parameters = {token: ENV["SLACK_BOT_API_TOKEN"]}.merge user_parameters
|
20
|
-
parameters.reduce(url + "?") { |
|
24
|
+
parameters = { token: ENV["SLACK_BOT_API_TOKEN"] }.merge user_parameters
|
25
|
+
parameters.reduce(url + "?") { |final_url, param|
|
21
26
|
parameter = param[0]
|
22
27
|
value = URI.encode param[1].to_s
|
23
|
-
"#{
|
28
|
+
"#{final_url}#{parameter}=#{value}&"
|
24
29
|
}.gsub(/&$/, "")
|
25
30
|
end
|
26
31
|
end
|
data/lib/boty/slack/user.rb
CHANGED
data/lib/boty/slack/users.rb
CHANGED
data/lib/boty/version.rb
CHANGED
data/script/knows.rb
CHANGED
@@ -6,25 +6,26 @@ end
|
|
6
6
|
class KnownFormmater
|
7
7
|
def initialize(actions)
|
8
8
|
@actions = actions
|
9
|
-
@
|
9
|
+
@descriptions = @actions.map(&:desc)
|
10
|
+
@max_size = @descriptions.map(&:command).map(&:length).max
|
10
11
|
end
|
11
12
|
|
12
13
|
def format
|
13
|
-
@
|
14
|
-
|
14
|
+
@descriptions.inject("```\n") { |message, description|
|
15
|
+
message << format_description(description) + "\n"
|
15
16
|
} + "```"
|
16
17
|
end
|
17
18
|
|
18
19
|
private
|
19
20
|
|
20
|
-
def name(
|
21
|
-
pad = @max_size -
|
22
|
-
(" " * pad) +
|
21
|
+
def name(trigger)
|
22
|
+
pad = @max_size - trigger.length
|
23
|
+
(" " * pad) + trigger
|
23
24
|
end
|
24
25
|
|
25
|
-
def
|
26
|
-
message = name command
|
27
|
-
message << ": #{
|
26
|
+
def format_description(description)
|
27
|
+
message = name description.command
|
28
|
+
message << ": #{description.description}" if description.description
|
28
29
|
message
|
29
30
|
end
|
30
31
|
end
|
data/script/pug.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
desc "pug me", I18n.t("scripts.pug_me")
|
2
2
|
command(/pug me/i) do
|
3
3
|
response = http.get "http://pugme.herokuapp.com/random"
|
4
|
-
say "<#{response[
|
4
|
+
say "<#{response['pug']}>"
|
5
5
|
end
|
6
6
|
|
7
7
|
desc "pug bomb X", I18n.t("scripts.pug_bomb")
|
8
8
|
command(/pug bomb( \d+)?/i) do |count|
|
9
9
|
count = (count || "5").strip
|
10
|
+
if count.to_i > 5
|
11
|
+
count = "5"
|
12
|
+
say "wow! so many pugs! sendind 5 instead."
|
13
|
+
end
|
10
14
|
response = http.get "http://pugme.herokuapp.com/bomb", count: count
|
11
15
|
response["pugs"].each do |pug| say "<#{pug}>" end
|
12
16
|
end
|
data/spec/boty/bot_spec.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
module Boty
|
2
2
|
RSpec.describe Bot do
|
3
|
+
include Boty
|
3
4
|
subject(:bot) { described_class.new bot_info }
|
4
5
|
|
5
|
-
let(:bot_info)
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
let(:bot_info) do
|
7
|
+
{
|
8
|
+
"id" => "666",
|
9
|
+
"name" => "jabber"
|
10
|
+
}
|
11
|
+
end
|
9
12
|
|
10
13
|
describe "#on" do
|
11
14
|
it "binds an event `'type'` to a block" do
|
@@ -22,18 +25,20 @@ module Boty
|
|
22
25
|
end
|
23
26
|
|
24
27
|
describe "#off" do
|
25
|
-
let(:data)
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
let(:data) do
|
29
|
+
{
|
30
|
+
"type" => "bbq",
|
31
|
+
"text" => "omg. wtf."
|
32
|
+
}
|
33
|
+
end
|
29
34
|
|
30
35
|
it "unbounds an event by type AND block, just if the block is the same" do
|
31
36
|
@permanent_executed = false
|
32
|
-
permanent_block = ->(_)
|
37
|
+
permanent_block = ->(_) do @permanent_executed = true end
|
33
38
|
bot.on :bbq, &permanent_block
|
34
39
|
|
35
40
|
@ephemeral_executed = false
|
36
|
-
ephemeral_block = ->(_)
|
41
|
+
ephemeral_block = ->(_) do @ephemeral_executed = true end
|
37
42
|
bot.on :bbq, &ephemeral_block
|
38
43
|
bot.off :bbq, &ephemeral_block
|
39
44
|
|
@@ -45,9 +50,9 @@ module Boty
|
|
45
50
|
|
46
51
|
it "unbounds all events by type" do
|
47
52
|
@first_block = @second_block = @third_block = false
|
48
|
-
bot.on(:bbq)
|
49
|
-
bot.on(:bbq)
|
50
|
-
bot.on(:bbq)
|
53
|
+
bot.on(:bbq) do |_| @first_block = true end
|
54
|
+
bot.on(:bbq) do |_| @second_block = true end
|
55
|
+
bot.on(:bbq) do |_| @third_block = true end
|
51
56
|
bot.off(:bbq)
|
52
57
|
|
53
58
|
bot.event data
|
@@ -59,21 +64,23 @@ module Boty
|
|
59
64
|
end
|
60
65
|
|
61
66
|
describe "#match", :users do
|
62
|
-
let(:data)
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
let(:data) do
|
68
|
+
{
|
69
|
+
"type" => "message",
|
70
|
+
"text" => "bbq omg lol"
|
71
|
+
}
|
72
|
+
end
|
66
73
|
|
67
74
|
it "binds a regex to events of `type => message`" do
|
68
|
-
|
75
|
+
message = nil
|
69
76
|
bot.match(/omg/i) do
|
70
|
-
|
77
|
+
message = self.message
|
71
78
|
end
|
72
79
|
bot.event data
|
73
80
|
|
74
|
-
expect(
|
75
|
-
expect(
|
76
|
-
expect(
|
81
|
+
expect(message).to be_a Boty::Slack::Message
|
82
|
+
expect(message.text).to eq "bbq omg lol"
|
83
|
+
expect(message.match[0]).to eq "omg"
|
77
84
|
end
|
78
85
|
|
79
86
|
it "binds various actions to events of type message" do
|
@@ -82,23 +89,22 @@ module Boty
|
|
82
89
|
bot.match(/omg/i) do iterations << "second" end
|
83
90
|
bot.event data
|
84
91
|
|
85
|
-
expect(iterations).to eq
|
92
|
+
expect(iterations).to eq %w(first second)
|
86
93
|
end
|
87
94
|
|
88
95
|
it "passes the matched strings as parameters to block action" do
|
89
|
-
|
96
|
+
rspec = self
|
90
97
|
bot.match(/(bbq) omg (lol)/i) do |bbq, lol|
|
91
|
-
|
98
|
+
rspec.expect(bbq).to rspec.eq "bbq"
|
99
|
+
rspec.expect(lol).to rspec.eq "lol"
|
92
100
|
end
|
93
|
-
bot.event data
|
94
101
|
|
95
|
-
|
96
|
-
expect(_bbq).to eq "bbq"
|
102
|
+
bot.event data
|
97
103
|
end
|
98
104
|
|
99
105
|
it "evals the block in the context of the bot" do
|
100
106
|
dsl = nil
|
101
|
-
bot.match(/omg/)
|
107
|
+
bot.match(/omg/) do dsl = self end
|
102
108
|
bot.event data
|
103
109
|
|
104
110
|
expect(dsl.bot).to eq bot
|
@@ -106,10 +112,12 @@ module Boty
|
|
106
112
|
end
|
107
113
|
|
108
114
|
describe "#respond", :users do
|
109
|
-
let(:data)
|
110
|
-
|
111
|
-
|
112
|
-
|
115
|
+
let(:data) do
|
116
|
+
{
|
117
|
+
"type" => "message",
|
118
|
+
"text" => "hey <@jabber>, omg me"
|
119
|
+
}
|
120
|
+
end
|
113
121
|
|
114
122
|
it "binds actions for messages only when there is a mention (@bot)" do
|
115
123
|
expect { |b|
|
@@ -146,7 +154,7 @@ module Boty
|
|
146
154
|
|
147
155
|
it "evals the block in the context of the bot" do
|
148
156
|
dsl = nil
|
149
|
-
bot.respond(/omg me/)
|
157
|
+
bot.respond(/omg me/) do dsl = self end
|
150
158
|
bot.event data
|
151
159
|
|
152
160
|
expect(dsl.bot).to eq bot
|
@@ -159,10 +167,12 @@ module Boty
|
|
159
167
|
end
|
160
168
|
|
161
169
|
describe "#no_match" do
|
162
|
-
let(:data)
|
163
|
-
|
164
|
-
|
165
|
-
|
170
|
+
let(:data) do
|
171
|
+
{
|
172
|
+
"type" => "message",
|
173
|
+
"text" => "bbq omg lol"
|
174
|
+
}
|
175
|
+
end
|
166
176
|
|
167
177
|
it "removes a message based on the regex AND the block" do
|
168
178
|
permanent_executed = false
|
@@ -182,8 +192,8 @@ module Boty
|
|
182
192
|
|
183
193
|
it "removes all binds for a specific regex" do
|
184
194
|
first = second = false
|
185
|
-
bot.match(/omg/i)
|
186
|
-
bot.match(/omg/i)
|
195
|
+
bot.match(/omg/i) do first = true end
|
196
|
+
bot.match(/omg/i) do second = true end
|
187
197
|
bot.no_match(/omg/i)
|
188
198
|
|
189
199
|
bot.event data
|
@@ -194,10 +204,12 @@ module Boty
|
|
194
204
|
end
|
195
205
|
|
196
206
|
describe "#no_respond" do
|
197
|
-
let(:data)
|
198
|
-
|
199
|
-
|
200
|
-
|
207
|
+
let(:data) do
|
208
|
+
{
|
209
|
+
"type" => "message",
|
210
|
+
"text" => "hey <@#{bot.name}>, omg me"
|
211
|
+
}
|
212
|
+
end
|
201
213
|
|
202
214
|
it "removes a message based on the regex AND the block" do
|
203
215
|
permanent_executed = false
|
@@ -217,8 +229,8 @@ module Boty
|
|
217
229
|
|
218
230
|
it "removes all binds for a specific regex" do
|
219
231
|
first = second = false
|
220
|
-
bot.respond(/omg/i)
|
221
|
-
bot.respond(/omg/i)
|
232
|
+
bot.respond(/omg/i) do first = true end
|
233
|
+
bot.respond(/omg/i) do second = true end
|
222
234
|
bot.no_respond(/omg/i)
|
223
235
|
|
224
236
|
dsl.bot.event data
|
@@ -231,22 +243,22 @@ module Boty
|
|
231
243
|
|
232
244
|
describe "#say" do
|
233
245
|
it "sends a string using the slack api to general (default) channel" do
|
234
|
-
expect(Slack.chat).to receive(:post_message)
|
235
|
-
with "something", channel: "#general"
|
246
|
+
expect(Slack.chat).to receive(:post_message)
|
247
|
+
.with "something", channel: "#general"
|
236
248
|
|
237
249
|
bot.say "something"
|
238
250
|
end
|
239
251
|
|
240
252
|
it "sends a message to the channel specified by parameter" do
|
241
|
-
expect(Slack.chat).to receive(:post_message)
|
242
|
-
with "omg pugs!", channel: "#omg"
|
253
|
+
expect(Slack.chat).to receive(:post_message)
|
254
|
+
.with "omg pugs!", channel: "#omg"
|
243
255
|
|
244
256
|
bot.say "omg pugs!", channel: "#omg"
|
245
257
|
end
|
246
258
|
|
247
259
|
it "accepts extra parameters and send them to the slack api" do
|
248
|
-
expect(Slack.chat).to receive(:post_message)
|
249
|
-
with "omg pugs!", channel: "#omg", omg: "lol"
|
260
|
+
expect(Slack.chat).to receive(:post_message)
|
261
|
+
.with "omg pugs!", channel: "#omg", omg: "lol"
|
250
262
|
|
251
263
|
bot.say "omg pugs!", channel: "#omg", omg: "lol"
|
252
264
|
end
|
@@ -262,9 +274,9 @@ module Boty
|
|
262
274
|
|
263
275
|
describe "#im" do
|
264
276
|
before do
|
265
|
-
|
266
|
-
|
267
|
-
and_return
|
277
|
+
user = Boty::Slack::User.new "id" => "U123", "name" => "julian"
|
278
|
+
allow(Slack.users).to receive(:by_name).with("julian")
|
279
|
+
.and_return user
|
268
280
|
end
|
269
281
|
|
270
282
|
it "sends a message in the back channel (particular, im...)" do
|
@@ -287,9 +299,8 @@ module Boty
|
|
287
299
|
end
|
288
300
|
|
289
301
|
it "logs when fails on discover the destiny", :logger do
|
290
|
-
allow(Slack.users).to receive(:by_name)
|
291
|
-
with("omg_doesnt_exists").
|
292
|
-
and_return nil
|
302
|
+
allow(Slack.users).to receive(:by_name)
|
303
|
+
.with("omg_doesnt_exists").and_return nil
|
293
304
|
bot.im "lol", destiny: "omg_doesnt_exists"
|
294
305
|
|
295
306
|
expect(logger.logs.last).to eq "User not found, refusing to send im."
|
@@ -304,46 +315,52 @@ module Boty
|
|
304
315
|
end
|
305
316
|
|
306
317
|
describe "#desc" do
|
318
|
+
let(:know_how) {
|
319
|
+
bot.know_how.map { |action|
|
320
|
+
{ action.desc.command => action.desc.description }
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
307
324
|
it "describes the next command to be created" do
|
308
325
|
bot.desc "omg", "lol all the way down"
|
309
|
-
bot.respond(/omg/)
|
326
|
+
bot.respond(/omg/)
|
310
327
|
|
311
|
-
expect(
|
328
|
+
expect(know_how).to include(
|
312
329
|
"omg" => "lol all the way down"
|
313
|
-
|
330
|
+
)
|
314
331
|
end
|
315
332
|
|
316
333
|
it "describes the next match do be created" do
|
317
334
|
bot.desc "ula", "babula"
|
318
|
-
bot.match(/ula/)
|
335
|
+
bot.match(/ula/)
|
319
336
|
|
320
|
-
expect(
|
337
|
+
expect(know_how).to include(
|
321
338
|
"ula" => "babula"
|
322
|
-
|
339
|
+
)
|
323
340
|
end
|
324
341
|
|
325
342
|
it "stores the description for a regex when no command usage is given" do
|
326
343
|
bot.desc "just a description"
|
327
|
-
bot.match(/just desc/i)
|
328
|
-
expect(
|
344
|
+
bot.match(/just desc/i)
|
345
|
+
expect(know_how).to include(
|
329
346
|
"/just desc/i" => "just a description"
|
330
|
-
|
347
|
+
)
|
331
348
|
end
|
332
349
|
|
333
350
|
it "presents the commands without description as regexes" do
|
334
|
-
bot.match(/without desc/i)
|
351
|
+
bot.match(/without desc/i)
|
335
352
|
|
336
|
-
expect(
|
353
|
+
expect(know_how).to include(
|
337
354
|
"/without desc/i" => nil
|
338
|
-
|
355
|
+
)
|
339
356
|
end
|
340
357
|
|
341
358
|
it "knows when a regex is case insensitive" do
|
342
359
|
bot.match(/without desc insensitive/)
|
343
360
|
|
344
|
-
expect(
|
361
|
+
expect(know_how).to include(
|
345
362
|
"/without desc insensitive/" => nil
|
346
|
-
|
363
|
+
)
|
347
364
|
end
|
348
365
|
end
|
349
366
|
end
|