signalwire 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a5ba44a20acd7bb12393399af0f7457543d60030
4
- data.tar.gz: '069bc5cbbe6465918eab2e726d88b2120b5519a8'
2
+ SHA256:
3
+ metadata.gz: b79e0a17481f2f0fcb5cdf7a1b5860f86565e60826808b3b0c4c671f6797d173
4
+ data.tar.gz: d798019a441d67cf6d6cdbba6093e13b43353a788465b7333bdf48bf9e0ab969
5
5
  SHA512:
6
- metadata.gz: b93d4efd4ab92f26fba1934720c1a03b50e17ad5576ea743af02654584170ff702a793fc2b201bb614a9b44d3ae82cd4feffc49de3d5790cd82b6bd88fcc82eb
7
- data.tar.gz: 27353d85dd32d496b747c78659badb0c56df081cfdb37d707a6e8acb400d0e17399aecca433237b3a8c3efc633d96b29dd4cce346f8ef52b3b159fda58a1d535
6
+ metadata.gz: fcadfef6643451bea578ce6a8fd8355307f53704545c6078e0265ed109c03b7c24b196d25c8703416db25a93ca2aa3158bb49818197294493fa01f43922c054d
7
+ data.tar.gz: 4cf8ec00e2eb43921000836f1f48012f82e05506c44070960c9b2736d8ffefeb32d5331c8ad5dabe7f537f56bd6a949ef3ab9a70668a3ab8532789dfd4323075
@@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
+ ## [Unreleased]
7
+
8
+ ## [2.1.3] - 2019-08-20
9
+ ### Fixed
10
+ - Restore the correct parameter for the REST client space URL
11
+ - Correctly handle reconnect on a server-side disconnect
12
+ - Fix REST pagination URL
13
+ ### Changed
14
+ - SDK now uses `signalwire.receive` to set up contexts
15
+ - The `call.*` actions are now `calling.*`
16
+ - Support positional parameters in older methods
17
+
6
18
  ## [2.1.2] - 2019-08-01
7
19
  ### Fixed
8
20
  - Fix CPU usage
@@ -17,7 +17,7 @@ class MyConsumer < Signalwire::Relay::Consumer
17
17
 
18
18
  def on_incoming_call(call)
19
19
  call.answer
20
- call.play_tts 'the quick brown fox jumps over the lazy dog'
20
+ call.play_tts text: 'the quick brown fox jumps over the lazy dog'
21
21
 
22
22
  call.hangup
23
23
  end
@@ -18,7 +18,7 @@ class MyConsumer < Signalwire::Relay::Consumer
18
18
 
19
19
  def on_incoming_call(call)
20
20
  call.answer
21
- call.play_tts 'connecting you to the clock service'
21
+ call.play_tts text: 'connecting you to the clock service'
22
22
  call.connect [[{ type: 'phone', params: { to_number: '+12027621401', from_number: ENV['FROM_NUMBER'], timeout: 30 } }]]
23
23
  sleep 20
24
24
  call.hangup
@@ -13,9 +13,9 @@ class OutboundConsumer < Signalwire::Relay::Consumer
13
13
  def ready
14
14
  dial_result = client.calling.new_call(from: ENV['FROM_NUMBER'], to: ENV['TO_NUMBER']).dial
15
15
  collect_params = { "initial_timeout": 10.0, "digits": { "max": 1, "digit_timeout": 5.0 } }
16
- result = dial_result.call.prompt_tts( collect_params, 'how many hamburgers would you like to order?')
16
+ result = dial_result.call.prompt_tts collect: collect_params, text: 'how many hamburgers would you like to order?')
17
17
 
18
- dial_result.call.play_tts "You ordered #{result.result} hamburgers. Thank you!"
18
+ dial_result.call.play_tts text: "You ordered #{result.result} hamburgers. Thank you!"
19
19
  dial_result.call.hangup
