boty 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +18 -1
  5. data/README.md +39 -3
  6. data/Rakefile +1 -1
  7. data/boty.gemspec +9 -5
  8. data/lib/boty.rb +2 -1
  9. data/lib/boty/action.rb +26 -35
  10. data/lib/boty/action_description.rb +24 -0
  11. data/lib/boty/bot.rb +36 -25
  12. data/lib/boty/dsl.rb +3 -3
  13. data/lib/boty/eventable.rb +4 -3
  14. data/lib/boty/http.rb +3 -4
  15. data/lib/boty/locale.rb +12 -13
  16. data/lib/boty/logger.rb +14 -3
  17. data/lib/boty/rspec.rb +15 -16
  18. data/lib/boty/session.rb +7 -8
  19. data/lib/boty/slack.rb +11 -3
  20. data/lib/boty/slack/channel.rb +2 -1
  21. data/lib/boty/slack/chat.rb +5 -1
  22. data/lib/boty/slack/rtm.rb +1 -1
  23. data/lib/boty/slack/url.rb +10 -5
  24. data/lib/boty/slack/user.rb +2 -1
  25. data/lib/boty/slack/users.rb +1 -1
  26. data/lib/boty/version.rb +1 -1
  27. data/script/knows.rb +10 -9
  28. data/script/pug.rb +5 -1
  29. data/spec/boty/bot_spec.rb +89 -72
  30. data/spec/boty/cli_spec.rb +5 -5
  31. data/spec/boty/dsl_spec.rb +12 -13
  32. data/spec/boty/rspec_spec.rb +2 -1
  33. data/spec/boty/script_loader_spec.rb +8 -6
  34. data/spec/boty/session_spec.rb +2 -2
  35. data/spec/boty/slack/chat_spec.rb +18 -18
  36. data/spec/boty/slack/im_spec.rb +4 -4
  37. data/spec/boty/slack/message_spec.rb +11 -9
  38. data/spec/boty/slack/rtm_spec.rb +3 -3
  39. data/spec/boty/slack/url_spec.rb +5 -5
  40. data/spec/boty/slack/users_spec.rb +23 -23
  41. data/spec/happy_path_spec.rb +19 -18
  42. data/spec/script/i18n_spec.rb +18 -10
  43. data/spec/script/knows_spec.rb +8 -7
  44. data/spec/script/pug_spec.rb +27 -10
  45. data/spec/script/remember_spec.rb +27 -21
  46. data/spec/spec_helper.rb +4 -3
  47. data/spec/support/em_support.rb +1 -3
  48. data/spec/support/faraday_support.rb +0 -1
  49. data/spec/support/faye_support.rb +9 -6
  50. data/spec/support/file_system_matchers.rb +4 -4
  51. data/spec/support/logger_support.rb +9 -12
  52. data/spec/support/session_support.rb +26 -15
  53. data/spec/support/slack_support.rb +9 -6
  54. data/spec/support/template_project_support.rb +24 -23
  55. data/spec/support/thor_support.rb +3 -3
  56. data/template/project/%bot_name%.rb +4 -1
  57. data/template/project/spec/spec_helper.rb +4 -2
  58. metadata +21 -4
@@ -6,21 +6,21 @@ module Boty
6
6
  subject(:cli) { described_class.new }
7
7
 
8
8
  before(:all) do
9
- FileUtils.mkdir_p "tmp" if !Dir.exists? "tmp"
9
+ FileUtils.mkdir_p "tmp" unless Dir.exist? "tmp"
10
10
  FileUtils.chdir "tmp"
11
11
  end
12
12
 
13
13
  before do
14
- FileUtils.rm_rf "nice_bot" if Dir.exists? "nice_bot"
14
+ FileUtils.rm_rf "nice_bot" if Dir.exist? "nice_bot"
15
15
 
