vonage 7.10.0 → 7.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc021f5f0b897743382fe24b1973b1fa1ffa57086b590577d9f794a3fbef5355
4
- data.tar.gz: 500df71d3f79eb6c8de37f5dc694d705526eab298f92cec34e90420290aa8e00
3
+ metadata.gz: 42d5bfc879e0b399da415f92a0f65313c3aa3f22760945c7832996290e7cbebb
4
+ data.tar.gz: be7e53025cad9a1fa877d9749e82ff22fa4c6ec4cb2da63ecefef136269fc810
5
5
  SHA512:
6
- metadata.gz: '049c59c41953de3695a71b722adf03e868bae4edb4f36f145a0e03b61859f512ed508ca3f1e8b1eee54200d058a55265858b9be4f8449c9ea68e60b274ed7282'
7
- data.tar.gz: 57fcf30de159323ef20feee16dec66f1eab1b7360e2b75e17a96f368f54c3015db4f83bd4d9b51c1b69739e5c762d25131e0d66bbd1cd09ec14325bfa5f8daae
6
+ metadata.gz: 29f033e6795e3d52bdef207656a7230925037b04dbdbd57bbdbce4cf74b91842cb9cfcd7e04b9061a5267210905d14b68961dc4daab26bf349dff0ece9a6e659
7
+ data.tar.gz: 43c52d578923fd7a5a7b04b243b040df2ba1cef5dd0c38c37007820207a5ab411a9976a0b42a2dff653b19d6e856ade248163a8856ac93c88dd49209d4cd6b4f
data/lib/vonage/client.rb CHANGED
@@ -117,6 +117,13 @@ module Vonage
117
117
  @sms ||= T.let(SMS.new(config), T.nilable(Vonage::SMS))
118
118
  end
119
119
 
120
+ # @return [Subaccounts]
121
+ #
122
+ sig { returns(T.nilable(Vonage::Subaccounts)) }
123
+ def subaccounts
124
+ @subaccounts ||= T.let(Subaccounts.new(config), T.nilable(Vonage::Subaccounts))
125
+ end
126
+
120
127
  # @return [TFA]
121
128
  #
122
129
  sig { returns(T.nilable(Vonage::TFA)) }
@@ -51,6 +51,7 @@ module Vonage
51
51
 
52
52
  Get = Net::HTTP::Get
53
53
  Put = Net::HTTP::Put
54
+ Patch = Net::HTTP::Patch
54
55
  Post = Net::HTTP::Post
55
56
  Delete = Net::HTTP::Delete
56
57
 
