slack-ruby-client 0.4.0 → 0.5.0

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -1
  3. data/.rubocop_todo.yml +23 -6
  4. data/.travis.yml +3 -0
  5. data/CHANGELOG.md +11 -0
  6. data/Gemfile +2 -0
  7. data/README.md +89 -1
  8. data/RELEASING.md +3 -1
  9. data/UPGRADING.md +26 -0
  10. data/bin/commands.rb +20 -0
  11. data/bin/commands/api.rb +14 -0
  12. data/bin/commands/auth.rb +12 -0
  13. data/bin/commands/channels.rb +140 -0
  14. data/bin/commands/chat.rb +47 -0
  15. data/bin/commands/emoji.rb +12 -0
  16. data/bin/commands/files.rb +61 -0
  17. data/bin/commands/groups.rb +158 -0
  18. data/bin/commands/im.rb +53 -0
  19. data/bin/commands/mpim.rb +53 -0
  20. data/bin/commands/oauth.rb +16 -0
  21. data/bin/commands/pins.rb +37 -0
  22. data/bin/commands/reactions.rb +53 -0
  23. data/bin/commands/rtm.rb +15 -0
  24. data/bin/commands/search.rb +40 -0
  25. data/bin/commands/stars.rb +37 -0
  26. data/bin/commands/team.rb +32 -0
  27. data/bin/commands/usergroups.rb +73 -0
  28. data/bin/commands/users.rb +48 -0
  29. data/bin/slack +50 -0
  30. data/examples/hi_real_time/Gemfile +2 -0
  31. data/examples/hi_real_time_and_web/Gemfile +2 -0
  32. data/examples/hi_real_time_async/Gemfile +5 -0
  33. data/examples/hi_real_time_async/hi.rb +29 -0
  34. data/lib/slack-ruby-client.rb +2 -2
  35. data/lib/slack/real_time/client.rb +72 -30
  36. data/lib/slack/real_time/concurrency.rb +8 -0
  37. data/lib/slack/real_time/concurrency/celluloid.rb +92 -0
  38. data/lib/slack/real_time/concurrency/eventmachine.rb +39 -0
  39. data/lib/slack/real_time/config.rb +23 -1
  40. data/lib/slack/real_time/socket.rb +50 -12
  41. data/lib/slack/version.rb +1 -1
  42. data/lib/slack/web/api/endpoints.rb +2 -0
  43. data/lib/slack/web/api/endpoints/groups.rb +1 -1
  44. data/lib/slack/web/api/endpoints/team.rb +1 -1
  45. data/lib/slack/web/api/endpoints/usergroups.rb +113 -0
  46. data/lib/slack/web/api/error.rb +6 -0
  47. data/lib/slack/web/api/schema/group.json +14 -0
  48. data/lib/slack/web/api/tasks/generate.rake +19 -3
  49. data/lib/slack/web/api/templates/command.erb +34 -0
  50. data/lib/slack/web/api/templates/commands.erb +5 -0
  51. data/lib/slack/web/config.rb +2 -0
  52. data/lib/slack/web/faraday/connection.rb +3 -2
  53. data/lib/slack/web/faraday/response/raise_error.rb +2 -1
  54. data/slack-ruby-client.gemspec +4 -2
  55. data/spec/fixtures/slack/web/429_error.yml +83 -0
  56. data/spec/fixtures/slack/web/rtm_start.yml +1 -1
  57. data/spec/fixtures/slack/web/users_list.yml +72 -0
  58. data/spec/integration/integration_spec.rb +88 -0
  59. data/spec/slack/real_time/client_spec.rb +8 -5
  60. data/spec/slack/real_time/concurrency/celluloid_spec.rb +58 -0
  61. data/spec/slack/real_time/concurrency/eventmachine_spec.rb +49 -0
  62. data/spec/slack/slack_spec.rb +52 -0
  63. data/spec/slack/web/api/endpoints/auth_spec.rb +6 -1
  64. data/spec/slack/web/api/endpoints/users_spec.rb +13 -0
  65. data/spec/slack/web/api/error_spec.rb +14 -0
  66. data/spec/slack/web/client_spec.rb +16 -0
  67. data/spec/support/real_time/concurrency/mock.rb +31 -0
  68. data/spec/support/real_time/connected_client.rb +5 -2
  69. metadata +55 -8
  70. data/spec/slack/real_time/socket_spec.rb +0 -46
