voiceml 0.9.2 → 0.9.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -13
  3. data/lib/voiceml/client.rb +53 -13
  4. data/lib/voiceml/errors.rb +15 -2
  5. data/lib/voiceml/models/accounts.rb +47 -3
  6. data/lib/voiceml/models/applications.rb +6 -0
  7. data/lib/voiceml/models/assistants_v1.rb +40 -0
  8. data/lib/voiceml/models/calls.rb +4 -0
  9. data/lib/voiceml/models/common.rb +35 -4
  10. data/lib/voiceml/models/conferences.rb +8 -0
  11. data/lib/voiceml/models/conversations_v1.rb +131 -29
  12. data/lib/voiceml/models/diagnostics.rb +33 -12
  13. data/lib/voiceml/models/exports.rb +58 -0
  14. data/lib/voiceml/models/incoming_phone_numbers.rb +4 -0
  15. data/lib/voiceml/models/media.rb +4 -0
  16. data/lib/voiceml/models/messages.rb +29 -0
  17. data/lib/voiceml/models/messaging_v1.rb +35 -2
  18. data/lib/voiceml/models/monitor_v1.rb +54 -0
  19. data/lib/voiceml/models/notifications.rb +2 -0
  20. data/lib/voiceml/models/outgoing_caller_ids.rb +6 -0
  21. data/lib/voiceml/models/payments.rb +2 -0
  22. data/lib/voiceml/models/pricing.rb +38 -4
  23. data/lib/voiceml/models/queues.rb +8 -0
  24. data/lib/voiceml/models/recordings.rb +5 -1
  25. data/lib/voiceml/models/routes_v2.rb +6 -2
  26. data/lib/voiceml/models/sip.rb +34 -6
  27. data/lib/voiceml/models/sip_registrations.rb +49 -0
  28. data/lib/voiceml/models/siprec.rb +5 -17
  29. data/lib/voiceml/models/streams.rb +4 -16
  30. data/lib/voiceml/models/transcriptions.rb +35 -4
  31. data/lib/voiceml/models/usage_records.rb +48 -0
  32. data/lib/voiceml/models/user_defined_messages.rb +2 -0
  33. data/lib/voiceml/models/voice_v1.rb +29 -19
  34. data/lib/voiceml/request_validator.rb +125 -0
  35. data/lib/voiceml/resources/accounts.rb +75 -0
  36. data/lib/voiceml/resources/applications.rb +3 -1
  37. data/lib/voiceml/resources/assistants_v1.rb +53 -77
  38. data/lib/voiceml/resources/base.rb +138 -16
  39. data/lib/voiceml/resources/calls.rb +34 -49
  40. data/lib/voiceml/resources/conferences.rb +26 -5
  41. data/lib/voiceml/resources/conversations_v1.rb +147 -172
  42. data/lib/voiceml/resources/diagnostics.rb +20 -35
  43. data/lib/voiceml/resources/exports.rb +36 -0
  44. data/lib/voiceml/resources/incoming_phone_numbers.rb +53 -32
  45. data/lib/voiceml/resources/messages.rb +79 -15
  46. data/lib/voiceml/resources/messaging_v1.rb +47 -13
  47. data/lib/voiceml/resources/monitor_v1.rb +68 -0
  48. data/lib/voiceml/resources/notifications.rb +1 -1
  49. data/lib/voiceml/resources/outgoing_caller_ids.rb +77 -0
  50. data/lib/voiceml/resources/pricing.rb +13 -5
  51. data/lib/voiceml/resources/queues.rb +6 -5
  52. data/lib/voiceml/resources/recordings.rb +39 -5
  53. data/lib/voiceml/resources/routes_v2.rb +10 -4
  54. data/lib/voiceml/resources/sip.rb +30 -11
  55. data/lib/voiceml/resources/transcriptions.rb +40 -0
  56. data/lib/voiceml/resources/usage_records.rb +51 -0
  57. data/lib/voiceml/resources/voice_v1.rb +31 -38
  58. data/lib/voiceml/transport.rb +277 -230
  59. data/lib/voiceml/version.rb +1 -1
  60. data/lib/voiceml.rb +14 -15
  61. metadata +18 -6
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'common'
4
+ require_relative 'notifications'
4
5
 