16
- allow(cli).to receive(:ask).
17
- and_return ENV["SLACK_COMPANY"], ENV["SLACK_BOT_API_TOKEN"]
16
+ allow(cli).to receive(:ask)
17
+ .and_return ENV["SLACK_COMPANY"], ENV["SLACK_BOT_API_TOKEN"]
18
18
 
19
19
  allow(cli).to receive(:run)
20
20
  end
21
21
 
22
22
  after(:all) do
23
- FileUtils.rm_rf "nice_bot" if Dir.exists? "nice_bot"
23
+ FileUtils.rm_rf "nice_bot" if Dir.exist? "nice_bot"
24
24
  FileUtils.chdir "../"
25
25
  end
26
26
 
@@ -1,6 +1,6 @@
1
1
  module Boty
2
2
  RSpec.describe DSL do
3
- let(:bot) { Bot.new({"id" => "U123", "name" => "jeeba"}) }
3
+ let(:bot) { Bot.new("id" => "U123", "name" => "jeeba") }
4
4
  subject(:dsl) { described_class.new bot }
5
5
 
6
6
  def message(text, extras = {})
@@ -13,12 +13,11 @@ module Boty
13
13
 
14
14
  before do
15
15
  # used by message class
16
- allow(Slack.users).to receive(:info).with("U5678").
17
- and_return(Slack::User.new("id" => "U5678", "name" => "julian"))
16
+ allow(Slack.users).to receive(:info).with("U5678")
17
+ .and_return Slack::User.new("id" => "U5678", "name" => "julian")
18
18
  end
19
19
 
20
- methods_from_bot = [ :name, :brain, :know_how, :im, :say,
21
- :desc, :respond, :match ]
20
+ methods_from_bot = %i(name brain know_how im say desc respond match)
22
21
  methods_from_bot.each do |bot_method|
23
22
  it "responds to :#{bot_method}" do
24
23
  expect(dsl.respond_to?(bot_method)).to eq true
@@ -36,8 +35,8 @@ module Boty
36
35
  say "Ohay <@#{user.id}>! I'm here, that's for sure."
37
36
  end
38
37
 
39
- expect(dsl).to receive(:say).
40
- with "Ohay <@U5678>! I'm here, that's for sure."
38
+ expect(dsl).to receive(:say)
39
+ .with "Ohay <@U5678>! I'm here, that's for sure."
41
40
 
42
41
  message "jeeba, are you there?"
43
42
  end
@@ -47,8 +46,8 @@ module Boty
47
46
  say "Ohay <@#{user.id}>! It matched."
48
47
  end
49
48
 
50
- expect(bot).to receive(:say).
51
- with "Ohay <@U5678>! It matched."
49
+ expect(bot).to receive(:say)
50
+ .with "Ohay <@U5678>! It matched."
52
51
 
53
52
  message "called with match?"
54
53
  end
@@ -80,16 +79,16 @@ module Boty
80
79
  executed = false
81
80
  dsl.match "omg" do executed = true end
82
81
 
83
- expect { message "bbq omg lol." }.
84
- to change { executed }.from(false).to true
82
+ expect { message "bbq omg lol." }
83
+ .to change { executed }.from(false).to true
85
84
  end
86
85
 
87
86
  it "binds a string with #respond" do
88
87
  executed = false
89
88
  dsl.respond "omg" do executed = true end
90
89
 
91
- expect { message "<@jeeba>: bbq omg lol." }.
92
- to change { executed }.from(false).to true
90
+ expect { message "<@jeeba>: bbq omg lol." }
91
+ .to change { executed }.from(false).to true
93
92
  end
94
93
  end
95
94
 
@@ -28,7 +28,8 @@ module Boty
28
28
 
29
29
  context "helpers" do
30
30
  it "includes #message_event to fire `data['type'] = 'message' events" do
31
- expect(@_bot).to receive(:event).with "type" => "message", "text" => "omg"
31
+ expect(@_bot).to receive(:event)
32
+ .with "type" => "message", "text" => "omg"
32
33
  message "omg"
33
34
  end
34
35
  end
@@ -1,15 +1,17 @@
1
1
  module Boty