@@ -13,8 +13,16 @@ namespace :slack do
13
13
 
14
14
  desc 'Update API.'
15
15
  task update: [:git_update] do
16
+ group_schema = JSON.parse(File.read('lib/slack/web/api/schema/group.json'))
17
+ groups = Dir.glob('lib/slack/web/api/slack-api-ref/groups/**/*.json').each_with_object({}) do |path, result|
18
+ name = File.basename(path, '.json')
19
+ parsed = JSON.parse(File.read(path))
20
+ JSON::Validator.validate(group_schema, parsed, insert_defaults: true)
21
+ result[name] = parsed
22
+ end
23
+
16
24
  method_schema = JSON.parse(File.read('lib/slack/web/api/schema/method.json'))
17
- data = Dir.glob('lib/slack/web/api/slack-api-ref/methods/*.json').each_with_object({}) do |path, result|
25
+ data = Dir.glob('lib/slack/web/api/slack-api-ref/methods/**/*.json').each_with_object({}) do |path, result|
18
26
  name = File.basename(path, '.json')
19
27
  prefix, name = name.split('.')
20
28
  result[prefix] ||= {}
@@ -24,18 +32,26 @@ namespace :slack do
24
32
  end
25
33
 
26
34
  method_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/method.erb'))
35
+ command_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/command.erb'))
27
36
  data.each_with_index do |(group, names), index|
28
37
  printf "%2d/%2d %10s %s\n", index, data.size, group, names.keys
29
- rendered = method_template.result(group: group, names: names)
30
- File.write "lib/slack/web/api/endpoints/#{group}.rb", rendered
38
+ # method
39
+ rendered_method = method_template.result(group: group, names: names)
40
+ File.write "lib/slack/web/api/endpoints/#{group}.rb", rendered_method
31
41
  Dir.glob("lib/slack/web/api/patches/#{group}*.patch").sort.each do |patch|
32
42
  puts "- patching #{patch}"
33
43
  system("git apply #{patch}") || fail('failed to apply patch')
34
44
  end
45
+ # command
46
+ rendered_command = command_template.result(group: groups[group], names: names)
47
+ File.write "bin/commands/#{group}.rb", rendered_command
35
48
  end
36
49
 
37
50
  endpoints_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/endpoints.erb'))
38
51
  File.write 'lib/slack/web/api/endpoints.rb', endpoints_template.result(files: data.keys)
52
+
53
+ commands_template = Erubis::Eruby.new(File.read('lib/slack/web/api/templates/commands.erb'))
54
+ File.write 'bin/commands.rb', commands_template.result(files: data.keys)
39
55
  end
40
56
  end
41
57
  end
@@ -0,0 +1,34 @@
1
+ # This file was auto-generated by lib/slack/web/api/tasks/generate.rake
2
+
3
+ <% desc = group['desc'] || "#{group['name'].capitalize} methods." %>
4
+ <% if desc.include?("'") %>
5
+ desc "<%= desc %>"
6
+ <% else %>
7
+ desc '<%= desc %>'
8
+ <% end %>
9
+ command '<%= group['name'] %>' do |g|
10
+ <% names.each_with_index do |(name, data), index| %>
11
+ <% if index > 0 %>
12
+
13
+ <% end %>
14
+ <% short_desc = data["desc"].split("\n").first %>
15
+ <% if short_desc.include?("'") %>
16
+ g.desc "<%= short_desc %>"
17
+ <% else %>
18
+ g.desc '<%= short_desc %>'
19
+ <% end %>
20
+ g.long_desc %( <%= data["desc"].split("\n").join(" ") %> )
21
+ g.command '<%= name %>' do |c|
22
+ <% data["args"].each do |arg_name, arg_v| %>
23
+ <% if arg_v["desc"].include?("'") %>
24
+ c.flag '<%= arg_name %>', desc: "<%= arg_v["desc"] %>"
25
+ <% else %>
26
+ c.flag '<%= arg_name %>', desc: '<%= arg_v["desc"] %>'
27
+ <% end %>
28
+ <% end %>
29
+ c.action do |_global_options, options, _args|
30
+ puts JSON.dump($client.<%=group['name'] %>_<%= name %>(options))
31
+ end
32
+ end
33
+ <% end %>
34
+ end
@@ -0,0 +1,5 @@
1
+ # This file was auto-generated by lib/slack/web/api/tasks/generate.rake
2
+
3
+ <% files.each do |f| %>
4
+ require 'commands/<%= f %>'
5
+ <% end %>
@@ -8,6 +8,7 @@ module Slack
8
8
  :user_agent,
