slack-ruby-bot-bhe 0.5.5.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.
Files changed (90) hide show
  1. checksums.yaml +17 -0
  2. data/.gitignore +3 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +6 -0
  5. data/.rubocop_todo.yml +58 -0
  6. data/.travis.yml +3 -0
  7. data/CHANGELOG.md +81 -0
  8. data/CONTRIBUTING.md +139 -0
  9. data/DEPLOYMENT.md +33 -0
  10. data/Gemfile +3 -0
  11. data/LICENSE.md +22 -0
  12. data/README.md +263 -0
  13. data/RELEASING.md +67 -0
  14. data/Rakefile +19 -0
  15. data/TUTORIAL.md +205 -0
  16. data/UPGRADING.md +64 -0
  17. data/examples/minimal/Gemfile +3 -0
  18. data/examples/minimal/Procfile +1 -0
  19. data/examples/minimal/pongbot.rb +9 -0
  20. data/examples/weather/Gemfile +3 -0
  21. data/examples/weather/Procfile +1 -0
  22. data/examples/weather/weatherbot.rb +9 -0
  23. data/lib/config/application.rb +14 -0
  24. data/lib/config/boot.rb +8 -0
  25. data/lib/config/environment.rb +3 -0
  26. data/lib/initializers/giphy.rb +5 -0
  27. data/lib/slack-ruby-bot.rb +25 -0
  28. data/lib/slack-ruby-bot/about.rb +7 -0
  29. data/lib/slack-ruby-bot/app.rb +46 -0
  30. data/lib/slack-ruby-bot/bot.rb +7 -0
  31. data/lib/slack-ruby-bot/client.rb +44 -0
  32. data/lib/slack-ruby-bot/commands.rb +5 -0
  33. data/lib/slack-ruby-bot/commands/about.rb +12 -0
  34. data/lib/slack-ruby-bot/commands/base.rb +121 -0
  35. data/lib/slack-ruby-bot/commands/help.rb +9 -0
  36. data/lib/slack-ruby-bot/commands/hi.rb +9 -0
  37. data/lib/slack-ruby-bot/commands/unknown.rb +11 -0
  38. data/lib/slack-ruby-bot/config.rb +40 -0
  39. data/lib/slack-ruby-bot/hooks.rb +3 -0
  40. data/lib/slack-ruby-bot/hooks/base.rb +10 -0
  41. data/lib/slack-ruby-bot/hooks/hello.rb +11 -0
  42. data/lib/slack-ruby-bot/hooks/message.rb +50 -0
  43. data/lib/slack-ruby-bot/rspec.rb +12 -0
  44. data/lib/slack-ruby-bot/rspec/support/fixtures/slack/auth_test.yml +16 -0
  45. data/lib/slack-ruby-bot/rspec/support/fixtures/slack/migration_in_progress.yml +30 -0
  46. data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/it_behaves_like_a_slack_bot.rb +27 -0
  47. data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_error.rb +30 -0
  48. data/lib/slack-ruby-bot/rspec/support/slack-ruby-bot/respond_with_slack_message.rb +19 -0
  49. data/lib/slack-ruby-bot/rspec/support/slack_api_key.rb +5 -0
  50. data/lib/slack-ruby-bot/rspec/support/slack_ruby_bot_configure.rb +9 -0
  51. data/lib/slack-ruby-bot/rspec/support/vcr.rb +8 -0
  52. data/lib/slack-ruby-bot/server.rb +111 -0
  53. data/lib/slack-ruby-bot/version.rb +3 -0
  54. data/lib/slack_ruby_bot.rb +1 -0
  55. data/screenshots/aliases.gif +0 -0
  56. data/screenshots/demo.gif +0 -0
  57. data/screenshots/dms.gif +0 -0
  58. data/screenshots/register-bot.png +0 -0
  59. data/screenshots/weather.gif +0 -0
  60. data/slack-ruby-bot.gemspec +28 -0
  61. data/slack.png +0 -0
  62. data/spec/slack-ruby-bot/app_spec.rb +15 -0
  63. data/spec/slack-ruby-bot/commands/about_spec.rb +19 -0
  64. data/spec/slack-ruby-bot/commands/aliases_spec.rb +22 -0
  65. data/spec/slack-ruby-bot/commands/bot_spec.rb +19 -0
  66. data/spec/slack-ruby-bot/commands/commands_precedence_spec.rb +22 -0
  67. data/spec/slack-ruby-bot/commands/commands_regexp_escape_spec.rb +17 -0
  68. data/spec/slack-ruby-bot/commands/commands_spaces_spec.rb +20 -0
  69. data/spec/slack-ruby-bot/commands/commands_spec.rb +21 -0
  70. data/spec/slack-ruby-bot/commands/commands_with_block_spec.rb +23 -0
  71. data/spec/slack-ruby-bot/commands/direct_messages_spec.rb +38 -0
  72. data/spec/slack-ruby-bot/commands/empty_text_spec.rb +22 -0
  73. data/spec/slack-ruby-bot/commands/help_spec.rb +10 -0
  74. data/spec/slack-ruby-bot/commands/hi_spec.rb +19 -0
  75. data/spec/slack-ruby-bot/commands/match_spec.rb +17 -0
  76. data/spec/slack-ruby-bot/commands/message_loop_spec.rb +34 -0
  77. data/spec/slack-ruby-bot/commands/nil_message_spec.rb +22 -0
  78. data/spec/slack-ruby-bot/commands/not_implemented_spec.rb +15 -0
  79. data/spec/slack-ruby-bot/commands/operators_spec.rb +20 -0
  80. data/spec/slack-ruby-bot/commands/operators_with_block_spec.rb +23 -0
  81. data/spec/slack-ruby-bot/commands/send_gif_spec.rb +32 -0
  82. data/spec/slack-ruby-bot/commands/send_message_spec.rb +19 -0
  83. data/spec/slack-ruby-bot/commands/send_message_with_gif_spec.rb +73 -0
  84. data/spec/slack-ruby-bot/commands/unknown_spec.rb +18 -0
  85. data/spec/slack-ruby-bot/config_spec.rb +55 -0
  86. data/spec/slack-ruby-bot/rspec/respond_with_error_spec.rb +19 -0
  87. data/spec/slack-ruby-bot/server_spec.rb +73 -0
  88. data/spec/slack-ruby-bot/version_spec.rb +7 -0
  89. data/spec/spec_helper.rb +1 -0
  90. metadata +313 -0