20
20
  # this makes it so the errors don't stop the process
21
21
  rescue StandardError => e
@@ -14,7 +14,7 @@ class OutboundConsumer < Signalwire::Relay::Consumer
14
14
  logger.info 'Dialing out'
15
15
  call = client.calling.new_call(from: ENV['FROM_NUMBER'], to: ENV['TO_NUMBER'])
16
16
  call.dial
17
- call.play_tts 'the quick brown fox jumps over the lazy dog', 'en-US', 'male'
17
+ call.play_tts text: 'the quick brown fox jumps over the lazy dog', language: 'en-US', gender: 'male'
18
18
  call.hangup
19
19
  end
20
20
  end
@@ -14,9 +14,9 @@ class OutboundConsumer < Signalwire::Relay::Consumer
14
14
  logger.info 'Dialing out'
15
15
  call = client.calling.new_call(from: ENV['FROM_NUMBER'], to: ENV['TO_NUMBER'])
16
16
  call.dial
17
- call.play_tts 'please leave your message after the beep. Press pound when done.'
17
+ call.play_tts text: 'please leave your message after the beep. Press pound when done.'
18
18
  result = call.record({"audio": { "beep": "true", "terminators": "#"}})
19
- call.play_tts 'you said:'
19
+ call.play_tts text: 'you said:'
20
20
  call.play_audio result.url
21
21
  call.hangup
22
22
  end
@@ -12,14 +12,14 @@ class MyConsumer < Signalwire::Relay::Consumer
12
12
  contexts ['incoming']
13
13
  def on_incoming_call(call)
14
14
  call.answer
15
- call.play_tts 'Welcome to Relay'
15
+ call.play_tts text: 'Welcome to Relay'
16
16
  dial = call.connect [[{ type: 'phone', params: { to_number: MY_NUMBER, from_number: call.from, timeout: 30 } }]]
17
17
  pp "Connected"
18
18
  pp dial.successful
19
- dial.call.play_tts "Hello!" if dial.successful
19
+ dial.call.play_tts(text: "Hello!") if dial.successful
20
20
  pp "Waiting on Ending"
21
21
  dial.call.wait_for_ending
22
- call.play_tts 'finished. hanging up.'
22
+ call.play_tts text: 'finished. hanging up.'
23
23
  call.hangup
24
24
  rescue StandardError => e
25
25
  logger.error e.inspect
@@ -37,9 +37,9 @@ module Signalwire::Blade
37
37
  end
38
38
 
39
39
  def reconnect!
40
+ @connected = false
40
41
  return if @shutdown
41
42
  sleep Signalwire::Blade::RECONNECT_PERIOD
42
- @connected = false
43
43
  logger.info "Attempting reconnection"
44
44
  main_loop!
45
45
  end
@@ -66,20 +66,22 @@ module Signalwire::Blade
66
66
 
67
67
  def setup_started_event
68
68
  on :started do |_event|
69
- @connected = true
70
- myreq = connect_request
71
- start_periodic_timer
72
-
73
- write_command(myreq) do |event|
74
- @session_id = event.dig(:result, :sessionid) unless @session_id
75
- @node_id = event.dig(:result, :nodeid) unless @node_d
76
- logger.info "Blade Session connected with id: #{@session_id}"
77
- broadcast :connected, event
69
+ begin
70
+ @connected = true
71
+ myreq = connect_request
72
+ start_periodic_timer
73
+
74
+ write_command(myreq) do |event|
75
+ @session_id = event.dig(:result, :sessionid) unless @session_id
76
+ @node_id = event.dig(:result, :nodeid) unless @node_d
77
+ logger.info "Blade Session connected with id: #{@session_id}"
78
+ broadcast :connected, event
79
+ end
80
+
81
+ rescue StandardError => e
82
+ logger.error e.inspect
83
+ logger.error e.backtrace
78
84
  end