@@ -0,0 +1,11 @@
1
+ # typed: true
2
+
3
+ class Vonage::Subaccounts::BalanceTransfers::ListResponse < Vonage::Response
4
+ include Enumerable
5
+
6
+ def each
7
+ return enum_for(:each) unless block_given?
8
+
9
+ @entity._embedded.balance_transfers.each { |item| yield item }
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # typed: true
2
+
3
+ class Vonage::Subaccounts::CreditTransfers::ListResponse < Vonage::Response
4
+ include Enumerable
5
+
6
+ def each
7
+ return enum_for(:each) unless block_given?
8
+
9
+ @entity._embedded.credit_transfers.each { |item| yield item }
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ # typed: true
2
+
3
+ class Vonage::Subaccounts::ListResponse < Vonage::Response
4
+ include Enumerable
5
+
6
+ def primary_account
7
+ @entity._embedded.primary_account
8
+ end
9
+
10
+ def each
11
+ return enum_for(:each) unless block_given?
12
+
13
+ @entity._embedded.subaccounts.each { |item| yield item }
14
+ end
15
+ end
@@ -0,0 +1,203 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Subaccounts < Namespace
6
+ self.authentication = Basic
7
+
8
+ self.request_body = JSON
9
+
10
+ # Retrieve list of subaccounts.
11
+ #
12
+ # @example
13
+ # response = client.subaccounts.list
14
+ #
15
+ # @see https://developer.vonage.com/en/api/subaccounts#retrieveSubaccountsList
16
+ #
17
+ def list
18
+ request("/accounts/#{@config.api_key}/subaccounts", response_class: ListResponse)
19
+ end
20
+
21
+ # Retrieve a subaccount.
22
+ #
23
+ # @example
24
+ # response = client.subaccounts.find(subaccount_key: 'abc123')
25
+ #
26
+ # @option params [required, String] :subaccount_key
27
+ # The API key for the subaccount you want to retrieve
28
+ #
29
+ # @see https://developer.vonage.com/en/api/subaccounts#retrieveSubaccount
30
+ #
31
+ def find(subaccount_key:)
32
+ request("/accounts/#{@config.api_key}/subaccounts/#{subaccount_key}")
33
+ end
34
+
35
+ # Create a subaccount.
36
+ #
37
+ # @example
38
+ # response = client.subaccounts.create(name: 'Foo')
39
+ #
40
+ # @option params [required, String] :name
41
+ # The name of the subaccount
42
+ #
43
+ # @option params [optional, String] :secret
44
+ # An account secret for use by the subaccount. Can be used in combination with your API key to authenticate your API requests.
45
+ # Requirements:
46
+ # - 8 characters and no more than 25
47
+ # - 1 lower-case letter
48
+ # - 1 capital letter
49
+ # - 1 digit
50
+ # - must be unique
51
+ #
52
+ # @option params [optional, Boolean] :use_primary_account_balance
53
+ # Whether the subaccount uses the primary account balance (true, the default) or has its own balance (false).
54
+ # Once set to `false` cannot be changed back to `true`
55
+ #
56
+ # @see https://developer.vonage.com/en/api/subaccounts#createSubAccount
57
+ #
58
+ def create(name:, **params)
59
+ request("/accounts/#{@config.api_key}/subaccounts", params: params.merge(name: name), type: Post)
60
+ end
61
+
62
+ # Modify a subaccount.
63
+ #
64
+ # @example
65
+ # response = client.subaccounts.update(name: 'Bar')
66
+ #
67
+ # @option params [required, String] :subaccount_key
68
+ # The API key for the subaccount you want to modify
69
+ #
70
+ # @option params [optional, String] :name
71
+ # The name of the subaccount
72
+ #
73
+ # @option params [optional, Boolean] :use_primary_account_balance
74
+ # Whether the subaccount uses the primary account balance (true, the default) or has its own balance (false).
75
+ # Once set to `false` cannot be changed back to `true`
76
+ #
77
+ # @option params [optional, String] :suspended
78
+ # Whether the subaccount is suspended (true) or not (false, the default)
79
+ #
80
+ # @see https://developer.vonage.com/en/api/subaccounts#modifySubaccount
81
+ #
82
+ def update(subaccount_key:, **params)
83
+ request("/accounts/#{@config.api_key}/subaccounts/#{subaccount_key}", params: params, type: Patch)
84
+ end
85
+
86
+ # Retrieve list of credit transfers.
87
+ #
88
+ # @example
89
+ # response = client.subaccounts.list_credit_transfers(start_date: "2023-06-15T15:53:50Z")
90
+ #
91
+ # @option params [optional, String] :start_date
92
+ # The ISO format datetime from which to list transfers. Example: 2019-03-02T16:34:49Z.
93
+ # Defaults to "1970-01-01T00:00:00Z" if omitted
94
+ #
95
+ # @option params [optional, String] :end_date
96
+ # The ISO format datetime to which to list transfers. Example: 2019-03-02T16:34:49Z.
97
+ # If absent then all transfers until now is returned.
98
+ #
99
+ # @option params [optional, String] :subaccount
100
+ # Subaccount to filter by.
101
+ #
102
+ # @see https://developer.vonage.com/en/api/subaccounts#retrieveCreditTransfers
103
+ #
104
+ def list_credit_transfers(start_date: "1970-01-01T00:00:00Z", **params)
105
+ path = "/accounts/#{@config.api_key}/credit-transfers?#{Params.encode(params.merge(start_date: start_date))}"
106
+
107
+ request(path, response_class: CreditTransfers::ListResponse)
108
+ end
109
+
110
+ # Transfer credit.
111
+ #
112
+ # @example
113
+ # response = client.subaccounts.transfer_credit(from: 'abc123', to: 'def456', amount: 10.00)
114
+ #
115
+ # @option params [required, String] :from
116
+ # The API key of the account or subaccount to transfer credit from.
117
+ #
118
+ # @option params [required, String] :to
119
+ # The API key of the account or subaccount to transfer credit to.
120
+ #
121
+ # @option params [required, Number] :amount
122
+ # The amount to transfer
123
+ #
124
+ # @option params [optional, String] :reference
125
+ # A reference for the transfer.
126
+ #
127
+ # @see https://developer.vonage.com/en/api/subaccounts#transferCredit
128
+ #
129
+ def transfer_credit(from:, to:, amount:, **params)
130
+ request("/accounts/#{@config.api_key}/credit-transfers", params: params.merge(from: from, to: to, amount: amount), type: Post)
131
+ end
132
+
133
+ # Retrieve list of balance transfers.
134
+ #
135
+ # @example
136
+ # response = client.subaccounts.list_balance_transfers(start_date: "2023-06-15T15:53:50Z")
137
+ #
138
+ # @option params [optional, String] :start_date
139
+ # The ISO format datetime from which to list transfers. Example: 2019-03-02T16:34:49Z.
140
+ # Defaults to "1970-01-01T00:00:00Z" if omitted
141
+ #
142
+ # @option params [optional, String] :end_date
143
+ # The ISO format datetime to which to list transfers. Example: 2019-03-02T16:34:49Z.
144
+ # If absent then all transfers until now is returned.
145
+ #
146
+ # @option params [optional, String] :subaccount
147
+ # Subaccount to filter by.
148
+ #
149
+ # @see https://developer.vonage.com/en/api/subaccounts#retrieveBalanceTransfers
150
+ #
151
+ def list_balance_transfers(start_date: "1970-01-01T00:00:00Z", **params)
152
+ path = "/accounts/#{@config.api_key}/balance-transfers?#{Params.encode(params.merge(start_date: start_date))}"
153
+
154
+ request(path, response_class: BalanceTransfers::ListResponse)
155
+ end
156
+
157
+ # Transfer balance.
158
+ #
159
+ # @example
160
+ # response = client.subaccounts.transfer_balance(from: 'abc123', to: 'def456', amount: 10.00)
161
+ #
162
+ # @option params [required, String] :from
163
+ # The API key of the account or subaccount to transfer balance from.
164
+ #
165
+ # @option params [required, String] :to
166
+ # The API key of the account or subaccount to transfer balance to.
167
+ #
168
+ # @option params [required, Number] :amount
169
+ # The amount to transfer
170
+ #
171
+ # @option params [optional, String] :reference
172
+ # A reference for the transfer.
173
+ #
174
+ # @see https://developer.vonage.com/en/api/subaccounts#transferBalance
175
+ #
176
+ def transfer_balance(from:, to:, amount:, **params)
177
+ request("/accounts/#{@config.api_key}/balance-transfers", params: params.merge(from: from, to: to, amount: amount), type: Post)
178
+ end
179
+
180
+ # Transfer number.
181
+ #
182
+ # @example
183
+ # response = client.subaccounts.transfer_number(from: 'abc123', to: 'def456', number: 447900000000, country: 'GB')
184
+ #
185
+ # @option params [required, String] :from
186
+ # The API key of the account or subaccount to transfer the number from.
187
+ #
188
+ # @option params [required, String] :to
189
+ # The API key of the account or subaccount to transfer the number to.
190
+ #
191
+ # @option params [required, Number] :number
192
+ # The number to transfer
193
+ #
194
+ # @option params [required, String] :country
195
+ # An ISO-3166-1 alpha 2 code representing the country for the number, e.g. GB.
196
+ #
197
+ # @see https://developer.vonage.com/en/api/subaccounts#transferNumber
198
+ #
199
+ def transfer_number(from:, to:, number:, country:)
200
+ request("/accounts/#{@config.api_key}/transfer-number", params: {from: from, to: to, number: number, country: country}, type: Post)
201
+ end
202
+ end
203
+ end
@@ -1,5 +1,5 @@
1
1
  # typed: strong
