voiceml 0.7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +265 -0
- data/lib/voiceml/client.rb +83 -0
- data/lib/voiceml/errors.rb +75 -0
- data/lib/voiceml/models/applications.rb +46 -0
- data/lib/voiceml/models/calls.rb +48 -0
- data/lib/voiceml/models/common.rb +64 -0
- data/lib/voiceml/models/conferences.rb +85 -0
- data/lib/voiceml/models/diagnostics.rb +56 -0
- data/lib/voiceml/models/incoming_phone_numbers.rb +59 -0
- data/lib/voiceml/models/messages.rb +56 -0
- data/lib/voiceml/models/payments.rb +96 -0
- data/lib/voiceml/models/queues.rb +82 -0
- data/lib/voiceml/models/recordings.rb +59 -0
- data/lib/voiceml/models/siprec.rb +44 -0
- data/lib/voiceml/models/streams.rb +44 -0
- data/lib/voiceml/models/transcriptions.rb +44 -0
- data/lib/voiceml/resources/applications.rb +62 -0
- data/lib/voiceml/resources/base.rb +38 -0
- data/lib/voiceml/resources/calls.rb +414 -0
- data/lib/voiceml/resources/conferences.rb +178 -0
- data/lib/voiceml/resources/diagnostics.rb +64 -0
- data/lib/voiceml/resources/incoming_phone_numbers.rb +162 -0
- data/lib/voiceml/resources/messages.rb +101 -0
- data/lib/voiceml/resources/notifications.rb +32 -0
- data/lib/voiceml/resources/queues.rb +120 -0
- data/lib/voiceml/resources/recordings.rb +89 -0
- data/lib/voiceml/transport.rb +296 -0
- data/lib/voiceml/version.rb +5 -0
- data/lib/voiceml.rb +27 -0
- metadata +118 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# A Twilio-compatible Conference resource.
|
|
7
|
+
class Conference
|
|
8
|
+
ATTRIBUTES = %w[
|
|
9
|
+
sid account_sid friendly_name status region api_version uri
|
|
10
|
+
date_created date_updated reason_conference_ended
|
|
11
|
+
call_sid_ending_conference subresource_uris member_count
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
15
|
+
|
|
16
|
+
def initialize(attrs = {})
|
|
17
|
+
ATTRIBUTES.each do |field|
|
|
18
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
19
|
+
instance_variable_set("@#{field}", value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.from_hash(hash)
|
|
24
|
+
return nil if hash.nil?
|
|
25
|
+
|
|
26
|
+
new(hash)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Paginated `GET /Conferences` response.
|
|
31
|
+
class ConferenceList
|
|
32
|
+
include Pageable
|
|
33
|
+
|
|
34
|
+
attr_reader :conferences
|
|
35
|
+
|
|
36
|
+
def initialize(hash = {})
|
|
37
|
+
assign_page_fields(hash)
|
|
38
|
+
@conferences = (hash['conferences'] || []).map { |c| Conference.from_hash(c) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.from_hash(hash)
|
|
42
|
+
new(hash || {})
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# A participant in a live conference.
|
|
47
|
+
class Participant
|
|
48
|
+
ATTRIBUTES = %w[
|
|
49
|
+
call_sid conference_sid account_sid muted hold coaching call_sid_to_coach queue_time
|
|
50
|
+
start_conference_on_enter end_conference_on_exit status label
|
|
51
|
+
api_version uri date_created date_updated
|
|
52
|
+
].freeze
|
|
53
|
+
|
|
54
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
55
|
+
|
|
56
|
+
def initialize(attrs = {})
|
|
57
|
+
ATTRIBUTES.each do |field|
|
|
58
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
59
|
+
instance_variable_set("@#{field}", value)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.from_hash(hash)
|
|
64
|
+
return nil if hash.nil?
|
|
65
|
+
|
|
66
|
+
new(hash)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Paginated `GET /Conferences/{Sid}/Participants` response.
|
|
71
|
+
class ParticipantList
|
|
72
|
+
include Pageable
|
|
73
|
+
|
|
74
|
+
attr_reader :participants
|
|
75
|
+
|
|
76
|
+
def initialize(hash = {})
|
|
77
|
+
assign_page_fields(hash)
|
|
78
|
+
@participants = (hash['participants'] || []).map { |p| Participant.from_hash(p) }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.from_hash(hash)
|
|
82
|
+
new(hash || {})
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# `GET /Calls/{Sid}/Notifications` — always an empty list (Twilio-compat stub).
|
|
7
|
+
class NotificationsList
|
|
8
|
+
attr_reader :notifications, :page, :page_size, :total, :uri
|
|
9
|
+
|
|
10
|
+
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']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.from_hash(hash)
|
|
19
|
+
new(hash || {})
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# `GET /Calls/{Sid}/Events` — always an empty list (Twilio-compat stub).
|
|
24
|
+
# The canonical event source is the customer's StatusCallback URL.
|
|
25
|
+
class EventsList
|
|
26
|
+
attr_reader :events, :page, :page_size, :total, :uri
|
|
27
|
+
|
|
28
|
+
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']
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.from_hash(hash)
|
|
37
|
+
new(hash || {})
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# `GET /health` response. Hard-check failures flip `ok` to false (server returns 503);
|
|
42
|
+
# soft-check warnings surface in `warnings` only.
|
|
43
|
+
class HealthStatus
|
|
44
|
+
attr_reader :ok, :warnings, :failures
|
|
45
|
+
|
|
46
|
+
def initialize(hash = {})
|
|
47
|
+
@ok = hash['ok']
|
|
48
|
+
@warnings = (hash['warnings'] || []).map { |w| HealthFailure.from_hash(w) }
|
|
49
|
+
@failures = (hash['failures'] || []).map { |f| HealthFailure.from_hash(f) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.from_hash(hash)
|
|
53
|
+
new(hash || {})
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# A Twilio-compatible IncomingPhoneNumber — a DID assigned to the tenant.
|
|
7
|
+
#
|
|
8
|
+
# `sid` is the canonical `PN`-prefixed identifier (34 chars); `phone_number` carries the
|
|
9
|
+
# E.164 form. These are distinct fields — twilio-ruby callers that lookup-by-number then
|
|
10
|
+
# fetch-by-sid work unchanged.
|
|
11
|
+
#
|
|
12
|
+
# Twilio-compat fields VoiceML doesn't track (regulatory, SMS, emergency, trunking) are
|
|
13
|
+
# surfaced verbatim so strict-binding consumers can read e.g. `.capabilities['voice']`.
|
|
14
|
+
class IncomingPhoneNumber
|
|
15
|
+
ATTRIBUTES = %w[
|
|
16
|
+
sid account_sid phone_number friendly_name api_version uri
|
|
17
|
+
voice_url voice_method voice_fallback_url voice_fallback_method
|
|
18
|
+
voice_application_sid voice_caller_id_lookup voice_receive_mode
|
|
19
|
+
origin beta capabilities type
|
|
20
|
+
sms_url sms_method sms_fallback_url sms_fallback_method sms_application_sid
|
|
21
|
+
status_callback status_callback_method
|
|
22
|
+
trunk_sid address_sid address_requirements identity_sid bundle_sid
|
|
23
|
+
emergency_status emergency_address_sid emergency_address_status
|
|
24
|
+
status date_created date_updated
|
|
25
|
+
].freeze
|
|
26
|
+
|
|
27
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
28
|
+
|
|
29
|
+
def initialize(attrs = {})
|
|
30
|
+
ATTRIBUTES.each do |field|
|
|
31
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
32
|
+
instance_variable_set("@#{field}", value)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.from_hash(hash)
|
|
37
|
+
return nil if hash.nil?
|
|
38
|
+
|
|
39
|
+
new(hash)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Paginated `GET /IncomingPhoneNumbers` response. Same envelope shape as `CallList`.
|
|
44
|
+
class IncomingPhoneNumberList
|
|
45
|
+
include Pageable
|
|
46
|
+
|
|
47
|
+
attr_reader :incoming_phone_numbers
|
|
48
|
+
|
|
49
|
+
def initialize(hash = {})
|
|
50
|
+
assign_page_fields(hash)
|
|
51
|
+
@incoming_phone_numbers =
|
|
52
|
+
(hash['incoming_phone_numbers'] || []).map { |n| IncomingPhoneNumber.from_hash(n) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.from_hash(hash)
|
|
56
|
+
new(hash || {})
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# A Twilio-compatible Message resource.
|
|
7
|
+
#
|
|
8
|
+
# VoiceML's outbound SMS today is fire-and-forget through the SDK 2.2 gateway —
|
|
9
|
+
# `status` pins to `"sent"` on successful dispatch and `"failed"` otherwise.
|
|
10
|
+
# There is no in-flight `queued`/`sending`/`delivered` lifecycle.
|
|
11
|
+
#
|
|
12
|
+
# Two wire shapes deserve a note:
|
|
13
|
+
#
|
|
14
|
+
# - `num_segments` and `num_media` are **strings** on the wire (Twilio-compatible),
|
|
15
|
+
# not integers. `num_media` is always `"0"` because the gateway has no MMS today.
|
|
16
|
+
# - `error_code` is a nullable integer; `error_message`, `price`, `price_unit`,
|
|
17
|
+
# `date_sent`, and `messaging_service_sid` are nullable strings.
|
|
18
|
+
class Message
|
|
19
|
+
ATTRIBUTES = %w[
|
|
20
|
+
sid account_sid api_version to from body status num_segments num_media
|
|
21
|
+
direction price price_unit error_code error_message messaging_service_sid
|
|
22
|
+
date_created date_updated date_sent uri subresource_uris
|
|
23
|
+
].freeze
|
|
24
|
+
|
|
25
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
26
|
+
|
|
27
|
+
def initialize(attrs = {})
|
|
28
|
+
ATTRIBUTES.each do |field|
|
|
29
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
30
|
+
instance_variable_set("@#{field}", value)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.from_hash(hash)
|
|
35
|
+
return nil if hash.nil?
|
|
36
|
+
|
|
37
|
+
new(hash)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Paginated `GET /Messages` response.
|
|
42
|
+
class MessageList
|
|
43
|
+
include Pageable
|
|
44
|
+
|
|
45
|
+
attr_reader :messages
|
|
46
|
+
|
|
47
|
+
def initialize(hash = {})
|
|
48
|
+
assign_page_fields(hash)
|
|
49
|
+
@messages = (hash['messages'] || []).map { |m| Message.from_hash(m) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.from_hash(hash)
|
|
53
|
+
new(hash || {})
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module VoiceML
|
|
4
|
+
# A Twilio-compatible CallPayment resource — the REST companion to the
|
|
5
|
+
# `<Pay>` TwiML verb.
|
|
6
|
+
#
|
|
7
|
+
# The response shape mirrors Twilio's deliberately-minimal payload — runtime
|
|
8
|
+
# configuration (ChargeAmount, PaymentConnector, ValidCardTypes, etc.) is
|
|
9
|
+
# captured server-side and not echoed back. Tenant-side BYO is binding: the
|
|
10
|
+
# account must have `pay_enabled = true` AND a `stripe_secret_key` set, or
|
|
11
|
+
# the call fails 403.
|
|
12
|
+
class CallPayment
|
|
13
|
+
ATTRIBUTES = %w[
|
|
14
|
+
sid account_sid call_sid api_version
|
|
15
|
+
date_created date_updated uri
|
|
16
|
+
].freeze
|
|
17
|
+
|
|
18
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
19
|
+
|
|
20
|
+
def initialize(attrs = {})
|
|
21
|
+
ATTRIBUTES.each do |field|
|
|
22
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
23
|
+
instance_variable_set("@#{field}", value)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.from_hash(hash)
|
|
28
|
+
return nil if hash.nil?
|
|
29
|
+
|
|
30
|
+
new(hash)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Narrows the `BankAccountType` field on a Pay session.
|
|
35
|
+
module PaymentBankAccountType
|
|
36
|
+
CONSUMER_CHECKING = 'consumer-checking'
|
|
37
|
+
CONSUMER_SAVINGS = 'consumer-savings'
|
|
38
|
+
COMMERCIAL_CHECKING = 'commercial-checking'
|
|
39
|
+
|
|
40
|
+
ALL = [CONSUMER_CHECKING, CONSUMER_SAVINGS, COMMERCIAL_CHECKING].freeze
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Narrows the `Input` field. DTMF is the only supported value today.
|
|
44
|
+
module PaymentInput
|
|
45
|
+
DTMF = 'dtmf'
|
|
46
|
+
|
|
47
|
+
ALL = [DTMF].freeze
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Narrows the `PaymentMethod` field.
|
|
51
|
+
module PaymentMethod
|
|
52
|
+
CREDIT_CARD = 'credit-card'
|
|
53
|
+
ACH_DEBIT = 'ach-debit'
|
|
54
|
+
|
|
55
|
+
ALL = [CREDIT_CARD, ACH_DEBIT].freeze
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Narrows the `TokenType` field.
|
|
59
|
+
module PaymentTokenType
|
|
60
|
+
ONE_TIME = 'one-time'
|
|
61
|
+
REUSABLE = 'reusable'
|
|
62
|
+
PAYMENT_METHOD = 'payment-method'
|
|
63
|
+
|
|
64
|
+
ALL = [ONE_TIME, REUSABLE, PAYMENT_METHOD].freeze
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Narrows the `Capture` field on Pay-session updates — tells the runtime
|
|
68
|
+
# which input the user is about to type next.
|
|
69
|
+
module PaymentCapture
|
|
70
|
+
PAYMENT_CARD_NUMBER = 'payment-card-number'
|
|
71
|
+
EXPIRATION_DATE = 'expiration-date'
|
|
72
|
+
SECURITY_CODE = 'security-code'
|
|
73
|
+
POSTAL_CODE = 'postal-code'
|
|
74
|
+
BANK_ROUTING_NUMBER = 'bank-routing-number'
|
|
75
|
+
BANK_ACCOUNT_NUMBER = 'bank-account-number'
|
|
76
|
+
PAYMENT_CARD_NUMBER_MATCHER = 'payment-card-number-matcher'
|
|
77
|
+
EXPIRATION_DATE_MATCHER = 'expiration-date-matcher'
|
|
78
|
+
SECURITY_CODE_MATCHER = 'security-code-matcher'
|
|
79
|
+
POSTAL_CODE_MATCHER = 'postal-code-matcher'
|
|
80
|
+
|
|
81
|
+
ALL = [
|
|
82
|
+
PAYMENT_CARD_NUMBER, EXPIRATION_DATE, SECURITY_CODE, POSTAL_CODE,
|
|
83
|
+
BANK_ROUTING_NUMBER, BANK_ACCOUNT_NUMBER,
|
|
84
|
+
PAYMENT_CARD_NUMBER_MATCHER, EXPIRATION_DATE_MATCHER,
|
|
85
|
+
SECURITY_CODE_MATCHER, POSTAL_CODE_MATCHER
|
|
86
|
+
].freeze
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Narrows the `Status` field on Pay-session updates.
|
|
90
|
+
module PaymentSessionStatus
|
|
91
|
+
COMPLETE = 'complete'
|
|
92
|
+
CANCEL = 'cancel'
|
|
93
|
+
|
|
94
|
+
ALL = [COMPLETE, CANCEL].freeze
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# A Twilio-compatible Queue resource.
|
|
7
|
+
class Queue
|
|
8
|
+
ATTRIBUTES = %w[
|
|
9
|
+
sid account_sid friendly_name current_size max_size
|
|
10
|
+
average_wait_time date_created date_updated uri
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
14
|
+
|
|
15
|
+
def initialize(attrs = {})
|
|
16
|
+
ATTRIBUTES.each do |field|
|
|
17
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
18
|
+
instance_variable_set("@#{field}", value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.from_hash(hash)
|
|
23
|
+
return nil if hash.nil?
|
|
24
|
+
|
|
25
|
+
new(hash)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Paginated `GET /Queues` response.
|
|
30
|
+
class QueueList
|
|
31
|
+
include Pageable
|
|
32
|
+
|
|
33
|
+
attr_reader :queues
|
|
34
|
+
|
|
35
|
+
def initialize(hash = {})
|
|
36
|
+
assign_page_fields(hash)
|
|
37
|
+
@queues = (hash['queues'] || []).map { |q| Queue.from_hash(q) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.from_hash(hash)
|
|
41
|
+
new(hash || {})
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# A member (call) waiting in a queue.
|
|
46
|
+
class QueueMember
|
|
47
|
+
ATTRIBUTES = %w[
|
|
48
|
+
call_sid queue_sid account_sid date_enqueued wait_time position uri
|
|
49
|
+
].freeze
|
|
50
|
+
|
|
51
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
52
|
+
|
|
53
|
+
def initialize(attrs = {})
|
|
54
|
+
ATTRIBUTES.each do |field|
|
|
55
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
56
|
+
instance_variable_set("@#{field}", value)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.from_hash(hash)
|
|
61
|
+
return nil if hash.nil?
|
|
62
|
+
|
|
63
|
+
new(hash)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Paginated `GET /Queues/{Sid}/Members` response.
|
|
68
|
+
class QueueMemberList
|
|
69
|
+
include Pageable
|
|
70
|
+
|
|
71
|
+
attr_reader :queue_members
|
|
72
|
+
|
|
73
|
+
def initialize(hash = {})
|
|
74
|
+
assign_page_fields(hash)
|
|
75
|
+
@queue_members = (hash['queue_members'] || []).map { |m| QueueMember.from_hash(m) }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.from_hash(hash)
|
|
79
|
+
new(hash || {})
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# A Twilio-compatible Recording resource.
|
|
7
|
+
class Recording
|
|
8
|
+
ATTRIBUTES = %w[
|
|
9
|
+
sid account_sid call_sid conference_sid status source channels
|
|
10
|
+
duration api_version uri date_created date_updated start_time
|
|
11
|
+
price price_unit encryption_details subresource_uris media_url error_code
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
15
|
+
|
|
16
|
+
def initialize(attrs = {})
|
|
17
|
+
ATTRIBUTES.each do |field|
|
|
18
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
19
|
+
instance_variable_set("@#{field}", value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.from_hash(hash)
|
|
24
|
+
return nil if hash.nil?
|
|
25
|
+
|
|
26
|
+
new(hash)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# `GET /Recordings` (account-scoped) and `GET /Calls/{Sid}/Recordings` (per-call) response.
|
|
31
|
+
# The per-call form populates only `recordings`; pagination fields remain `nil`.
|
|
32
|
+
class RecordingList
|
|
33
|
+
include Pageable
|
|
34
|
+
|
|
35
|
+
attr_reader :recordings
|
|
36
|
+
|
|
37
|
+
def initialize(hash = {})
|
|
38
|
+
assign_page_fields(hash)
|
|
39
|
+
@recordings = (hash['recordings'] || []).map { |r| Recording.from_hash(r) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.from_hash(hash)
|
|
43
|
+
new(hash || {})
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Result of fetching `GET /Recordings/{Sid}.wav`. Wraps the WAV bytes with the response's
|
|
48
|
+
# content-type and whether we followed a 302 -> S3 redirect to retrieve them.
|
|
49
|
+
class RecordingAudio
|
|
50
|
+
attr_reader :sid, :content, :content_type, :via_redirect
|
|
51
|
+
|
|
52
|
+
def initialize(sid:, content:, content_type:, via_redirect:)
|
|
53
|
+
@sid = sid
|
|
54
|
+
@content = content
|
|
55
|
+
@content_type = content_type
|
|
56
|
+
@via_redirect = via_redirect
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# SIPREC-session resource (REST equivalent of `<Start><Siprec>`).
|
|
7
|
+
class SiprecSession
|
|
8
|
+
ATTRIBUTES = %w[
|
|
9
|
+
sid account_sid call_sid name connector_name status api_version uri
|
|
10
|
+
date_created date_updated
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
14
|
+
|
|
15
|
+
def initialize(attrs = {})
|
|
16
|
+
ATTRIBUTES.each do |field|
|
|
17
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
18
|
+
instance_variable_set("@#{field}", value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.from_hash(hash)
|
|
23
|
+
return nil if hash.nil?
|
|
24
|
+
|
|
25
|
+
new(hash)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Paginated `GET /Calls/{Sid}/Siprec` response.
|
|
30
|
+
class SiprecList
|
|
31
|
+
include Pageable
|
|
32
|
+
|
|
33
|
+
attr_reader :siprec
|
|
34
|
+
|
|
35
|
+
def initialize(hash = {})
|
|
36
|
+
assign_page_fields(hash)
|
|
37
|
+
@siprec = (hash['siprec'] || []).map { |s| SiprecSession.from_hash(s) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.from_hash(hash)
|
|
41
|
+
new(hash || {})
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# Media-stream session (REST equivalent of `<Connect><Stream>` / `<Start><Stream>`).
|
|
7
|
+
class Stream
|
|
8
|
+
ATTRIBUTES = %w[
|
|
9
|
+
sid account_sid call_sid name status api_version uri
|
|
10
|
+
date_created date_updated
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
14
|
+
|
|
15
|
+
def initialize(attrs = {})
|
|
16
|
+
ATTRIBUTES.each do |field|
|
|
17
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
18
|
+
instance_variable_set("@#{field}", value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.from_hash(hash)
|
|
23
|
+
return nil if hash.nil?
|
|
24
|
+
|
|
25
|
+
new(hash)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Paginated `GET /Calls/{Sid}/Streams` response.
|
|
30
|
+
class StreamList
|
|
31
|
+
include Pageable
|
|
32
|
+
|
|
33
|
+
attr_reader :streams
|
|
34
|
+
|
|
35
|
+
def initialize(hash = {})
|
|
36
|
+
assign_page_fields(hash)
|
|
37
|
+
@streams = (hash['streams'] || []).map { |s| Stream.from_hash(s) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.from_hash(hash)
|
|
41
|
+
new(hash || {})
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'common'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# Real-time per-call transcription (REST equivalent of `<Start><Transcription>`).
|
|
7
|
+
class CallTranscription
|
|
8
|
+
ATTRIBUTES = %w[
|
|
9
|
+
sid account_sid call_sid name language_code transcription_engine
|
|
10
|
+
status api_version uri date_created date_updated
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
attr_reader(*ATTRIBUTES.map(&:to_sym))
|
|
14
|
+
|
|
15
|
+
def initialize(attrs = {})
|
|
16
|
+
ATTRIBUTES.each do |field|
|
|
17
|
+
value = attrs.key?(field) ? attrs[field] : attrs[field.to_sym]
|
|
18
|
+
instance_variable_set("@#{field}", value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.from_hash(hash)
|
|
23
|
+
return nil if hash.nil?
|
|
24
|
+
|
|
25
|
+
new(hash)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Paginated `GET /Calls/{Sid}/Transcriptions` response.
|
|
30
|
+
class TranscriptionList
|
|
31
|
+
include Pageable
|
|
32
|
+
|
|
33
|
+
attr_reader :transcriptions
|
|
34
|
+
|
|
35
|
+
def initialize(hash = {})
|
|
36
|
+
assign_page_fields(hash)
|
|
37
|
+
@transcriptions = (hash['transcriptions'] || []).map { |t| CallTranscription.from_hash(t) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.from_hash(hash)
|
|
41
|
+
new(hash || {})
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base'
|
|
4
|
+
require_relative '../models/applications'
|
|
5
|
+
|
|
6
|
+
module VoiceML
|
|
7
|
+
# Operations on `/Applications` — persistent TwiML+callback bundles.
|
|
8
|
+
class ApplicationsResource < BaseResource
|
|
9
|
+
APPLICATION_FIELDS = {
|
|
10
|
+
'FriendlyName' => :friendly_name,
|
|
11
|
+
'VoiceUrl' => :voice_url,
|
|
12
|
+
'VoiceMethod' => :voice_method,
|
|
13
|
+
'VoiceFallbackUrl' => :voice_fallback_url,
|
|
14
|
+
'VoiceFallbackMethod' => :voice_fallback_method,
|
|
15
|
+
'VoiceCallerIdLookup' => :voice_caller_id_lookup,
|
|
16
|
+
'StatusCallback' => :status_callback,
|
|
17
|
+
'StatusCallbackMethod' => :status_callback_method,
|
|
18
|
+
'StatusCallbackEvent' => :status_callback_event
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
21
|
+
LIST_FIELDS = {
|
|
22
|
+
'FriendlyName' => :friendly_name,
|
|
23
|
+
'Page' => :page,
|
|
24
|
+
'PageSize' => :page_size,
|
|
25
|
+
'PageToken' => :page_token
|
|
26
|
+
}.freeze
|
|
27
|
+
|
|
28
|
+
# @return [VoiceML::Application]
|
|
29
|
+
def create(**kwargs)
|
|
30
|
+
Application.from_hash(
|
|
31
|
+
@transport.request(:post, path('Applications'),
|
|
32
|
+
form: form_params(APPLICATION_FIELDS, kwargs))
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @return [VoiceML::ApplicationList]
|
|
37
|
+
def list(**kwargs)
|
|
38
|
+
ApplicationList.from_hash(
|
|
39
|
+
@transport.request(:get, path('Applications'), params: form_params(LIST_FIELDS, kwargs))
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [VoiceML::Application]
|
|
44
|
+
def get(application_sid)
|
|
45
|
+
Application.from_hash(@transport.request(:get, path('Applications', application_sid)))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [VoiceML::Application]
|
|
49
|
+
def update(application_sid, **kwargs)
|
|
50
|
+
Application.from_hash(
|
|
51
|
+
@transport.request(:post, path('Applications', application_sid),
|
|
52
|
+
form: form_params(APPLICATION_FIELDS, kwargs))
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @return [nil]
|
|
57
|
+
def delete(application_sid)
|
|
58
|
+
@transport.request(:delete, path('Applications', application_sid))
|
|
59
|
+
nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|