vonage 7.11.0 → 7.13.0
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/lib/vonage/client.rb +14 -0
- data/lib/vonage/config.rb +4 -0
- data/lib/vonage/namespace.rb +48 -2
- data/lib/vonage/proactive_connect/events/list_response.rb +11 -0
- data/lib/vonage/proactive_connect/events.rb +68 -0
- data/lib/vonage/proactive_connect/item.rb +104 -0
- data/lib/vonage/proactive_connect/items/file_response.rb +32 -0
- data/lib/vonage/proactive_connect/items/list_response.rb +11 -0
- data/lib/vonage/proactive_connect/items.rb +107 -0
- data/lib/vonage/proactive_connect/list.rb +168 -0
- data/lib/vonage/proactive_connect/lists/list_response.rb +11 -0
- data/lib/vonage/proactive_connect/lists.rb +35 -0
- data/lib/vonage/proactive_connect.rb +33 -0
- data/lib/vonage/subaccounts/balance_transfers/list_response.rb +11 -0
- data/lib/vonage/subaccounts/credit_transfers/list_response.rb +11 -0
- data/lib/vonage/subaccounts/list_response.rb +15 -0
- data/lib/vonage/subaccounts.rb +203 -0
- data/lib/vonage/version.rb +1 -1
- data/vonage.gemspec +1 -0
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ab386887cbecc55b2e4c2fe915edb4ec7cac9bfc62d7205d577daf2f451b443
|
4
|
+
data.tar.gz: ba606e264741711abdc23d3109b9a741efd8e6848e0743e48719c7414478d10e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3d11a57f0782eff2acc885e8edc0243f5acb6f93e27c54dc3ff057a15b3b82c413fb24deda53519e5d3d7b109e22de21244eed798ef8c5cb8abb070117bdac5
|
7
|
+
data.tar.gz: b199fe7cc3e00eb2a7bb13e62f2448c3cda49dfe7c7b476825872074fe71e89d7f930778d75f83f8b1204c6429155bc363e85468a5c71b89849a8037fb37220a
|
data/lib/vonage/client.rb
CHANGED
@@ -96,6 +96,13 @@ module Vonage
|
|
96
96
|
@pricing ||= T.let(PricingTypes.new(config), T.nilable(Vonage::PricingTypes))
|
97
97
|
end
|
98
98
|
|
99
|
+
# @return [ProactiveConnect]
|
100
|
+
#
|
101
|
+
sig { returns(T.nilable(Vonage::ProactiveConnect)) }
|
102
|
+
def proactive_connect
|
103
|
+
@proactive_connect ||= T.let(ProactiveConnect.new(config), T.nilable(Vonage::ProactiveConnect))
|
104
|
+
end
|
105
|
+
|
99
106
|
# @return [Redact]
|
100
107
|
#
|
101
108
|
sig { returns(T.nilable(Vonage::Redact)) }
|
@@ -117,6 +124,13 @@ module Vonage
|
|
117
124
|
@sms ||= T.let(SMS.new(config), T.nilable(Vonage::SMS))
|
118
125
|
end
|
119
126
|
|
127
|
+
# @return [Subaccounts]
|
128
|
+
#
|
129
|
+
sig { returns(T.nilable(Vonage::Subaccounts)) }
|
130
|
+
def subaccounts
|
131
|
+
@subaccounts ||= T.let(Subaccounts.new(config), T.nilable(Vonage::Subaccounts))
|
132
|
+
end
|
133
|
+
|
120
134
|
# @return [TFA]
|
121
135
|
#
|
122
136
|
sig { returns(T.nilable(Vonage::TFA)) }
|
data/lib/vonage/config.rb
CHANGED
@@ -18,6 +18,7 @@ module Vonage
|
|
18
18
|
self.signature_secret = ENV['VONAGE_SIGNATURE_SECRET']
|
19
19
|
self.signature_method = ENV['VONAGE_SIGNATURE_METHOD'] || 'md5hash'
|
20
20
|
self.token = T.let(nil, T.nilable(String))
|
21
|
+
self.vonage_host = 'api-eu.vonage.com'
|
21
22
|
end
|
22
23
|
|
23
24
|
# Merges the config with the given options hash.
|
@@ -198,6 +199,9 @@ module Vonage
|
|
198
199
|
sig { params(token: T.nilable(String)).returns(T.nilable(String)) }
|
199
200
|
attr_writer :token
|
200
201
|
|
202
|
+
sig { returns(String) }
|
203
|
+
attr_accessor :vonage_host
|
204
|
+
|
201
205
|
protected
|
202
206
|
|
203
207
|
sig { params(name: Symbol, value: T.untyped).void }
|
data/lib/vonage/namespace.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
require 'net/http'
|
4
|
+
require 'net/http/post/multipart'
|
4
5
|
require 'json'
|
5
6
|
|
6
7
|
module Vonage
|
@@ -8,7 +9,8 @@ module Vonage
|
|
8
9
|
def initialize(config)
|
9
10
|
@config = config
|
10
11
|
|
11
|
-
@host = self.class.host == :api_host ? @config.api_host : @config.rest_host
|
12
|
+
# @host = self.class.host == :api_host ? @config.api_host : @config.rest_host
|
13
|
+
@host = set_host
|
12
14
|
|
13
15
|
@http = Net::HTTP.new(@host, Net::HTTP.https_default_port, p_addr = nil)
|
14
16
|
@http.use_ssl = true
|
@@ -21,7 +23,7 @@ module Vonage
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def self.host=(host)
|
24
|
-
raise ArgumentError unless host
|
26
|
+
raise ArgumentError unless %i[rest_host vonage_host].include?(host)
|
25
27
|
|
26
28
|
@host = host
|
27
29
|
end
|
@@ -51,6 +53,7 @@ module Vonage
|
|
51
53
|
|
52
54
|
Get = Net::HTTP::Get
|
53
55
|
Put = Net::HTTP::Put
|
56
|
+
Patch = Net::HTTP::Patch
|
54
57
|
Post = Net::HTTP::Post
|
55
58
|
Delete = Net::HTTP::Delete
|
56
59
|
|
@@ -117,6 +120,36 @@ module Vonage
|
|
117
120
|
end
|
118
121
|
end
|
119
122
|
|
123
|
+
def multipart_post_request(path, filepath:, file_name:, mime_type:, response_class: Response, &block)
|
124
|
+
authentication = self.class.authentication.new(@config)
|
125
|
+
|
126
|
+
uri = URI('https://' + @host + path)
|
127
|
+
|
128
|
+
response = File.open(filepath) do |file|
|
129
|
+
request = Net::HTTP::Post::Multipart.new(
|
130
|
+
uri,
|
131
|
+
{file: Multipart::Post::UploadIO.new(file, mime_type, file_name)}
|
132
|
+
)
|
133
|
+
|
134
|
+
request['User-Agent'] = UserAgent.string(@config.app_name, @config.app_version)
|
135
|
+
|
136
|
+
# Set BearerToken if needed
|
137
|
+
authentication.update(request)
|
138
|
+
|
139
|
+
logger.log_request_info(request)
|
140
|
+
|
141
|
+
@http.request(request, &block)
|
142
|
+
end
|
143
|
+
|
144
|
+
logger.log_response_info(response, @host)
|
145
|
+
|
146
|
+
return if block
|
147
|
+
|
148
|
+
logger.debug(response.body) if response.body
|
149
|
+
|
150
|
+
parse(response, response_class)
|
151
|
+
end
|
152
|
+
|
120
153
|
def iterable_request(path, response: nil, response_class: nil, params: {}, &block)
|
121
154
|
json_response = ::JSON.parse(response.body)
|
122
155
|
response = parse(response, response_class)
|
@@ -217,6 +250,19 @@ module Vonage
|
|
217
250
|
def logger
|
218
251
|
@config.logger
|
219
252
|
end
|
253
|
+
|
254
|
+
private
|
255
|
+
|
256
|
+
def set_host
|
257
|
+
case self.class.host
|
258
|
+
when :rest_host
|
259
|
+
@config.rest_host
|
260
|
+
when :vonage_host
|
261
|
+
@config.vonage_host
|
262
|
+
else
|
263
|
+
@config.api_host
|
264
|
+
end
|
265
|
+
end
|
220
266
|
end
|
221
267
|
|
222
268
|
private_constant :Namespace
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Vonage
|
5
|
+
class ProactiveConnect::Events < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
self.authentication = BearerToken
|
9
|
+
|
10
|
+
self.host = :vonage_host
|
11
|
+
|
12
|
+
# Find all events
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# response = proactive_connect.events.list
|
16
|
+
#
|
17
|
+
# @param [optional, String] :page
|
18
|
+
# Page of results to jump to
|
19
|
+
#
|
20
|
+
# @param [optional, String] :page_size
|
21
|
+
# Number of results per page
|
22
|
+
#
|
23
|
+
# @param [optional, String] order
|
24
|
+
# Sort in either ascending (asc, the default) or descending (desc) order
|
25
|
+
#
|
26
|
+
# @param [optional, String] :run_id
|
27
|
+
# Run IDs to filter by, if not specified, returns events for any run id
|
28
|
+
#
|
29
|
+
# @param [optional, String] :type
|
30
|
+
# Event types to filter by
|
31
|
+
#
|
32
|
+
# @param [optional, String] action_id
|
33
|
+
# Action IDs to filter by.
|
34
|
+
#
|
35
|
+
# @param [optional, String] :invocation_id
|
36
|
+
# Invocation IDs to filter by
|
37
|
+
#
|
38
|
+
# @param [optional, String] :recipient_id
|
39
|
+
# Recipient IDs to filter by
|
40
|
+
#
|
41
|
+
# @param [optional, String] :run_item_id
|
42
|
+
# Run item IDs to filter by
|
43
|
+
#
|
44
|
+
# @param [optional, String] src_ctx
|
45
|
+
# The name of the segment / matcher the item / event to filter by (exact string)
|
46
|
+
#
|
47
|
+
# @param [optional, String] :src_type
|
48
|
+
# Source types to filter by
|
49
|
+
#
|
50
|
+
# @param [optional, String] :trace_id
|
51
|
+
# Trace IDs to filter events by
|
52
|
+
#
|
53
|
+
# @param [optional, String] date_start
|
54
|
+
# ISO-8601 formatted date for when to begin events filter
|
55
|
+
#
|
56
|
+
# @param [optional, String] :date_end
|
57
|
+
# ISO-8601 formatted date for when to end events filter
|
58
|
+
#
|
59
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#eventsFindAll
|
60
|
+
#
|
61
|
+
def list(**params)
|
62
|
+
path = "/v0.1/bulk/events"
|
63
|
+
path += "?#{Params.encode(params)}" unless params.empty?
|
64
|
+
|
65
|
+
request(path, response_class: ListResponse)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Vonage
|
5
|
+
class ProactiveConnect::Item < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
self.authentication = BearerToken
|
9
|
+
|
10
|
+
self.host = :vonage_host
|
11
|
+
|
12
|
+
self.request_body = JSON
|
13
|
+
|
14
|
+
# Create a list item
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# response = proactive_connect.item.create(list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865', data: {name: 'Joe Bloggs', email: 'joe@email.com'})
|
18
|
+
#
|
19
|
+
# @param [required, String] :list_id
|
20
|
+
# Unique identifier for the list
|
21
|
+
#
|
22
|
+
# @param [required, Hash] :data
|
23
|
+
# A hash of data containing the item's data attributes and values
|
24
|
+
#
|
25
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#itemsCreate
|
26
|
+
#
|
27
|
+
def create(list_id:, data:)
|
28
|
+
raise ArgumentError.new(":data must be a Hash") unless data.is_a? Hash
|
29
|
+
request(
|
30
|
+
"/v0.1/bulk/lists/#{list_id}/items",
|
31
|
+
params: { data: data },
|
32
|
+
type: Post
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get list item by id
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# response = proactive_connect.item.find(list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865', item_id: 'd97ebf20-e4de-4e50-921a-7bb4dceb373a')
|
40
|
+
#
|
41
|
+
# @param [required, String] :list_id
|
42
|
+
# Unique identifier for the list
|
43
|
+
#
|
44
|
+
# @param [required, String] :item_id
|
45
|
+
# Unique identifier for the item
|
46
|
+
#
|
47
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#itemsGet
|
48
|
+
#
|
49
|
+
def find(list_id:, item_id:)
|
50
|
+
request("/v0.1/bulk/lists/#{list_id}/items/#{item_id}")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Update list item
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# response = proactive_connect.item.create(
|
57
|
+
# list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865',
|
58
|
+
# item_id: 'd97ebf20-e4de-4e50-921a-7bb4dceb373a',
|
59
|
+
# data: {name: 'Jane Bloggs', email: 'joe@email.com'}
|
60
|
+
# )
|
61
|
+
#
|
62
|
+
# @param [required, String] :list_id
|
63
|
+
# Unique identifier for the list
|
64
|
+
#
|
65
|
+
# @param [required, String] :item_id
|
66
|
+
# Unique identifier for the item
|
67
|
+
#
|
68
|
+
# @param [required, Hash] :data
|
69
|
+
# A hash of data containing the item's data attributes and values
|
70
|
+
# All attributes for the item must be passed, even ones for which the value is not changing.
|
71
|
+
# If an attribute is omitted, existing data for that attribute will be deleted.
|
72
|
+
#
|
73
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#itemsUpdate
|
74
|
+
#
|
75
|
+
def update(list_id:, item_id:, data:)
|
76
|
+
raise ArgumentError.new(":data must be a Hash") unless data.is_a? Hash
|
77
|
+
request(
|
78
|
+
"/v0.1/bulk/lists/#{list_id}/items/#{item_id}",
|
79
|
+
params: { data: data },
|
80
|
+
type: Put
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Delete list item
|
85
|
+
#
|
86
|
+
# @example
|
87
|
+
# response = proactive_connect.item.delete(list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865', item_id: 'd97ebf20-e4de-4e50-921a-7bb4dceb373a')
|
88
|
+
#
|
89
|
+
# @param [required, String] :list_id
|
90
|
+
# Unique identifier for the list
|
91
|
+
#
|
92
|
+
# @param [required, String] :item_id
|
93
|
+
# Unique identifier for the item
|
94
|
+
#
|
95
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#itemsDelete
|
96
|
+
#
|
97
|
+
def delete(list_id:, item_id:)
|
98
|
+
request(
|
99
|
+
"/v0.1/bulk/lists/#{list_id}/items/#{item_id}",
|
100
|
+
type: Delete
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
class Vonage::ProactiveConnect::Items::FileResponse < Vonage::Response
|
4
|
+
DEFAULT_FILENAME = 'vonage-proactive-connect-list-items.csv'
|
5
|
+
|
6
|
+
attr_accessor :filename
|
7
|
+
|
8
|
+
def initialize(entity=nil, http_response=nil)
|
9
|
+
super
|
10
|
+
self.filename = initial_filename
|
11
|
+
end
|
12
|
+
|
13
|
+
def save(filepath:)
|
14
|
+
pn = Pathname.new(filepath)
|
15
|
+
raise ArgumentError, ':filepath not a directory' unless pn.directory?
|
16
|
+
raise ArgumentError, ':filepath not absolute' unless pn.absolute?
|
17
|
+
raise ArgumentError, ':filepath not writable' unless pn.writable?
|
18
|
+
|
19
|
+
File.open("#{pn.cleanpath}/#{filename}", 'w') {|f| f.write(http_response.body) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def data
|
23
|
+
http_response ? http_response.body : nil
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def initial_filename
|
29
|
+
match_data = http_response['Content-Disposition'].match(/filename=(\"?)(.+)\1/)
|
30
|
+
match_data ? match_data[2] : DEFAULT_FILENAME
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Vonage
|
5
|
+
class ProactiveConnect::Items < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
self.authentication = BearerToken
|
9
|
+
|
10
|
+
self.host = :vonage_host
|
11
|
+
|
12
|
+
# Find all list items
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# response = proactive_connect.items.list(list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865')
|
16
|
+
#
|
17
|
+
# @param [required, String] :list_id
|
18
|
+
# Unique identifier for the list
|
19
|
+
#
|
20
|
+
# @param [optional, String] :page
|
21
|
+
# Page of results to jump to
|
22
|
+
#
|
23
|
+
# @param [optional, String] :page_size
|
24
|
+
# Number of results per page
|
25
|
+
#
|
26
|
+
# @param [optional, String] order
|
27
|
+
# Sort in either ascending (asc, the default) or descending (desc) order
|
28
|
+
#
|
29
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#itemsFindAll
|
30
|
+
#
|
31
|
+
def list(list_id:, **params)
|
32
|
+
path = "/v0.1/bulk/lists/#{list_id}/items"
|
33
|
+
path += "?#{Params.encode(params)}" unless params.empty?
|
34
|
+
|
35
|
+
request(path, response_class: ListResponse)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Download list items as a CSV file format
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# response = proactive_connect.items.download_csv(list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865')
|
42
|
+
#
|
43
|
+
# @param [required, String] :list_id
|
44
|
+
# ID for the list to download
|
45
|
+
#
|
46
|
+
# @param [optional, String] order
|
47
|
+
# Sort in either ascending (asc, the default) or descending (desc) order
|
48
|
+
#
|
49
|
+
# @param [optional, String] :filename
|
50
|
+
# A name to set for the returned File object. If not set, the File object will use the actual filename (if available)
|
51
|
+
# or a default of `download.csv` if the actual filename is not available.
|
52
|
+
#
|
53
|
+
# @param [optional, String] :filepath
|
54
|
+
# A filepath to a directory where the file should be written.
|
55
|
+
# If not set, the file is not written, though the the file can be written at any time by calling `save` on the returned
|
56
|
+
# object and passing in `:filepath` as an argument to the `save` method, for example:
|
57
|
+
# response = proactive_connect.items.download_csv(list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865')
|
58
|
+
# response.save('/files/downloads/')
|
59
|
+
# If set, the filepath must be:
|
60
|
+
# - An absolute path
|
61
|
+
# - For a valid directory
|
62
|
+
# - The directory must be writable
|
63
|
+
#
|
64
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#itemsDownload
|
65
|
+
#
|
66
|
+
def download_csv(list_id:, order: 'asc', **params)
|
67
|
+
response = request("/v0.1/bulk/lists/#{list_id}/items/download?order=#{order}", response_class: FileResponse)
|
68
|
+
|
69
|
+
response.filename = params[:filename] if params[:filename]
|
70
|
+
response.save(filepath: params[:filepath]) if params[:filepath]
|
71
|
+
|
72
|
+
response
|
73
|
+
end
|
74
|
+
|
75
|
+
# Import list items from a CSV file
|
76
|
+
#
|
77
|
+
# @example
|
78
|
+
# response = proactive_connect.items.upload_csv(list_id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865', filepath: '/files/import.csv')
|
79
|
+
#
|
80
|
+
# @param [required, String] :list_id
|
81
|
+
# ID for the list to download
|
82
|
+
#
|
83
|
+
# @param [optional, String] order
|
84
|
+
# Sort in either ascending (asc, the default) or descending (desc) order
|
85
|
+
#
|
86
|
+
# @param [optional, String] :filename
|
87
|
+
# A name to set for the returned File object. If not set, the File object will use the actual filename (if available)
|
88
|
+
# or a default of `download.csv` if the actual filename is not available.
|
89
|
+
#
|
90
|
+
# @param [required, String] :filepath
|
91
|
+
# A filepath for the file to import. The file must be:
|
92
|
+
# - A valid file
|
93
|
+
# - Readable
|
94
|
+
# - Must have a `.csv` extension
|
95
|
+
#
|
96
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#itemsImport
|
97
|
+
#
|
98
|
+
def upload_csv(list_id:, filepath:)
|
99
|
+
pn = Pathname.new(filepath)
|
100
|
+
raise ArgumentError, ':filepath not for a file' unless pn.file?
|
101
|
+
raise ArgumentError, 'file at :filepath not readable' unless pn.readable?
|
102
|
+
raise ArgumentError, 'file at :filepath not csv' unless pn.extname == '.csv'
|
103
|
+
|
104
|
+
multipart_post_request("/v0.1/bulk/lists/#{list_id}/items/import", filepath: filepath, file_name: pn.basename, mime_type: 'text/csv')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Vonage
|
5
|
+
class ProactiveConnect::List < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
self.authentication = BearerToken
|
9
|
+
|
10
|
+
self.host = :vonage_host
|
11
|
+
|
12
|
+
self.request_body = JSON
|
13
|
+
|
14
|
+
# Create list
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# response = proactive_connect.list.create(name: 'List Number 1')
|
18
|
+
#
|
19
|
+
# @param [required, String] :name
|
20
|
+
# A name for the list
|
21
|
+
#
|
22
|
+
# @param [optional, String] :description
|
23
|
+
# A description of the list
|
24
|
+
#
|
25
|
+
# @param [optional, Array] :tags
|
26
|
+
# An Array of up to 10 Strings assigining tags to the list. Each String must be between 1 and 15 characters
|
27
|
+
#
|
28
|
+
# @param [optional, Array] :attributes
|
29
|
+
# Array of Hash objects. Each Hash represents an attribute for the list.
|
30
|
+
#
|
31
|
+
# @option attributes [required, String] :name
|
32
|
+
# The name of the attribute
|
33
|
+
#
|
34
|
+
# @option attributes [optional, String] :alias
|
35
|
+
# Alternative name to use for this attribute.
|
36
|
+
# Use when you wish to correlate between 2 or more list that are using different attribute names for the same semantic data
|
37
|
+
#
|
38
|
+
# @option attributes [optional, Boolean] :key
|
39
|
+
# Set to `true` if this attribute should be used to correlate between 2 or more lists. Default is `false`
|
40
|
+
#
|
41
|
+
# @param [optional, Hash] :datasource
|
42
|
+
# Datasource for the list
|
43
|
+
#
|
44
|
+
# @option datasource [required, String] :type
|
45
|
+
# Must be set to `manual`, which is the default
|
46
|
+
#
|
47
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#listsCreate
|
48
|
+
#
|
49
|
+
def create(name:, **params)
|
50
|
+
request(
|
51
|
+
"/v0.1/bulk/lists",
|
52
|
+
params: params.merge({ name: name }),
|
53
|
+
type: Post
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Get list by id
|
58
|
+
#
|
59
|
+
# @example
|
60
|
+
# response = proactive_connect.list.find(id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865')
|
61
|
+
#
|
62
|
+
# @param [required, String] :id
|
63
|
+
# Unique identifier for the list
|
64
|
+
#
|
65
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#listsGet
|
66
|
+
#
|
67
|
+
def find(id:)
|
68
|
+
request("/v0.1/bulk/lists/#{id}")
|
69
|
+
end
|
70
|
+
|
71
|
+
# Update list
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# response = proactive_connect.list.update(name: 'List Number 1')
|
75
|
+
#
|
76
|
+
# @param [required, String] :id
|
77
|
+
# The id of the list to update
|
78
|
+
#
|
79
|
+
# @param [required, String] :name
|
80
|
+
# The name of the list
|
81
|
+
#
|
82
|
+
# @param [optional, String] :description
|
83
|
+
# A description of the list
|
84
|
+
#
|
85
|
+
# @param [optional, Array] :tags
|
86
|
+
# An Array of up to 10 Strings assigining tags to the list. Each String must be between 1 and 15 characters
|
87
|
+
#
|
88
|
+
# @param [optional, Array] :attributes
|
89
|
+
# Array of Hash objects. Each Hash represents an attribute for the list.
|
90
|
+
#
|
91
|
+
# @option attributes [required, String] :name
|
92
|
+
# The name of the attribute
|
93
|
+
#
|
94
|
+
# @option attributes [optional, String] :alias
|
95
|
+
# Alternative name to use for this attribute.
|
96
|
+
# Use when you wish to correlate between 2 or more list that are using different attribute names for the same semantic data
|
97
|
+
#
|
98
|
+
# @option attributes [optional, Boolean] :key
|
99
|
+
# Set to `true` if this attribute should be used to correlate between 2 or more lists. Default is `false`
|
100
|
+
#
|
101
|
+
# @param [optional, Hash] :datasource
|
102
|
+
# Datasource for the list
|
103
|
+
#
|
104
|
+
# @option datasource [required, String] :type
|
105
|
+
# Must be set to `manual`, which is the default
|
106
|
+
#
|
107
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#listsUpdate
|
108
|
+
#
|
109
|
+
def update(id:, name:, **params)
|
110
|
+
request(
|
111
|
+
"/v0.1/bulk/lists/#{id}",
|
112
|
+
params: params.merge({ name: name }),
|
113
|
+
type: Put
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Delete a list by id
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# response = proactive_connect.list.delete(id: '74ea1ecf-06c9-4072-a285-61677bd353e8')
|
121
|
+
#
|
122
|
+
# @param [required, String] :id
|
123
|
+
# Unique identifier for the list
|
124
|
+
#
|
125
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#listsDelete
|
126
|
+
#
|
127
|
+
def delete(id:)
|
128
|
+
request(
|
129
|
+
"/v0.1/bulk/lists/#{id}",
|
130
|
+
type: Delete
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Clear list by deleting all items
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
# response = proactive_connect.list.clear_items(id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865')
|
138
|
+
#
|
139
|
+
# @param [required, String] :id
|
140
|
+
# Unique identifier for the list
|
141
|
+
#
|
142
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#listsClear
|
143
|
+
#
|
144
|
+
def clear_items(id:)
|
145
|
+
request(
|
146
|
+
"/v0.1/bulk/lists/#{id}/clear",
|
147
|
+
type: Post
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Fetch and replace all items from datasource
|
152
|
+
#
|
153
|
+
# @example
|
154
|
+
# response = proactive_connect.list.fetch_and_replace_items(id: 'e546eebe-8e23-4e4d-bb7c-29d4700c9865')
|
155
|
+
#
|
156
|
+
# @param [required, String] :id
|
157
|
+
# Unique identifier for the list
|
158
|
+
#
|
159
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#listsFetch
|
160
|
+
#
|
161
|
+
def fetch_and_replace_items(id:)
|
162
|
+
request(
|
163
|
+
"/v0.1/bulk/lists/#{id}/fetch",
|
164
|
+
type: Post
|
165
|
+
)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Vonage
|
5
|
+
class ProactiveConnect::Lists < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
self.authentication = BearerToken
|
9
|
+
|
10
|
+
self.host = :vonage_host
|
11
|
+
|
12
|
+
# Find all lists
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# response = proactive_connect.lists.list
|
16
|
+
#
|
17
|
+
# @param [optional, String] :page
|
18
|
+
# Page of results to jump to
|
19
|
+
#
|
20
|
+
# @param [optional, String] :page_size
|
21
|
+
# Number of results per page
|
22
|
+
#
|
23
|
+
# @param [optional, String] order
|
24
|
+
# Sort in either ascending (asc, the default) or descending (desc) order
|
25
|
+
#
|
26
|
+
# @see https://developer.vonage.com/en/api/proactive-connect#listsFindAll
|
27
|
+
#
|
28
|
+
def list(**params)
|
29
|
+
path = "/v0.1/bulk/lists"
|
30
|
+
path += "?#{Params.encode(params)}" unless params.empty?
|
31
|
+
|
32
|
+
request(path, response_class: ListResponse)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Vonage
|
5
|
+
class ProactiveConnect < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
sig { returns(T.nilable(Vonage::ProactiveConnect::Lists)) }
|
9
|
+
def lists
|
10
|
+
@lists ||= Lists.new(@config)
|
11
|
+
end
|
12
|
+
|
13
|
+
sig { returns(T.nilable(Vonage::ProactiveConnect::List)) }
|
14
|
+
def list
|
15
|
+
@list ||= List.new(@config)
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { returns(T.nilable(Vonage::ProactiveConnect::Items)) }
|
19
|
+
def items
|
20
|
+
@items ||= Items.new(@config)
|
21
|
+
end
|
22
|
+
|
23
|
+
sig { returns(T.nilable(Vonage::ProactiveConnect::Item)) }
|
24
|
+
def item
|
25
|
+
@item ||= Item.new(@config)
|
26
|
+
end
|
27
|
+
|
28
|
+
sig { returns(T.nilable(Vonage::ProactiveConnect::Events)) }
|
29
|
+
def events
|
30
|
+
@events ||= Events.new(@config)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
class Vonage::Subaccounts::ListResponse < Vonage::Response
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def primary_account
|
7
|
+
@entity._embedded.primary_account
|
8
|
+
end
|
9
|
+
|
10
|
+
def each
|
11
|
+
return enum_for(:each) unless block_given?
|
12
|
+
|
13
|
+
@entity._embedded.subaccounts.each { |item| yield item }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Vonage
|
5
|
+
class Subaccounts < Namespace
|
6
|
+
self.authentication = Basic
|
7
|
+
|
8
|
+
self.request_body = JSON
|
9
|
+
|
10
|
+
# Retrieve list of subaccounts.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# response = client.subaccounts.list
|
14
|
+
#
|
15
|
+
# @see https://developer.vonage.com/en/api/subaccounts#retrieveSubaccountsList
|
16
|
+
#
|
17
|
+
def list
|
18
|
+
request("/accounts/#{@config.api_key}/subaccounts", response_class: ListResponse)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Retrieve a subaccount.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# response = client.subaccounts.find(subaccount_key: 'abc123')
|
25
|
+
#
|
26
|
+
# @option params [required, String] :subaccount_key
|
27
|
+
# The API key for the subaccount you want to retrieve
|
28
|
+
#
|
29
|
+
# @see https://developer.vonage.com/en/api/subaccounts#retrieveSubaccount
|
30
|
+
#
|
31
|
+
def find(subaccount_key:)
|
32
|
+
request("/accounts/#{@config.api_key}/subaccounts/#{subaccount_key}")
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create a subaccount.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# response = client.subaccounts.create(name: 'Foo')
|
39
|
+
#
|
40
|
+
# @option params [required, String] :name
|
41
|
+
# The name of the subaccount
|
42
|
+
#
|
43
|
+
# @option params [optional, String] :secret
|
44
|
+
# An account secret for use by the subaccount. Can be used in combination with your API key to authenticate your API requests.
|
45
|
+
# Requirements:
|
46
|
+
# - 8 characters and no more than 25
|
47
|
+
# - 1 lower-case letter
|
48
|
+
# - 1 capital letter
|
49
|
+
# - 1 digit
|
50
|
+
# - must be unique
|
51
|
+
#
|
52
|
+
# @option params [optional, Boolean] :use_primary_account_balance
|
53
|
+
# Whether the subaccount uses the primary account balance (true, the default) or has its own balance (false).
|
54
|
+
# Once set to `false` cannot be changed back to `true`
|
55
|
+
#
|
56
|
+
# @see https://developer.vonage.com/en/api/subaccounts#createSubAccount
|
57
|
+
#
|
58
|
+
def create(name:, **params)
|
59
|
+
request("/accounts/#{@config.api_key}/subaccounts", params: params.merge(name: name), type: Post)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Modify a subaccount.
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# response = client.subaccounts.update(name: 'Bar')
|
66
|
+
#
|
67
|
+
# @option params [required, String] :subaccount_key
|
68
|
+
# The API key for the subaccount you want to modify
|
69
|
+
#
|
70
|
+
# @option params [optional, String] :name
|
71
|
+
# The name of the subaccount
|
72
|
+
#
|
73
|
+
# @option params [optional, Boolean] :use_primary_account_balance
|
74
|
+
# Whether the subaccount uses the primary account balance (true, the default) or has its own balance (false).
|
75
|
+
# Once set to `false` cannot be changed back to `true`
|
76
|
+
#
|
77
|
+
# @option params [optional, String] :suspended
|
78
|
+
# Whether the subaccount is suspended (true) or not (false, the default)
|
79
|
+
#
|
80
|
+
# @see https://developer.vonage.com/en/api/subaccounts#modifySubaccount
|
81
|
+
#
|
82
|
+
def update(subaccount_key:, **params)
|
83
|
+
request("/accounts/#{@config.api_key}/subaccounts/#{subaccount_key}", params: params, type: Patch)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Retrieve list of credit transfers.
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# response = client.subaccounts.list_credit_transfers(start_date: "2023-06-15T15:53:50Z")
|
90
|
+
#
|
91
|
+
# @option params [optional, String] :start_date
|
92
|
+
# The ISO format datetime from which to list transfers. Example: 2019-03-02T16:34:49Z.
|
93
|
+
# Defaults to "1970-01-01T00:00:00Z" if omitted
|
94
|
+
#
|
95
|
+
# @option params [optional, String] :end_date
|
96
|
+
# The ISO format datetime to which to list transfers. Example: 2019-03-02T16:34:49Z.
|
97
|
+
# If absent then all transfers until now is returned.
|
98
|
+
#
|
99
|
+
# @option params [optional, String] :subaccount
|
100
|
+
# Subaccount to filter by.
|
101
|
+
#
|
102
|
+
# @see https://developer.vonage.com/en/api/subaccounts#retrieveCreditTransfers
|
103
|
+
#
|
104
|
+
def list_credit_transfers(start_date: "1970-01-01T00:00:00Z", **params)
|
105
|
+
path = "/accounts/#{@config.api_key}/credit-transfers?#{Params.encode(params.merge(start_date: start_date))}"
|
106
|
+
|
107
|
+
request(path, response_class: CreditTransfers::ListResponse)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Transfer credit.
|
111
|
+
#
|
112
|
+
# @example
|
113
|
+
# response = client.subaccounts.transfer_credit(from: 'abc123', to: 'def456', amount: 10.00)
|
114
|
+
#
|
115
|
+
# @option params [required, String] :from
|
116
|
+
# The API key of the account or subaccount to transfer credit from.
|
117
|
+
#
|
118
|
+
# @option params [required, String] :to
|
119
|
+
# The API key of the account or subaccount to transfer credit to.
|
120
|
+
#
|
121
|
+
# @option params [required, Number] :amount
|
122
|
+
# The amount to transfer
|
123
|
+
#
|
124
|
+
# @option params [optional, String] :reference
|
125
|
+
# A reference for the transfer.
|
126
|
+
#
|
127
|
+
# @see https://developer.vonage.com/en/api/subaccounts#transferCredit
|
128
|
+
#
|
129
|
+
def transfer_credit(from:, to:, amount:, **params)
|
130
|
+
request("/accounts/#{@config.api_key}/credit-transfers", params: params.merge(from: from, to: to, amount: amount), type: Post)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Retrieve list of balance transfers.
|
134
|
+
#
|
135
|
+
# @example
|
136
|
+
# response = client.subaccounts.list_balance_transfers(start_date: "2023-06-15T15:53:50Z")
|
137
|
+
#
|
138
|
+
# @option params [optional, String] :start_date
|
139
|
+
# The ISO format datetime from which to list transfers. Example: 2019-03-02T16:34:49Z.
|
140
|
+
# Defaults to "1970-01-01T00:00:00Z" if omitted
|
141
|
+
#
|
142
|
+
# @option params [optional, String] :end_date
|
143
|
+
# The ISO format datetime to which to list transfers. Example: 2019-03-02T16:34:49Z.
|
144
|
+
# If absent then all transfers until now is returned.
|
145
|
+
#
|
146
|
+
# @option params [optional, String] :subaccount
|
147
|
+
# Subaccount to filter by.
|
148
|
+
#
|
149
|
+
# @see https://developer.vonage.com/en/api/subaccounts#retrieveBalanceTransfers
|
150
|
+
#
|
151
|
+
def list_balance_transfers(start_date: "1970-01-01T00:00:00Z", **params)
|
152
|
+
path = "/accounts/#{@config.api_key}/balance-transfers?#{Params.encode(params.merge(start_date: start_date))}"
|
153
|
+
|
154
|
+
request(path, response_class: BalanceTransfers::ListResponse)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Transfer balance.
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# response = client.subaccounts.transfer_balance(from: 'abc123', to: 'def456', amount: 10.00)
|
161
|
+
#
|
162
|
+
# @option params [required, String] :from
|
163
|
+
# The API key of the account or subaccount to transfer balance from.
|
164
|
+
#
|
165
|
+
# @option params [required, String] :to
|
166
|
+
# The API key of the account or subaccount to transfer balance to.
|
167
|
+
#
|
168
|
+
# @option params [required, Number] :amount
|
169
|
+
# The amount to transfer
|
170
|
+
#
|
171
|
+
# @option params [optional, String] :reference
|
172
|
+
# A reference for the transfer.
|
173
|
+
#
|
174
|
+
# @see https://developer.vonage.com/en/api/subaccounts#transferBalance
|
175
|
+
#
|
176
|
+
def transfer_balance(from:, to:, amount:, **params)
|
177
|
+
request("/accounts/#{@config.api_key}/balance-transfers", params: params.merge(from: from, to: to, amount: amount), type: Post)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Transfer number.
|
181
|
+
#
|
182
|
+
# @example
|
183
|
+
# response = client.subaccounts.transfer_number(from: 'abc123', to: 'def456', number: 447900000000, country: 'GB')
|
184
|
+
#
|
185
|
+
# @option params [required, String] :from
|
186
|
+
# The API key of the account or subaccount to transfer the number from.
|
187
|
+
#
|
188
|
+
# @option params [required, String] :to
|
189
|
+
# The API key of the account or subaccount to transfer the number to.
|
190
|
+
#
|
191
|
+
# @option params [required, Number] :number
|
192
|
+
# The number to transfer
|
193
|
+
#
|
194
|
+
# @option params [required, String] :country
|
195
|
+
# An ISO-3166-1 alpha 2 code representing the country for the number, e.g. GB.
|
196
|
+
#
|
197
|
+
# @see https://developer.vonage.com/en/api/subaccounts#transferNumber
|
198
|
+
#
|
199
|
+
def transfer_number(from:, to:, number:, country:)
|
200
|
+
request("/accounts/#{@config.api_key}/transfer-number", params: {from: from, to: to, number: number, country: country}, type: Post)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
data/lib/vonage/version.rb
CHANGED
data/vonage.gemspec
CHANGED
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.add_dependency('vonage-jwt', '~> 0.1.0')
|
16
16
|
s.add_dependency('zeitwerk', '~> 2', '>= 2.2')
|
17
17
|
s.add_dependency('sorbet-runtime', '~> 0.5')
|
18
|
+
s.add_dependency('multipart-post', '~> 2.0')
|
18
19
|
s.add_runtime_dependency('rexml')
|
19
20
|
s.add_runtime_dependency('phonelib')
|
20
21
|
s.require_path = 'lib'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vonage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vonage
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-06-
|
11
|
+
date: 2023-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: vonage-jwt
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0.5'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: multipart-post
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.0'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.0'
|
61
75
|
- !ruby/object:Gem::Dependency
|
62
76
|
name: rexml
|
63
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -141,6 +155,16 @@ files:
|
|
141
155
|
- lib/vonage/params.rb
|
142
156
|
- lib/vonage/pricing.rb
|
143
157
|
- lib/vonage/pricing_types.rb
|
158
|
+
- lib/vonage/proactive_connect.rb
|
159
|
+
- lib/vonage/proactive_connect/events.rb
|
160
|
+
- lib/vonage/proactive_connect/events/list_response.rb
|
161
|
+
- lib/vonage/proactive_connect/item.rb
|
162
|
+
- lib/vonage/proactive_connect/items.rb
|
163
|
+
- lib/vonage/proactive_connect/items/file_response.rb
|
164
|
+
- lib/vonage/proactive_connect/items/list_response.rb
|
165
|
+
- lib/vonage/proactive_connect/list.rb
|
166
|
+
- lib/vonage/proactive_connect/lists.rb
|
167
|
+
- lib/vonage/proactive_connect/lists/list_response.rb
|
144
168
|
- lib/vonage/redact.rb
|
145
169
|
- lib/vonage/response.rb
|
146
170
|
- lib/vonage/secrets.rb
|
@@ -149,6 +173,10 @@ files:
|
|
149
173
|
- lib/vonage/service_error.rb
|
150
174
|
- lib/vonage/signature.rb
|
151
175
|
- lib/vonage/sms.rb
|
176
|
+
- lib/vonage/subaccounts.rb
|
177
|
+
- lib/vonage/subaccounts/balance_transfers/list_response.rb
|
178
|
+
- lib/vonage/subaccounts/credit_transfers/list_response.rb
|
179
|
+
- lib/vonage/subaccounts/list_response.rb
|
152
180
|
- lib/vonage/tfa.rb
|
153
181
|
- lib/vonage/user_agent.rb
|
154
182
|
- lib/vonage/verify.rb
|