2
2
 
3
3
  module Vonage
4
- VERSION = "7.10.0"
4
+ VERSION = "7.12.0"
5
5
  end
@@ -2,9 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
  require 'phonelib'
4
4
 
5
- module Vonage
5
+ module Vonage
6
6
  class Voice::Actions::Connect
7
- attr_accessor :endpoint, :from, :eventType, :timeout, :limit, :machineDetection, :eventUrl, :eventMethod, :ringbackTone
7
+ attr_accessor :endpoint, :from, :eventType, :timeout, :limit, :machineDetection, :advanced_machine_detection, :eventUrl, :eventMethod, :ringbackTone
8
8
 
9
9
  def initialize(attributes = {})
10
10
  @endpoint = attributes.fetch(:endpoint)
@@ -13,6 +13,7 @@ module Vonage
13
13
  @timeout = attributes.fetch(:timeout, nil)
14
14
  @limit = attributes.fetch(:limit, nil)
15
15
  @machineDetection = attributes.fetch(:machineDetection, nil)
16
+ @advanced_machine_detection = attributes.fetch(:advanced_machine_detection, nil)
16
17
  @eventUrl = attributes.fetch(:eventUrl, nil)
17
18
  @eventMethod = attributes.fetch(:eventMethod, nil)
18
19
  @ringbackTone = attributes.fetch(:ringbackTone, nil)