9
9
  :ca_path,
10
10
  :ca_file,
11
+ :logger,
11
12
  :endpoint,
12
13
  :token
13
14
  ]
@@ -21,6 +22,7 @@ module Slack
21
22
  self.ca_file = "#{ca_path}/ca-certificates.crt"
22
23
  self.token = nil
23
24
  self.proxy = nil
25
+ self.logger = nil
24
26
  end
25
27
  end
26
28
 
@@ -16,10 +16,11 @@ module Slack
16
16
  ::Faraday::Connection.new(endpoint, options) do |connection|
17
17
  connection.use ::Faraday::Request::Multipart
18
18
  connection.use ::Faraday::Request::UrlEncoded
19
- connection.use ::Faraday::Response::RaiseError
20
19
  connection.use ::Slack::Web::Faraday::Response::RaiseError
21
20
  connection.use ::FaradayMiddleware::ParseJson
22
- connection.adapter(::Faraday.default_adapter)
21
+ connection.use ::Faraday::Response::RaiseError
22
+ connection.response :logger, logger if logger
23
+ connection.adapter ::Faraday.default_adapter
23
24
  end
24
25
  end
25
26
  end
@@ -5,7 +5,8 @@ module Slack
5
5
  class RaiseError < ::Faraday::Response::Middleware
6
6
  def on_complete(env)
7
7
  body = env.body
8
- fail Slack::Web::Api::Error, body['error'] unless body['ok']
8
+ return if body['ok']
9
+ fail Slack::Web::Api::Error.new(body['error'], env.response)
9
10
  end
10
11
  end
11
12
  end
@@ -3,6 +3,8 @@ require 'slack/version'
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'slack-ruby-client'
6
+ s.bindir = 'bin'
7
+ s.executables << 'slack'
6
8
  s.version = Slack::VERSION
7
9
  s.authors = ['Daniel Doubrovkine']
8
10
  s.email = 'dblock@dblock.org'
@@ -16,9 +18,9 @@ Gem::Specification.new do |s|
16
18
  s.summary = 'Slack Web and RealTime API client.'
17
19
  s.add_dependency 'faraday'
18
20
  s.add_dependency 'faraday_middleware'
19
- s.add_dependency 'faye-websocket'
20
- s.add_dependency 'eventmachine'
21
21
  s.add_dependency 'json'
22
+ s.add_dependency 'websocket-driver'
23
+ s.add_dependency 'gli'
22
24
  s.add_development_dependency 'erubis'
23
25
  s.add_development_dependency 'json-schema'
24
26
  s.add_development_dependency 'rake'
