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.
- checksums.yaml +4 -4
- data/README.md +13 -6
- data/lib/voiceml/client.rb +29 -2
- data/lib/voiceml/hosts.rb +62 -0
- data/lib/voiceml/models/accounts.rb +54 -0
- data/lib/voiceml/models/assistants_v1.rb +239 -0
- data/lib/voiceml/models/conversations_v1.rb +610 -0
- data/lib/voiceml/models/media.rb +48 -0
- data/lib/voiceml/models/messaging_v1.rb +40 -0
- data/lib/voiceml/models/notifications.rb +39 -0
- data/lib/voiceml/models/outgoing_caller_ids.rb +70 -0
- data/lib/voiceml/models/pricing.rb +231 -0
- data/lib/voiceml/models/routes_v2.rb +14 -0
- data/lib/voiceml/models/sip.rb +22 -0
- data/lib/voiceml/models/user_defined_messages.rb +31 -0
- data/lib/voiceml/models/voice_v1.rb +152 -0
- data/lib/voiceml/resources/assistants_v1.rb +508 -0
- data/lib/voiceml/resources/conversations_v1.rb +1175 -0
- data/lib/voiceml/resources/messaging_v1.rb +87 -0
- data/lib/voiceml/resources/pricing.rb +140 -0
- data/lib/voiceml/resources/routes_v2.rb +22 -2
- data/lib/voiceml/resources/voice_v1.rb +250 -0
- data/lib/voiceml/transport.rb +44 -4
- data/lib/voiceml/version.rb +1 -1
- data/lib/voiceml.rb +11 -0
- metadata +18 -2
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../models/messaging_v1'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# `client.messaging_v1` — Twilio Messaging v1 (messaging.twilio.com/v1).
|
|
7
|
+
# The whole group is routed at the messaging host (`messaging.voicetel.com`) by the
|
|
8
|
+
# client, which is what disambiguates a Messaging Service (`MG...`) from a
|
|
9
|
+
# Conversation Service (`IS...`) — they share the `/v1/Services` path shape.
|
|
10
|
+
class MessagingV1Resource
|
|
11
|
+
attr_reader :services
|
|
12
|
+
|
|
13
|
+
def initialize(transport)
|
|
14
|
+
@services = MessagingV1ServicesResource.new(transport)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Operations on `/v1/Services` at the messaging host.
|
|
19
|
+
#
|
|
20
|
+
# `create` / `list` / `fetch` / `delete` reuse the shared path; `update`
|
|
21
|
+
# (`POST /v1/Services/{sid}`) is unique to Messaging Service.
|
|
22
|
+
class MessagingV1ServicesResource
|
|
23
|
+
SERVICE_FIELDS = {
|
|
24
|
+
'FriendlyName' => :friendly_name,
|
|
25
|
+
'InboundRequestUrl' => :inbound_request_url,
|
|
26
|
+
'InboundMethod' => :inbound_method,
|
|
27
|
+
'FallbackUrl' => :fallback_url,
|
|
28
|
+
'FallbackMethod' => :fallback_method,
|
|
29
|
+
'StatusCallback' => :status_callback,
|
|
30
|
+
'StickySender' => :sticky_sender,
|
|
31
|
+
'MmsConverter' => :mms_converter,
|
|
32
|
+
'SmartEncoding' => :smart_encoding,
|
|
33
|
+
'ScanMessageContent' => :scan_message_content,
|
|
34
|
+
'FallbackToLongCode' => :fallback_to_long_code,
|
|
35
|
+
'AreaCodeGeomatch' => :area_code_geomatch,
|
|
36
|
+
'SynchronousValidation' => :synchronous_validation,
|
|
37
|
+
'ValidityPeriod' => :validity_period,
|
|
38
|
+
'Usecase' => :usecase,
|
|
39
|
+
'UseInboundWebhookOnNumber' => :use_inbound_webhook_on_number
|
|
40
|
+
}.freeze
|
|
41
|
+
|
|
42
|
+
def initialize(transport)
|
|
43
|
+
@transport = transport
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def create(friendly_name:, **kwargs)
|
|
47
|
+
kwargs[:friendly_name] = friendly_name
|
|
48
|
+
MessagingService.from_hash(
|
|
49
|
+
@transport.request(:post, '/v1/Services', form: build_form(kwargs))
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def list(page_size: nil)
|
|
54
|
+
params = {}
|
|
55
|
+
params['PageSize'] = page_size unless page_size.nil?
|
|
56
|
+
MessagingServiceList.new(@transport.request(:get, '/v1/Services', params: params))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def fetch(sid)
|
|
60
|
+
MessagingService.from_hash(@transport.request(:get, "/v1/Services/#{sid}"))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def update(sid, **kwargs)
|
|
64
|
+
MessagingService.from_hash(
|
|
65
|
+
@transport.request(:post, "/v1/Services/#{sid}", form: build_form(kwargs))
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def delete(sid)
|
|
70
|
+
@transport.request(:delete, "/v1/Services/#{sid}")
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def build_form(kwargs)
|
|
77
|
+
out = {}
|
|
78
|
+
SERVICE_FIELDS.each do |wire, k|
|
|
79
|
+
value = kwargs[k]
|
|
80
|
+
next if value.nil?
|
|
81
|
+
|
|
82
|
+
out[wire] = value
|
|
83
|
+
end
|
|
84
|
+
out
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
require_relative '../models/pricing'
|
|
6
|
+
|
|
7
|
+
module VoiceML
|
|
8
|
+
# `client.pricing` — Twilio Pricing v1/v2 (pricing.twilio.com) surface.
|
|
9
|
+
#
|
|
10
|
+
# Read-only. Served on the default host (VoiceML has no pricing subdomain). Layout:
|
|
11
|
+
#
|
|
12
|
+
# client.pricing.v1.voice.countries.list / fetch
|
|
13
|
+
# client.pricing.v1.voice.numbers.fetch
|
|
14
|
+
# client.pricing.v1.messaging.countries.list / fetch
|
|
15
|
+
# client.pricing.v1.phone_numbers.countries.list / fetch
|
|
16
|
+
# client.pricing.v2.voice.countries.list / fetch
|
|
17
|
+
# client.pricing.v2.voice.numbers.fetch
|
|
18
|
+
# client.pricing.v2.trunking.countries.list / fetch
|
|
19
|
+
# client.pricing.v2.trunking.numbers.fetch
|
|
20
|
+
#
|
|
21
|
+
# Every `countries.list` returns the shared PricingCountriesList envelope; `fetch`
|
|
22
|
+
# returns the product-specific country/number body. Number path segments are
|
|
23
|
+
# URL-encoded (E.164 `+` -> `%2B`).
|
|
24
|
+
class PricingResource
|
|
25
|
+
attr_reader :v1, :v2
|
|
26
|
+
|
|
27
|
+
def initialize(transport)
|
|
28
|
+
@v1 = PricingV1Resource.new(transport)
|
|
29
|
+
@v2 = PricingV2Resource.new(transport)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# A pricing product group exposing `.countries` and optionally `.numbers`.
|
|
34
|
+
class PricingProduct
|
|
35
|
+
attr_reader :countries, :numbers
|
|
36
|
+
|
|
37
|
+
def initialize(countries, numbers = nil)
|
|
38
|
+
@countries = countries
|
|
39
|
+
@numbers = numbers
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# `.../Countries` list + per-country fetch. `model` is the fetch body class.
|
|
44
|
+
class PricingCountriesResource
|
|
45
|
+
def initialize(transport, base_path, model)
|
|
46
|
+
@transport = transport
|
|
47
|
+
@base = base_path
|
|
48
|
+
@model = model
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def list(page_size: nil)
|
|
52
|
+
params = {}
|
|
53
|
+
params['PageSize'] = page_size unless page_size.nil?
|
|
54
|
+
PricingCountriesList.new(@transport.request(:get, @base, params: params))
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def fetch(iso_country)
|
|
58
|
+
@model.from_hash(@transport.request(:get, "#{@base}/#{iso_country}"))
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# `/v1/Voice/Numbers/{Number}` — single-number fetch.
|
|
63
|
+
class PricingV1VoiceNumbersResource
|
|
64
|
+
def initialize(transport)
|
|
65
|
+
@transport = transport
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def fetch(number)
|
|
69
|
+
PricingVoiceNumber.from_hash(
|
|
70
|
+
@transport.request(:get, "/v1/Voice/Numbers/#{URI.encode_www_form_component(number)}")
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# `/v2/Voice/Numbers/{Destination}` — origin-aware single-number fetch.
|
|
76
|
+
class PricingV2VoiceNumbersResource
|
|
77
|
+
def initialize(transport)
|
|
78
|
+
@transport = transport
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def fetch(destination_number, origination_number: nil)
|
|
82
|
+
params = {}
|
|
83
|
+
params['OriginationNumber'] = origination_number unless origination_number.nil?
|
|
84
|
+
PricingVoiceNumberV2.from_hash(
|
|
85
|
+
@transport.request(:get, "/v2/Voice/Numbers/#{URI.encode_www_form_component(destination_number)}",
|
|
86
|
+
params: params)
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# `/v2/Trunking/Numbers/{Destination}` — origin-aware single-number fetch.
|
|
92
|
+
class PricingV2TrunkingNumbersResource
|
|
93
|
+
def initialize(transport)
|
|
94
|
+
@transport = transport
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def fetch(destination_number, origination_number: nil)
|
|
98
|
+
params = {}
|
|
99
|
+
params['OriginationNumber'] = origination_number unless origination_number.nil?
|
|
100
|
+
PricingTrunkingNumber.from_hash(
|
|
101
|
+
@transport.request(:get, "/v2/Trunking/Numbers/#{URI.encode_www_form_component(destination_number)}",
|
|
102
|
+
params: params)
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# `client.pricing.v1.*` — Voice, Messaging, PhoneNumbers.
|
|
108
|
+
class PricingV1Resource
|
|
109
|
+
attr_reader :voice, :messaging, :phone_numbers
|
|
110
|
+
|
|
111
|
+
def initialize(transport)
|
|
112
|
+
@voice = PricingProduct.new(
|
|
113
|
+
PricingCountriesResource.new(transport, '/v1/Voice/Countries', PricingVoiceCountry),
|
|
114
|
+
PricingV1VoiceNumbersResource.new(transport)
|
|
115
|
+
)
|
|
116
|
+
@messaging = PricingProduct.new(
|
|
117
|
+
PricingCountriesResource.new(transport, '/v1/Messaging/Countries', PricingMessagingCountry)
|
|
118
|
+
)
|
|
119
|
+
@phone_numbers = PricingProduct.new(
|
|
120
|
+
PricingCountriesResource.new(transport, '/v1/PhoneNumbers/Countries', PricingPhoneNumberCountry)
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# `client.pricing.v2.*` — Voice, Trunking.
|
|
126
|
+
class PricingV2Resource
|
|
127
|
+
attr_reader :voice, :trunking
|
|
128
|
+
|
|
129
|
+
def initialize(transport)
|
|
130
|
+
@voice = PricingProduct.new(
|
|
131
|
+
PricingCountriesResource.new(transport, '/v2/Voice/Countries', PricingVoiceCountryV2),
|
|
132
|
+
PricingV2VoiceNumbersResource.new(transport)
|
|
133
|
+
)
|
|
134
|
+
@trunking = PricingProduct.new(
|
|
135
|
+
PricingCountriesResource.new(transport, '/v2/Trunking/Countries', PricingTrunkingCountry),
|
|
136
|
+
PricingV2TrunkingNumbersResource.new(transport)
|
|
137
|
+
)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -6,9 +6,10 @@ module VoiceML
|
|
|
6
6
|
# `client.routes_v2` — Twilio routes/v2 Inbound Processing Region API.
|
|
7
7
|
# Sits outside the /2010-04-01/Accounts/... namespace.
|
|
8
8
|
class RoutesV2Resource
|
|
9
|
-
attr_reader :sip_domains
|
|
9
|
+
attr_reader :sip_domains, :phone_numbers
|
|
10
10
|
def initialize(transport)
|
|
11
|
-
@sip_domains
|
|
11
|
+
@sip_domains = RoutesV2SipDomainsResource.new(transport)
|
|
12
|
+
@phone_numbers = RoutesV2PhoneNumbersResource.new(transport)
|
|
12
13
|
end
|
|
13
14
|
end
|
|
14
15
|
|
|
@@ -30,4 +31,23 @@ module VoiceML
|
|
|
30
31
|
RoutesV2SipDomain.from_hash(@transport.request(:post, "/v2/SipDomains/#{domain_name}", form: form))
|
|
31
32
|
end
|
|
32
33
|
end
|
|
34
|
+
|
|
35
|
+
# Operations on /v2/PhoneNumbers/{PhoneNumber}. Keyed by E.164 phone number or
|
|
36
|
+
# its PN sid; account resolved from HTTP Basic auth.
|
|
37
|
+
class RoutesV2PhoneNumbersResource
|
|
38
|
+
def initialize(transport)
|
|
39
|
+
@transport = transport
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def fetch(phone_number)
|
|
43
|
+
RoutesV2PhoneNumber.from_hash(@transport.request(:get, "/v2/PhoneNumbers/#{phone_number}"))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update(phone_number, voice_region: nil, friendly_name: nil)
|
|
47
|
+
form = {}
|
|
48
|
+
form['VoiceRegion'] = voice_region unless voice_region.nil?
|
|
49
|
+
form['FriendlyName'] = friendly_name unless friendly_name.nil?
|
|
50
|
+
RoutesV2PhoneNumber.from_hash(@transport.request(:post, "/v2/PhoneNumbers/#{phone_number}", form: form))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
33
53
|
end
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../models/voice_v1'
|
|
4
|
+
|
|
5
|
+
module VoiceML
|
|
6
|
+
# `client.voice_v1` — Twilio Voice v1 (voice.twilio.com/v1) surface.
|
|
7
|
+
# Sits outside the /2010-04-01/Accounts/... namespace; account resolved from Basic auth.
|
|
8
|
+
class VoiceV1Resource
|
|
9
|
+
attr_reader :ip_records, :source_ip_mappings, :byoc_trunks,
|
|
10
|
+
:connection_policies, :dialing_permissions
|
|
11
|
+
|
|
12
|
+
def initialize(transport)
|
|
13
|
+
@ip_records = VoiceV1IpRecordsResource.new(transport)
|
|
14
|
+
@source_ip_mappings = VoiceV1SourceIpMappingsResource.new(transport)
|
|
15
|
+
@byoc_trunks = VoiceV1ByocTrunksResource.new(transport)
|
|
16
|
+
@connection_policies = VoiceV1ConnectionPoliciesResource.new(transport)
|
|
17
|
+
@dialing_permissions = VoiceV1DialingPermissionsResource.new(transport)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# /v1/IpRecords + /v1/IpRecords/{Sid}
|
|
22
|
+
class VoiceV1IpRecordsResource
|
|
23
|
+
def initialize(transport)
|
|
24
|
+
@transport = transport
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def list(page_size: nil)
|
|
28
|
+
params = {}
|
|
29
|
+
params['PageSize'] = page_size unless page_size.nil?
|
|
30
|
+
VoiceV1IpRecordList.new(@transport.request(:get, '/v1/IpRecords', params: params))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def create(ip_address:, friendly_name: nil, cidr_prefix_length: nil)
|
|
34
|
+
form = { 'IpAddress' => ip_address }
|
|
35
|
+
form['FriendlyName'] = friendly_name unless friendly_name.nil?
|
|
36
|
+
form['CidrPrefixLength'] = cidr_prefix_length unless cidr_prefix_length.nil?
|
|
37
|
+
VoiceV1IpRecord.from_hash(@transport.request(:post, '/v1/IpRecords', form: form))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def fetch(sid)
|
|
41
|
+
VoiceV1IpRecord.from_hash(@transport.request(:get, "/v1/IpRecords/#{sid}"))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def update(sid, friendly_name: nil)
|
|
45
|
+
form = {}
|
|
46
|
+
form['FriendlyName'] = friendly_name unless friendly_name.nil?
|
|
47
|
+
VoiceV1IpRecord.from_hash(@transport.request(:post, "/v1/IpRecords/#{sid}", form: form))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def delete(sid)
|
|
51
|
+
@transport.request(:delete, "/v1/IpRecords/#{sid}")
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# /v1/SourceIpMappings + /v1/SourceIpMappings/{Sid}
|
|
57
|
+
class VoiceV1SourceIpMappingsResource
|
|
58
|
+
def initialize(transport)
|
|
59
|
+
@transport = transport
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def list(page_size: nil)
|
|
63
|
+
params = {}
|
|
64
|
+
params['PageSize'] = page_size unless page_size.nil?
|
|
65
|
+
VoiceV1SourceIpMappingList.new(@transport.request(:get, '/v1/SourceIpMappings', params: params))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def create(ip_record_sid:, sip_domain_sid:)
|
|
69
|
+
form = { 'IpRecordSid' => ip_record_sid, 'SipDomainSid' => sip_domain_sid }
|
|
70
|
+
VoiceV1SourceIpMapping.from_hash(@transport.request(:post, '/v1/SourceIpMappings', form: form))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def fetch(sid)
|
|
74
|
+
VoiceV1SourceIpMapping.from_hash(@transport.request(:get, "/v1/SourceIpMappings/#{sid}"))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def update(sid, sip_domain_sid:)
|
|
78
|
+
form = { 'SipDomainSid' => sip_domain_sid }
|
|
79
|
+
VoiceV1SourceIpMapping.from_hash(@transport.request(:post, "/v1/SourceIpMappings/#{sid}", form: form))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def delete(sid)
|
|
83
|
+
@transport.request(:delete, "/v1/SourceIpMappings/#{sid}")
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# /v1/ByocTrunks + /v1/ByocTrunks/{Sid}
|
|
89
|
+
class VoiceV1ByocTrunksResource
|
|
90
|
+
TRUNK_FIELDS = {
|
|
91
|
+
'FriendlyName' => :friendly_name,
|
|
92
|
+
'VoiceUrl' => :voice_url,
|
|
93
|
+
'VoiceMethod' => :voice_method,
|
|
94
|
+
'VoiceFallbackUrl' => :voice_fallback_url,
|
|
95
|
+
'VoiceFallbackMethod' => :voice_fallback_method,
|
|
96
|
+
'StatusCallbackUrl' => :status_callback_url,
|
|
97
|
+
'StatusCallbackMethod' => :status_callback_method,
|
|
98
|
+
'CnamLookupEnabled' => :cnam_lookup_enabled,
|
|
99
|
+
'ConnectionPolicySid' => :connection_policy_sid,
|
|
100
|
+
'FromDomainSid' => :from_domain_sid
|
|
101
|
+
}.freeze
|
|
102
|
+
|
|
103
|
+
def initialize(transport)
|
|
104
|
+
@transport = transport
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def list(page_size: nil)
|
|
108
|
+
params = {}
|
|
109
|
+
params['PageSize'] = page_size unless page_size.nil?
|
|
110
|
+
VoiceV1ByocTrunkList.new(@transport.request(:get, '/v1/ByocTrunks', params: params))
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def create(**kwargs)
|
|
114
|
+
VoiceV1ByocTrunk.from_hash(@transport.request(:post, '/v1/ByocTrunks', form: build_form(kwargs)))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def fetch(sid)
|
|
118
|
+
VoiceV1ByocTrunk.from_hash(@transport.request(:get, "/v1/ByocTrunks/#{sid}"))
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def update(sid, **kwargs)
|
|
122
|
+
VoiceV1ByocTrunk.from_hash(@transport.request(:post, "/v1/ByocTrunks/#{sid}", form: build_form(kwargs)))
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def delete(sid)
|
|
126
|
+
@transport.request(:delete, "/v1/ByocTrunks/#{sid}")
|
|
127
|
+
nil
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
def build_form(kwargs)
|
|
133
|
+
out = {}
|
|
134
|
+
TRUNK_FIELDS.each do |wire, k|
|
|
135
|
+
value = kwargs[k]
|
|
136
|
+
next if value.nil?
|
|
137
|
+
|
|
138
|
+
out[wire] = value
|
|
139
|
+
end
|
|
140
|
+
out
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# /v1/ConnectionPolicies + /v1/ConnectionPolicies/{Sid} + nested /Targets
|
|
145
|
+
class VoiceV1ConnectionPoliciesResource
|
|
146
|
+
TARGET_FIELDS = {
|
|
147
|
+
'Target' => :target,
|
|
148
|
+
'FriendlyName' => :friendly_name,
|
|
149
|
+
'Priority' => :priority,
|
|
150
|
+
'Weight' => :weight,
|
|
151
|
+
'Enabled' => :enabled
|
|
152
|
+
}.freeze
|
|
153
|
+
|
|
154
|
+
def initialize(transport)
|
|
155
|
+
@transport = transport
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def list(page_size: nil)
|
|
159
|
+
params = {}
|
|
160
|
+
params['PageSize'] = page_size unless page_size.nil?
|
|
161
|
+
VoiceV1ConnectionPolicyList.new(@transport.request(:get, '/v1/ConnectionPolicies', params: params))
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def create(friendly_name: nil)
|
|
165
|
+
form = {}
|
|
166
|
+
form['FriendlyName'] = friendly_name unless friendly_name.nil?
|
|
167
|
+
VoiceV1ConnectionPolicy.from_hash(@transport.request(:post, '/v1/ConnectionPolicies', form: form))
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def fetch(sid)
|
|
171
|
+
VoiceV1ConnectionPolicy.from_hash(@transport.request(:get, "/v1/ConnectionPolicies/#{sid}"))
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def update(sid, friendly_name: nil)
|
|
175
|
+
form = {}
|
|
176
|
+
form['FriendlyName'] = friendly_name unless friendly_name.nil?
|
|
177
|
+
VoiceV1ConnectionPolicy.from_hash(@transport.request(:post, "/v1/ConnectionPolicies/#{sid}", form: form))
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def delete(sid)
|
|
181
|
+
@transport.request(:delete, "/v1/ConnectionPolicies/#{sid}")
|
|
182
|
+
nil
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# --- /v1/ConnectionPolicies/{ConnectionPolicySid}/Targets ---
|
|
186
|
+
def list_targets(connection_policy_sid, page_size: nil)
|
|
187
|
+
params = {}
|
|
188
|
+
params['PageSize'] = page_size unless page_size.nil?
|
|
189
|
+
VoiceV1ConnectionPolicyTargetList.new(
|
|
190
|
+
@transport.request(:get, "/v1/ConnectionPolicies/#{connection_policy_sid}/Targets", params: params)
|
|
191
|
+
)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def create_target(connection_policy_sid, target:, friendly_name: nil, priority: nil, weight: nil, enabled: nil)
|
|
195
|
+
kwargs = { target: target, friendly_name: friendly_name, priority: priority, weight: weight, enabled: enabled }
|
|
196
|
+
VoiceV1ConnectionPolicyTarget.from_hash(
|
|
197
|
+
@transport.request(:post, "/v1/ConnectionPolicies/#{connection_policy_sid}/Targets",
|
|
198
|
+
form: build_target_form(kwargs))
|
|
199
|
+
)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def fetch_target(connection_policy_sid, sid)
|
|
203
|
+
VoiceV1ConnectionPolicyTarget.from_hash(
|
|
204
|
+
@transport.request(:get, "/v1/ConnectionPolicies/#{connection_policy_sid}/Targets/#{sid}")
|
|
205
|
+
)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def update_target(connection_policy_sid, sid, **kwargs)
|
|
209
|
+
VoiceV1ConnectionPolicyTarget.from_hash(
|
|
210
|
+
@transport.request(:post, "/v1/ConnectionPolicies/#{connection_policy_sid}/Targets/#{sid}",
|
|
211
|
+
form: build_target_form(kwargs))
|
|
212
|
+
)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def delete_target(connection_policy_sid, sid)
|
|
216
|
+
@transport.request(:delete, "/v1/ConnectionPolicies/#{connection_policy_sid}/Targets/#{sid}")
|
|
217
|
+
nil
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
private
|
|
221
|
+
|
|
222
|
+
def build_target_form(kwargs)
|
|
223
|
+
out = {}
|
|
224
|
+
TARGET_FIELDS.each do |wire, k|
|
|
225
|
+
value = kwargs[k]
|
|
226
|
+
next if value.nil?
|
|
227
|
+
|
|
228
|
+
out[wire] = value
|
|
229
|
+
end
|
|
230
|
+
out
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# /v1/Settings — DialingPermissions inheritance toggle (singleton).
|
|
235
|
+
class VoiceV1DialingPermissionsResource
|
|
236
|
+
def initialize(transport)
|
|
237
|
+
@transport = transport
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def fetch_settings
|
|
241
|
+
VoiceV1DialingPermissionsSettings.from_hash(@transport.request(:get, '/v1/Settings'))
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def update_settings(dialing_permissions_inheritance: nil)
|
|
245
|
+
form = {}
|
|
246
|
+
form['DialingPermissionsInheritance'] = dialing_permissions_inheritance unless dialing_permissions_inheritance.nil?
|
|
247
|
+
VoiceV1DialingPermissionsSettings.from_hash(@transport.request(:post, '/v1/Settings', form: form))
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
data/lib/voiceml/transport.rb
CHANGED
|
@@ -66,10 +66,14 @@ module VoiceML
|
|
|
66
66
|
# Perform a request. Pass `form:` for a form-urlencoded POST body, `json:` for a JSON body,
|
|
67
67
|
# or neither for a plain GET/DELETE. `params:` are query-string params.
|
|
68
68
|
#
|
|
69
|
+
# `base_url:` overrides the client's default host for this one call (used to route product
|
|
70
|
+
# resources at their subdomain — Conversations, Messaging Service). When set, the request
|
|
71
|
+
# goes to an absolute URL so the correct host/SNI is used per request; see `ScopedTransport`.
|
|
72
|
+
#
|
|
69
73
|
# @return [Hash, Array, nil] the parsed JSON body (or `nil` for empty 2xx).
|
|
70
74
|
# @raise [VoiceML::ApiError] for non-2xx responses (subclasses by status family).
|
|
71
|
-
def request(method, path, params: nil, form: nil, json: nil)
|
|
72
|
-
uri = build_uri(path, params)
|
|
75
|
+
def request(method, path, params: nil, form: nil, json: nil, base_url: nil)
|
|
76
|
+
uri = build_uri(request_path(path, base_url), params)
|
|
73
77
|
|
|
74
78
|
attempt = 0
|
|
75
79
|
loop do
|
|
@@ -95,8 +99,8 @@ module VoiceML
|
|
|
95
99
|
# redirect that `GET /Recordings/{sid}.wav` issues when audio has been archived.
|
|
96
100
|
#
|
|
97
101
|
# @return [Array(Integer, String, Hash)] status code, response body bytes, header hash.
|
|
98
|
-
def fetch_bytes(path)
|
|
99
|
-
uri = build_uri(path, nil)
|
|
102
|
+
def fetch_bytes(path, base_url: nil)
|
|
103
|
+
uri = build_uri(request_path(path, base_url), nil)
|
|
100
104
|
visited = []
|
|
101
105
|
loop do
|
|
102
106
|
raise ApiError.new('too many redirects', status_code: 0) if visited.length > 5
|
|
@@ -126,6 +130,14 @@ module VoiceML
|
|
|
126
130
|
Errno::EHOSTUNREACH, SocketError, EOFError]
|
|
127
131
|
end
|
|
128
132
|
|
|
133
|
+
# Prefix `path` with a per-request `base_url` override, if any. Leaves absolute paths and
|
|
134
|
+
# the default-host case untouched so `build_uri` handles them as before.
|
|
135
|
+
def request_path(path, base_url)
|
|
136
|
+
return path if base_url.nil? || base_url.empty?
|
|
137
|
+
|
|
138
|
+
"#{base_url}#{path}"
|
|
139
|
+
end
|
|
140
|
+
|
|
129
141
|
def build_uri(path, params)
|
|
130
142
|
uri = if path.start_with?('http://', 'https://')
|
|
131
143
|
URI.parse(path)
|
|
@@ -293,4 +305,32 @@ module VoiceML
|
|
|
293
305
|
[8.0, 0.5 * (2**attempt)].min
|
|
294
306
|
end
|
|
295
307
|
end
|
|
308
|
+
|
|
309
|
+
# A transport view pinned to a specific product base URL.
|
|
310
|
+
#
|
|
311
|
+
# Wraps a real `Transport` and forwards every call, injecting a `base_url` override so an
|
|
312
|
+
# entire resource group lands on its product subdomain (`conversations.voicetel.com` /
|
|
313
|
+
# `messaging.voicetel.com`) without each resource needing to know its own host.
|
|
314
|
+
#
|
|
315
|
+
# @api private
|
|
316
|
+
class ScopedTransport
|
|
317
|
+
attr_reader :base_url
|
|
318
|
+
|
|
319
|
+
def initialize(inner, base_url)
|
|
320
|
+
@inner = inner
|
|
321
|
+
@base_url = Transport.strip_trailing_slashes(base_url)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def account_sid
|
|
325
|
+
@inner.account_sid
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def request(method, path, params: nil, form: nil, json: nil)
|
|
329
|
+
@inner.request(method, path, params: params, form: form, json: json, base_url: @base_url)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def fetch_bytes(path)
|
|
333
|
+
@inner.fetch_bytes(path, base_url: @base_url)
|
|
334
|
+
end
|
|
335
|
+
end
|
|
296
336
|
end
|
data/lib/voiceml/version.rb
CHANGED
data/lib/voiceml.rb
CHANGED
|
@@ -25,3 +25,14 @@ require_relative 'voiceml/version'
|
|
|
25
25
|
require_relative 'voiceml/errors'
|
|
26
26
|
require_relative 'voiceml/transport'
|
|
27
27
|
require_relative 'voiceml/client'
|
|
28
|
+
|
|
29
|
+
# Model-only resources — surfaces that voiceml runs as Twilio-compat stubs
|
|
30
|
+
# (no first-class client.* getter yet) but still need decodable Ruby classes
|
|
31
|
+
# for response-shape conformance and migration tooling. Resource files
|
|
32
|
+
# require their own models; these are the standalone ones.
|
|
33
|
+
require_relative 'voiceml/models/accounts'
|
|
34
|
+
require_relative 'voiceml/models/outgoing_caller_ids'
|
|
35
|
+
require_relative 'voiceml/models/media'
|
|
36
|
+
require_relative 'voiceml/models/notifications'
|
|
37
|
+
require_relative 'voiceml/models/user_defined_messages'
|
|
38
|
+
require_relative 'voiceml/models/assistants_v1'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: voiceml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- VoiceTel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|
|
@@ -64,14 +64,23 @@ files:
|
|
|
64
64
|
- lib/voiceml.rb
|
|
65
65
|
- lib/voiceml/client.rb
|
|
66
66
|
- lib/voiceml/errors.rb
|
|
67
|
+
- lib/voiceml/hosts.rb
|
|
68
|
+
- lib/voiceml/models/accounts.rb
|
|
67
69
|
- lib/voiceml/models/applications.rb
|
|
70
|
+
- lib/voiceml/models/assistants_v1.rb
|
|
68
71
|
- lib/voiceml/models/calls.rb
|
|
69
72
|
- lib/voiceml/models/common.rb
|
|
70
73
|
- lib/voiceml/models/conferences.rb
|
|
74
|
+
- lib/voiceml/models/conversations_v1.rb
|
|
71
75
|
- lib/voiceml/models/diagnostics.rb
|
|
72
76
|
- lib/voiceml/models/incoming_phone_numbers.rb
|
|
77
|
+
- lib/voiceml/models/media.rb
|
|
73
78
|
- lib/voiceml/models/messages.rb
|
|
79
|
+
- lib/voiceml/models/messaging_v1.rb
|
|
80
|
+
- lib/voiceml/models/notifications.rb
|
|
81
|
+
- lib/voiceml/models/outgoing_caller_ids.rb
|
|
74
82
|
- lib/voiceml/models/payments.rb
|
|
83
|
+
- lib/voiceml/models/pricing.rb
|
|
75
84
|
- lib/voiceml/models/queues.rb
|
|
76
85
|
- lib/voiceml/models/recordings.rb
|
|
77
86
|
- lib/voiceml/models/routes_v2.rb
|
|
@@ -79,18 +88,25 @@ files:
|
|
|
79
88
|
- lib/voiceml/models/siprec.rb
|
|
80
89
|
- lib/voiceml/models/streams.rb
|
|
81
90
|
- lib/voiceml/models/transcriptions.rb
|
|
91
|
+
- lib/voiceml/models/user_defined_messages.rb
|
|
92
|
+
- lib/voiceml/models/voice_v1.rb
|
|
82
93
|
- lib/voiceml/resources/applications.rb
|
|
94
|
+
- lib/voiceml/resources/assistants_v1.rb
|
|
83
95
|
- lib/voiceml/resources/base.rb
|
|
84
96
|
- lib/voiceml/resources/calls.rb
|
|
85
97
|
- lib/voiceml/resources/conferences.rb
|
|
98
|
+
- lib/voiceml/resources/conversations_v1.rb
|
|
86
99
|
- lib/voiceml/resources/diagnostics.rb
|
|
87
100
|
- lib/voiceml/resources/incoming_phone_numbers.rb
|
|
88
101
|
- lib/voiceml/resources/messages.rb
|
|
102
|
+
- lib/voiceml/resources/messaging_v1.rb
|
|
89
103
|
- lib/voiceml/resources/notifications.rb
|
|
104
|
+
- lib/voiceml/resources/pricing.rb
|
|
90
105
|
- lib/voiceml/resources/queues.rb
|
|
91
106
|
- lib/voiceml/resources/recordings.rb
|
|
92
107
|
- lib/voiceml/resources/routes_v2.rb
|
|
93
108
|
- lib/voiceml/resources/sip.rb
|
|
109
|
+
- lib/voiceml/resources/voice_v1.rb
|
|
94
110
|
- lib/voiceml/transport.rb
|
|
95
111
|
- lib/voiceml/version.rb
|
|
96
112
|
homepage: https://voiceml.voicetel.com
|