5
6
  module VoiceML
6
7
  # `GET /Calls/{Sid}/Notifications` — always an empty list (Twilio-compat stub).
7
8
  class NotificationsList
8
- attr_reader :notifications, :page, :page_size, :total, :uri
9
+ include RawAttributes
10
+ include Pageable
11
+ attr_reader :notifications
9
12
 
10
13
  def initialize(hash = {})
11
- @notifications = hash['notifications'] || []
12
- @page = hash['page'] || 0
13
- @page_size = hash['page_size'] || 0
14
- @total = hash['total'] || 0
15
- @uri = hash['uri']
14
+ @raw_attributes = hash
15
+ assign_page_fields(hash)
16
+ @notifications = (hash['notifications'] || []).map { |n| Notification.from_hash(n) }
16
17
  end
17
18
 
18
19
  def self.from_hash(hash)
@@ -23,14 +24,14 @@ module VoiceML
23
24
  # `GET /Calls/{Sid}/Events` — always an empty list (Twilio-compat stub).
24
25
  # The canonical event source is the customer's StatusCallback URL.
25
26
  class EventsList
26
- attr_reader :events, :page, :page_size, :total, :uri
27
+ include RawAttributes
28
+ include Pageable
29
+ attr_reader :events
27
30
 
28
31
  def initialize(hash = {})
29
- @events = hash['events'] || []
30
- @page = hash['page'] || 0
31
- @page_size = hash['page_size'] || 0
32
- @total = hash['total'] || 0
33
- @uri = hash['uri']
32
+ @raw_attributes = hash
33
+ assign_page_fields(hash)
34
+ @events = (hash['events'] || []).map { |event| CallEvent.from_hash(event) }
34
35
  end
35
36
 
36
37
  def self.from_hash(hash)
@@ -38,12 +39,32 @@ module VoiceML
38
39
  end
39
40
  end
40
41
 
42
+ # Request/response pair from a call's event log.
43
+ class CallEvent
44
+ include RawAttributes
45
+ ATTRIBUTES = %w[request response].freeze
46
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
47
+
48
+ def initialize(attrs = {})
49
+ @raw_attributes = attrs
50
+ ATTRIBUTES.each do |field|
51
+ instance_variable_set("@#{field}", attrs.key?(field) ? attrs[field] : attrs[field.to_sym])
52
+ end
53
+ end
54
+
55
+ def self.from_hash(hash)
56
+ hash.nil? ? nil : new(hash)
57
+ end
58
+ end
59
+
41
60
  # `GET /health` response. Hard-check failures flip `ok` to false (server returns 503);
42
61
  # soft-check warnings surface in `warnings` only.
43
62
  class HealthStatus
63
+ include RawAttributes
44
64
  attr_reader :ok, :warnings, :failures
45
65
 
46
66
  def initialize(hash = {})
67
+ @raw_attributes = hash
47
68
  @ok = hash['ok']
48
69
  @warnings = (hash['warnings'] || []).map { |w| HealthFailure.from_hash(w) }
49
70
  @failures = (hash['failures'] || []).map { |f| HealthFailure.from_hash(f) }
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module VoiceML
6
+ # One day's archive entry from `GET /Exports`.
7
+ class Export
8
+ include RawAttributes
9
+ ATTRIBUTES = %w[date size uri].freeze
10
+
11
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
12
+
13
+ def initialize(attrs = {})
14
+ @raw_attributes = attrs
15
+ ATTRIBUTES.each do |field|
16
+ value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
17
+ instance_variable_set("@#{field}", value)
18
+ end
19
+ end
20
+
21
+ def self.from_hash(hash)
22
+ return nil if hash.nil?
23
+
24
+ new(hash)
25
+ end
26
+ end
27
+
28
+ # `GET /Exports` response — the account's available archives, newest first.
29
+ class ExportList
30
+ include RawAttributes
31
+
32
+ attr_reader :account_sid, :uri, :exports
33
+
34
+ def initialize(hash = {})
35
+ @raw_attributes = hash
36
+ @account_sid = hash['account_sid']
37
+ @uri = hash['uri']
38
+ @exports = (hash['exports'] || []).map { |e| Export.from_hash(e) }
39
+ end
40
+
41
+ def self.from_hash(hash)
42
+ new(hash || {})
43
+ end
44
+ end
45
+
46
+ # Result of `GET /Exports/{Date}` — the archive bytes, following the same
47
+ # 302 -> presigned-object redirect recording audio uses.
48
+ class ExportDownload
49
+ attr_reader :date, :content, :content_type, :via_redirect
50
+
51
+ def initialize(date:, content:, content_type:, via_redirect:)
52
+ @date = date
53
+ @content = content
54
+ @content_type = content_type
55
+ @via_redirect = via_redirect
56
+ end
57
+ end
58
+ end
@@ -12,6 +12,7 @@ module VoiceML
12
12
  # Twilio-compat fields VoiceML doesn't track (regulatory, SMS, emergency, trunking) are