@@ -39,6 +40,10 @@ module Vonage
39
40
  verify_machine_detection
40
41
  end
41
42
 
43
+ if self.advanced_machine_detection
44
+ verify_advanced_machine_detection
45
+ end
46
+
42
47
  if self.eventUrl
43
48
  verify_event_url
44
49
  end
@@ -82,6 +87,25 @@ module Vonage
82
87
  raise ClientError.new("Invalid 'machineDetection' value, must be either: 'continue' or 'hangup' if defined") unless self.machineDetection == 'continue' || self.machineDetection == 'hangup'
83
88
  end
84
89
 
90
+ def verify_advanced_machine_detection
91
+ raise ClientError.new("Invalid 'advanced_machine_detection' value, must be a Hash") unless self.advanced_machine_detection.is_a?(Hash)
92
+ verify_advanced_machine_detection_behavior if self.advanced_machine_detection[:behavior]
93
+ verify_advanced_machine_detection_mode if self.advanced_machine_detection[:mode]
94
+ verify_advanced_machine_detection_beep_timeout if self.advanced_machine_detection[:beep_timeout]
95
+ end
96
+
97
+ def verify_advanced_machine_detection_behavior
98
+ raise ClientError.new("Invalid 'advanced_machine_detection[:behavior]' value, must be a `continue` or `hangup`") unless ['continue', 'hangup'].include?(self.advanced_machine_detection[:behavior])
99
+ end
100
+
101
+ def verify_advanced_machine_detection_mode
102
+ raise ClientError.new("Invalid 'advanced_machine_detection[:mode]' value, must be a `detect` or `detect_beep`") unless ['detect', 'detect_beep'].include?(self.advanced_machine_detection[:mode])
103
+ end
104
+
105
+ def verify_advanced_machine_detection_beep_timeout
106
+ raise ClientError.new("Invalid 'advanced_machine_detection[:beep_timeout]' value, must be between 45 and 120") unless self.advanced_machine_detection[:beep_timeout].between?(45, 120)
107
+ end
108
+
85
109
  def verify_event_url
86
110
  uri = URI.parse(self.eventUrl)
87
111
 
@@ -196,4 +220,4 @@ module Vonage
196
220
  }
197
221
  end
198
222
  end
199
- end
223
+ end
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
  module Vonage
4
4
  class Voice::Actions::Talk
5
- attr_accessor :text, :bargeIn, :loop, :level, :language, :style
5
+ attr_accessor :text, :bargeIn, :loop, :level, :language, :style, :premium
6
6
 
7
7
  def initialize(attributes= {})
8
8
  @text = attributes.fetch(:text)
@@ -11,6 +11,7 @@ module Vonage
11
11
  @level = attributes.fetch(:level, nil)
