websockethook 0.1.0 → 0.1.01

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a598958034d0bc23bffba798c4e79791c6101441
4
- data.tar.gz: de4ba13cfc67d63f6fe9de5e07bfa995273b7d1c
3
+ metadata.gz: dd91e0fc65cf4e459ff0657766ea34ac7a9f1d8e
4
+ data.tar.gz: 77ddfff2e872950d7621d7c58ac99ce9792f4e88
5
5
  SHA512:
6
- metadata.gz: 6b6726ea1ce6af24499f6fc3fa09798de312c3a368e789e3b447df55f62c31c5ade4546f5240c2a8dcec81df54c30bb5dc35339aab183a4edc901831ab430d3e
7
- data.tar.gz: 1ec3c17f5344aacdcb34d1a056e6b40b5084152d8a82053beed896ae3087cffc1001aa0b4eda7d06f1c74db638ce5f57aec1fb8ea666cea81ba279f214a3bd8d
6
+ metadata.gz: 93056aaea58aac3939e1fe79d083d2f6eaf2fd465a234dcd50b748eb421a12484837c8b828ecd27d407b3ae3b68c16d0a28378ae91f0933adbae6990dd371105
7
+ data.tar.gz: 6de885962949b5db7165709a3dfcfe7aae3d89de67ddd869a3a8a058ca117f4abb0af15753db30559c0083a4ecafae6d29543837ea17cc3ace456367aa52caf4
data/lib/websockethook.rb CHANGED
@@ -6,27 +6,18 @@ class WebSocketHook
6
6
  DEFAULT_HOST = 'ws://web.sockethook.io'
7
7
 
8
8
  def initialize(options = {})
9
- @host = options[:host] || DEFAULT_HOST
10
- @pause = options[:sleep] || 0.1
11
- @stay_alive = options[:stay_alive] || true
12
- @ping = options[:ping] || 20
13
- hooks = options[:hooks] || []
14
- @stopping = false
15
- @hooks = []
16
-
17
- raise 'Host (:host) must be a URL' unless @host.is_a?(String)
18
- raise 'Pause (:pause) must be a float or integer' unless @pause.is_a?(Float) || @pause.is_a?(Integer)
19
- raise 'Stay Alive (:stay_alive) must be a boolean (true/false)' unless @stay_alive == true || @stay_alive == false
20
- raise 'Ping (:ping) must be an integer' unless @ping.is_a?(Integer)
21
- raise 'Stopping (:stopping) must be boolean (true/false)' unless @stopping == true || @stopping == false
22
- raise 'Hooks (:hooks) must be an array' unless hooks.is_a?(Array)
23
-
24
- hooks.each {|hook| register(hook) }
9
+ @stopping = false
10
+ @hooks = []
11
+ initialize_host options
12
+ initialize_pause options
13
+ initialize_keep_alive options
14
+ initialize_ping options
15
+ initialize_hooks options
25
16
  end
26
17
 
27
18
  def register(id)
28
- raise "Hook id '#{id}' must be a String" unless id.is_a?(String)
29
- raise "Hook id must only be alphanumeric, '_', '.', or '_'" unless /^[a-zA-Z0-9\-_\.]*$/ === id
19
+ fail "Hook id '#{id}' must be a String" unless id.is_a?(String)
20
+ fail "Hook id must only be alphanumeric, '_', '.', or '_'" unless /^[a-zA-Z0-9\-_\.]*$/ === id
30
21
  @hooks << id unless @hooks.include?(id)
31
22
  end
32
23
 
@@ -35,13 +26,13 @@ class WebSocketHook
35
26
  end
36
27
 
37
28
  def listen(&block)
38
- raise 'Block must be provided' unless block && block.is_a?(Proc)
29
+ fail 'Block must be provided' unless block && block.is_a?(Proc)
39
30
  begin
40
31
  @stopping = false
41
32
  listener(&block)
42
- restart = @stay_alive && !@stopping
33
+ restart = @keep_alive && !@stopping
43
34
  if restart
44
- block.call type:'restart', message:'restarting connection since it was lost'
35
+ block.call type: 'restart', message: 'restarting connection since it was lost'
45
36
  sleep 5
46
37
  end
47
38
  end while restart
@@ -54,51 +45,79 @@ class WebSocketHook
54
45
 
55
46
  private
56
47
 
48
+ def initialize_host(options = {})
49
+ @host = options[:host] || DEFAULT_HOST
50
+ fail 'Host (:host) must be a URL' unless @host.is_a?(String)
51
+ end
52
+
53
+ def initialize_pause(options = {})
54
+ @pause = options[:sleep] || 0.1
55
+ fail 'Pause (:pause) must be a float or integer' unless @pause.is_a?(Float) || @pause.is_a?(Integer)
56
+ end
57
+
58
+ def initialize_keep_alive(options = {})
59
+ @keep_alive = options[:keep_alive] || true
60
+ fail 'Keep Alive (:keep_alive) must be a boolean (true/false)' unless @keep_alive == true || @keep_alive == false
61
+ end
62
+
63
+ def initialize_ping(options = {})
64
+ @ping = options[:ping] || 20
65
+ fail 'Ping (:ping) must be an integer' unless @ping.is_a?(Integer)
66
+ end
67
+
68
+ def initialize_hooks(options = {})
69
+ hooks = options[:hooks] || []
70
+ fail 'Hooks (:hooks) must be an array' unless hooks.is_a?(Array)
71
+ hooks.each { |hook| register(hook) }
72
+ end
73
+
57
74
  def stop_em
58
- begin
59
- EM.stop
60
- rescue
61
- end
75
+ EM.stop
76
+ rescue
62
77
  end
63
78
 
64
79
  def listener(&block)