13
13
  # surfaced verbatim so strict-binding consumers can read e.g. `.capabilities['voice']`.
14
14
  class IncomingPhoneNumber
15
+ include RawAttributes
15
16
  ATTRIBUTES = %w[
16
17
  sid account_sid phone_number friendly_name api_version uri
17
18
  voice_url voice_method voice_fallback_url voice_fallback_method
@@ -27,6 +28,7 @@ module VoiceML
27
28
  attr_reader(*ATTRIBUTES.map(&:to_sym))
28
29
 
29
30
  def initialize(attrs = {})
31
+ @raw_attributes = attrs
30
32
  ATTRIBUTES.each do |field|
31
33
  value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
32
34
  instance_variable_set("@#{field}", value)
@@ -42,11 +44,13 @@ module VoiceML
42
44
 
43
45
  # Paginated `GET /IncomingPhoneNumbers` response. Same envelope shape as `CallList`.
44
46
  class IncomingPhoneNumberList
47
+ include RawAttributes
45
48
  include Pageable
46
49
 
47
50
  attr_reader :incoming_phone_numbers
48
51
 
49
52
  def initialize(hash = {})
53
+ @raw_attributes = hash
50
54
  assign_page_fields(hash)
51
55
  @incoming_phone_numbers =
52
56
  (hash['incoming_phone_numbers'] || []).map { |n| IncomingPhoneNumber.from_hash(n) }
@@ -8,6 +8,7 @@ module VoiceML
8
8
  # shape conformance and to round-trip migrated tooling. `parent_sid` ties
9
9
  # the media back to its parent Message (SM... sid).
10
10
  class Media
11
+ include RawAttributes
11
12
  ATTRIBUTES = %w[
12
13
  sid account_sid parent_sid content_type
13
14
  date_created date_updated uri
@@ -16,6 +17,7 @@ module VoiceML
16
17
  attr_reader(*ATTRIBUTES.map(&:to_sym))
17
18
 
18
19
  def initialize(attrs = {})
20
+ @raw_attributes = attrs
19
21
  ATTRIBUTES.each do |field|
20
22
  value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
21
23
  instance_variable_set("@#{field}", value)
@@ -32,11 +34,13 @@ module VoiceML
32
34
  # Paginated `GET /Messages/{Sid}/Media` response. Twilio's envelope key is
33
35
  # `media_list` (not `media`) — the SDK preserves that on the wire.
34
36
  class MediaList
37
+ include RawAttributes
35
38
  include Pageable
36
39
 
37
40
  attr_reader :media_list
38
41
 
39
42
  def initialize(hash = {})
43
+ @raw_attributes = hash
40
44
  assign_page_fields(hash)
41
45
  @media_list = (hash['media_list'] || []).map { |m| Media.from_hash(m) }
42
46
  end
@@ -16,6 +16,7 @@ module VoiceML
16
16
  # - `error_code` is a nullable integer; `error_message`, `price`, `price_unit`,
17
17
  # `date_sent`, and `messaging_service_sid` are nullable strings.
18
18
  class Message
19
+ include RawAttributes
19
20
  ATTRIBUTES = %w[
20
21
  sid account_sid api_version to from body status num_segments num_media
21
22
  direction price price_unit error_code error_message messaging_service_sid
@@ -25,6 +26,7 @@ module VoiceML
25
26
  attr_reader(*ATTRIBUTES.map(&:to_sym))
26
27
 
27
28
  def initialize(attrs = {})
29
+ @raw_attributes = attrs
28
30
  ATTRIBUTES.each do |field|
29
31
  value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
30
32
  instance_variable_set("@#{field}", value)
@@ -40,11 +42,13 @@ module VoiceML
40
42
 
41
43
  # Paginated `GET /Messages` response.
42
44
  class MessageList
45
+ include RawAttributes
43
46
  include Pageable
44
47
 
45
48
  attr_reader :messages
46
49
 
47
50
  def initialize(hash = {})
51
+ @raw_attributes = hash
48
52
  assign_page_fields(hash)
49
53
  @messages = (hash['messages'] || []).map { |m| Message.from_hash(m) }
50
54
  end
@@ -53,4 +57,29 @@ module VoiceML
53
57
  new(hash || {})
54
58
  end
55
59
  end
60
+
61
+ # Delivery-quality feedback echoed back on a Message
62
+ # (`POST /Messages/{Sid}/Feedback.json`). VoiceML records the outcome on
63
+ # the response only; there is no separate downstream analytics surface.
64
+ # Any submitted `Outcome` other than `confirmed` echoes as `unconfirmed`.
65
+ class MessageFeedback
66
+ include RawAttributes
67
+ ATTRIBUTES = %w[account_sid message_sid outcome date_created date_updated uri].freeze
68
+
69
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
70
+
71
+ def initialize(attrs = {})
72
+ @raw_attributes = attrs
73
+ ATTRIBUTES.each do |field|
74
+ value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
75
+ instance_variable_set("@#{field}", value)
76
+ end
77
+ end
78
+
79
+ def self.from_hash(hash)
80
+ return nil if hash.nil?
81
+
82
+ new(hash)
83
+ end
84
+ end
56
85
  end
@@ -14,27 +14,60 @@ module VoiceML
14
14
  # MessagingService — `MG...`. The feature-toggle fields are accept-and-echo on
15
15
  # VoiceML; the service's operative role is gating scheduled sends.
16
16
  class MessagingService
17
+ include RawAttributes
17
18
  ATTRIBUTES = %w[
18
19
  sid account_sid friendly_name date_created date_updated
19
20
  inbound_request_url inbound_method fallback_url fallback_method status_callback
20
21
  sticky_sender mms_converter smart_encoding scan_message_content
21
22
  fallback_to_long_code area_code_geomatch synchronous_validation validity_period
22
- url usecase use_inbound_webhook_on_number
23
+ url usecase use_inbound_webhook_on_number advanced_opt_out
23
24
  ].freeze
24
25
  attr_reader(*ATTRIBUTES.map(&:to_sym))
25
26
  def initialize(attrs = {})
26
- ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
27
+ @raw_attributes = attrs
28
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs.key?(f) ? attrs[f] : attrs[f.to_sym]) }
27
29
  end
28
30
  def self.from_hash(h); h.nil? ? nil : new(h); end
29
31
  end
30
32
 
31
33
  # List envelope for `GET /v1/Services` on the messaging host.
32
34
  class MessagingServiceList
35
+ include RawAttributes
33
36
  include V1Pageable
34
37
  attr_reader :services
35
38
  def initialize(hash = {})
39
+ @raw_attributes = hash
36
40
  assign_meta_fields(hash)
37
41
  @services = (hash['services'] || []).map { |h| MessagingService.from_hash(h) }
38
42
  end
39
43
  end
44
+
45
+ # MessagingServicePhoneNumber — a sender-pool phone number attached to a
46
+ # Messaging Service (`/v1/Services/{ChatServiceSid}/PhoneNumbers`). Lives on
47
+ # the messaging host.
48
+ class MessagingServicePhoneNumber
49
+ include RawAttributes
50
+ ATTRIBUTES = %w[
51
+ sid account_sid service_sid date_created date_updated
52
+ phone_number country_code capabilities url
53
+ ].freeze
54
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
55
+ def initialize(attrs = {})
56
+ @raw_attributes = attrs
57
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs.key?(f) ? attrs[f] : attrs[f.to_sym]) }
58
+ end
59
+ def self.from_hash(h); h.nil? ? nil : new(h); end
60
+ end
61
+
62
+ # List envelope for `GET /v1/Services/{ChatServiceSid}/PhoneNumbers`.
63
+ class MessagingServicePhoneNumberList
64
+ include RawAttributes
65
+ include V1Pageable
66
+ attr_reader :phone_numbers
67
+ def initialize(hash = {})
68
+ @raw_attributes = hash
69
+ assign_meta_fields(hash)
70
+ @phone_numbers = (hash['phone_numbers'] || []).map { |h| MessagingServicePhoneNumber.from_hash(h) }
71
+ end
72
+ end
40
73
  end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module VoiceML