79
-
80
- rescue StandardError => e
81
- logger.error e.inspect
82
- logger.error e.backtrace
83
85
  end
84
86
  end
85
87
 
@@ -107,10 +109,20 @@ module Signalwire::Blade
107
109
  end
108
110
 
109
111
  def write_command(command, &block)
110
- once(:message, id: command.id, &block) if block_given?
112
+ if block_given?
113
+ once :message, id: command.id do |event|
114
+ handle_execute_response(event, &block)
115
+ end
116
+ end
117
+
111
118
  transmit(command.build_request.to_json)
112
119
  end
113
120
 
121
+ def handle_execute_response(event, &block)
122
+ logger.error("Blade error occurred, code #{event.error_code}: #{event.error_message}") if event.error?
123
+ block.call(event)
124
+ end
125
+
114
126
  def execute(params, &block)
115
127
  block_given? ? write_command(Execute.new(params), &block) : write_command(Execute.new(params))
116
128
  end
@@ -163,11 +175,13 @@ module Signalwire::Blade
163
175
  # reconnect logic goes here
164
176
  logger.error "We got disconnected!"
165
177
  pinger.cancel
166
- reconnect!
178
+ reconnect! if connected?
167
179
  end
168
-
169
- @ws.ping 'detecting presence' do
170
- timeouter.cancel
180
+
181
+ if @connected
182
+ @ws.ping 'detecting presence' do
183
+ timeouter.cancel
184
+ end
171
185
  end
172
186
  end
173
187
  end
@@ -34,5 +34,17 @@ module Signalwire::Blade
34
34
  def to_s
35
35
  inspect
36
36
  end
37
+
38
+ def error?
39
+ @payload.has_key?(:error)
40
+ end
41
+
42
+ def error_code
43
+ @payload.dig(:error, :code)
44
+ end
45
+
46
+ def error_message
47
+ @payload.dig(:error, :message)
48
+ end
37
49
  end
38
50
  end
@@ -117,16 +117,20 @@ module Signalwire::Relay::Calling
117
117
  PlayAction.new(component: play_component)
118
118
  end
119
119
 
120
- def prompt(collect_object, play_object)
121
- component = Prompt.new(call: self, collect: collect_object, play: play_object)
120
+ def prompt(collect_p = nil, play_p = nil, collect: nil, play: nil)
121
+ set_parameters(binding, %i{collect play}, %i{collect play})
122
+
123
+ component = Prompt.new(call: self, collect: collect, play: play)
122
124
  component.wait_for(Relay::CallPromptState::ERROR, Relay::CallPromptState::NO_INPUT,
123
125
  Relay::CallPromptState::NO_MATCH, Relay::CallPromptState::DIGIT,
124
126
  Relay::CallPromptState::SPEECH)
125
127
  PromptResult.new(component: component)
126
128
  end
127
129
 
128
- def prompt!(collect_object, play_object)
129
- component = Prompt,new(call: self, collect: collect_object, play: play_object)
130
+ def prompt!(collect_p = nil, play_p = nil, collect: nil, play: nil)
131
+ set_parameters(binding, %i{collect play}, %i{collect play})
132
+
133
+ component = Prompt,new(call: self, collect: collect, play: play)
130
134
  component.execute
131
135
  PromptAction.new(component: component)
132
136
  end
@@ -247,5 +251,14 @@ module Signalwire::Relay::Calling
247
251
  @busy = false
248
252
  @failed = false
249
253
  end
254
+
255
+ def set_parameters(passed_binding, keys, mandatory_keys)
256
+ keys.each do |x|
257
+ passed_binding.local_variable_set(x, passed_binding.local_variable_get(x) || passed_binding.local_variable_get("#{x}_p"))
258
+ end
259
+ mandatory_keys.each do |x|
260
+ raise ArgumentError if passed_binding.local_variable_get(x).nil?
261
+ end
262
+ end
250
263
  end
251
264
  end
