slack-bot-manager 0.1.0pre1 → 0.1.0pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +0 -3
  4. data/.rubocop.yml +6 -0
  5. data/.rubocop_todo.yml +81 -0
  6. data/.travis.yml +26 -0
  7. data/CHANGELOG.md +1 -1
  8. data/Gemfile +6 -0
  9. data/README.md +62 -11
  10. data/Rakefile +17 -0
  11. data/examples/dm-bot/Gemfile +5 -0
  12. data/examples/dm-bot/Gemfile.lock +40 -0
  13. data/examples/dm-bot/README.md +23 -0
  14. data/examples/dm-bot/dm-bot.rb +98 -0
  15. data/examples/dm-bot/tokens.yml.sample +2 -0
  16. data/lib/slack-bot-manager/client/base.rb +50 -14
  17. data/lib/slack-bot-manager/client/commands.rb +5 -7
  18. data/lib/slack-bot-manager/config.rb +41 -13
  19. data/lib/slack-bot-manager/errors.rb +10 -13
  20. data/lib/slack-bot-manager/extend.rb +13 -2
  21. data/lib/slack-bot-manager/logger.rb +12 -8
  22. data/lib/slack-bot-manager/manager/base.rb +5 -3
  23. data/lib/slack-bot-manager/manager/connection.rb +88 -87
  24. data/lib/slack-bot-manager/manager/storage/dalli.rb +63 -0
  25. data/lib/slack-bot-manager/manager/storage/redis.rb +55 -0
  26. data/lib/slack-bot-manager/manager/storage.rb +6 -0
  27. data/lib/slack-bot-manager/manager/tokens.rb +26 -20
  28. data/lib/slack-bot-manager/version.rb +1 -1
  29. data/lib/slack-bot-manager.rb +2 -0
  30. data/slack-bot-manager.gemspec +10 -9
  31. data/spec/fixtures/slack-bot-manager/web/rtm_start.yml +59 -0
  32. data/spec/integration/client_spec.rb +62 -0
  33. data/spec/integration/manager_spec.rb +121 -0
  34. data/spec/slack-bot-manager/client/base_spec.rb +96 -0
  35. data/spec/slack-bot-manager/config_spec.rb +19 -0
  36. data/spec/slack-bot-manager/errors_spec.rb +5 -0
  37. data/spec/slack-bot-manager/extend_spec.rb +5 -0
  38. data/spec/slack-bot-manager/logger_spec.rb +5 -0
  39. data/spec/slack-bot-manager/version_spec.rb +7 -0
  40. data/spec/spec_helper.rb +10 -0
  41. data/spec/support/vcr.rb +8 -0
  42. metadata +153 -6
@@ -1,87 +1,93 @@
1
1
  module SlackBotManager
2
2
  module Tokens
3
-
4
3
  # Add token(s) to be connected
5
4
  def add_token(*tokens)
6
- tokens.each do |token|
5
+ tokens.map do |token|
7
6
  begin
8
7
  team_info = check_token_status(token)
9
8
 
10
9
  # Add to token list
11
- self.redis.hset(self.tokens_key, team_info['team_id'], token)
10
+ storage.set(tokens_key, team_info['team_id'], token)
11
+ true
12
12
  rescue => err
13
13
  on_error(err)
14
+ false
14
15
  end
15
16
  end
16
17
  end
17
18
 
18
19
  # Remove token(s) and connection(s)
19
20
  def remove_token(*tokens)
20
- tokens.each do |token|
21
+ tokens.map do |token|
21
22
  begin
22
23
  id = get_id_from_token(token) # As token should be in list
23
- raise SlackBotManager::InvalidToken if !!id.empty?
24
+ fail SlackBotManager::InvalidToken if !id || id.empty?
24
25
 
25
26
  # Delete from token and connections list
26
- self.redis.hdel(self.tokens_key, id)
27
- self.redis.hdel(self.teams_key, id)
27
+ storage.delete(tokens_key, id)
28
+ storage.delete(teams_key, id)
29
+ true
28
30
  rescue => err