6
+ # Monitor v1 (`/v1/Alerts`) — failure events rendered in the Monitor Alert
7
+ # shape: call-scoped errors and messaging delivery failures alike.
8
+ #
9
+ # List rows omit the request/response detail; `fetch` includes it when the
10
+ # underlying event stored any (`request_headers`, `request_variables`,
11
+ # `response_body`, `response_headers`).
12
+ class MonitorAlert
13
+ include RawAttributes
14
+ ATTRIBUTES = %w[
15
+ sid account_sid alert_text api_version error_code log_level more_info
16
+ request_method request_url request_headers request_variables
17
+ response_body response_headers resource_sid service_sid
18
+ date_created date_generated date_updated url
19
+ ].freeze
20
+
21
+ attr_reader(*ATTRIBUTES.map(&:to_sym))
22
+
23
+ def initialize(attrs = {})
24
+ @raw_attributes = attrs
25
+ ATTRIBUTES.each do |field|
26
+ value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
27
+ instance_variable_set("@#{field}", value)
28
+ end
29
+ end
30
+
31
+ def self.from_hash(hash)
32
+ return nil if hash.nil?
33
+
34
+ new(hash)
35
+ end
36
+ end
37
+
38
+ # Paginated `GET /v1/Alerts` response: `alerts` plus the standard `/v1`
39
+ # `meta` envelope. The server serves a single page
40
+ # (`meta.next_page_url` is always `null`); `PageSize` does limit this
41
+ # collection (default 50, capped at 1000).
42
+ class MonitorAlertList
43
+ include RawAttributes
44
+ include V1Pageable
45
+
46
+ attr_reader :alerts
47
+
48
+ def initialize(hash = {})
49
+ @raw_attributes = hash
50
+ assign_meta_fields(hash)
51
+ @alerts = (hash['alerts'] || []).map { |h| MonitorAlert.from_hash(h) }
52
+ end
53
+ end
54
+ end
@@ -13,6 +13,7 @@ module VoiceML
13
13
  #
