voiceml 0.8.1 → 0.9.2

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.
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module VoiceML
6
+ # Twilio-compatible Notification resource — a log row for a specific webhook /
7
+ # TwiML invocation failure (HTTP non-2xx, parse error, etc.).
8
+ #
9
+ # VoiceML treats `/Notifications` and `/Calls/{Sid}/Notifications` as compat
10
+ # stubs (always-empty list, fetch-by-sid returns 404), so this model decodes
11
+ # Twilio's documented shape for migration tooling and conformance checks
12
+ # without implying voiceml emits notification rows.
13
+ #
14
+ # The same resource shape backs both account-scoped and call-scoped fetches.
15
+ class Notification
16
+ ATTRIBUTES = %w[
17
+ sid account_sid call_sid api_version
18
+ error_code more_info message_date message_text log
19
+ request_method request_url request_variables
20
+ response_body response_headers
21
+ date_created date_updated uri
22
+ ].freeze
23
+
24
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
25
+
26
+ def initialize(attrs = {})
27
+ ATTRIBUTES.each do |field|
28
+ value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
29
+ instance_variable_set("@#{field}", value)
30
+ end
31
+ end
32
+
33
+ def self.from_hash(hash)
34
+ return nil if hash.nil?
35
+
36
+ new(hash)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module VoiceML
6
+ # Twilio-compatible OutgoingCallerId resource. The `sid` is `PN`-prefixed
7
+ # to mirror Twilio (caller-id resources share the IncomingPhoneNumber SID
8
+ # space upstream); `phone_number` carries the verified E.164 number.
9
+ class OutgoingCallerId
10
+ ATTRIBUTES = %w[
11
+ sid account_sid friendly_name phone_number
12
+ date_created date_updated uri
13
+ ].freeze
14
+
15
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
16
+
17
+ def initialize(attrs = {})
18
+ ATTRIBUTES.each do |field|
19
+ value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
20
+ instance_variable_set("@#{field}", value)
21
+ end
22
+ end
23
+
24
+ def self.from_hash(hash)
25
+ return nil if hash.nil?
26
+
27
+ new(hash)
28
+ end
29
+ end
30
+
31
+ # Paginated `GET /OutgoingCallerIds` response.
32
+ class OutgoingCallerIdList
33
+ include Pageable
34
+
35
+ attr_reader :outgoing_caller_ids
36
+
37
+ def initialize(hash = {})
38
+ assign_page_fields(hash)
39
+ @outgoing_caller_ids =
40
+ (hash['outgoing_caller_ids'] || []).map { |o| OutgoingCallerId.from_hash(o) }
41
+ end
42
+
43
+ def self.from_hash(hash)
44
+ new(hash || {})
45
+ end
46
+ end
47
+
48
+ # `POST /OutgoingCallerIds` response — the verify-by-callback flow used to
49
+ # provision a new outgoing caller id. No `sid` on the wire (the resource
50
+ # doesn't exist until the validation_code is dialled back); the
51
+ # `validation_code` is what the user is prompted to enter on the live call.
52
+ class ValidationRequest
53
+ ATTRIBUTES = %w[account_sid call_sid friendly_name phone_number validation_code].freeze
54
+
55
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
56
+
57
+ def initialize(attrs = {})
58
+ ATTRIBUTES.each do |field|
59
+ value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
60
+ instance_variable_set("@#{field}", value)
61
+ end
62
+ end
63
+
64
+ def self.from_hash(hash)
65
+ return nil if hash.nil?
66
+
67
+ new(hash)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,231 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+ require_relative 'voice_v1' # V1Pageable lives here; PricingCountriesList reuses the `meta` envelope
5
+
6
+ module VoiceML
7
+ # Twilio Pricing (pricing.twilio.com) v1/v2 response models.
8
+ #
9
+ # VoiceML has no dedicated pricing subdomain, so these ride the default host
10
+ # (`voiceml.voicetel.com`) under `/v1` and `/v2`. All operations are read-only GETs.
11
+ # Every field is permissive/nullable — VoiceML is NANP-only, so a `Countries` list
12
+ # carries exactly one entry and a `Numbers` fetch 404s for non-NANP destinations.
13
+
14
+ # --- Price leaves ---------------------------------------------------------
15
+
16
+ class PricingInboundCallPrice
17
+ ATTRIBUTES = %w[base_price current_price number_type].freeze
18
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
19
+ def initialize(attrs = {})
20
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
21
+ end
22
+ def self.from_hash(h); h.nil? ? nil : new(h); end
23
+ end
24
+
25
+ class PricingOutboundCallPrice
26
+ ATTRIBUTES = %w[base_price current_price].freeze
27
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
28
+ def initialize(attrs = {})
29
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
30
+ end
31
+ def self.from_hash(h); h.nil? ? nil : new(h); end
32
+ end
33
+
34
+ class PricingOutboundCallPriceWithOrigin
35
+ attr_reader :origination_prefixes, :base_price, :current_price
36
+ def initialize(attrs = {})
37
+ @origination_prefixes = attrs['origination_prefixes'] || attrs[:origination_prefixes] || []
38
+ @base_price = attrs['base_price'] || attrs[:base_price]
39
+ @current_price = attrs['current_price'] || attrs[:current_price]
40
+ end
41
+ def self.from_hash(h); h.nil? ? nil : new(h); end
42
+ end
43
+
44
+ class PricingOutboundPrefixPrice
45
+ attr_reader :prefixes, :base_price, :current_price, :friendly_name
46
+ def initialize(attrs = {})
47
+ @prefixes = attrs['prefixes'] || attrs[:prefixes] || []
48
+ @base_price = attrs['base_price'] || attrs[:base_price]
49
+ @current_price = attrs['current_price'] || attrs[:current_price]
50
+ @friendly_name = attrs['friendly_name'] || attrs[:friendly_name]
51
+ end
52
+ def self.from_hash(h); h.nil? ? nil : new(h); end
53
+ end
54
+
55
+ class PricingOutboundPrefixPriceWithOrigin
56
+ attr_reader :origination_prefixes, :destination_prefixes, :base_price, :current_price, :friendly_name
57
+ def initialize(attrs = {})
58
+ @origination_prefixes = attrs['origination_prefixes'] || attrs[:origination_prefixes] || []
59
+ @destination_prefixes = attrs['destination_prefixes'] || attrs[:destination_prefixes] || []
60
+ @base_price = attrs['base_price'] || attrs[:base_price]
61
+ @current_price = attrs['current_price'] || attrs[:current_price]
62
+ @friendly_name = attrs['friendly_name'] || attrs[:friendly_name]
63
+ end
64
+ def self.from_hash(h); h.nil? ? nil : new(h); end
65
+ end
66
+
67
+ class PricingOutboundSMSPrice
68
+ attr_reader :carrier, :mcc, :mnc, :prices
69
+ def initialize(attrs = {})
70
+ @carrier = attrs['carrier'] || attrs[:carrier]
71
+ @mcc = attrs['mcc'] || attrs[:mcc]
72
+ @mnc = attrs['mnc'] || attrs[:mnc]
73
+ @prices = (attrs['prices'] || attrs[:prices] || []).map { |h| PricingInboundCallPrice.from_hash(h) }
74
+ end
75
+ def self.from_hash(h); h.nil? ? nil : new(h); end
76
+ end
77
+
78
+ class PricingPhoneNumberPrice
79
+ ATTRIBUTES = %w[number_type base_price current_price].freeze
80
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
81
+ def initialize(attrs = {})
82
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
83
+ end
84
+ def self.from_hash(h); h.nil? ? nil : new(h); end
85
+ end
86
+
87
+ # --- Countries list envelope ----------------------------------------------
88
+
89
+ class PricingCountryRef
90
+ ATTRIBUTES = %w[country iso_country url].freeze
91
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
92
+ def initialize(attrs = {})
93
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
94
+ end
95
+ def self.from_hash(h); h.nil? ? nil : new(h); end
96
+ end
97
+
98
+ class PricingCountriesList
99
+ include V1Pageable
100
+ attr_reader :countries
101
+ def initialize(hash = {})
102
+ assign_meta_fields(hash)
103
+ @countries = (hash['countries'] || []).map { |h| PricingCountryRef.from_hash(h) }
104
+ end
105
+ end
106
+
107
+ # --- Pricing v1 country / number bodies -----------------------------------
108
+
109
+ class PricingVoiceCountry
110
+ attr_reader :country, :iso_country, :outbound_prefix_prices, :inbound_call_prices, :price_unit, :url
111
+ def initialize(attrs = {})
112
+ @country = attrs['country'] || attrs[:country]
113
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
114
+ @outbound_prefix_prices =
115
+ (attrs['outbound_prefix_prices'] || []).map { |h| PricingOutboundPrefixPrice.from_hash(h) }
116
+ @inbound_call_prices =
117
+ (attrs['inbound_call_prices'] || []).map { |h| PricingInboundCallPrice.from_hash(h) }
118
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
119
+ @url = attrs['url'] || attrs[:url]
120
+ end
121
+ def self.from_hash(h); h.nil? ? nil : new(h); end
122
+ end
123
+
124
+ class PricingVoiceNumber
125
+ attr_reader :number, :country, :iso_country, :outbound_call_price, :inbound_call_price, :price_unit, :url
126
+ def initialize(attrs = {})
127
+ @number = attrs['number'] || attrs[:number]
128
+ @country = attrs['country'] || attrs[:country]
129
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
130
+ @outbound_call_price = PricingOutboundCallPrice.from_hash(attrs['outbound_call_price'])
131
+ @inbound_call_price = PricingInboundCallPrice.from_hash(attrs['inbound_call_price'])
132
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
133
+ @url = attrs['url'] || attrs[:url]
134
+ end
135
+ def self.from_hash(h); h.nil? ? nil : new(h); end
136
+ end
137
+
138
+ class PricingMessagingCountry
139
+ attr_reader :country, :iso_country, :outbound_sms_prices, :inbound_sms_prices, :price_unit, :url
140
+ def initialize(attrs = {})
141
+ @country = attrs['country'] || attrs[:country]
142
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
143
+ @outbound_sms_prices =
144
+ (attrs['outbound_sms_prices'] || []).map { |h| PricingOutboundSMSPrice.from_hash(h) }
145
+ @inbound_sms_prices =
146
+ (attrs['inbound_sms_prices'] || []).map { |h| PricingInboundCallPrice.from_hash(h) }
147
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
148
+ @url = attrs['url'] || attrs[:url]
149
+ end
150
+ def self.from_hash(h); h.nil? ? nil : new(h); end
151
+ end
152
+
153
+ class PricingPhoneNumberCountry
154
+ attr_reader :country, :iso_country, :phone_number_prices, :price_unit, :url
155
+ def initialize(attrs = {})
156
+ @country = attrs['country'] || attrs[:country]
157
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
158
+ @phone_number_prices =
159
+ (attrs['phone_number_prices'] || []).map { |h| PricingPhoneNumberPrice.from_hash(h) }
160
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
161
+ @url = attrs['url'] || attrs[:url]
162
+ end
163
+ def self.from_hash(h); h.nil? ? nil : new(h); end
164
+ end
165
+
166
+ # --- Pricing v2 country / number bodies -----------------------------------
167
+
168
+ class PricingVoiceCountryV2
169
+ attr_reader :country, :iso_country, :outbound_prefix_prices, :inbound_call_prices, :price_unit, :url
170
+ def initialize(attrs = {})
171
+ @country = attrs['country'] || attrs[:country]
172
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
173
+ @outbound_prefix_prices =
174
+ (attrs['outbound_prefix_prices'] || []).map { |h| PricingOutboundPrefixPriceWithOrigin.from_hash(h) }
175
+ @inbound_call_prices =
176
+ (attrs['inbound_call_prices'] || []).map { |h| PricingInboundCallPrice.from_hash(h) }
177
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
178
+ @url = attrs['url'] || attrs[:url]
179
+ end
180
+ def self.from_hash(h); h.nil? ? nil : new(h); end
181
+ end
182
+
183
+ class PricingVoiceNumberV2
184
+ attr_reader :destination_number, :origination_number, :country, :iso_country,
185
+ :outbound_call_prices, :inbound_call_price, :price_unit, :url
186
+ def initialize(attrs = {})
187
+ @destination_number = attrs['destination_number'] || attrs[:destination_number]
188
+ @origination_number = attrs['origination_number'] || attrs[:origination_number]
189
+ @country = attrs['country'] || attrs[:country]
190
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
191
+ @outbound_call_prices =
192
+ (attrs['outbound_call_prices'] || []).map { |h| PricingOutboundCallPriceWithOrigin.from_hash(h) }
193
+ @inbound_call_price = PricingInboundCallPrice.from_hash(attrs['inbound_call_price'])
194
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
195
+ @url = attrs['url'] || attrs[:url]
196
+ end
197
+ def self.from_hash(h); h.nil? ? nil : new(h); end
198
+ end
199
+
200
+ class PricingTrunkingCountry
201
+ attr_reader :country, :iso_country, :terminating_prefix_prices, :originating_call_prices, :price_unit, :url
202
+ def initialize(attrs = {})
203
+ @country = attrs['country'] || attrs[:country]
204
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
205
+ @terminating_prefix_prices =
206
+ (attrs['terminating_prefix_prices'] || []).map { |h| PricingOutboundPrefixPriceWithOrigin.from_hash(h) }
207
+ @originating_call_prices =
208
+ (attrs['originating_call_prices'] || []).map { |h| PricingInboundCallPrice.from_hash(h) }
209
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
210
+ @url = attrs['url'] || attrs[:url]
211
+ end
212
+ def self.from_hash(h); h.nil? ? nil : new(h); end
213
+ end
214
+
215
+ class PricingTrunkingNumber
216
+ attr_reader :destination_number, :origination_number, :country, :iso_country,
217
+ :terminating_prefix_prices, :originating_call_price, :price_unit, :url
218
+ def initialize(attrs = {})
219
+ @destination_number = attrs['destination_number'] || attrs[:destination_number]
220
+ @origination_number = attrs['origination_number'] || attrs[:origination_number]
221
+ @country = attrs['country'] || attrs[:country]
222
+ @iso_country = attrs['iso_country'] || attrs[:iso_country]
223
+ @terminating_prefix_prices =
224
+ (attrs['terminating_prefix_prices'] || []).map { |h| PricingOutboundPrefixPriceWithOrigin.from_hash(h) }
225
+ @originating_call_price = PricingInboundCallPrice.from_hash(attrs['originating_call_price'])
226
+ @price_unit = attrs['price_unit'] || attrs[:price_unit]
227
+ @url = attrs['url'] || attrs[:url]
228
+ end
229
+ def self.from_hash(h); h.nil? ? nil : new(h); end
230
+ end
231
+ end
@@ -14,4 +14,18 @@ module VoiceML
14
14
  end