65
- EM.run do
66
- ws_settings = {ping: @ping}
67
- ws = Faye::WebSocket::Client.new(@host, nil, ws_settings)
68
-
80
+ websocket(block) do |ws|
81
+ ws.on :open do
82
+ @hooks.each do |hook|
83
+ ws.send({type:'register',id:hook}.to_json)
84
+ end
85
+ end
69
86
  ws.on :message do |message|
70
87
  data = nil
71
88
  begin
72
- data = JSON.parse(message.data, symbolize_names:true)
89
+ data = JSON.parse(message.data, symbolize_names: true)
73
90
  rescue => ex
74
- block.call type:'error', message: "Message received, but couldn't parse: #{ex.message}"
91
+ block.call type: 'error', message: "Message received, but couldn't parse: #{ex.message}"
75
92
  end
76
- content = data.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo }
93
+ content = data.inject({}) { |memo, (k, v)| memo[k.to_sym] = v; memo }
94
+ data[:data][:url] = "#{@host.sub('ws://','http://')}#{data[:data][:path]}" if data[:type]=='registered' && data[:data] && data[:data][:path]
77
95
  block.call(content) if data && block
78
96
  end
79
97
 
80
- ws.on :open do
81
- block.call(type:'open') if block
82
- @hooks.each do |hook|
83
- ws.send({type:'register', id:hook}.to_json)
84
- end
85
- end
86
-
87
- ws.on :close do
88
- block.call(type:'close') if block
89
- stop_em
90
- end
98
+ handle_ws(ws, :error, block) { @hooks.each { |hook| ws.send({ type: 'register', id: hook }.to_json) } }
99
+ handle_ws(ws, :close, block) { stop_em }
100
+ handle_ws(ws, :error, block) { stop_em }
101
+ end
102
+ end
91
103
 
92
- ws.on :error do
93
- block.call(type:'error') if block
94
- stop_em
95
- end
104
+ def websocket(callback_block, &socket_block)
105
+ EM.run do
106
+ ws_settings = { ping: @ping }
107
+ ws = Faye::WebSocket::Client.new(@host, nil, ws_settings)
108
+ socket_block.call(ws)
96
109
  end
97
- block.call(type:'stopped')
110
+ callback_block.call(type: 'stopped')
98
111
  rescue => ex
99
- block.call type:'error', message:ex.message
112
+ callback_block.call type: 'error', message: ex.message
100
113
  rescue Interrupt
101
114
  stop
102
- block.call(type:'stopped')
115
+ callback_block.call(type: 'stopped')
116
+ end
117
+
118
+ def handle_ws(ws, action, callback_block, &_block)
119
+ ws.on action do
120
+ callback_block.call(type: action.to_s)
121
+ end
103
122
  end
104
- end
123
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,8 @@
1
- require "codeclimate-test-reporter"
1
+ require 'codeclimate-test-reporter'
2
2
  require 'rspec'
3
+ require 'wrong'
3
4
 
4
5
  CodeClimate::TestReporter.start if ENV['CODECLIMATE_REPO_TOKEN']
5
6
 
6
- RSpec.configure do |c|
7
-
8
- end
7
+ RSpec.configure do |_c|
8
+ end
@@ -1,12 +1,78 @@
1
1
  require 'spec_helper'
2
-
3
2
  require 'websockethook'
3
+ require 'securerandom'
4
+ require 'rest-client'
4
5
 
5
6
  describe WebSocketHook do
7
+ include Wrong
6
8
 
7
9
  it 'can initialize' do
8
- expect {
10
+ expect do
9
11
  ws = WebSocketHook.new
10
- }.to_not raise_error
12
+ end.to_not raise_error
13
+ end
14
+
15
+ it 'can register a hook' do
16
+ ws = WebSocketHook.new
17
+ data = []
18
+ t = Thread.new { ws.listen { |msg| data << msg } }
19
+
20
+ eventually do
21
+ data.any? do |line|
22
+ line[:type] == 'registered'
23
+ end
24
+ end
25
+
26
+ ws.stop
27
+ t.kill
28
+ end
29
+
30
+ it 'can register a hook with an id' do
31
+ id = "test_#{SecureRandom.hex(4)}"
32
+ ws = WebSocketHook.new
33
+ ws.register id
34
+ data = []
35
+ t = Thread.new { ws.listen { |msg| data << msg } }
36
+
37
+ eventually do
38
+ data.any? do |line|
39
+ line[:type] == 'registered' && line[:data][:id] == id
40
+ end
41
+ end
42
+
43
+ ws.stop
44
+ t.kill
45
+ end
46
+
47
+ it 'can trigger a hook with data' do
48
+ id = "test_#{SecureRandom.hex(4)}"
49
+ ws = WebSocketHook.new
50
+ ws.register id
51
+ data = []
52
+ t = Thread.new { ws.listen { |msg| data << msg } }
53
+ hook_url = ''
54
+
55
+ check_eventually data do |line|
56
+ found = line[:type] == 'registered' && line[:data][:id] == id
57
+ hook_url = line[:data][:url] if found
58
+ found
59
+ end
60
+
61
+ RestClient.post(hook_url,this_is_a:'test')
62
+
63
+ check_eventually data do |line|
64
+ line[:type] == 'hook' && line[:data] == {this_is_a:'test'}
65
+ end
66
+
67
+ ws.stop
68
+ t.kill
69
+ end
70
+
71
+ def check_eventually(data, &block)
72
+ eventually do
73
+ data.any? do |line|
74
+ block.yield(line)
75
+ end
76
+ end
11
77
  end
12
- end
78
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: websockethook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.01
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Skierkowski
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 10.4.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: wrong
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.7.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.7.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: rest-client
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.8.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.8.0
69
97
  description: Listen for web hooks in your app without creating a web service.
70
98
  email:
71
99
  - maciej@factor.io