14
14
  # The same resource shape backs both account-scoped and call-scoped fetches.
15
15
  class Notification
16
+ include RawAttributes
16
17
  ATTRIBUTES = %w[
17
18
  sid account_sid call_sid api_version
18
19
  error_code more_info message_date message_text log
@@ -24,6 +25,7 @@ module VoiceML
24
25
  attr_reader(*ATTRIBUTES.map(&:to_sym))
25
26
 
26
27
  def initialize(attrs = {})
28
+ @raw_attributes = attrs
27
29
  ATTRIBUTES.each do |field|
28
30
  value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
29
31
  instance_variable_set("@#{field}", value)
@@ -7,6 +7,7 @@ module VoiceML
7
7
  # to mirror Twilio (caller-id resources share the IncomingPhoneNumber SID
8
8
  # space upstream); `phone_number` carries the verified E.164 number.
9
9
  class OutgoingCallerId
10
+ include RawAttributes
10
11
  ATTRIBUTES = %w[
11
12
  sid account_sid friendly_name phone_number
12
13
  date_created date_updated uri
@@ -15,6 +16,7 @@ module VoiceML
15
16
  attr_reader(*ATTRIBUTES.map(&:to_sym))
16
17
 
17
18
  def initialize(attrs = {})
19
+ @raw_attributes = attrs
18
20
  ATTRIBUTES.each do |field|
19
21
  value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
20
22
  instance_variable_set("@#{field}", value)
@@ -30,11 +32,13 @@ module VoiceML
30
32
 
31
33
  # Paginated `GET /OutgoingCallerIds` response.
32
34
  class OutgoingCallerIdList
35
+ include RawAttributes
33
36
  include Pageable
34
37
 
35
38
  attr_reader :outgoing_caller_ids
36
39
 
37
40
  def initialize(hash = {})
41
+ @raw_attributes = hash
38
42
  assign_page_fields(hash)
39
43
  @outgoing_caller_ids =
40
44
  (hash['outgoing_caller_ids'] || []).map { |o| OutgoingCallerId.from_hash(o) }
@@ -50,11 +54,13 @@ module VoiceML
50
54
  # doesn't exist until the validation_code is dialled back); the
51
55
  # `validation_code` is what the user is prompted to enter on the live call.
52
56
  class ValidationRequest
57
+ include RawAttributes
53
58
  ATTRIBUTES = %w[account_sid call_sid friendly_name phone_number validation_code].freeze
54
59
 
55
60
  attr_reader(*ATTRIBUTES.map(&:to_sym))
56
61
 
57
62
  def initialize(attrs = {})
63
+ @raw_attributes = attrs
58
64
  ATTRIBUTES.each do |field|
59
65
  value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
60
66
  instance_variable_set("@#{field}", value)
@@ -10,6 +10,7 @@ module VoiceML
10
10
  # account must have `pay_enabled = true` AND a `stripe_secret_key` set, or
11
11
  # the call fails 403.
12
12
  class CallPayment
13
+ include RawAttributes
13
14
  ATTRIBUTES = %w[
14
15
  sid account_sid call_sid api_version
15
16
  date_created date_updated uri
@@ -18,6 +19,7 @@ module VoiceML
18
19
  attr_reader(*ATTRIBUTES.map(&:to_sym))
19
20
 
20
21
  def initialize(attrs = {})
22
+ @raw_attributes = attrs
21
23
  ATTRIBUTES.each do |field|
22
24
  value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
23
25
  instance_variable_set("@#{field}", value)
@@ -14,26 +14,32 @@ module VoiceML
14
14
  # --- Price leaves ---------------------------------------------------------
15
15
 
16
16
  class PricingInboundCallPrice
17
+ include RawAttributes
17
18
  ATTRIBUTES = %w[base_price current_price number_type].freeze
18
19
  attr_reader(*ATTRIBUTES.map(&:to_sym))
19
20
  def initialize(attrs = {})
20
- ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
21
+ @raw_attributes = attrs
22
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs.key?(f) ? attrs[f] : attrs[f.to_sym]) }
21
23
  end
22
24
  def self.from_hash(h); h.nil? ? nil : new(h); end
23
25
  end
24
26
 
25
27
  class PricingOutboundCallPrice
28
+ include RawAttributes
26
29
  ATTRIBUTES = %w[base_price current_price].freeze
27
30
  attr_reader(*ATTRIBUTES.map(&:to_sym))
28
31
  def initialize(attrs = {})
29
- ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
32
+ @raw_attributes = attrs
33
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs.key?(f) ? attrs[f] : attrs[f.to_sym]) }
30
34
  end