15
15
  def self.from_hash(h); h.nil? ? nil : new(h); end
16
16
  end
17
+
18
+ # Twilio routes/v2 Inbound Processing Region binding for a claimed phone number.
19
+ # Keyed by E.164 phone number or its PN sid; account resolved from HTTP Basic auth.
20
+ class RoutesV2PhoneNumber
21
+ ATTRIBUTES = %w[
22
+ sid phone_number account_sid friendly_name voice_region url
23
+ date_created date_updated
24
+ ].freeze
25
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
26
+ def initialize(attrs = {})
27
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
28
+ end
29
+ def self.from_hash(h); h.nil? ? nil : new(h); end
30
+ end
17
31
  end
@@ -37,6 +37,7 @@ module VoiceML
37
37
  assign_page_fields(hash)
38
38
  @domains = (hash['domains'] || []).map { |h| SipDomain.from_hash(h) }
39
39
  end
40
+ def self.from_hash(hash); new(hash || {}); end
40
41
  end
41
42
 
42
43
  # SipCredentialList — `CL...`.
@@ -58,6 +59,7 @@ module VoiceML
58
59
  assign_page_fields(hash)
59
60
  @credential_lists = (hash['credential_lists'] || []).map { |h| SipCredentialList.from_hash(h) }
60
61
  end