2
2
  RSpec.describe Boty::ScriptLoader, :fakefs, :users do
3
- let(:dsl) { Boty::DSL.new Bot.new({ "name" => "jabber", "id" => "123" }) }
4
- let(:data) {{
5
- "type" => "message",
6
- "text" => "hey <@jabber>, pug me"
7
- }}
3
+ let(:dsl) { Boty::DSL.new Bot.new("name" => "jabber", "id" => "123") }
4
+ let(:data) do
5
+ {
6
+ "type" => "message",
7
+ "text" => "hey <@jabber>, pug me"
8
+ }
9
+ end
8
10
 
9
11
  subject(:loader) { described_class.new Boty::DSL.new(bot) }
10
12
 
11
13
  before do
12
- FileUtils.mkdir "script" unless Dir.exists? "script"
14
+ FileUtils.mkdir "script" unless Dir.exist? "script"
13
15
  File.open "script/omg.rb", "w" do |f|
14
16
  f.write <<-RUBY
15
17
  respond(/pug me/i) do
@@ -33,8 +33,8 @@ module Boty
33
33
  end
34
34
 
35
35
  it "intializes the sse client with the session url" do
36
- expect(Faye::WebSocket::Client).to receive(:new).
37
- with("ws://example.org/slack/sse/url")
36
+ expect(Faye::WebSocket::Client).to receive(:new)
37
+ .with("ws://example.org/slack/sse/url")
38
38
 
39
39
  session.start
40
40
  end
@@ -8,26 +8,26 @@ module Boty
8
8
  }
9
9
 
10
10
  let(:post_message_url) {
11
- "https://slack.com/api/chat.postMessage?"+
12
- "token=#{ENV['SLACK_BOT_API_TOKEN']}&#{parameters}"
11
+ "https://slack.com/api/chat.postMessage?" \
12
+ "token=#{ENV['SLACK_BOT_API_TOKEN']}&#{parameters}"
13
13
  }
14
14
 
15
15
  describe "#post_message" do
16
16
  it "uses api end point to send message with default parameters" do
17
- expect(Slack::URL).to receive(:get).
18
- with(post_message_url + "&text=omglolbbq")
17
+ expect(Slack::URL).to receive(:get)
18
+ .with(post_message_url + "&text=omglolbbq")
19
19
  chat.post_message "omglolbbq"
20
20
  end
21
21
 
22
22
  it "uri encodes the message" do
23
- expect(Slack::URL).to receive(:get).
24
- with(post_message_url + "&text=omg%20lol%20bbq")
23
+ expect(Slack::URL).to receive(:get)
24
+ .with(post_message_url + "&text=omg%20lol%20bbq")
25
25
  chat.post_message "omg lol bbq"
26
26
  end
27
27
 
28
28
  it "accepts extra api parameters" do
29
- expect(Slack::URL).to receive(:get).
30
- with(post_message_url + "&text=omg&extra=param")
29
+ expect(Slack::URL).to receive(:get)
30
+ .with(post_message_url + "&text=omg&extra=param")
31
31
  chat.post_message "omg", extra: "param"
32
32
  end
33
33
 
@@ -35,8 +35,8 @@ module Boty
35
35
  let(:parameters) { "as_user=true&channel=lol" }
36
36
 
37
37
  it "sends to a specific channel when one is given" do
38
- expect(Slack::URL).to receive(:get).
39
- with(post_message_url + "&text=omg")
38
+ expect(Slack::URL).to receive(:get)
39
+ .with(post_message_url + "&text=omg")
40
40
  chat.post_message "omg", channel: "lol"
41
41
  end
42
42
  end
@@ -44,26 +44,26 @@ module Boty
44
44
 
45
45
  describe "#post_im" do
46
46
  let(:im_open_url) {
47
- "https://slack.com/api/im.open?"+
48
- "token=#{ENV['SLACK_BOT_API_TOKEN']}&user=U1234"
47
+ "https://slack.com/api/im.open?" \
48
+ "token=#{ENV['SLACK_BOT_API_TOKEN']}&user=U1234"
49
49
  }