31
35
  def self.from_hash(h); h.nil? ? nil : new(h); end
32
36
  end
33
37
 
34
38
  class PricingOutboundCallPriceWithOrigin
39
+ include RawAttributes
35
40
  attr_reader :origination_prefixes, :base_price, :current_price
36
41
  def initialize(attrs = {})
42
+ @raw_attributes = attrs
37
43
  @origination_prefixes = attrs['origination_prefixes'] || attrs[:origination_prefixes] || []
38
44
  @base_price = attrs['base_price'] || attrs[:base_price]
39
45
  @current_price = attrs['current_price'] || attrs[:current_price]
@@ -42,8 +48,10 @@ module VoiceML
42
48
  end
43
49
 
44
50
  class PricingOutboundPrefixPrice
51
+ include RawAttributes
45
52
  attr_reader :prefixes, :base_price, :current_price, :friendly_name
46
53
  def initialize(attrs = {})
54
+ @raw_attributes = attrs
47
55
  @prefixes = attrs['prefixes'] || attrs[:prefixes] || []
48
56
  @base_price = attrs['base_price'] || attrs[:base_price]
49
57
  @current_price = attrs['current_price'] || attrs[:current_price]
@@ -53,8 +61,10 @@ module VoiceML
53
61
  end
54
62
 