62
+ def self.from_hash(hash); new(hash || {}); end
61
63
  end
62
64
 
63
65
  # SipCredential — `CR...`. Password is write-only (never returned).
@@ -82,6 +84,7 @@ module VoiceML
82
84
  assign_page_fields(hash)
83
85
  @credentials = (hash['credentials'] || []).map { |h| SipCredential.from_hash(h) }
84
86
  end
87
+ def self.from_hash(hash); new(hash || {}); end
85
88
  end
86
89
 
87
90
  # SipIpAccessControlList — `AL...`.
@@ -103,6 +106,7 @@ module VoiceML
103
106
  assign_page_fields(hash)
104
107
  @ip_access_control_lists = (hash['ip_access_control_lists'] || []).map { |h| SipIpAccessControlList.from_hash(h) }
105
108
  end
109
+ def self.from_hash(hash); new(hash || {}); end
106
110
  end
107
111
 
108
112
  # SipIpAddress — `IP...`.
@@ -126,6 +130,7 @@ module VoiceML
126
130
  assign_page_fields(hash)
127
131
  @ip_addresses = (hash['ip_addresses'] || []).map { |h| SipIpAddress.from_hash(h) }
128
132
  end
133
+ def self.from_hash(hash); new(hash || {}); end
129
134
  end