@@ -0,0 +1,27 @@
1
+ shared_examples 'a slack ruby bot' do
2
+ context 'not configured' do
3
+ before do
4
+ @slack_api_token = ENV.delete('SLACK_API_TOKEN')
5
+ end
6
+ after do
7
+ ENV['SLACK_API_TOKEN'] = @slack_api_token
8
+ end
9
+ it 'requires SLACK_API_TOKEN' do
10
+ expect { subject }.to raise_error RuntimeError, "Missing ENV['SLACK_API_TOKEN']."
11
+ end
12
+ end
13
+ context 'configured', vcr: { cassette_name: 'auth_test' } do
14
+ context 'run' do
15
+ before do
16
+ subject.send(:auth!)
17
+ end
18
+ it 'succeeds auth' do
19
+ expect(subject.config.url).to eq 'https://rubybot.slack.com/'
20
+ expect(subject.config.team).to eq 'team_name'
21
+ expect(subject.config.user).to eq 'user_name'
22
+ expect(subject.config.team_id).to eq 'TDEADBEEF'
23
+ expect(subject.config.user_id).to eq 'UBAADFOOD'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ require 'rspec/expectations'
2
+
3
+ RSpec::Matchers.define :respond_with_error do |error, error_message|
4
+ match do |actual|
5
+ channel, user, message = parse(actual)
6
+ allow(Giphy).to receive(:random)
7
+ begin
8
+ expect do
9
+ client = app.send(:client)
10
+ app.send(:message, client, text: message, channel: channel, user: user)
11
+ end.to raise_error error, error_message
12
+ rescue RSpec::Expectations::ExpectationNotMetError => e
13
+ @error_message = e.message
14
+ raise e
15
+ end
16
+ true
17
+ end
18
+
19
+ failure_message do |actual|
20
+ _, _, message = parse(actual)
21
+ @error_message || "expected for '#{message}' to fail with '#{expected}'"
22
+ end
23
+
24
+ private
25
+
26
+ def parse(actual)
27
+ actual = { message: actual } unless actual.is_a?(Hash)
28
+ [actual[:channel] || 'channel', actual[:user] || 'user', actual[:message]]
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ require 'rspec/expectations'
2
+
3
+ RSpec::Matchers.define :respond_with_slack_message do |expected|
4
+ match do |actual|
5
+ channel, user, message = parse(actual)
6
+ allow(Giphy).to receive(:random)
7
+ client = app.send(:client)
8
+ expect(SlackRubyBot::Commands::Base).to receive(:send_client_message).with(client, channel: channel, text: expected)
9
+ app.send(:message, client, text: message, channel: channel, user: user)
10
+ true
11
+ end
12
+
13
+ private
14
+
15
+ def parse(actual)
16
+ actual = { message: actual } unless actual.is_a?(Hash)
17
+ [actual[:channel] || 'channel', actual[:user] || 'user', actual[:message]]
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ RSpec.configure do |config|
2
+ config.before :all do
3
+ ENV['SLACK_API_TOKEN'] ||= 'test'
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ RSpec.configure do |config|
2
+ config.before :each do
3
+ SlackRubyBot.configure do |c|
4
+ c.token = 'testtoken'
5
+ c.user = 'rubybot'
6
+ c.user_id = 'DEADBEEF'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ require 'vcr'
2
+
3
+ VCR.configure do |config|
4
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), 'fixtures/slack')
5
+ config.hook_into :webmock
6
+ # config.default_cassette_options = { record: :new_episodes }
7
+ config.configure_rspec_metadata!
8
+ end
@@ -0,0 +1,111 @@
1
+ module SlackRubyBot
2
+ class Server
3
+ cattr_accessor :hooks
4
+ attr_accessor :token
5
+ attr_accessor :aliases
6
+ attr_accessor :send_gifs
7
+
8
+ include SlackRubyBot::Hooks::Hello
9
+ include SlackRubyBot::Hooks::Message
10
+
11
+ def initialize(options = {})
12
+ @token = options[:token]
13
+ @aliases = options[:aliases]
14
+ @send_gifs = options.key?(:send_gifs) ? !!options[:send_gifs] : true
15
+ end
16
+
17
+ def run
18
+ auth!
19
+ loop do
20
+ begin
21
+ start!
22
+ rescue Slack::Web::Api::Error => e
23
+ logger.error e
24
+ case e.message
25
+ when 'migration_in_progress'
26
+ sleep 1 # ignore, try again
27
+ else
28
+ raise e
29
+ end
30
+ rescue Faraday::Error::TimeoutError, Faraday::Error::ConnectionFailed, Faraday::Error::SSLError => e
31
+ logger.error e
32
+ sleep 1 # ignore, try again
33
+ rescue StandardError => e
34
+ logger.error e
35
+ raise e
36
+ ensure
37
+ @client = nil
38
+ end
39
+ end
40
+ end
41
+
42
+ def auth!
43
+ client.auth = client.web_client.auth_test
44
+ logger.info "Welcome '#{client.auth['user']}' to the '#{client.auth['team']}' team at #{client.auth['url']}."
45
+ end
46
+
47
+ def start!
48
+ @stopping = false
49
+ @async = false
50
+ client.start!
51
+ end
52
+
53
+ def start_async
54
+ @stopping = false
55
+ @async = true
56
+ client.start_async
57
+ end
58
+
59
+ def stop!
60
+ @stopping = true
61
+ client.stop! if @client
62
+ end
63
+
64
+ def restart!(wait = 1)
65
+ if @async
66
+ start_async
67
+ else
68
+ start!
69
+ end
70
+ rescue StandardError => e
71
+ sleep wait
72
+ logger.error "#{e.message}, reconnecting in #{wait} second(s)."
73
+ logger.debug e
74
+ restart! [wait * 2, 60].min
75
+ end
76
+
77
+ private
78
+
79
+ def logger
80
+ @logger ||= begin
81
+ $stdout.sync = true
82
+ Logger.new(STDOUT)
83
+ end
84
+ end
85
+
86
+ def client
87
+ @client ||= begin
88
+ client = SlackRubyBot::Client.new(aliases: aliases, send_gifs: send_gifs, token: token)
89
+ client.on :close do |_data|
90
+ @client = nil
91
+ restart! unless @stopping
92
+ end
93
+ hooks.each do |hook|
94
+ client.on hook do |data|
95
+ begin
96
+ send hook, client, data
97
+ rescue StandardError => e
98
+ logger.error e
99
+ begin
100
+ client.message(channel: data['channel'], text: e.message) if data.key?('channel')
101
+ rescue
102
+ # ignore
103
+ end
104
+ end
105
+ end
106
+ end
107
+ client
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,3 @@
1
+ module SlackRubyBot
2
+ VERSION = '0.5.5.3'
3
+ end
@@ -0,0 +1 @@
1
+ require 'slack-ruby-bot'
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,28 @@
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
+ require 'slack-ruby-bot/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'slack-ruby-bot-bhe'
6
+ s.version = SlackRubyBot::VERSION
7
+ s.authors = ['Matthew Brown']
8
+ s.email = 'mbrown@bhei.com'
9
+ s.platform = Gem::Platform::RUBY
10
+ s.required_rubygems_version = '>= 1.3.6'
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files -- spec/*`.split("\n")
13
+ s.require_paths = ['lib']
14
+ s.homepage = 'http://github.com/mbrown-bhe/slack-ruby-bot'
15
+ s.licenses = ['MIT']
16
+ s.summary = 'The easiest way to write a Slack bot in Ruby.'
17
+ s.add_dependency 'hashie'
18
+ s.add_dependency 'slack-ruby-client-bhe', '>= 0.5.0'
19
+ s.add_dependency 'faye-websocket'
20
+ s.add_dependency 'activesupport'
21
+ s.add_dependency 'giphy', '~> 2.0.2'
22
+ s.add_development_dependency 'rake'
23
+ s.add_development_dependency 'rspec'
24
+ s.add_development_dependency 'rack-test'
25
+ s.add_development_dependency 'vcr'
26
+ s.add_development_dependency 'webmock'
27
+ s.add_development_dependency 'rubocop', '0.32.1'
28
+ end
Binary file
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::App do
4
+ def app
5
+ SlackRubyBot::App.new
6
+ end
7
+ it_behaves_like 'a slack ruby bot'
8
+
9
+ describe '.instance' do
10
+ it 'creates an instance of the App subclass' do
11
+ klass = Class.new(SlackRubyBot::App)
12
+ expect(klass.instance.class).to be klass
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::Commands::Default do
4
+ def app
5
+ SlackRubyBot::App.new
6
+ end
7
+ it 'lowercase' do
8
+ expect(message: SlackRubyBot.config.user).to respond_with_slack_message(SlackRubyBot::ABOUT)
9
+ end
10
+ it 'upcase' do
11
+ expect(message: SlackRubyBot.config.user.upcase).to respond_with_slack_message(SlackRubyBot::ABOUT)
12
+ end
13
+ it 'name:' do
14
+ expect(message: "#{SlackRubyBot.config.user}:").to respond_with_slack_message(SlackRubyBot::ABOUT)
15
+ end
16
+ it 'id' do
17
+ expect(message: "<@#{SlackRubyBot.config.user_id}>").to respond_with_slack_message(SlackRubyBot::ABOUT)
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot do
4
+ def app
5
+ SlackRubyBot::App.new
6
+ end
7
+ before do
8
+ ENV['SLACK_RUBY_BOT_ALIASES'] = ':emoji: alias каспаров'
9
+ end
10
+ after do
11
+ ENV.delete('SLACK_RUBY_BOT_ALIASES')
12
+ end
13
+ it 'responds to emoji' do
14
+ expect(message: ':emoji: hi').to respond_with_slack_message('Hi <@user>!')
15
+ end
16
+ it 'responds to an alias' do
17
+ expect(message: 'alias hi').to respond_with_slack_message('Hi <@user>!')
18
+ end
19
+ it 'responds to a non-English alias' do
20
+ expect(message: 'каспаров hi').to respond_with_slack_message('Hi <@user>!')
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::Bot do
4
+ let! :command do
5
+ Class.new(SlackRubyBot::Bot) do
6
+ command 'bot_spec' do |client, data, match|
7
+ send_message client, data.channel, match['expression']
8
+ end
9
+ end
10
+ end
11
+ def app
12
+ SlackRubyBot::App.new
13
+ end
14
+ let(:client) { app.send(:client) }
15
+ it 'sends a message' do
16
+ expect(SlackRubyBot::Commands::Base).to receive(:send_client_message).with(client, channel: 'channel', text: 'message')
17
+ app.send(:message, client, text: "#{SlackRubyBot.config.user} bot_spec message", channel: 'channel', user: 'user')
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::Commands do
4
+ let! :command do
5
+ Class.new(SlackRubyBot::Commands::Base) do
6
+ command 'tomato' do |client, data, match|
7
+ send_message client, data.channel, "#{match[:command]}: #{match[:expression]}"
8
+ end
9
+
10
+ command 'tomatoes' do |client, data, match|
11
+ send_message client, data.channel, "#{match[:command]}: #{match[:expression]}"
12
+ end
13
+ end
14
+ end
15
+ def app
16
+ SlackRubyBot::App.new
17
+ end
18
+ it 'matches commands' do
19
+ expect(message: "#{SlackRubyBot.config.user} tomato red").to respond_with_slack_message('tomato: red')
20
+ expect(message: "#{SlackRubyBot.config.user} tomatoes green").to respond_with_slack_message('tomatoes: green')
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::Commands do
4
+ let! :command do
5
+ Class.new(SlackRubyBot::Commands::Base) do
6
+ command '(' do |client, data, match|
7
+ send_message client, data.channel, "#{match[:command]}: #{match[:expression]}"
8
+ end
9
+ end
10
+ end
11
+ def app
12
+ SlackRubyBot::App.new
13
+ end
14
+ it 'does not return error' do
15
+ expect(message: "#{SlackRubyBot.config.user} ( /").to respond_with_slack_message('(: /')
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::Commands do
4
+ let! :command do
5
+ Class.new(SlackRubyBot::Commands::Base) do
6
+ command 'space' do |client, data, match|
7
+ send_message client, data.channel, "#{match[:command]}: #{match[:expression]}"
8
+ end
9
+ end
10
+ end
11
+ def app
12
+ SlackRubyBot::App.new
13
+ end
14
+ it 'matches leading spaces' do
15
+ expect(message: " #{SlackRubyBot.config.user} space red").to respond_with_slack_message('space: red')
16
+ end
17
+ it 'matches trailing spaces' do
18
+ expect(message: "#{SlackRubyBot.config.user} space red ").to respond_with_slack_message('space: red')
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::Commands do
4
+ let! :command do
5
+ Class.new(SlackRubyBot::Commands::Base) do
6
+ command 'sayhi'
7
+ command 'saybye'
8
+
9
+ def self.call(client, data, match)
10
+ send_message client, data.channel, "#{match[:command]}: #{match[:expression]}"
11
+ end
12
+ end
13
+ end
14
+ def app
15
+ SlackRubyBot::App.new
16
+ end
17
+ it 'supports multiple commands' do
18
+ expect(message: "#{SlackRubyBot.config.user} sayhi arg1 arg2").to respond_with_slack_message('sayhi: arg1 arg2')
19
+ expect(message: "#{SlackRubyBot.config.user} saybye arg1 arg2").to respond_with_slack_message('saybye: arg1 arg2')
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackRubyBot::Commands do
4
+ let! :command do
5
+ Class.new(SlackRubyBot::Commands::Base) do
6
+ command 'sayhi' do |client, data, match|
7
+ send_message client, data.channel, "#{match[:command]}: #{match[:expression]}"
8
+ end
9
+
10
+ command 'one', 'two' do |client, data, match|
11
+ send_message client, data.channel, "#{match[:command]}: #{match[:expression]}"
12
+ end
13
+ end
14
+ end
15
+ def app
16
+ SlackRubyBot::App.new
17
+ end
18
+ it 'supports multiple commands' do
19
+ expect(message: "#{SlackRubyBot.config.user} sayhi arg1 arg2").to respond_with_slack_message('sayhi: arg1 arg2')
20
+ expect(message: "#{SlackRubyBot.config.user} one arg1 arg2").to respond_with_slack_message('one: arg1 arg2')
21
+ expect(message: "#{SlackRubyBot.config.user} two arg1 arg2").to respond_with_slack_message('two: arg1 arg2')
22
+ end
23
+ end