12
12
  @language = attributes.fetch(:language, nil)
13
13
  @style = attributes.fetch(:style, nil)
14
+ @premium = attributes.fetch(:premium, nil)
14
15
 
15
16
  after_initialize!
16
17
  end
@@ -31,6 +32,10 @@ module Vonage
31
32
  if self.style
32
33
  verify_style
33
34
  end
35
+
36
+ if self.premium
37
+ verify_premium
38
+ end
34
39
  end
35
40
 
36
41
  def verify_barge_in
@@ -49,6 +54,10 @@ module Vonage
49
54
  raise ClientError.new("Expected 'style' value to be an Integer") unless self.style.is_a?(Integer)
50
55
  end
51
56
 
57
+ def verify_premium
58
+ raise ClientError.new("Expected 'premium' value to be a Boolean") unless self.premium == true || self.premium == false
59
+ end
60
+
52
61
  def action
53
62
  create_talk!(self)
54
63
  end
@@ -70,4 +79,4 @@ module Vonage
70
79
  ncco
71
80
  end
72
81
  end
73
- end
82
+ end
@@ -12,8 +12,18 @@ module Vonage
12
12
  # @option params [required, String] :text
13
13
  # The text to read.
14
14
  #
15
+ # @option params [String] :language
16
+ # The language to use. See {https://developer.vonage.com/en/api/voice#startTalk-req-body} for a list of valid language codes.
17
+ #
18
+ # @option params [Integer] :style
19
+ # The vocal style, as identified by an assigned integer.
20
+ # See {https://developer.vonage.com/en/voice/voice-api/concepts/text-to-speech#supported-languages} for a list of available styles.
21
+ #
22
+ # @option params [Boolean] :premium
23
+ # Set to `true` to use the premium version of the specified style if available, otherwise the standard version will be used.
24
+ #
15
25
  # @option params [String] :voice_name
16
- # The voice & language to use.
26
+ # The voice & language to use. [DEPRECATED: use `language` and `style` instead].
17
27
  #
18
28
  # @option params [Integer] :loop
19
29
  # The number of times to repeat the text the file, 0 for infinite.
data/lib/vonage/voice.rb CHANGED
@@ -48,6 +48,17 @@ module Vonage
48
48
  # @option params [String] :machine_detection
49
49
  # Configure the behavior when Vonage detects that the call is answered by voicemail.
50
50
  #
51
+ # @option params [Hash] :advanced_machine_detection
52
+ # Configure the behavior of Vonage's advanced machine detection. Overrides machine_detection if both are set.
53
+ # Hash with three possible properties:
54
+ # - :behavior [String]: Must be one of `continue` or `hangup`. When hangup is used, the call will be terminated if a
55
+ # machine is detected. When continue is used, the call will continue even if a machine is detected.
56
+ # - :mode [String]: Must be one of `detect` or `detect_beep`. Detect if machine answered and sends a human or
57
+ # machine status in the webhook payload. When set to `detect_beep`, the system also attempts to detect
58
+ # voice mail beep and sends an additional parameter `sub_state` in the webhook with the value `beep_start`.
59
+ # - :beep_timeout [Integer]: Min: 45, Max: 120. Maximum time in seconds Vonage should wait for a machine beep
60
+ # to be detected. A machine event with `sub_state` set to `beep_timeout` will be sent if the timeout is exceeded.
61
+ #
51
62
  # @option params [Integer] :length_timer
52
63
  # Set the number of seconds that elapse before Vonage hangs up after the call state changes to in_progress.
53
64
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vonage
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.10.0
4
+ version: 7.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vonage
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-31 00:00:00.000000000 Z
11
+ date: 2023-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: vonage-jwt
@@ -149,6 +149,10 @@ files:
149
149
  - lib/vonage/service_error.rb
150
150
  - lib/vonage/signature.rb
151
151
  - lib/vonage/sms.rb
152
+ - lib/vonage/subaccounts.rb
153
+ - lib/vonage/subaccounts/balance_transfers/list_response.rb
154
+ - lib/vonage/subaccounts/credit_transfers/list_response.rb
155
+ - lib/vonage/subaccounts/list_response.rb
152
156
  - lib/vonage/tfa.rb