130
135
 
131
136
  # SipDomainMapping — round-trip shape for every domain mapping sub-resource.
@@ -149,6 +154,7 @@ module VoiceML
149
154
  assign_page_fields(hash)
150
155
  @credential_list_mappings = (hash['credential_list_mappings'] || []).map { |h| SipDomainMapping.from_hash(h) }
151
156
  end
157
+ def self.from_hash(hash); new(hash || {}); end
152
158
  end
153
159
 
154
160
  class SipIpAccessControlListMappingList
@@ -158,5 +164,21 @@ module VoiceML
158
164
  assign_page_fields(hash)
159
165
  @ip_access_control_list_mappings = (hash['ip_access_control_list_mappings'] || []).map { |h| SipDomainMapping.from_hash(h) }
160
166
  end
167
+ def self.from_hash(hash); new(hash || {}); end
168
+ end
169
+
170
+ # SipAuthMappingList — page envelope used by all four `/Auth/*` mapping list
171
+ # endpoints. Twilio's spec uses a generic `contents` envelope key here (not
172
+ # `credential_list_mappings` / `ip_access_control_list_mappings`) because
173
+ # the same list shape is reused across CredentialList and IpAccessControlList
174
+ # auth mappings; the inner items decode as SipDomainMapping either way.
175
+ class SipAuthMappingList
176
+ include Pageable
177
+ attr_reader :contents
178
+ def initialize(hash = {})
179
+ assign_page_fields(hash)
180
+ @contents = (hash['contents'] || []).map { |h| SipDomainMapping.from_hash(h) }
181
+ end
182
+ def self.from_hash(hash); new(hash || {}); end
161
183
  end