@@ -16,36 +16,50 @@ module Signalwire::Relay::Calling
16
16
  play! silence_payload(duration)
17
17
  end
18
18
 
19
- def play_tts(sentence, language='en-US', gender='female')
20
- play tts_payload(sentence, language, gender)
19
+ def play_tts(text_p=nil, language_p=Relay::DEFAULT_LANGUAGE, gender_p=Relay::DEFAULT_GENDER, text: nil, language: Relay::DEFAULT_LANGUAGE, gender: Relay::DEFAULT_GENDER)
20
+ set_parameters(binding, %i{text language gender}, %i{text})
21
+
22
+ play tts_payload(text, language, gender)
21
23
  end
22
24
 
23
- def play_tts!(sentence, language='en-US', gender='female')
24
- play! tts_payload(sentence, language, gender)
25
+ def play_tts!(text_p=nil, language_p=Relay::DEFAULT_LANGUAGE, gender_p=Relay::DEFAULT_GENDER, text: nil, language: Relay::DEFAULT_LANGUAGE, gender: Relay::DEFAULT_GENDER)
26
+ set_parameters(binding, %i{text language gender}, %i{text})
27
+ play! tts_payload(text, language, gender)
25
28
  end
26
29
 
27
- def prompt_audio(collect, url)
30
+ def prompt_audio(collect_p = nil, url_p = nil, collect: nil, url: nil)
31
+ set_parameters(binding, %i{collect url}, %i{collect url})
32
+
28
33
  prompt(collect, audio_payload(url))
29
34
  end
30
35
 
31
- def prompt_audio!(collect, url)
36
+ def prompt_audio!(collect_p = nil, url_p = nil, collect: nil, url: nil)
37
+ set_parameters(binding, %i{collect url}, %i{collect url})
38
+
32
39
  prompt!(collect, audio_payload(url))
33
40
  end
34
41
 
35
- def prompt_silence(collect, duration)
42
+ def prompt_silence(collect_p = nil, duration_p = nil, collect: nil, duration: nil)
43
+ set_parameters(binding, %i{collect duration}, %i{collect duration})
44
+
36
45
  prompt(collect, silence_payload(duration))
37
46
  end
38
47
 
39
- def prompt_silence!(collect, url)
48
+ def prompt_silence!(collect_p = nil, duration_p = nil, collect: nil, duration: nil)
49
+ set_parameters(binding, %i{collect duration}, %i{collect duration})
50
+
40
51
  prompt!(collect, silence_payload(duration))
41
52
  end
42
53
 
43
- def prompt_tts(collect, sentence, language='en-US', gender='female')
44
- prompt(collect, tts_payload(sentence, language, gender))
54
+ def prompt_tts(collect_p = nil, text_p = nil, language_p=Relay::DEFAULT_LANGUAGE, gender_p=Relay::DEFAULT_GENDER, collect: nil, text: nil, language: Relay::DEFAULT_LANGUAGE, gender: Relay::DEFAULT_GENDER)
55
+ set_parameters(binding, %i{collect text language gender}, %i{collect text})
56
+ prompt(collect, tts_payload(text, language, gender))
45
57
  end
46
58
 
47
- def prompt_tts!(collect, sentence, language='en-US', gender='female')
48
- prompt!(collect, tts_payload(sentence, language, gender))
59
+ def prompt_tts!(collect_p = nil, text_p = nil, language_p=Relay::DEFAULT_LANGUAGE, gender_p=Relay::DEFAULT_GENDER, collect: nil, text: nil, language: Relay::DEFAULT_LANGUAGE, gender: Relay::DEFAULT_GENDER)
60
+ set_parameters(binding, %i{collect text language gender}, %i{collect text})
61
+
62
+ prompt!(collect, tts_payload(text, language, gender))
49
63
  end
50
64
 
51
65
  def wait_for_ringing
@@ -64,6 +78,8 @@ module Signalwire::Relay::Calling
64
78
  wait_for(Relay::CallState::ENDED)