55
63
  class PricingOutboundPrefixPriceWithOrigin
64
+ include RawAttributes
56
65
  attr_reader :origination_prefixes, :destination_prefixes, :base_price, :current_price, :friendly_name
57
66
  def initialize(attrs = {})
67
+ @raw_attributes = attrs
58
68
  @origination_prefixes = attrs['origination_prefixes'] || attrs[:origination_prefixes] || []
59
69
  @destination_prefixes = attrs['destination_prefixes'] || attrs[:destination_prefixes] || []
60
70
  @base_price = attrs['base_price'] || attrs[:base_price]
@@ -65,8 +75,10 @@ module VoiceML
65
75
  end
66
76
 
67
77
  class PricingOutboundSMSPrice
78
+ include RawAttributes
68
79
  attr_reader :carrier, :mcc, :mnc, :prices
69
80
  def initialize(attrs = {})
81
+ @raw_attributes = attrs
70
82
  @carrier = attrs['carrier'] || attrs[:carrier]
71
83
  @mcc = attrs['mcc'] || attrs[:mcc]
72
84
  @mnc = attrs['mnc'] || attrs[:mnc]
@@ -76,10 +88,12 @@ module VoiceML
76
88
  end
77
89
 
78
90
  class PricingPhoneNumberPrice
91
+ include RawAttributes
79
92
  ATTRIBUTES = %w[number_type base_price current_price].freeze
80
93
  attr_reader(*ATTRIBUTES.map(&:to_sym))
81
94
  def initialize(attrs = {})
82
- ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
95
+ @raw_attributes = attrs
96
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs.key?(f) ? attrs[f] : attrs[f.to_sym]) }
83
97
  end
84
98
  def self.from_hash(h); h.nil? ? nil : new(h); end
85
99
  end
@@ -87,18 +101,22 @@ module VoiceML
87
101
  # --- Countries list envelope ----------------------------------------------
88
102
 
89
103
  class PricingCountryRef
104
+ include RawAttributes
90
105
  ATTRIBUTES = %w[country iso_country url].freeze
91
106
  attr_reader(*ATTRIBUTES.map(&:to_sym))
92
107
  def initialize(attrs = {})
93
- ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs[f] || attrs[f.to_sym]) }
108
+ @raw_attributes = attrs
109
+ ATTRIBUTES.each { |f| instance_variable_set("@#{f}", attrs.key?(f) ? attrs[f] : attrs[f.to_sym]) }
94
110
  end
95
111
  def self.from_hash(h); h.nil? ? nil : new(h); end
96
112
  end
97
113
 
98
114
  class PricingCountriesList
115
+ include RawAttributes
99
116
  include V1Pageable
100
117
  attr_reader :countries
101
118
  def initialize(hash = {})
119
+ @raw_attributes = hash
102
120
  assign_meta_fields(hash)
103
121
  @countries = (hash['countries'] || []).map { |h| PricingCountryRef.from_hash(h) }
104
122
  end
@@ -107,8 +125,10 @@ module VoiceML
107
125
  # --- Pricing v1 country / number bodies -----------------------------------
108
126
 
109
127
  class PricingVoiceCountry
128
+ include RawAttributes
110
129
  attr_reader :country, :iso_country, :outbound_prefix_prices, :inbound_call_prices, :price_unit, :url
111
130
  def initialize(attrs = {})
131
+ @raw_attributes = attrs
112
132
  @country = attrs['country'] || attrs[:country]
113
133
  @iso_country = attrs['iso_country'] || attrs[:iso_country]
114
134
  @outbound_prefix_prices =