50
50
 
51
51
  before do
52
- allow(Slack::URL).to receive(:get).with(im_open_url).
53
- and_return("channel" => { "id" => "C4321" })
52
+ allow(Slack::URL).to receive(:get).with(im_open_url)
53
+ .and_return("channel" => { "id" => "C4321" })
54
54
  allow(chat).to receive(:post_message)
55
55
  end
56
56
 
57
57
  it "calls `#im.open` to open the channel" do
58
- expect(chat.im).to receive(:open).with("U1234").
59
- and_return Channel.new(id: "C4321", info: {})
58
+ expect(chat.im).to receive(:open).with("U1234")
59
+ .and_return Channel.new(id: "C4321", info: {})
60
60
 
61
61
  chat.post_im "U1234", "message"
62
62
  end
63
63
 
64
64
  it "sends the message to the im channel returned by `#im.open`" do
65
- expect(chat).to receive(:post_message).
66
- with "message", channel: "C4321"
65
+ expect(chat).to receive(:post_message)
66
+ .with "message", channel: "C4321"
67
67
 
68
68
  chat.post_im "U1234", "message"
69
69
  end
@@ -8,8 +8,8 @@ module Boty
8
8
  let(:action) { :open }
9
9
 
10
10
  let(:im_url) {
11
- "https://slack.com/api/im.#{action}?"+
12
- "token=#{ENV['SLACK_BOT_API_TOKEN']}"
11
+ "https://slack.com/api/im.#{action}?" \
12
+ "token=#{ENV['SLACK_BOT_API_TOKEN']}"
13
13
  }
14
14
 
15
15
  describe "#open" do
@@ -20,8 +20,8 @@ module Boty
20
20
  end
21
21
 
22
22
  it "returns a channel object with the im channel information" do