65
79
  end
66
80
 
81
+ private
82
+
67
83
  def audio_payload(url)
68
84
  [{ type: "audio", params: { url: url } }]
69
85
  end
@@ -72,8 +88,8 @@ module Signalwire::Relay::Calling
72
88
  [{ type: "silence", params: { duration: duration } }]
73
89
  end
74
90
 
75
- def tts_payload(sentence, language='en-US', gender='male')
76
- [{ "type": 'tts', "params": { "text": sentence, "language": language, "gender": gender } }]
91
+ def tts_payload(text, language=Relay::DEFAULT_LANGUAGE, gender=Relay::DEFAULT_GENDER)
92
+ [{ "type": 'tts', "params": { "text": text, "language": language, "gender": gender } }]
77
93
  end
78
94
  end
79
95
  end
@@ -79,7 +79,7 @@ module Signalwire::Relay
79
79
  block.call(event, success) if block_given?
80
80
  logger.error "Relay command failed with code #{code} and message: #{message}" unless success
81
81
  else
82
- logger.error 'Unknown Relay command failure, result code not found'
82
+ logger.error("Relay error occurred, code #{event.error_code}: #{event.error_message}") if event.error?
83
83
  block.call(event, :failure) if block_given?
84
84
  end
85
85
  else
@@ -100,7 +100,7 @@ module Signalwire::Relay
100
100
  return if contexts.include?(context)
101
101
  receive_command = {
102
102
  protocol: @protocol,
103
- method: 'call.receive',
103
+ method: 'signalwire.receive',
104
104
  params: {
105
105
  context: context
106
106
  }
@@ -121,7 +121,11 @@ module Signalwire::Relay
121
121
  @session.on :connected do |event|
122
122
  logger.debug 'Relay client connected'
123
123
  broadcast :connecting, event
124
- protocol_setup
124
+ if event.error?
125
+ logger.error("Error setting up Blade connection")
126
+ else
127
+ protocol_setup
128
+ end
125
129
  end
126
130
  end
127
131
 
@@ -149,6 +153,7 @@ module Signalwire::Relay
149
153
  @session.subscribe(notification_request) do
150
154
  logger.debug "Subscribed to notifications for #{protocol}"
151
155
  @connected = true
156
+ @contexts = Concurrent::Array.new
152
157
  broadcast :ready, self
153
158
  end
154
159
  end
@@ -5,6 +5,8 @@ module Signalwire::Relay
5
5
  COMMAND_TIMEOUT = 30
6
6
  DEFAULT_CALL_TIMEOUT = 30
7
7
  PING_TIMEOUT = 5
8
+ DEFAULT_LANGUAGE = 'en-US'
9
+ DEFAULT_GENDER = 'female'
8
10
 
9
11
  module CallState
10
12
  NONE = 'none'
@@ -104,17 +106,17 @@ module Signalwire::Relay
104
106
  end
105
107
 
106
108
  module ComponentMethod
107
- ANSWER = 'call.answer'
108
- CONNECT = 'call.connect'
109
- DIAL = 'call.begin' # BEGIN is a reserved word
110
- HANGUP = 'call.end' # END is a reserved word
111
- PLAY = 'call.play'
112
- PROMPT = 'call.play_and_collect'
113
- RECORD = 'call.record'
114
- SEND_FAX = 'call.send_fax'
115
- RECEIVE_FAX = 'call.receive_fax'
116
- TAP = 'call.tap'
117
- DETECT = 'call.detect'
109
+ ANSWER = 'calling.answer'
110
+ CONNECT = 'calling.connect'
111
+ DIAL = 'calling.begin' # BEGIN is a reserved word
112
+ HANGUP = 'calling.end' # END is a reserved word
113
+ PLAY = 'calling.play'
114
+ PROMPT = 'calling.play_and_collect'
115
+ RECORD = 'calling.record'
116
+ SEND_FAX = 'calling.send_fax'
117
+ RECEIVE_FAX = 'calling.receive_fax'
118
+ TAP = 'calling.tap'
119
+ DETECT = 'calling.detect'
118
120
  end
119
121
 
120
122
  module CommonState
@@ -47,6 +47,11 @@ module Signalwire::Relay
47
47
  def run
48
48
  logger.info "Starting up #{self.class}"
49
49
  setup
50
+
51
+ client.on :ready do
52
+ setup_contexts
53
+ end
54
+
50
55
  client.once :ready do
51
56
  setup_receive_listeners
52
57
  setup_all_events_listener
@@ -70,13 +75,19 @@ module Signalwire::Relay
70
75
  private
71
76
 
72
77
  def setup_receive_listeners
73
- self.class.contexts.each do |cxt|
74
- client.calling.receive context: cxt do |call|
78
+ self.class.contexts.each do |ctx|
79
+ client.calling.receive context: ctx do |call|
75
80
  on_incoming_call(call)
76
81
  end
77
82
  end
78
83
  end
79
84
 
85
+ def setup_contexts
86
+ self.class.contexts.each do |ctx|
87
+ @client.setup_context(ctx)
88
+ end
89
+ end
90
+
80
91
  def setup_task_listeners
81
92
  client.on :task do |task|
82
93
  on_task(task)
@@ -3,7 +3,7 @@
3
3
  module Signalwire::REST
4
4
  class Client < Twilio::REST::Client
5
5
  def initialize(username = nil, password = nil, account_sid = nil, region = nil, http_client = Twilio::HTTP::Client.new, **args)
6
- host = args.delete(:SIGNALWIRE_HOST)
6
+ host = args.delete(:signalwire_space_url)
7
7
 
8
8
  unless host.nil?
9
9
  Signalwire::Sdk.configure do |config|
@@ -12,7 +12,7 @@ module Twilio
12
12
  'SignalWire Space URL is not configured. Enter your SignalWire Space domain via the '\
13
13
  'SIGNALWIRE_HOST environment variable, or hostname in the configuration.')