@@ -0,0 +1,83 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://slack.com/api/auth.test
6
+ body:
7
+ encoding: UTF-8
8
+ string: token=
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ User-Agent:
13
+ - Slack Ruby Client 0.1.0
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: 429
21
+ message: OK
22
+ headers:
23
+ Access-Control-Allow-Origin:
24
+ - '*'
25
+ Date:
26
+ - Sat, 25 Jul 2015 14:42:07 GMT
27
+ Server:
28
+ - Apache
29
+ Connection:
30
+ - keep-alive
31
+ body:
32
+ encoding: US-ASCII
33
+ string: ''
34
+ http_version:
35
+ recorded_at: Sat, 25 Jul 2015 14:42:08 GMT
36
+ - request:
37
+ method: post
38
+ uri: https://slack.com/api/auth.test
39
+ body:
40
+ encoding: UTF-8
41
+ string: token
42
+ headers:
43
+ Accept:
44
+ - application/json; charset=utf-8
45
+ User-Agent:
46
+ - Slack Ruby Client/0.5.0
47
+ Content-Type:
48
+ - application/x-www-form-urlencoded
49
+ Accept-Encoding:
50
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
51
+ response:
52
+ status:
53
+ code: 200
54
+ message: OK
55
+ headers:
56
+ Access-Control-Allow-Origin:
57
+ - '*'
58
+ Content-Security-Policy:
59
+ - referrer no-referrer;
60
+ Content-Type:
61
+ - application/json; charset=utf-8
62
+ Date:
63
+ - Tue, 24 Nov 2015 20:03:05 GMT
64
+ Server:
65
+ - Apache
66
+ Strict-Transport-Security:
67
+ - max-age=31536000; includeSubDomains; preload
68
+ X-Accepted-Oauth-Scopes:
69
+ - identify
70
+ X-Content-Type-Options:
71
+ - nosniff
72
+ X-Xss-Protection:
73
+ - '0'
74
+ Content-Length:
75
+ - '33'
76
+ Connection:
77
+ - keep-alive
78
+ body:
79
+ encoding: UTF-8
80
+ string: '{"ok":false,"error":"not_authed"}'
81
+ http_version:
82
+ recorded_at: Tue, 24 Nov 2015 20:03:05 GMT
83
+ recorded_with: VCR 2.9.3
@@ -5,7 +5,7 @@ http_interactions:
5
5
  uri: https://slack.com/api/rtm.start
6
6
  body:
7
7
  encoding: UTF-8
8
- string: token=xoxb-7171717171-ABCDEFGhIJ2lZifrEaQP5vF4
8
+ string: token=token
9
9
  headers:
10
10
  Accept:
11
11
  - application/json; charset=utf-8
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://slack.com/api/users.list
6
+ body:
7
+ encoding: UTF-8
8
+ string: presence=true&token=token
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ User-Agent:
13
+ - Slack Ruby Client/0.5.0
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
+ - Sun, 06 Dec 2015 20:18:45 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
+ - users:read,read
45
+ X-Content-Type-Options:
46
+ - nosniff
47
+ X-Oauth-Scopes:
48
+ - identify,read,post,client
49
+ X-Xss-Protection:
50
+ - '0'
51
+ Content-Length:
52
+ - '1450'
53
+ Connection:
54
+ - keep-alive
55
+ body:
56
+ encoding: ASCII-8BIT
57
+ string: '{"ok":true,"members":[{"id":"U092BDCLV","team_id":"T04KB5WQH","name":"artsy","deleted":false,"status":null,"color":"e0a729","real_name":"Artsy
58
+ Bot","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B092B5DDG","image_24":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_512":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_1024":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-08-13\/9080316676_7bbab49314a0429c7f7d_original.jpg","first_name":"Artsy","last_name":"Bot","title":"Searches
59
+ Artsy.","real_name":"Artsy Bot","real_name_normalized":"Artsy Bot"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U07KECJ77","team_id":"T04KB5WQH","name":"aws","deleted":false,"status":null,"color":"e96699","real_name":"AWS
60
+ Cloud","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B07KECJ6R","image_24":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-07-14\/7660472085_4755a86e204c9706c84f_original.jpg","first_name":"AWS","last_name":"Cloud","real_name":"AWS
61
+ Cloud","real_name_normalized":"AWS Cloud"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U0EA7TZJN","team_id":"T04KB5WQH","name":"bar","deleted":false,"status":null,"color":"5b89d5","real_name":"","tz":null,"tz_label":"Pacific
62
+ Standard Time","tz_offset":-28800,"profile":{"bot_id":"B0EA31LQM","image_24":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_72.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_192.jpg","image_512":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_512.jpg","image_1024":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_512.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-11-11\/14346833313_f359ba59a1211d17912b_original.jpg","real_name":"","real_name_normalized":""},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U092V4E9L","team_id":"T04KB5WQH","name":"broskoski","deleted":false,"status":null,"color":"684b6c","real_name":"Cab","tz":"America\/Indiana\/Indianapolis","tz_label":"Eastern
63
+ Standard Time","tz_offset":-18000,"profile":{"first_name":"Cab","real_name":"Cab","real_name_normalized":"Cab","email":"cab@artsymail.com","image_24":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=24&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=32&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=48&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=72&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0017-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=192&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0017-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/99621cbca6ea94706a8f5dcdc5e8af4a.jpg?s=512&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0017-512.png"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"presence":"away"},{"id":"U04KB5WQR","team_id":"T04KB5WQH","name":"example","deleted":false,"status":null,"color":"9f69e7","real_name":"","tz":"America\/Indiana\/Indianapolis","tz_label":"Eastern
64
+ Standard Time","tz_offset":-18000,"profile":{"real_name":"","real_name_normalized":"","email":"user@example.org","image_24":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=24&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-24.png","image_32":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=32&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-32.png","image_48":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=48&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-48.png","image_72":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=72&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F66f9%2Fimg%2Favatars%2Fava_0015-72.png","image_192":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=192&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0015-192.png","image_512":"https:\/\/secure.gravatar.com\/avatar\/3d925b45ac07ec0ae5bd04888f6c5b61.jpg?s=512&d=https%3A%2F%2Fslack.global.ssl.fastly.net%2F7fa9%2Fimg%2Favatars%2Fava_0015-512.png"},"is_admin":true,"is_owner":true,"is_primary_owner":true,"is_restricted":false,"is_ultra_restricted":false,"is_bot":false,"presence":"active"},{"id":"U04JZBDQQ","team_id":"T04KB5WQH","name":"foo","deleted":true,"profile":{"bot_id":"B04JZBDQC","image_24":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_72.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_192.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4645387956_44604ca32e800d947f22_original.jpg","real_name":"","real_name_normalized":""},"is_bot":true,"presence":"away"},{"id":"U04JPQ0JS","team_id":"T04KB5WQH","name":"gamebot","deleted":false,"status":null,"color":"4bbe2e","real_name":"Game
65
+ Bot","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B04JPQ0JE","image_24":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-04-28\/4635825662_28d3661bf00dc6013442_original.jpg","first_name":"Game","last_name":"Bot","title":"Game
66
+ ons.","real_name":"Game Bot","real_name_normalized":"Game Bot"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U06JGTU5V","team_id":"T04KB5WQH","name":"mathbot","deleted":false,"status":null,"color":"3c989f","real_name":"Math
67
+ Bot","tz":null,"tz_label":"Pacific Standard Time","tz_offset":-28800,"profile":{"bot_id":"B06JH1N93","image_24":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-06-19\/6629501812_c507c80d735dfc75bbc8_original.jpg","first_name":"Math","last_name":"Bot","real_name":"Math
68
+ Bot","real_name_normalized":"Math Bot"},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"},{"id":"U07518DTL","team_id":"T04KB5WQH","name":"rubybot","deleted":false,"status":null,"color":"674b1b","real_name":"","tz":null,"tz_label":"Pacific
69
+ Standard Time","tz_offset":-28800,"profile":{"bot_id":"B0751JU2H","image_24":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_24.jpg","image_32":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_32.jpg","image_48":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_48.jpg","image_72":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_48.jpg","image_192":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_48.jpg","image_original":"https:\/\/avatars.slack-edge.com\/2015-07-02\/7171641589_359bf095c1fe0841e582_original.jpg","real_name":"","real_name_normalized":""},"is_admin":false,"is_owner":false,"is_primary_owner":false,"is_restricted":false,"is_ultra_restricted":false,"is_bot":true,"presence":"away"}]}'
70
+ http_version:
71
+ recorded_at: Sun, 06 Dec 2015 20:18:46 GMT
72
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,88 @@
1
+ require 'slack'
2
+ require 'logger'
3
+
4
+ RSpec.describe 'integration test', skip: !ENV['SLACK_API_TOKEN'] && 'missing SLACK_API_TOKEN' do
5
+ before do
6
+ Thread.abort_on_exception = true
7
+ end
8
+
9
+ let(:logger) { Logger.new(STDOUT) }
10
+
11
+ let(:queue) { Queue.new }
12
+
13
+ let(:client) { Slack::RealTime::Client.new(token: ENV['SLACK_API_TOKEN']) }
14
+
15
+ let(:connection) do
16
+ # starts the client and pushes an item on a queue when connected
17
+ client.start_async do |driver|
18
+ driver.on :open do |data|
19
+ logger.debug "connection.on :open, data=#{data}"
20
+ queue.push nil
21
+ end
22
+ end
23
+ end
24
+
25
+ before do
26
+ client.on :hello do
27
+ logger.info "Successfully connected, welcome '#{client.self['name']}' to the '#{client.team['name']}' team at https://#{client.team['domain']}.slack.com."
28
+ end
29
+
30
+ client.on :close do
31
+ # pushes another item to the queue when disconnected
32
+ queue.push nil
33
+ end
34
+ end
35
+
36
+ def start_server
37
+ logger.debug '#start_server'
38
+ # start server and wait for on :open
39
+ c = connection
40
+ logger.debug "connection is #{c}"
41
+ queue.pop
42
+ end
43
+
44
+ def wait_for_server
45
+ logger.debug '#wait_for_server'
46
+ queue.pop
47
+ logger.debug '#wait_for_server, joined'
48
+ end
49
+
50
+ def stop_server
51
+ logger.debug '#stop_server'
52
+ client.stop!
53
+ logger.debug '#stop_server, stopped'
54
+ end
55
+
56
+ after do
57
+ wait_for_server
58
+ end
59
+
60
+ context 'client connected' do
61
+ before do
62
+ start_server
63
+ end
64
+
65
+ it 'responds to message' do
66
+ message = SecureRandom.hex
67
+
68
+ client.on :message do |data|
69
+ logger.debug data
70
+ expect(data).to include('text' => message, 'subtype' => 'bot_message')
71
+ logger.debug 'client.stop!'
72
+ client.stop!
73
+ end
74
+
75
+ logger.debug "chat_postMessage, channel=@#{client.self['name']}, message=#{message}"
76
+ client.web_client.chat_postMessage channel: "@#{client.self['name']}", text: message
77
+ end
78
+ end
79
+
80
+ it 'gets hello' do
81
+ client.on :hello do |data|
82
+ logger.debug "client.on :hello, data=#{data}"
83
+ client.stop!
84
+ end
85
+
86
+ start_server
87
+ end
88
+ end
@@ -1,10 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' } do
4
- let(:ws) { double(Faye::WebSocket::Client, on: true) }
4
+ let(:ws) { double(Slack::RealTime::Concurrency::Mock::WebSocket, on: true) }
5
5
  let(:url) { 'wss://ms173.slack-msgs.com/websocket/lqcUiAvrKTP-uuid=' }