162
184
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module VoiceML
6
+ # Twilio-compatible UserDefinedMessage resource — out-of-band messages a
7
+ # caller can attach to an in-progress call, delivered via the SDK 2.x
8
+ # WebSocket. VoiceML doesn't surface this as a first-class resource yet;
9
+ # the model exists to decode the response shape (KX-prefixed sid +
10
+ # account/call sids) for conformance and round-trip tooling.
11
+ class UserDefinedMessage
12
+ ATTRIBUTES = %w[
13
+ sid account_sid call_sid date_created
14
+ ].freeze
15
+
16
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
17
+
18
+ def initialize(attrs = {})
19
+ ATTRIBUTES.each do |field|
20
+ value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
21
+ instance_variable_set("@#{field}", value)
22
+ end
23
+ end
24
+
25
+ def self.from_hash(hash)
26
+ return nil if hash.nil?
27
+
28
+ new(hash)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module VoiceML
6
+ # Twilio Voice v1 (voice.twilio.com/v1) resources.
7
+ #
8
+ # Distinct from the 2010-04-01 surface in two ways:
9
+ # - No `/Accounts/{AccountSid}` segment — account resolves from HTTP Basic auth.
10
+ # - List pages carry a `meta` envelope (URLs + page/page_size + key) instead of
11
+ # the flat Twilio2010 `next_page_uri` shape.
12
+ #
13
+ # Six resources implemented for v0.9.0:
14
+ # - ByocTrunk (BY...) — bring-your-own-carrier trunk
15
+ # - ConnectionPolicy (NY...) — origination policy
16
+ # - ConnectionPolicyTarget (NE...)
17
+ # - Settings — DialingPermissions inheritance
18
+ # - SourceIpMapping (IB...) — bind IpRecord -> SipDomain
19
+ # - IpRecord (IL...) — standalone allowed source IP
20
+
21
+ # Shared `meta` envelope for `/v1/*` list responses.
22
+ module V1Pageable
23
+ META_FIELDS = %w[first_page_url next_page_url previous_page_url url page page_size key].freeze
24
+
25
+ META_FIELDS.each { |f| attr_reader f.to_sym }
26
+
27
+ def assign_meta_fields(hash)
28
+ meta = hash['meta'] || {}
29
+ META_FIELDS.each { |f| instance_variable_set("@#{f}", meta[f]) }
30
+ end
31
+ end
32
+
33
+ # VoiceV1IpRecord — `IL...`.
34
+ class VoiceV1IpRecord
35
+ ATTRIBUTES = %w[
36
+ account_sid sid friendly_name ip_address cidr_prefix_length
37
+ date_created date_updated url
38
+ ].freeze
39
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
40
+ def initialize(attrs = {})
41
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
42
+ end
43
+ def self.from_hash(h); h.nil? ? nil : new(h); end
44
+ end
45
+
46
+ class VoiceV1IpRecordList
47
+ include V1Pageable
48
+ attr_reader :ip_records
49
+ def initialize(hash = {})
50
+ assign_meta_fields(hash)
51
+ @ip_records = (hash['ip_records'] || []).map { |h| VoiceV1IpRecord.from_hash(h) }
52
+ end
53
+ end
54
+
55
+ # VoiceV1SourceIpMapping — `IB...`. Binds an IpRecord to a SipDomain.
56
+ class VoiceV1SourceIpMapping
57
+ ATTRIBUTES = %w[
58
+ sid ip_record_sid sip_domain_sid date_created date_updated url
59
+ ].freeze
60
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
61
+ def initialize(attrs = {})
62
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
63
+ end
64
+ def self.from_hash(h); h.nil? ? nil : new(h); end
65
+ end
66
+
67
+ class VoiceV1SourceIpMappingList
68
+ include V1Pageable
69
+ attr_reader :source_ip_mappings
70
+ def initialize(hash = {})
71
+ assign_meta_fields(hash)
72
+ @source_ip_mappings = (hash['source_ip_mappings'] || []).map { |h| VoiceV1SourceIpMapping.from_hash(h) }
73
+ end
74
+ end
75
+
76
+ # VoiceV1ByocTrunk — `BY...`. Bring-your-own-carrier trunk.
77
+ class VoiceV1ByocTrunk
78
+ ATTRIBUTES = %w[
79
+ account_sid sid friendly_name voice_url voice_method voice_fallback_url
80
+ voice_fallback_method status_callback_url status_callback_method
81
+ cnam_lookup_enabled connection_policy_sid from_domain_sid
82
+ date_created date_updated url
83
+ ].freeze
84
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
85
+ def initialize(attrs = {})
86
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
87
+ end
88
+ def self.from_hash(h); h.nil? ? nil : new(h); end
89
+ end
90
+
91
+ class VoiceV1ByocTrunkList
92
+ include V1Pageable
93
+ attr_reader :byoc_trunks
94
+ def initialize(hash = {})
95
+ assign_meta_fields(hash)
96
+ @byoc_trunks = (hash['byoc_trunks'] || []).map { |h| VoiceV1ByocTrunk.from_hash(h) }
97
+ end
98
+ end
99
+
100
+ # VoiceV1ConnectionPolicy — `NY...`.
101
+ class VoiceV1ConnectionPolicy
102
+ ATTRIBUTES = %w[
103
+ account_sid sid friendly_name date_created date_updated url links
104
+ ].freeze
105
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
106
+ def initialize(attrs = {})
107
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
108
+ end
109
+ def self.from_hash(h); h.nil? ? nil : new(h); end
110
+ end
111
+
112
+ class VoiceV1ConnectionPolicyList
113
+ include V1Pageable
114
+ attr_reader :connection_policies
115
+ def initialize(hash = {})
116
+ assign_meta_fields(hash)
117
+ @connection_policies = (hash['connection_policies'] || []).map { |h| VoiceV1ConnectionPolicy.from_hash(h) }
118
+ end
119
+ end
120
+
121
+ # VoiceV1ConnectionPolicyTarget — `NE...`. Scoped to a parent ConnectionPolicy.
122
+ class VoiceV1ConnectionPolicyTarget
123
+ ATTRIBUTES = %w[
124
+ account_sid connection_policy_sid sid friendly_name target priority weight
125
+ enabled date_created date_updated url
126
+ ].freeze
127
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
128
+ def initialize(attrs = {})
129
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
130
+ end
131
+ def self.from_hash(h); h.nil? ? nil : new(h); end
132
+ end
133
+
134
+ class VoiceV1ConnectionPolicyTargetList
135
+ include V1Pageable
136
+ attr_reader :targets
137
+ def initialize(hash = {})
138
+ assign_meta_fields(hash)
139
+ @targets = (hash['targets'] || []).map { |h| VoiceV1ConnectionPolicyTarget.from_hash(h) }
140
+ end
141
+ end
142
+
143
+ # VoiceV1DialingPermissionsSettings — `/v1/Settings`.
144
+ class VoiceV1DialingPermissionsSettings
145
+ ATTRIBUTES = %w[dialing_permissions_inheritance url].freeze
146
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
147
+ def initialize(attrs = {})
148
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
149
+ end
150
+ def self.from_hash(h); h.nil? ? nil : new(h); end
151
+ end
152
+ end