vonage 7.2.1 → 7.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +46 -1
  3. data/lib/vonage/abstract_authentication.rb +1 -1
  4. data/lib/vonage/applications/list_response.rb +1 -1
  5. data/lib/vonage/applications.rb +11 -3
  6. data/lib/vonage/basic.rb +1 -1
  7. data/lib/vonage/bearer_token.rb +1 -1
  8. data/lib/vonage/config.rb +1 -1
  9. data/lib/vonage/conversations/events.rb +6 -2
  10. data/lib/vonage/conversations/legs.rb +6 -2
  11. data/lib/vonage/conversations/members.rb +6 -2
  12. data/lib/vonage/conversations/users.rb +6 -2
  13. data/lib/vonage/conversations.rb +10 -3
  14. data/lib/vonage/entity.rb +0 -2
  15. data/lib/vonage/form_data.rb +1 -1
  16. data/lib/vonage/gsm7.rb +4 -1
  17. data/lib/vonage/json.rb +1 -1
  18. data/lib/vonage/jwt.rb +1 -1
  19. data/lib/vonage/namespace.rb +121 -16
  20. data/lib/vonage/numbers/list_response.rb +1 -1
  21. data/lib/vonage/numbers/response.rb +2 -2
  22. data/lib/vonage/numbers.rb +9 -1
  23. data/lib/vonage/params.rb +1 -1
  24. data/lib/vonage/response.rb +1 -0
  25. data/lib/vonage/secrets/list_response.rb +1 -1
  26. data/lib/vonage/secrets.rb +6 -2
  27. data/lib/vonage/user_agent.rb +4 -1
  28. data/lib/vonage/verify.rb +1 -1
  29. data/lib/vonage/version.rb +1 -1
  30. data/lib/vonage/voice/actions/connect.rb +199 -0
  31. data/lib/vonage/voice/actions/conversation.rb +107 -0
  32. data/lib/vonage/voice/actions/input.rb +119 -0
  33. data/lib/vonage/voice/actions/notify.rb +57 -0
  34. data/lib/vonage/voice/actions/record.rb +130 -0
  35. data/lib/vonage/voice/actions/stream.rb +72 -0
  36. data/lib/vonage/voice/actions/talk.rb +73 -0
  37. data/lib/vonage/voice/list_response.rb +1 -1
  38. data/lib/vonage/voice/ncco.rb +42 -0
  39. data/lib/vonage/voice.rb +9 -1
  40. data/vonage.gemspec +2 -0
  41. metadata +39 -3