6
6
  before do
7
- allow(EM).to receive(:run).and_yield
7
+ Slack::RealTime.configure do |config|
8
+ config.concurrency = Slack::RealTime::Concurrency::Mock
9
+ end
8
10
  end
9
11
  context 'token' do
10
12
  before do
@@ -42,7 +44,8 @@ RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' }
42
44
  let(:socket) { double(Slack::RealTime::Socket, connected?: true) }
43
45
  before do
44
46
  allow(Slack::RealTime::Socket).to receive(:new).with(url, ping: 30).and_return(socket)
45
- allow(socket).to receive(:connect!).and_yield(ws)
47
+ allow(socket).to receive(:connect!)
48
+ allow(socket).to receive(:start_sync).and_yield
46
49
  client.start!
47
50
  end
48
51
  context 'properties provided upon connection' do
@@ -151,7 +154,7 @@ RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' }
151
154
  expect(client.websocket_ping).to eq 15
152
155
  end
153
156
  it 'creates a connection with custom ping' do
154
- expect(Faye::WebSocket::Client).to receive(:new).with(url, nil, ping: 15).and_return(ws)
157
+ expect(Slack::RealTime::Concurrency::Mock::WebSocket).to receive(:new).with(url, nil, ping: 15).and_return(ws)
155
158
  client.start!
156
159
  end
157
160
  end
@@ -173,7 +176,7 @@ RSpec.describe Slack::RealTime::Client, vcr: { cassette_name: 'web/rtm_start' }
173
176
  )
174
177
  end
175
178
  it 'creates a connection with custom proxy' do
176
- expect(Faye::WebSocket::Client).to receive(:new).with(
179
+ expect(Slack::RealTime::Concurrency::Mock::WebSocket).to receive(:new).with(
177
180
  url,
178
181
  nil,
179
182
  ping: 30,