29
31
  on_error(err)
32
+ false
30
33
  end
31
34
  end
32
35
  end
33
36
 
34
37
  # Remove all tokens
35
38
  def clear_tokens
36
- remove_token(*self.redis.hgetall(self.tokens_key).values)
37
- rescue => err
39
+ remove_token(*storage.get_all(tokens_key).values)
40
+ rescue
38
41
  nil
39
42
  end
40
43
 
41
44
  # Restart token connection(s)
42
45
  def update_token(*tokens)
43
- tokens.each do |token|
46
+ tokens.map do |token|
44
47
  begin
45
48
  id = get_id_from_token(token) # As token should be in list
46
- raise SlackBotManager::InvalidToken if !!id.empty?
49
+ fail SlackBotManager::InvalidToken if !id || id.empty?
47
50
 
48
51
  # Issue reset command
49
- self.redis.hset(self.teams_key, id, 'restart')
52
+ storage.set(teams_key, id, 'restart')
53
+ true
50
54
  rescue => err
51
55
  on_error(err)
56
+ false
52
57
  end
53
58
  end
54
59
  end
55
60
 
56
61
  # Check token connection(s)
57
62
  def check_token(*tokens)
58
- rtm_keys = self.redis.hgetall(self.teams_key)
63
+ rtm_keys = storage.get_all(teams_key)
59
64
 
60
- tokens.each do |token|
65
+ tokens.map do |token|
61
66
  begin
62
67
  team_info = check_token_status(token)
63
-
64
- info("Team #{team_info['team_id']} :: #{rtm_keys[ team_info['team_id'] ] || 'not_connected'}")
68
+ key_info = rtm_keys[team_info['team_id']] || 'not_connected'
69
+ info("Team #{team_info['team_id']} :: #{key_info}")
70
+ true
65
71
  rescue => err
66
72
  on_error(err)
73
+ false
67
74
  end
68
75
  end
69
76
  end
70
77
 
71
- protected
78
+ protected
72
79
 
73
80
  # Get team id from Slack. (also test if token is valid)
74
81
  def check_token_status(token)
75
82
  info = Slack::Web::Client.new(token: token).auth_test
76
- raise SlackBotManager::InvalidToken unless info && info['ok']
83
+ fail SlackBotManager::InvalidToken unless info && info['ok']
77
84
  info
78
85
  end
79
86
 
80
87
  # Given a token, get id from tokens list
81
88
  def get_id_from_token(token)
82
- self.redis.hgetall(self.tokens_key).each{|id,t| return id if t == token }
89
+ storage.get_all(tokens_key).each { |id, t| return id if t == token }
83
90
  false
84
91
  end
85
-
86
92
  end
87
93
  end
@@ -1,3 +1,3 @@
1
1
  module SlackBotManager
2
- VERSION = '0.1.0pre1'
2
+ VERSION = '0.1.0pre2'.freeze
3
3
  end
@@ -1,6 +1,7 @@
1
1
  # Core requirements
2
2
  require 'logger'
3
3
  require 'redis'
4
+ require 'English'
4
5
  require 'slack-ruby-client'
5
6
 
6
7
  # core components
@@ -17,4 +18,5 @@ require 'slack-bot-manager/client/base'
17
18
  # connection manager
18
19
  require 'slack-bot-manager/manager/connection'
19
20
  require 'slack-bot-manager/manager/tokens'
21
+ require 'slack-bot-manager/manager/storage'
20
22
  require 'slack-bot-manager/manager/base'
@@ -17,13 +17,14 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.add_dependency 'slack-ruby-client', '>=0.5.1'
19
19
  s.add_dependency 'faye-websocket', '>=0.10.0'
20
- s.add_dependency 'redis', '>=3.2.2'
21
20
 