153
157
  - lib/vonage/user_agent.rb
154
158
  - lib/vonage/verify.rb
@@ -168,7 +172,6 @@ files:
168
172
  - lib/vonage/voice/actions/conversation.rb
169
173
  - lib/vonage/voice/actions/input.rb
170
174
  - lib/vonage/voice/actions/notify.rb
171
- - lib/vonage/voice/actions/pay.rb
172
175
  - lib/vonage/voice/actions/record.rb
173
176
  - lib/vonage/voice/actions/stream.rb
174
177
  - lib/vonage/voice/actions/talk.rb
@@ -1,107 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
- module Vonage
4
- class Voice::Actions::Pay
5
- attr_accessor :amount, :currency, :eventUrl, :prompts, :voice
6
-
7
- def initialize(attributes= {})
8
- @amount = attributes.fetch(:amount)
9
- @currency = attributes.fetch(:currency, nil)
10
- @eventUrl = attributes.fetch(:eventUrl, nil)
11
- @prompts = attributes.fetch(:prompts, nil)
12
- @voice = attributes.fetch(:voice, nil)
13
-
14
- after_initialize!
15
- end
16
-
17
- def action
18
- create_pay!(self)
19
- end
20
-
21
- def create_pay!(builder)
22
- ncco = [
23
- {
24
- action: 'pay',
25
- amount: builder.amount
26
- }
27
- ]
28
-
29
- ncco[0].merge!(currency: builder.currency) if builder.currency
30
- ncco[0].merge!(eventUrl: builder.eventUrl) if builder.eventUrl
31
- ncco[0].merge!(prompts: builder.prompts) if builder.prompts
32
- ncco[0].merge!(voice: builder.voice) if builder.voice
33
-
34
- ncco
35
- end
36
-
37
- private
38
-
39
- def after_initialize!
40
- verify_amount
41
-
42
- if self.eventUrl
43
- verify_event_url
44
- end
45
-
46
- if self.prompts
47
- verify_prompts
48
- end
49
-
50
- if self.voice
51
- verify_voice
52
- end
53
- end
54
-
55
- def verify_amount
56
- verify_amount_class
57
- verify_amount_value
58
- end
59
-
60
- def verify_event_url
61
- raise ClientError.new("Expected 'eventUrl' parameter to be an Array containing a single string item") unless self.eventUrl.is_a?(Array)
62
-
63
- uri = URI.parse(self.eventUrl[0])
64
-
65
- raise ClientError.new("Invalid 'eventUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
66
- end
67
-
68
- def verify_prompts
69
- verify_prompts_structure
70
- verify_prompts_values
71
- end
72
-
73
- def verify_voice
74
- verify_voice_structure
75
- verify_voice_style if self.voice[:style]
76
- end
77
-
78
- def verify_amount_class
79
- raise ClientError.new("Invalid 'amount' value, must be a float") unless self.amount.is_a?(Float)
80
- end
81
-
82
- def verify_amount_value
83
- raise ClientError.new("Invalid 'amount' value, must be greater than 0") unless self.amount > 0
84
- end
85
-
86
- def verify_prompts_structure
87
- raise ClientError.new("Invalid 'prompt', must be an array of at least one hash") unless self.prompts.is_a?(Array) && !self.prompts.empty? && self.prompts.all?(Hash)
88
- end
89
-
90
- def verify_prompts_values
91
- self.prompts.each do |prompt|
92
- prompt_keys = prompt.keys
93
- [:type, :text, :errors].each do |key|
94
- raise ClientError.new("Invalid 'prompt', '#{key}' is required") unless prompt_keys.include?(key)
95
- end
96
- end
97
- end
98
-
99
- def verify_voice_structure
100
- raise ClientError.new("Expected 'voice' value to be a Hash") unless self.voice.is_a?(Hash)
101
- end
102
-
103
- def verify_voice_style
104
- raise ClientError.new("Expected 'style' value to be an Integer") unless self.voice[:style].is_a?(Integer)
105
- end
106
- end
107
- end