@@ -122,8 +142,10 @@ module VoiceML
122
142
  end
123
143
 
124
144
  class PricingVoiceNumber
145
+ include RawAttributes
125
146
  attr_reader :number, :country, :iso_country, :outbound_call_price, :inbound_call_price, :price_unit, :url
126
147
  def initialize(attrs = {})
148
+ @raw_attributes = attrs
127
149
  @number = attrs['number'] || attrs[:number]
128
150
  @country = attrs['country'] || attrs[:country]
129
151
  @iso_country = attrs['iso_country'] || attrs[:iso_country]
@@ -136,8 +158,10 @@ module VoiceML
136
158
  end
137
159
 
138
160
  class PricingMessagingCountry
161
+ include RawAttributes
139
162
  attr_reader :country, :iso_country, :outbound_sms_prices, :inbound_sms_prices, :price_unit, :url
140
163
  def initialize(attrs = {})
164
+ @raw_attributes = attrs
141
165
  @country = attrs['country'] || attrs[:country]
142
166
  @iso_country = attrs['iso_country'] || attrs[:iso_country]
143
167
  @outbound_sms_prices =
@@ -151,8 +175,10 @@ module VoiceML
151
175
  end
152
176
 
153
177
  class PricingPhoneNumberCountry
178
+ include RawAttributes
154
179
  attr_reader :country, :iso_country, :phone_number_prices, :price_unit, :url
155
180
  def initialize(attrs = {})
181
+ @raw_attributes = attrs
156
182
  @country = attrs['country'] || attrs[:country]
157
183
  @iso_country = attrs['iso_country'] || attrs[:iso_country]
158
184
  @phone_number_prices =
@@ -166,8 +192,10 @@ module VoiceML
166
192
  # --- Pricing v2 country / number bodies -----------------------------------
167
193
 
168
194
  class PricingVoiceCountryV2
195
+ include RawAttributes
169
196
  attr_reader :country, :iso_country, :outbound_prefix_prices, :inbound_call_prices, :price_unit, :url
170
197
  def initialize(attrs = {})
198
+ @raw_attributes = attrs
171
199
  @country = attrs['country'] || attrs[:country]
172
200
  @iso_country = attrs['iso_country'] || attrs[:iso_country]
173
201
  @outbound_prefix_prices =
@@ -181,9 +209,11 @@ module VoiceML
181
209
  end
182
210
 
183
211
  class PricingVoiceNumberV2
212
+ include RawAttributes
184
213
  attr_reader :destination_number, :origination_number, :country, :iso_country,
185
214
  :outbound_call_prices, :inbound_call_price, :price_unit, :url
186
215
  def initialize(attrs = {})
216
+ @raw_attributes = attrs
187
217
  @destination_number = attrs['destination_number'] || attrs[:destination_number]
188
218
  @origination_number = attrs['origination_number'] || attrs[:origination_number]
189
219
  @country = attrs['country'] || attrs[:country]
@@ -198,8 +228,10 @@ module VoiceML
198
228
  end
199
229
 
200
230
  class PricingTrunkingCountry
231
+ include RawAttributes
201
232
  attr_reader :country, :iso_country, :terminating_prefix_prices, :originating_call_prices, :price_unit, :url
202
233
  def initialize(attrs = {})
234
+ @raw_attributes = attrs
203
235
  @country = attrs['country'] || attrs[:country]
204
236
  @iso_country = attrs['iso_country'] || attrs[:iso_country]
205
237
  @terminating_prefix_prices =
@@ -213,9 +245,11 @@ module VoiceML
213
245
  end
214
246
 
215
247
  class PricingTrunkingNumber
248
+ include RawAttributes
216
249
  attr_reader :destination_number, :origination_number, :country, :iso_country,
217
250
  :terminating_prefix_prices, :originating_call_price, :price_unit, :url
218
251
  def initialize(attrs = {})
252
+ @raw_attributes = attrs
219
253
  @destination_number = attrs['destination_number'] || attrs[:destination_number]
220
254
  @origination_number = attrs['origination_number'] || attrs[:origination_number]
221
255
  @country = attrs['country'] || attrs[:country]