22
- # s.add_development_dependency 'erubis'
23
- # s.add_development_dependency 'json-schema'
24
- # s.add_development_dependency 'rake'
25
- # s.add_development_dependency 'rspec'
26
- # s.add_development_dependency 'vcr'
27
- # s.add_development_dependency 'webmock'
28
- # s.add_development_dependency 'rubocop', '0.35.0'
29
- end
21
+ s.add_development_dependency 'redis', '>=3.2'
22
+ s.add_development_dependency 'dalli', '>=2.7'
23
+ s.add_development_dependency 'erubis'
24
+ s.add_development_dependency 'json-schema'
25
+ s.add_development_dependency 'rake'
26
+ s.add_development_dependency 'rspec'
27
+ s.add_development_dependency 'vcr'
28
+ s.add_development_dependency 'webmock'
29
+ s.add_development_dependency 'rubocop', '0.36.0'
30
+ end
@@ -0,0 +1,59 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://slack.com/api/rtm.start
6
+ body:
7
+ encoding: UTF-8
8
+ string: token=xoxb-zyx987wvu654
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ User-Agent:
13
+ - Slack Bot Manager/0.1.0pre2 <https://github.com/betaworks/slack-bot-manager>
14
+ Content-Type:
15
+ - application/x-www-form-urlencoded
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Access-Control-Allow-Origin:
24
+ - "*"
25
+ Cache-Control:
26
+ - private, no-cache, no-store, must-revalidate
27
+ Content-Security-Policy:
28
+ - referrer no-referrer;
29
+ Content-Type:
30
+ - application/json; charset=utf-8
31
+ Date:
32
+ - Mon, 01 Feb 2016 04:44:37 GMT
33
+ Expires:
34
+ - Mon, 26 Jul 1997 05:00:00 GMT
35
+ Pragma:
36
+ - no-cache
37
+ Server:
38
+ - Apache
39
+ Strict-Transport-Security:
40
+ - max-age=31536000; includeSubDomains; preload
41
+ Vary:
42
+ - Accept-Encoding
43
+ X-Accepted-Oauth-Scopes:
44
+ - rtm:stream,client
45
+ X-Content-Type-Options:
46
+ - nosniff
47
+ X-Oauth-Scopes:
48
+ - identify,bot:basic
49
+ X-Xss-Protection:
50
+ - '0'
51
+ Content-Length:
52
+ - '5183'
53
+ Connection:
54
+ - keep-alive
55
+ body:
56
+ encoding: ASCII-8BIT
57
+ string: '{"ok": true,"self": {"id": "U0GLEUCH1","name": "teambot","prefs": {"highlight_words": "","user_colors": "","color_names_in_list": true,"growls_enabled": true,"tz": null,"push_dm_alert": true,"push_mention_alert": true,"msg_replies": "{\"flexpane\":false }","push_everything": true,"push_idle_wait": 2,"push_sound": "b2.mp3","push_loud_channels": "","push_mention_channels": "","push_loud_channels_set": "","email_alerts": "instant","email_alerts_sleep_until": 0,"email_misc": true,"email_weekly": true,"welcome_message_hidden": false,"all_channels_loud": true,"loud_channels": "","never_channels": "","loud_channels_set": "","show_member_presence": true,"search_sort": "timestamp","expand_inline_imgs": true,"expand_internal_inline_imgs": true,"expand_snippets": false,"posts_formatting_guide": true,"seen_live_support_popup": false,"seen_welcome_2": false,"seen_ssb_prompt": false,"seen_spaces_new_xp_tooltip": false,"spaces_new_xp_banner_dismissed": false,"search_only_my_channels": false,"emoji_mode": "default","emoji_use": "","has_invited": false,"has_uploaded": false,"has_created_channel": false,"search_exclude_channels": "","messages_theme": "default","webapp_spellcheck": true,"no_joined_overlays": false,"no_created_overlays": false,"dropbox_enabled": false,"seen_domain_invite_reminder": false,"seen_member_invite_reminder": false,"mute_sounds": false,"arrow_history": false,"tab_ui_return_selects": true,"obey_inline_img_limit": true,"new_msg_snd": "knock_brush.mp3","collapsible": false,"collapsible_by_click": true,"require_at": false,"ssb_space_window": "","mac_ssb_bounce": "","mac_ssb_bullet": true,"expand_non_media_attachments": true,"show_typing": true,"pagekeys_handled": true,"last_snippet_type": "","display_real_names_override": 0,"time24": false,"enter_is_special_in_tbt": false,"graphic_emoticons": false,"convert_emoticons": true,"autoplay_chat_sounds": true,"ss_emojis": true,"sidebar_behavior": "","seen_onboarding_start": false,"onboarding_cancelled": false,"seen_onboarding_slackbot_conversation": false,"seen_onboarding_channels": false,"seen_onboarding_direct_messages": false,"seen_onboarding_invites": false,"seen_onboarding_search": false,"seen_onboarding_recent_mentions": false,"seen_onboarding_starred_items": false,"seen_onboarding_private_groups": false,"onboarding_slackbot_conversation_step": 0,"dnd_enabled": false,"dnd_start_hour": "22:00","dnd_end_hour": "08:00","mark_msgs_read_immediately": true,"start_scroll_at_oldest": true,"snippet_editor_wrap_long_lines": false,"ls_disabled": false,"sidebar_theme": "default","sidebar_theme_custom_values": "","f_key_search": false,"k_key_omnibox": true,"speak_growls": false,"mac_speak_voice": "com.apple.speech.synthesis.voice.Alex","mac_speak_speed": 250,"comma_key_prefs": false,"at_channel_suppressed_channels": "","push_at_channel_suppressed_channels": "","prompted_for_email_disabling": false,"full_text_extracts": false,"no_text_in_notifications": false,"muted_channels": "","no_macssb1_banner": false,"no_winssb1_banner": false,"no_omnibox_in_channels": false,"k_key_omnibox_auto_hide_count": 0,"hide_user_group_info_pane": false,"mentions_exclude_at_user_groups": false,"privacy_policy_seen": true,"search_exclude_bots": false,"fuzzy_matching": false,"load_lato_2": false,"fuller_timestamps": false,"last_seen_at_channel_warning": 0,"flex_resize_window": false,"msg_preview": false,"msg_preview_displaces": true,"msg_preview_persistent": true,"emoji_autocomplete_big": false,"winssb_run_from_tray": true,"winssb_window_flash_behavior": "idle","two_factor_auth_enabled": false,"two_factor_type": null,"two_factor_backup_type": null,"mentions_exclude_at_channels": true,"confirm_clear_all_unreads": true,"confirm_user_marked_away": true,"box_enabled": false,"seen_single_emoji_msg": false,"confirm_sh_call_start": true,"preferred_skin_tone": "","show_all_skin_tones": false,"separate_private_channels": false,"whats_new_read": 1452973574,"hotness": false,"frecency_jumper": "","jumbomoji": false},"created": 1452973574,"manual_presence": "active"},"team": {"id": "T0ABC123D","name": "Beta (Test x 2)","email_domain": "","domain": "betatesttest","msg_edit_window_mins": -1,"prefs": {"default_channels": ["C0GEN123X","C0RND123X"],"who_can_manage_integrations": {"user": ["U0GLEUCH1"]},"commands_only_regular": false,"msg_edit_window_mins": -1,"allow_message_deletion": true,"hide_referers": true,"display_real_names": false,"disable_file_uploads": "allow_all","who_can_at_everyone": "regular","who_can_at_channel": "ra","warn_before_at_channel": "always","who_can_create_channels": "regular","who_can_create_shared_channels": "admin","who_can_archive_channels": "regular","who_can_create_groups": "ra","who_can_post_general": "ra","who_can_kick_channels": "admin","who_can_kick_groups": "regular","dnd_enabled": true,"dnd_start_hour": "22:00","dnd_end_hour": "08:00","allow_shared_channels": false,"who_has_team_visibility": "ra","who_can_create_delete_user_groups": "admin","who_can_edit_user_groups": "admin","who_can_change_team_profile": "admin","retention_type": 0,"retention_duration": 0,"group_retention_type": 0,"group_retention_duration": 0,"dm_retention_type": 0,"dm_retention_duration": 0,"file_retention_type": 0,"file_retention_duration": 0,"allow_retention_override": true,"require_at_for_mention": 0,"compliance_export_start": 0,"invites_only_admins": true,"auth_mode": "normal"},"icon": {"image_34": "https://slack.global.ssl.fastly.net/66f9/img/avatars-teams/ava_0008-34.png","image_44": "https://slack.global.ssl.fastly.net/66f9/img/avatars-teams/ava_0008-44.png","image_68": "https://slack.global.ssl.fastly.net/66f9/img/avatars-teams/ava_0008-68.png","image_88": "https://slack.global.ssl.fastly.net/66f9/img/avatars-teams/ava_0008-88.png","image_102": "https://slack.global.ssl.fastly.net/66f9/img/avatars-teams/ava_0008-102.png","image_132": "https://slack.global.ssl.fastly.net/66f9/img/avatars-teams/ava_0008-132.png","image_default": true},"over_storage_limit": false,"plan": "","over_integrations_limit": true},"latest_event_ts": "1454301277.000000","channels": [{"id": "C0GEN123X","name": "general","is_channel": true,"created": 1449006552,"creator": "U0GLEUCH1","is_archived": false,"is_general": true,"has_pins": false,"is_member": true,"last_read": "1452885703.000003","latest": {"type": "message","user": "U0GLEUCH1","text": "Hello","ts": "1454301402.000005"},"unread_count": 116,"unread_count_display": 85,"members": ["U0GLEUCH1"],"topic": {"value": "Company-wide announcements and work-based matters","creator": "","last_set": 0},"purpose": {"value": "This channel is for team-wide communication and announcements. All team members are in this channel.","creator": "","last_set": 0}},{"id": "C0RND123X","name": "random","is_channel": true,"created": 1449006552,"creator": "U0GLEUCH1","is_archived": false,"is_general": false,"has_pins": false,"is_member": false}],"groups": [],"ims": [],"cache_ts": 1454301877,"subteams": {"self": [],"all": []},"dnd": {"dnd_enabled": false,"next_dnd_start_ts": 1,"next_dnd_end_ts": 1,"snooze_enabled": false},"users": [{"id": "U0GLEUCH1","team_id": "T0ABC123D","name": "gleuch","deleted": false,"status": null,"color": "9f69e7","real_name": "","tz": "America/Indiana/Indianapolis","tz_label": "Eastern Standard Time","tz_offset": -18000,"profile": {"avatar_hash": "g2008a0f04b2","real_name": "","real_name_normalized": "","email": "greg@betaworks.com","image_24": "https://secure.gravatar.com/avatar/2008a0f04b2a447fdf984e0ff3a5c8ae.jpg?s=24&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0023-24.png","image_32": "https://secure.gravatar.com/avatar/2008a0f04b2a447fdf984e0ff3a5c8ae.jpg?s=32&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0023-32.png","image_48": "https://secure.gravatar.com/avatar/2008a0f04b2a447fdf984e0ff3a5c8ae.jpg?s=48&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0023-48.png","image_72": "https://secure.gravatar.com/avatar/2008a0f04b2a447fdf984e0ff3a5c8ae.jpg?s=72&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F3654%2Fimg%2Favatars%2Fava_0023-72.png","image_192": "https://secure.gravatar.com/avatar/2008a0f04b2a447fdf984e0ff3a5c8ae.jpg?s=192&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0023-192.png","image_512": "https://secure.gravatar.com/avatar/2008a0f04b2a447fdf984e0ff3a5c8ae.jpg?s=512&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0023-512.png","fields": null},"is_admin": true,"is_owner": true,"is_primary_owner": true,"is_restricted": false,"is_ultra_restricted": false,"is_bot": false,"presence": "active"},{"id": "USLACKBOT","team_id": "T0ABC123D","name": "slackbot","deleted": false,"status": null,"color": "757575","real_name": "slackbot","tz": null,"tz_label": "Pacific Standard Time","tz_offset": -28800,"profile": {"first_name": "slackbot","last_name": "","image_24": "https://slack.global.ssl.fastly.net/0180/img/slackbot_24.png","image_32": "https://slack.global.ssl.fastly.net/66f9/img/slackbot_32.png","image_48": "https://slack.global.ssl.fastly.net/66f9/img/slackbot_48.png","image_72": "https://slack.global.ssl.fastly.net/0180/img/slackbot_72.png","image_192": "https://slack.global.ssl.fastly.net/66f9/img/slackbot_192.png","image_512": "https://slack.global.ssl.fastly.net/7fa9/img/slackbot_512.png","avatar_hash": "sv1444671949","real_name": "slackbot","real_name_normalized": "slackbot","email": null,"fields": null},"is_admin": false,"is_owner": false,"is_primary_owner": false,"is_restricted": false,"is_ultra_restricted": false,"is_bot": false,"presence": "active"}],"cache_version": "v12-rats","cache_ts_version": "v1-cat","bots": [{"id": "B0PLUS001","deleted": false,"name": "PlusPlus++","icons": {"image_36": "https://s3-us-west-2.amazonaws.com/slack-files2/avatars/2015-11-30/15612991041_8858260d7d5e37f0c994_36.jpg","image_48": "https://s3-us-west-2.amazonaws.com/slack-files2/avatars/2015-11-30/15612991041_8858260d7d5e37f0c994_48.jpg","image_72": "https://s3-us-west-2.amazonaws.com/slack-files2/avatars/2015-11-30/15612991041_8858260d7d5e37f0c994_72.jpg"}}],"url": "wss://ms001.slack-msgs.com/websocket/abc123xox=="}'
58
+ http_version:
59
+ recorded_at: Mon, 01 Feb 2016 04:44:44 GMT
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'client integration test', skip: !ENV['SLACK_API_TOKEN'] && 'missing SLACK_API_TOKEN' do
4
+ around do |ex|
5
+ WebMock.allow_net_connect!
6
+ VCR.turned_off { ex.run }
7
+ WebMock.disable_net_connect!
8
+ end
9
+
10
+ before do
11
+ Thread.abort_on_exception = true
12
+
13
+ SlackBotManager::Config.reset
14
+ SlackBotManager::Client.configure do |config|
15
+ config.log_level = ::Logger::WARN
16
+ end
17
+ end
18
+
19
+ after do
20
+ SlackBotManager::Config.reset
21
+ end
22
+
23
+ it 'client connection' do
24
+ conn = SlackBotManager::Client.new(ENV['SLACK_API_TOKEN'])
25
+ conn.connect
26
+ sleep 2
27
+ fail unless conn.connected?
28
+ fail if !conn.id || conn.id.empty?
29
+ conn.disconnect
30
+ sleep 2
31
+ fail unless conn.disconnected?
32
+ sleep 2
33
+ end
34
+
35
+ context 'with commands' do
36
+ let(:conn) { SlackBotManager::Client.new(ENV['SLACK_API_TOKEN']) }
37
+
38
+ after do
39
+ conn.off :hello
40
+ conn.off :message
41
+ end
42
+
43
+ it 'can handle special commands' do
44
+ hello = "Hello #{Time.now.to_i}"
45
+
46
+ # On hello, say hello
47
+ conn.on :hello do |_|
48
+ channel = client_channels.keys.first
49
+ send_message(channel, hello)
50
+ end
51
+
52
+ # Disconnect if message is not hello
53
+ conn.on :message do |_|
54
+ disconnect
55
+ end
56
+
57
+ conn.connect
58
+ sleep 3
59
+ fail if conn.connected?
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'manager integration test', skip: !ENV['SLACK_API_TOKEN'] && 'missing SLACK_API_TOKEN' do
4
+ around do |ex|
5
+ WebMock.allow_net_connect!
6
+ VCR.turned_off { ex.run }
7
+ WebMock.disable_net_connect!
8
+ end
9
+
10
+ before do
11
+ Thread.abort_on_exception = true
12
+
13
+ # Set quicker check interval
14
+ SlackBotManager::Config.reset
15
+ SlackBotManager::Manager.configure do |config|
16
+ config.check_interval = 1 # check every second while in spec mode
17
+ config.log_level = ::Logger::FATAL
18
+ end
19
+ end
20
+
21
+ after do
22
+ SlackBotManager::Config.reset
23
+ end
24
+
25
+ let(:manager) { SlackBotManager::Manager.new }
26
+
27
+ let(:thread) { nil }
28
+
29
+ # Start and run monitor in thread
30
+ def start_manager
31
+ manager.start
32
+ thread = Thread.new { manager.monitor }
33
+ end
34
+
35
+ def stop_manager
36
+ manager.stop
37
+ thread.exit
38
+ rescue
39
+ nil
40
+ end
41
+
42
+ context 'using storage' do
43
+ [:Redis, :Dalli].each do |store|
44
+ context store.to_s do
45
+ before do
46
+ SlackBotManager::Manager.configure do |config|
47
+ config.storage_method = SlackBotManager::Storage.const_get(store)
48
+ end
49
+ end
50
+
51
+ it 'can add, check, update, and remove a token' do
52
+ expect(manager.add_token(ENV['SLACK_API_TOKEN'])).to eq [true]
53
+ expect(manager.check_token(ENV['SLACK_API_TOKEN'])).to eq [true]
54
+ expect(manager.update_token(ENV['SLACK_API_TOKEN'])).to eq [true]
55
+ expect(manager.remove_token(ENV['SLACK_API_TOKEN'])).to eq [true]
56
+ expect(manager.remove_token(ENV['SLACK_API_TOKEN'])).to eq [false]
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'manager started' do
63
+ context 'with client token' do
64
+ # Start manager, remove token on complete
65
+ before { start_manager }
66
+ after { stop_manager }
67
+
68
+ it 'can add, check, update, and remove a token' do
69
+ # Add and remove
70
+ manager.add_token ENV['SLACK_API_TOKEN']
71
+ sleep 2
72
+ manager.remove_token ENV['SLACK_API_TOKEN']
73
+ sleep 2
74
+
75
+ # Add and check status
76
+ manager.add_token ENV['SLACK_API_TOKEN']
77
+ sleep 2
78
+ status = manager.check_token ENV['SLACK_API_TOKEN']
79
+ fail if !status || status.empty?
80
+ sleep 2
81
+
82
+ # Update token and remove
83
+ manager.update_token ENV['SLACK_API_TOKEN']
84
+ sleep 2
85
+ manager.remove_token ENV['SLACK_API_TOKEN']
86
+ end
87
+ end
88
+
89
+ context 'with commands' do
90
+ # Add/remove tokens to have it do RTM/WSS handshakes
91
+ before { manager.add_token ENV['SLACK_API_TOKEN'] }
92
+ after { manager.remove_token ENV['SLACK_API_TOKEN'] }
93
+
94
+ it 'start' do
95
+ manager.start
96
+ end
97
+ it 'stop' do
98
+ manager.start
99
+ sleep 2
100
+ manager.stop
101
+ end
102
+ it 'restart' do
103
+ manager.start
104
+ sleep 2
105
+ manager.restart
106
+ end
107
+ it 'monitor' do
108
+ manager.start
109
+ thread = Thread.new { manager.monitor }
110
+ # Let it run for a few seconds before killing
111
+ sleep 2
112
+ fail unless thread.status # nil or false means error
113
+ thread.exit
114
+ end
115
+ it 'status' do
116
+ manager.start
117
+ manager.status
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe SlackBotManager::Client, vcr: { cassette_name: 'web/rtm_start' } do
4
+ let(:url) { 'wss://ms001.slack-msgs.com/websocket/abc123xox==' }
5
+
6
+ before do
7
+ @token = ENV.delete('SLACK_API_TOKEN')
8
+
9
+ SlackBotManager::Config.reset
10
+ SlackBotManager::Client.configure do |config|
11
+ config.log_level = ::Logger::WARN
12
+ end
13
+ end
14
+
15
+ after do
16
+ ENV['SLACK_API_TOKEN'] = @token if @token
17
+ end
18
+
19
+ context 'iniitalize' do
20
+ it 'requires a token' do
21
+ client = SlackBotManager::Client.new('xoxb-abc123def456')
22
+ expect(client.token).to eq 'xoxb-abc123def456'
23
+ end
24
+ it 'be disconnected' do
25
+ client = SlackBotManager::Client.new('xoxb-abc123def456')
26
+ expect(client.status).to eq :disconnected
27
+ end
28
+ end
29
+
30
+ context 'connect' do
31
+ it 'should succeed' do
32
+ client = SlackBotManager::Client.new(@token)
33
+ expect(client.connect).to eq :connected
34
+ expect(client.connected?).to eq true
35
+ end
36
+ end
37
+
38
+ context 'disconnect' do
39
+ context 'should succeed' do
40
+ [nil, :disconnected, :token_revoked, :rate_limited, :another_reason].each do |reason|
41
+ it "on #{reason || 'nil'}" do
42
+ client = SlackBotManager::Client.new(@token)
43
+ client.connect
44
+ expect(client.disconnect(reason)).to eq true
45
+ expect(client.disconnected?).to eq true
46
+ expect(client.status).to eq(reason || :disconnected)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ context 'send message' do
53
+ context 'should succeed' do
54
+ let(:client) { SlackBotManager::Client.new(@token) }
55
+
56
+ it 'as socket message' do
57
+ client.connect
58
+ puts client.send_message('C123ABC', 'Hello!').inspect
59
+ end
60
+
61
+ it 'as post message'
62
+ it 'as post message with attachments'
63
+ end
64
+ end
65
+
66
+ context 'on/off methods' do
67
+ it 'should succeed' do
68
+ client = SlackBotManager::Client.new(@token)
69
+ client.on :hello do
70
+ return true
71
+ end
72
+ expect(client.respond_to?(:on_hello)).to be true
73
+ expect(client.on_hello).to be true
74
+ client.off :hello
75
+ expect(client.respond_to?(:on_hello)).to be false
76
+ end
77
+ end
78
+
79
+ context 'client methods' do
80
+ let(:client) { SlackBotManager::Client.new(@token) }
81
+
82
+ SlackBotManager::Config::RTM_CLIENT_METHODS.each do |name|
83
+ it "on #{name}" do
84
+ client = SlackBotManager::Client.new(@token)
85
+ client.connect
86
+
87
+ case name
88
+ when :url
89
+ expect(client.send("client_#{name}")).to eq(url)
90
+ else
91
+ expect(client.send("client_#{name}")).to be_an(Object)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBotManager::Config do
4
+ describe '#configure' do
5
+ before do
6
+ SlackBotManager.configure do |config|
7
+ config.verbose = true
8
+ end
9
+ end
10
+
11
+ after do
12
+ SlackBotManager::Config.reset
13
+ end
14
+
15
+ it 'sets verbose mode' do
16
+ expect(SlackBotManager.config.verbose).to eq true
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBotManager::Errors do
4
+ # TODO
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBotManager do
4
+ # TODO
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBotManager::Logger do
4
+ # TODO
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe SlackBotManager do
4
+ it 'has a version' do
5
+ expect(SlackBotManager::VERSION).to_not be nil
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
2
+
3
+ require 'rubygems'
4
+ require 'rspec'
5
+
6
+ require 'slack-bot-manager'
7
+
8
+ Dir[File.join(File.dirname(__FILE__), 'support', '**/*.rb')].each do |file|
9
+ require file
10
+ end
@@ -0,0 +1,8 @@
1
+ require 'vcr'
2
+
3
+ VCR.configure do |config|
4
+ config.cassette_library_dir = 'spec/fixtures/slack-bot-manager'
5
+ config.hook_into :webmock
6
+ config.default_cassette_options = { record: :new_episodes }
7
+ config.configure_rspec_metadata!
8
+ end