23
- expect(Slack::URL).to receive(:get).with(im_url + "&user=U1234").
24
- and_return(
23
+ expect(Slack::URL).to receive(:get).with(im_url + "&user=U1234")
24
+ .and_return(
25
25
  "ok" => true,
26
26
  "channel" => { "id" => "D024BFF1M" }
27
27
  )
@@ -6,14 +6,16 @@ module Boty
6
6
  let(:user_id) { "U7777" }
7
7
  let(:user_name) { "julian" }
8
8
 
9
- let(:message_json) {{
10
- "type" => "message",
11
- "text" => "omg lol bbq",
12
- "user" => "U7777",
13
- "channel" => "333",
14
- "ts" => "1234",
15
- "team" => "3452"
16
- }}
9
+ let(:message_json) do
10
+ {
11
+ "type" => "message",
12
+ "text" => "omg lol bbq",
13
+ "user" => "U7777",
14
+ "channel" => "333",
15
+ "ts" => "1234",
16
+ "team" => "3452"
17
+ }
18
+ end
17
19
 
18
20
  it "uses Slack.users.info to create a User instance" do
19
21
  expect(message.user.id).to eq "U7777"
@@ -25,7 +27,7 @@ module Boty
25
27
  expect(message.from? "U7777").to eq true
26
28
  end
27
29
 
28
- it "returns true if the param `respond_to? :id` returning the message author" do
30
+ it "returns true when param `#respond_to? :id` is the message author" do
29
31
  expect(message.from? OpenStruct.new(id: "U7777")).to eq true
30
32
  end
31
33
  end
@@ -4,9 +4,9 @@ module Boty
4
4
  subject(:rtm) { described_class.new }
5
5
 
6
6
  let(:url_with_default_parameters) {
7
- "https://#{ENV["SLACK_COMPANY"]}.slack.com/api/rtm.start?"+
8
- "token=#{ENV["SLACK_BOT_API_TOKEN"]}&"+
9
- "simple_latest=true&no_unreads=true"
7
+ "https://#{ENV['SLACK_COMPANY']}.slack.com/api/rtm.start?" \
8
+ "token=#{ENV['SLACK_BOT_API_TOKEN']}&" \
9
+ "simple_latest=true&no_unreads=true"
10
10
  }
11
11
 
12
12
  describe "#start" do
@@ -31,8 +31,8 @@ module Boty
31
31
  end
32
32
 
33
33
  it "parses the json response" do
34
- expect(Net::HTTP).to receive(:get).with(URI("http://example.org")).
35
- and_return "{\"it\": \"works\"}"
34
+ expect(Net::HTTP).to receive(:get).with(URI("http://example.org"))
35
+ .and_return "{\"it\": \"works\"}"
36
36
  response = url.get "http://example.org"
37
37
  expect(response).to eq "it" => "works"
38
38
  end
@@ -48,11 +48,11 @@ module Boty
48
48
 
49
49
  it "appends the api token" do
50
50
  url = client.send :parameterize, {}
51
- expect(url).to include "token=#{ENV["SLACK_BOT_API_TOKEN"]}"
51
+ expect(url).to include "token=#{ENV['SLACK_BOT_API_TOKEN']}"
52
52
  end
53
53
 
54
54
  it "add extra parameters" do
55
- url = client.send :parameterize, {really: "omg"}
55
+ url = client.send :parameterize, really: "omg"
56
56
  expect(url).to include "really=omg"
57
57
  end
58
58
 
@@ -62,7 +62,7 @@ module Boty
62
62
  end
63
63
 
64
64
  it "applies URI.encode to parameter values" do
65
- url = client.send :parameterize, {really: "omg lol"}
65
+ url = client.send :parameterize, really: "omg lol"
66
66
  expect(url).to include "really=omg%20lol"
67
67
  end
68
68
  end
@@ -2,49 +2,49 @@ module Boty
2
2
  module Slack
3
3
  RSpec.describe Users do
4
4
  def url_for(action)
5
- "https://slack.com/api/users.#{action}?"+
5
+ "https://slack.com/api/users.#{action}?" \
6
6
  "token=#{ENV['SLACK_BOT_API_TOKEN']}"
7
7
  end
8
8
 
9
9
  subject(:users) { described_class.new }
10
10
 
11
11
  before do
12
- allow(Slack::URL).to receive(:get).with(url_for(:info) + "&user=U123456").
13
- and_return(
12
+ allow(Slack::URL).to receive(:get)
13
+ .with(url_for(:info) + "&user=U123456").and_return(
14
14
  "ok" => true,
15
15
  "user" => {
16
16
  "id" => "U123456",
17
17
  "name" => "julian"
18
18
  }
19
- )
19
+ )
20
20
 
21
- allow(Slack::URL).to receive(:get).with(url_for(:list)).
22
- and_return(
23
- {
24
- "ok" => true,
25
- "members" => [
26
- {
27
- "id" => "U023BECGF",
28
- "name" => "bobby"
29
- },
30
- {
31
- "id" => "U123456",
32
- "name" => "julian"
33
- }
34
- ]
35
- }
36
- )
21
+ allow(Slack::URL).to receive(:get).with(url_for(:list))
22
+ .and_return(
23
+ "ok" => true,
24
+ "members" => [
25
+ {
26
+ "id" => "U023BECGF",
27
+ "name" => "bobby"
28
+ },
29
+ {
30
+ "id" => "U123456",
31
+ "name" => "julian"
32
+ }
33
+ ]
34
+ )
37
35
  end
38
36
 
39
37
  describe "#info" do
40
38
  it "calls Slack::URL get with token and user" do
41
- expect(Slack::URL).to receive(:get).with(url_for(:info) + "&user=U123456")
39
+ expect(Slack::URL).to receive(:get)
40
+ .with(url_for(:info) + "&user=U123456")
42
41
 
43
42
  users.info "U123456"
44
43
  end
45
44
 
46
45
  it "returns a channel object with the im channel information" do
47
- expect(Slack::URL).to receive(:get).with(url_for(:info) + "&user=U123456")
46
+ expect(Slack::URL).to receive(:get)
47
+ .with(url_for(:info) + "&user=U123456")
48
48
 
49
49
  user = users.info("U123456")
50
50
 
@@ -56,7 +56,7 @@ module Boty
56
56
  describe "#list" do
57
57
  it "retrieves the users list" do
58
58
  list = Slack.users.list
59
- expect(list.map(&:name)).to eq ["bobby", "julian"]
59
+ expect(list.map(&:name)).to eq %w(bobby julian)
60
60
  end
61
61
  end
62
62
 
@@ -5,13 +5,13 @@ module Boty
5
5
  def start_session(only_knows: nil)
6
6
  executable_bot = File.read "bot"
7
7
  @session = instance_eval executable_bot, "bot", 1
8
+ return unless only_knows
8
9
 
9
- if only_knows
10
- extra_to_remove = bot.know_how.keys - only_knows
11
- extra_to_remove.each do |command_desc|
12
- bot.no command_desc
10
+ bot.know_how.each { |action|
11
+ unless only_knows.include? action.desc.command
12
+ bot.no action.desc.command
13
13
  end
14
- end
14
+ }
15
15
  end
16
16
 
17
17
  def message(message)
@@ -37,13 +37,14 @@ module Boty
37
37
  allow(cli).to receive(:ask).and_return "omg", "lol"
38
38
  cli.new bot_name
39
39
  end
40
- expect(Dir.exists? bot_name).to eq true
40
+
41
+ expect(Dir.exist? bot_name).to eq true
41
42
 
42
43
  Dir.chdir bot_name
43
44
 
44
- expect(File.read ".env.local").to eq %{SLACK_COMPANY=omg
45
+ expect(File.read ".env.local").to eq %(SLACK_COMPANY=omg
45
46
  SLACK_BOT_API_TOKEN=lol
46
- }
47
+ )
47
48
  end
48
49
  end
49
50
 
@@ -61,37 +62,37 @@ SLACK_BOT_API_TOKEN=lol
61
62
  expect(Faye::WebSocket::Client).to receive(:new).with(rtm_ws_url)
62
63
  start_session
63
64
 
64
- expect(bot).to receive(:say).
65
- with "Ohay <@#{current_user}>! I'm here, that's for sure."
65
+ expect(bot).to receive(:say)
66
+ .with "Ohay <@#{current_user}>! I'm here, that's for sure."
66
67
  message "hey boty!"
67
68
  end
68
69
 
69
70
  describe "knows" do
70
71
  before do
71
- start_session only_knows: ['knows']
72
+ start_session only_knows: ["knows"]
72
73
  end
73
74
 
74
75
  it "responds in particular with the known commands and handlers" do
75
76
  # check that a im arrived to the current user with knows result
76
77
  message = "```\nknows: List all the commands known by this bot.\n```"
77
- expect{ message "<@boty>: knows" }.
78
- to send_im(current_user_id, message)
78
+ expect { message "<@boty>: knows" }
79
+ .to send_im(current_user_id, message)
79
80
  end
80
81
  end
81
82
 
82
83
  it "overrides default locale with the project specific one" do
83
84
  File.open("locale/xpto.yml", "w") do |file|
84
- file.write(%{xpto:
85
+ file.write(%(xpto:
85
86
  scripts:
86
- knows: "Wow! Such commands!"})
87
+ knows: "Wow! Such commands!"))
87
88
  end
88
- start_session only_knows: ['knows']
89
+ start_session only_knows: ["knows"]
89
90
  ::Boty.locale = :xpto
90
91
 
91
92
  message = "```\nknows: List all the commands known by this bot.\n```"
92
93
 
93
- expect{ message "<@boty>: knows" }.
94
- to send_im(current_user_id, message)
94
+ expect { message "<@boty>: knows" }
95
+ .to send_im(current_user_id, message)
95
96
  end
96
97
  end
97
98
  end