@@ -0,0 +1,199 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'phonelib'
4
+
5
+ module Vonage
6
+ class Voice::Actions::Connect
7
+ attr_accessor :endpoint, :from, :eventType, :timeout, :limit, :machineDetection, :eventUrl, :eventMethod, :ringbackTone
8
+
9
+ def initialize(attributes = {})
10
+ @endpoint = attributes.fetch(:endpoint)
11
+ @from = attributes.fetch(:from, nil)
12
+ @eventType = attributes.fetch(:eventType, nil)
13
+ @timeout = attributes.fetch(:timeout, nil)
14
+ @limit = attributes.fetch(:limit, nil)
15
+ @machineDetection = attributes.fetch(:machineDetection, nil)
16
+ @eventUrl = attributes.fetch(:eventUrl, nil)
17
+ @eventMethod = attributes.fetch(:eventMethod, nil)
18
+ @ringbackTone = attributes.fetch(:ringbackTone, nil)
19
+
20
+ after_initialize!
21
+ end
22
+
23
+ def after_initialize!
24
+ verify_endpoint
25
+
26
+ if self.from
27
+ verify_from
28
+ end
29
+
30
+ if self.eventType
31
+ verify_event_type
32
+ end
33
+
34
+ if self.limit
35
+ verify_limit
36
+ end
37
+
38
+ if self.machineDetection
39
+ verify_machine_detection
40
+ end
41
+
42
+ if self.eventUrl
43
+ verify_event_url
44
+ end
45
+
46
+ if self.eventMethod
47
+ verify_event_method
48
+ end
49
+
50
+ if self.ringbackTone
51
+ verify_ringback_tone
52
+ end
53
+ end
54
+
55
+ def verify_endpoint
56
+ case self.endpoint[:type]
57
+ when 'phone'
58
+ raise ClientError.new("Expected 'number' value to be in E.164 format") unless Phonelib.parse(endpoint[:number].to_i).valid?
59
+ when 'app'
60
+ raise ClientError.new("'user' must be defined") unless endpoint[:user]
61
+ when 'websocket'
62
+ raise ClientError.new("Expected 'uri' value to be a valid URI") unless URI.parse(endpoint[:uri]).kind_of?(URI::Generic)
63
+ raise ClientError.new("Expected 'content-type' parameter to be either 'audio/116;rate=16000' or 'audio/116;rate=8000") unless endpoint[:'content-type'] == 'audio/116;rate=16000' || endpoint[:'content-type'] == 'audio/116;rate=8000'
64
+ when 'sip'
65
+ raise ClientError.new("Expected 'uri' value to be a valid URI") unless URI.parse(endpoint[:uri]).kind_of?(URI::Generic)
66
+ end
67
+ end
68
+
69
+ def verify_from
70
+ raise ClientError.new("Invalid 'from' value, must be in E.164 format") unless Phonelib.parse(self.from.to_i).valid?
71
+ end
72
+
73
+ def verify_event_type
74
+ raise ClientError.new("Invalid 'eventType' value, must be 'synchronous' if defined") unless self.eventType == 'synchronous'
75
+ end
76
+
77
+ def verify_limit
78
+ raise ClientError.new("Invalid 'limit' value, must be between 0 and 7200 seconds") unless self.limit.to_i >= 0 && self.limit.to_i <= 7200
79
+ end
80
+
81
+ def verify_machine_detection
82
+ raise ClientError.new("Invalid 'machineDetection' value, must be either: 'continue' or 'hangup' if defined") unless self.machineDetection == 'continue' || self.machineDetection == 'hangup'
83
+ end
84
+
85
+ def verify_event_url
86
+ uri = URI.parse(self.eventUrl)
87
+
88
+ raise ClientError.new("Invalid 'eventUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
89
+
90
+ self.eventUrl
91
+ end
92
+
93
+ def verify_event_method
94
+ valid_methods = ['GET', 'POST']
95
+
96
+ raise ClientError.new("Invalid 'eventMethod' value. must be either: 'GET' or 'POST'") unless valid_methods.include?(self.eventMethod.upcase)
97
+ end
98
+
99
+ def verify_ringback_tone
100
+ uri = URI.parse(self.ringbackTone)
101
+
102
+ raise ClientError.new("Invalid 'ringbackTone' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
103
+
104
+ self.ringbackTone
105
+ end
106
+
107
+ def action
108
+ create_connect!(self)
109
+ end
110
+
111
+ def create_connect!(builder)
112
+ ncco = [
113
+ {
114
+ action: 'connect',
115
+ endpoint: [
116
+ create_endpoint(builder)
117
+ ]
118
+ }
119
+ ]
120
+
121
+ ncco[0].merge!(from: builder.from) if builder.from
122
+ ncco[0].merge!(eventType: builder.eventType) if builder.eventType
123
+ ncco[0].merge!(timeout: builder.timeout) if builder.timeout
124
+ ncco[0].merge!(limit: builder.limit) if builder.limit
125
+ ncco[0].merge!(machineDetection: builder.machineDetection) if builder.machineDetection
126
+ ncco[0].merge!(eventUrl: builder.eventUrl) if builder.eventUrl
127
+ ncco[0].merge!(eventMethod: builder.eventMethod) if builder.eventMethod
128
+ ncco[0].merge!(ringbackTone: builder.ringbackTone) if builder.ringbackTone
129
+
130
+ ncco
131
+ end
132
+
133
+ def create_endpoint(builder)
134
+ case builder.endpoint[:type]
135
+ when 'phone'
136
+ phone_endpoint(builder.endpoint)
137
+ when 'app'
138
+ app_endpoint(builder.endpoint)
139
+ when 'websocket'
140
+ websocket_endpoint(builder.endpoint)
141
+ when 'sip'
142
+ sip_endpoint(builder.endpoint)
143
+ when 'vbc'
144
+ vbc_endpoint(builder.endpoint)
145
+ else
146
+ raise ClientError.new("Invalid value for 'endpoint', please refer to the Vonage API Developer Portal https://developer.nexmo.com/voice/voice-api/ncco-reference#endpoint-types-and-values for a list of possible values")
147
+ end
148
+ end
149
+
150
+ def phone_endpoint(endpoint_attrs)
151
+ hash = {
152
+ type: 'phone',
153
+ number: endpoint_attrs[:number]
154
+ }
155
+
156
+ hash.merge!(dtmfAnswer: endpoint_attrs[:dtmfAnswer]) if endpoint_attrs[:dtmfAnswer]
157
+ hash.merge!(onAnswer: endpoint_attrs[:onAnswer]) if endpoint_attrs[:onAnswer]
158
+
159
+ hash
160
+ end
161
+
162
+ def app_endpoint(endpoint_attrs)
163
+ {
164
+ type: 'app',
165
+ user: endpoint_attrs[:user]
166
+ }
167
+ end
168
+
169
+ def websocket_endpoint(endpoint_attrs)
170
+ hash = {
171
+ type: 'websocket',
172
+ uri: endpoint_attrs[:uri],
173
+ :'content-type' => endpoint_attrs[:'content-type']
174
+ }
175
+
176
+ hash.merge!(headers: endpoint_attrs[:headers]) if endpoint_attrs[:headers]
177
+
178
+ hash
179
+ end
180
+
181
+ def sip_endpoint(endpoint_attrs)
182
+ hash = {
183
+ type: 'sip',
184
+ uri: endpoint_attrs[:uri]
185
+ }
186
+
187
+ hash.merge!(headers: endpoint_attrs[:headers]) if endpoint_attrs[:headers]
188
+
189
+ hash
190
+ end
191
+
192
+ def vbc_endpoint(endpoint_attrs)
193
+ {
194
+ type: 'vbc',
195
+ extension: endpoint_attrs[:extension]
196
+ }
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,107 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Voice::Actions::Conversation
6
+ attr_accessor :name, :musicOnHoldUrl, :startOnEnter, :endOnExit, :record, :canSpeak, :canHear, :mute
7
+
8
+ def initialize(attributes = {})
9
+ @name = attributes.fetch(:name)
10
+ @musicOnHoldUrl = attributes.fetch(:musicOnHoldUrl, nil)
11
+ @startOnEnter = attributes.fetch(:startOnEnter, nil)
12
+ @endOnExit = attributes.fetch(:endOnExit, nil)
13
+ @record = attributes.fetch(:record, nil)
14
+ @canSpeak = attributes.fetch(:canSpeak, nil)
15
+ @canHear = attributes.fetch(:canHear, nil)
16
+ @mute = attributes.fetch(:mute, nil)
17
+
18
+ after_initialize!
19
+ end
20
+
21
+ def after_initialize!
22
+ if self.musicOnHoldUrl
23
+ verify_music_on_hold_url
24
+ end
25
+
26
+ if self.startOnEnter
27
+ verify_start_on_enter
28
+ end
29
+
30
+ if self.endOnExit
31
+ verify_end_on_exit
32
+ end
33
+
34
+ if self.record
35
+ verify_record
36
+ end
37
+
38
+ if self.canSpeak
39
+ verify_can_speak
40
+ end
41
+
42
+ if self.canHear
43
+ verify_can_hear
44
+ end
45
+
46
+ if self.mute
47
+ verify_mute
48
+ end
49
+ end
50
+
51
+ def verify_music_on_hold_url
52
+ uri = URI.parse(self.musicOnHoldUrl)
53
+
54
+ raise ClientError.new("Invalid 'musicOnHoldUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
55
+
56
+ self.musicOnHoldUrl
57
+ end
58
+
59
+ def verify_start_on_enter
60
+ raise ClientError.new("Expected 'startOnEnter' value to be a Boolean") unless self.startOnEnter == true || self.startOnEnter == false
61
+ end
62
+
63
+ def verify_end_on_exit
64
+ raise ClientError.new("Expected 'endOnExit' value to be a Boolean") unless self.endOnExit == true || self.endOnExit == false
65
+ end
66
+
67
+ def verify_record
68
+ raise ClientError.new("Expected 'record' value to be a Boolean") unless self.record == true || self.record == false
69
+ end
70
+
71
+ def verify_can_speak
72
+ raise ClientError.new("Expected 'canSpeak' value to be an Array of leg UUIDs") unless self.canSpeak.is_a?(Array)
73
+ end
74
+
75
+ def verify_can_hear
76
+ raise ClientError.new("Expected 'canHear' value to be an Array of leg UUIDs") unless self.canHear.is_a?(Array)
77
+ end
78
+
79
+ def verify_mute
80
+ raise ClientError.new("Expected 'mute' value to be a Boolean") unless self.mute == true || self.mute == false
81
+ raise ClientError.new("The 'mute' value is not supported if the 'canSpeak' option is defined") if self.canSpeak
82
+ end
83
+
84
+ def action
85
+ create_conversation!(self)
86
+ end
87
+
88
+ def create_conversation!(builder)
89
+ ncco = [
90
+ {
91
+ action: 'conversation',
92
+ name: builder.name
93
+ }
94
+ ]
95
+
96
+ ncco[0].merge!(musicOnHoldUrl: builder.musicOnHoldUrl) if (builder.musicOnHoldUrl || builder.musicOnHoldUrl == false)
97
+ ncco[0].merge!(startOnEnter: builder.startOnEnter) if (builder.startOnEnter || builder.startOnEnter == false)
98
+ ncco[0].merge!(endOnExit: builder.endOnExit) if (builder.endOnExit || builder.endOnExit == false)
99
+ ncco[0].merge!(record: builder.record) if builder.record
100
+ ncco[0].merge!(canSpeak: builder.canSpeak) if builder.canSpeak
101
+ ncco[0].merge!(canHear: builder.canHear) if builder.canHear
102
+ ncco[0].merge!(mute: builder.mute) if builder.mute
103
+
104
+ ncco
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,119 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Voice::Actions::Input
6
+ attr_accessor :type, :dtmf, :speech, :eventUrl, :eventMethod
7
+
8
+ def initialize(attributes = {})
9
+ @type = attributes.fetch(:type)
10
+ @dtmf = attributes.fetch(:dtmf, nil)
11
+ @speech = attributes.fetch(:speech, nil)
12
+ @eventUrl = attributes.fetch(:eventUrl, nil)
13
+ @eventMethod = attributes.fetch(:eventMethod, nil)
14
+
15
+ after_initialize!
16
+ end
17
+
18
+ def after_initialize!
19
+ validate_type
20
+
21
+ if self.dtmf
22
+ validate_dtmf
23
+ end
24
+
25
+ if self.speech
26
+ validate_speech
27
+ end
28
+
29
+ if self.eventUrl
30
+ validate_event_url
31
+ end
32
+
33
+ if self.eventMethod
34
+ validate_event_method
35
+ end
36
+ end
37
+
38
+ def validate_type
39
+ valid_types = ['dtmf', 'speech']
40
+
41
+ raise ClientError.new("Invalid 'type', must be an Array of at least one String") unless self.type.is_a?(Array)
42
+ raise ClientError.new("Invalid 'type' value, must be 'dtmf', 'speech' or both 'dtmf' and 'speech'") if (valid_types & self.type).empty?
43
+ end
44
+
45
+ def validate_dtmf
46
+ raise ClientError.new("Expected 'dtmf' to be included in 'type' parameter if 'dtmf' options specified") unless self.type.include?('dtmf')
47
+
48
+ if self.dtmf[:timeOut]
49
+ raise ClientError.new("Expected 'timeOut' to not be more than 10 seconds") if self.dtmf[:timeOut] > 10
50
+ end
51
+
52
+ if self.dtmf[:maxDigits]
53
+ raise ClientError.new("Expected 'maxDigits' to not be more than 22") if self.dtmf[:maxDigits] > 22
54
+ end
55
+
56
+ if self.dtmf[:submitOnHash]
57
+ raise ClientError.new("Invalid 'submitOnHash' value, must be a Boolean") unless self.dtmf[:submitOnHash] == true || self.dtmf[:submitOnHash] == false
58
+ end
59
+ end
60
+
61
+ def validate_speech
62
+ raise ClientError.new("Expected 'speech' to be included in 'type' parameter if 'speech' options specified") unless self.type.include?('speech')
63
+
64
+ if self.speech[:uuid]
65
+ raise ClientError.new("Invalid 'uuid' value, must be an Array containing a single call leg ID element") unless self.speech[:uuid].is_a?(Array)
66
+ end
67
+
68
+ if self.speech[:endOnSilence]
69
+ raise ClientError.new("Expected 'endOnSilence' to not be more than 10 seconds") unless self.speech[:endOnSilence] <= 10 && self.speech[:endOnSilence] >= 0
70
+ end
71
+
72
+ if self.speech[:context]
73
+ raise ClientError.new("Expected 'context' to be an Array of strings") unless self.speech[:context].is_a?(Array)
74
+ end
75
+
76
+ if self.speech[:startTimeout]
77
+ raise ClientError.new("Expected 'startTimeout' to not be more than 10 seconds") unless self.speech[:startTimeout] <= 10 && self.speech[:startTimeout] >= 0
78
+ end
79
+
80
+ if self.speech[:maxDuration]
81
+ raise ClientError.new("Expected 'maxDuration' to not be more than 60 seconds") unless self.speech[:maxDuration] <= 60 && self.speech[:maxDuration] >= 0
82
+ end
83
+ end
84
+
85
+ def validate_event_url
86
+ uri = URI.parse(self.eventUrl)
87
+
88
+ raise ClientError.new("Invalid 'eventUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
89
+
90
+ self.eventUrl
91
+ end
92
+
93
+ def validate_event_method
94
+ valid_methods = ['GET', 'POST']
95
+
96
+ raise ClientError.new("Invalid 'eventMethod' value. must be either: 'GET' or 'POST'") unless valid_methods.include?(self.eventMethod.upcase)
97
+ end
98
+
99
+ def action
100
+ create_input!(self)
101
+ end
102
+
103
+ def create_input!(builder)
104
+ ncco = [
105
+ {
106
+ action: 'input',
107
+ type: builder.type
108
+ }
109
+ ]
110
+
111
+ ncco[0].merge!(dtmf: builder.dtmf) if builder.dtmf
112
+ ncco[0].merge!(speech: builder.speech) if builder.speech
113
+ ncco[0].merge!(eventUrl: builder.eventUrl) if builder.eventUrl
114
+ ncco[0].merge!(eventMethod: builder.eventMethod) if builder.eventMethod
115
+
116
+ ncco
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,57 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Voice::Actions::Notify
6
+ attr_accessor :payload, :eventUrl, :eventMethod
7
+
8
+ def initialize(attributes = {})
9
+ @payload = attributes.fetch(:payload)
10
+ @eventUrl = attributes.fetch(:eventUrl)
11
+ @eventMethod = attributes.fetch(:eventMethod, nil)
12
+
13
+ after_initialize!
14
+ end
15
+
16
+ def after_initialize!
17
+ validate_event_url
18
+
19
+ if self.eventMethod
20
+ validate_event_method
21
+ end
22
+ end
23
+
24
+ def validate_event_url
25
+ uri = URI.parse(self.eventUrl[0])
26
+
27
+ raise ClientError.new("Expected 'eventUrl' value to be an Array with a single string") unless self.eventUrl.is_a?(Array)
28
+ raise ClientError.new("Invalid 'eventUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
29
+
30
+ self.eventUrl
31
+ end
32
+
33
+ def validate_event_method
34
+ valid_methods = ['GET', 'POST']
35
+
36
+ raise ClientError.new("Invalid 'eventMethod' value. must be either: 'GET' or 'POST'") unless valid_methods.include?(self.eventMethod.upcase)
37
+ end
38
+
39
+ def action
40
+ create_notify!(self)
41
+ end
42
+
43
+ def create_notify!(builder)
44
+ ncco = [
45
+ {
46
+ action: 'notify',
47
+ payload: builder.payload,
48
+ eventUrl: builder.eventUrl
49
+ }
50
+ ]
51
+
52
+ ncco[0].merge!(eventMethod: builder.eventMethod) if builder.eventMethod
53
+
54
+ ncco
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,130 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Voice::Actions::Record
6
+ attr_accessor :format, :split, :channels, :endOnSilence, :endOnKey, :timeOut, :beepStart, :eventUrl, :eventMethod
7
+
8
+ def initialize(attributes = {})
9
+ @format = attributes.fetch(:format, nil)
10
+ @split = attributes.fetch(:split, nil)
11
+ @channels = attributes.fetch(:channels, nil)
12
+ @endOnSilence = attributes.fetch(:endOnSilence, nil)
13
+ @endOnKey = attributes.fetch(:endOnKey, nil)
14
+ @timeOut = attributes.fetch(:timeOut, nil)
15
+ @beepStart = attributes.fetch(:beepStart, nil)
16
+ @eventUrl = attributes.fetch(:eventUrl, nil)
17
+ @eventMethod = attributes.fetch(:eventMethod, nil)
18
+
19
+ after_initialize!
20
+ end
21
+
22
+ def after_initialize!
23
+ if self.format
24
+ validate_format
25
+ end
26
+
27
+ if self.split
28
+ validate_split
29
+ end
30
+
31
+ if self.channels
32
+ validate_channels
33
+ end
34
+
35
+ if self.endOnSilence
36
+ validate_end_on_silence
37
+ end
38
+
39
+ if self.endOnKey
40
+ validate_end_on_key
41
+ end
42
+
43
+ if self.timeOut
44
+ validate_time_out
45
+ end
46
+
47
+ if self.beepStart
48
+ validate_beep_start
49
+ end
50
+
51
+ if self.eventUrl
52
+ validate_event_url
53
+ end
54
+
55
+ if self.eventMethod
56
+ validate_event_method
57
+ end
58
+ end
59
+
60
+ def validate_format
61
+ valid_formats = ['mp3', 'wav', 'ogg']
62
+
63
+ raise ClientError.new("Invalid format, must be one of: 'mp3', 'wav', 'ogg'") unless valid_formats.include?(self.format)
64
+ end
65
+
66
+ def validate_split
67
+ raise ClientError.new("Expected 'split' value to be 'conversation' if defined") unless self.split == 'conversation'
68
+ end
69
+
70
+ def validate_channels
71
+ raise ClientError.new("The 'split' parameter must be defined to 'conversation' to also define 'channels'") unless self.split
72
+
73
+ raise ClientError.new("Expected 'split' parameter to be equal to or less than 32") unless self.channels <= 32
74
+ end
75
+
76
+ def validate_end_on_silence
77
+ raise ClientError.new("Expected 'endOnSilence' value to be between 3 and 10") unless self.endOnSilence <= 10 && self.endOnSilence >= 3
78
+ end
79
+
80
+ def validate_end_on_key
81
+ raise ClientError.new("Expected 'endOnKey' value to be a one of the following: a single digit between 1-9, '*' or '#'") unless self.endOnKey.match(/^(\*|[1-9]|\#)$/)
82
+ end
83
+
84
+ def validate_time_out
85
+ raise ClientError.new("Expected 'timeOut' value to be between 3 and 7200 seconds") unless self.timeOut <= 7200 && self.timeOut >= 3
86
+ end
87
+
88
+ def validate_beep_start
89
+ raise ClientError.new("Expected 'beepStart' value to be a Boolean") unless self.beepStart == true || self.beepStart == false
90
+ end
91
+
92
+ def validate_event_url
93
+ uri = URI.parse(self.eventUrl)
94
+
95
+ raise ClientError.new("Invalid 'eventUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
96
+
97
+ self.eventUrl
98
+ end
99
+
100
+ def validate_event_method
101
+ valid_methods = ['GET', 'POST']
102
+
103
+ raise ClientError.new("Invalid 'eventMethod' value. must be either: 'GET' or 'POST'") unless valid_methods.include?(self.eventMethod.upcase)
104
+ end
105
+
106
+ def action
107
+ create_record!(self)
108
+ end
109
+
110
+ def create_record!(builder)
111
+ ncco = [
112
+ {
113
+ action: 'record'
114
+ }
115
+ ]
116
+
117
+ ncco[0].merge!(format: builder.format) if builder.format
118
+ ncco[0].merge!(split: builder.split) if builder.split
119
+ ncco[0].merge!(channels: builder.channels) if builder.channels
120
+ ncco[0].merge!(endOnSilence: builder.endOnSilence) if builder.endOnSilence
121
+ ncco[0].merge!(endOnKey: builder.endOnKey) if builder.endOnKey
122
+ ncco[0].merge!(timeOut: builder.timeOut) if builder.timeOut
123
+ ncco[0].merge!(beepStart: builder.beepStart) if builder.beepStart
124
+ ncco[0].merge!(eventUrl: builder.eventUrl) if builder.eventUrl
125
+ ncco[0].merge!(eventMethod: builder.eventMethod) if builder.eventMethod
126
+
127
+ ncco
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,72 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Voice::Actions::Stream
6
+ attr_accessor :streamUrl, :level, :bargeIn, :loop
7
+
8
+ def initialize(attributes = {})
9
+ @streamUrl = attributes.fetch(:streamUrl)
10
+ @level = attributes.fetch(:level, nil)
11
+ @bargeIn = attributes.fetch(:bargeIn, nil)
12
+ @loop = attributes.fetch(:loop, nil)
13
+
14
+ after_initialize!
15
+ end
16
+
17
+ def after_initialize!
18
+ verify_stream_url
19
+
20
+ if self.level
21
+ verify_level
22
+ end
23
+
24
+ if self.bargeIn
25
+ verify_barge_in
26
+ end
27
+
28
+ if self.loop
29
+ verify_loop
30
+ end
31
+ end
32
+
33
+ def verify_stream_url
34
+ raise ClientError.new("Expected 'streamUrl' parameter to be an Array containing a single string item") unless self.streamUrl.is_a?(Array)
35
+
36
+ uri = URI.parse(self.streamUrl[0])
37
+
38
+ raise ClientError.new("Invalid 'streamUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
39
+ end
40
+
41
+ def verify_level
42
+ raise ClientError.new("Expected 'level' value to be a number between -1 and 1") unless self.level.between?(-1, 1)
43
+ end
44
+
45
+ def verify_barge_in
46
+ raise ClientError.new("Expected 'bargeIn' value to be a Boolean") unless self.bargeIn == true || self.bargeIn == false
47
+ end
48
+
49
+ def verify_loop
50
+ raise ClientError.new("Expected 'loop' value to be either 1 or 0") unless self.loop == 1 || self.loop == 0
51
+ end
52
+
53
+ def action
54
+ create_stream!(self)
55
+ end
56
+
57
+ def create_stream!(builder)
58
+ ncco = [
59
+ {
60
+ action: 'stream',
61
+ streamUrl: builder.streamUrl
62
+ }
63
+ ]
64
+
65
+ ncco[0].merge!(level: builder.level) if builder.level
66
+ ncco[0].merge!(bargeIn: builder.bargeIn) if (builder.bargeIn || builder.bargeIn == false)
67
+ ncco[0].merge!(loop: builder.loop) if builder.loop
68
+
69
+ ncco
70
+ end
71
+ end
72
+ end