slack-bot-manager 0.1.0pre1 → 0.1.0pre2

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 (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