14
14
 
15
- @base_url = "https://#{@host}/api/laml"
15
+ @base_url = "https://#{@host}"
16
16
  @port = 443
17
17
 
18
18
  # Versions
@@ -14,7 +14,7 @@ module Twilio
14
14
  'SIGNALWIRE_HOST or SIGNALWIRE_API_HOSTNAME environment variables, '\
15
15
  'or hostname in the configuration.')
16
16
 
17
- @base_url = "https://#{@host}/api/laml"
17
+ @base_url = "https://#{@host}"
18
18
  @port = 443
19
19
 
20
20
  # Versions
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Signalwire
4
- VERSION = '2.1.2'
4
+ VERSION = '2.1.3'
5
5
  end
@@ -22,6 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ['lib']
24
24
 
25
+ spec.required_ruby_version = '>= 2.0'
26
+
25
27
  spec.add_development_dependency 'bundler', '~> 1.16'
26
28
  spec.add_development_dependency 'bundler-audit', '~> 0.6.1'
27
29
  spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signalwire
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - SignalWire Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-02 00:00:00.000000000 Z
11
+ date: 2019-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -350,15 +350,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
350
350
  requirements:
351
351
  - - ">="
352
352
  - !ruby/object:Gem::Version
353
- version: '0'
353
+ version: '2.0'
354
354
  required_rubygems_version: !ruby/object:Gem::Requirement
355
355
  requirements:
356
356
  - - ">="
357
357
  - !ruby/object:Gem::Version
358
358
  version: '0'
359
359
  requirements: []
360
- rubyforge_project:
361
- rubygems_version: 2.5.2.3
360
+ rubygems_version: 3.0.3
362
361
  signing_key:
363
362
  specification_version: 4
364
363
  summary: Ruby client for Signalwire