vonage 7.12.0 → 7.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Meetings < Namespace
6
+ extend T::Sig
7
+
8
+ sig { returns(T.nilable(Vonage::Meetings::Rooms)) }
9
+ def rooms
10
+ @rooms ||= Rooms.new(@config)
11
+ end
12
+
13
+ sig { returns(T.nilable(Vonage::Meetings::Recordings)) }
14
+ def recordings
15
+ @recordings ||= Recordings.new(@config)
16
+ end
17
+
18
+ sig { returns(T.nilable(Vonage::Meetings::Sessions)) }
19
+ def sessions
20
+ @sessions ||= Sessions.new(@config)
21
+ end
22
+
23
+ sig { returns(T.nilable(Vonage::Meetings::Themes)) }
24
+ def themes
25
+ @themes ||= Themes.new(@config)
26
+ end
27
+
28
+ sig { returns(T.nilable(Vonage::Meetings::Applications)) }
29
+ def applications
30
+ @applications ||= Applications.new(@config)
31
+ end
32
+
33
+ sig { returns(T.nilable(Vonage::Meetings::DialInNumbers)) }
34
+ def dial_in_numbers
35
+ @dial_in_numbers ||= DialInNumbers.new(@config)
36
+ end
37
+ end
38
+ end
@@ -1,6 +1,8 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
+
3
4
  require 'net/http'
5
+ require 'net/http/post/multipart'
4
6
  require 'json'
5
7
 
6
8
  module Vonage
@@ -8,7 +10,7 @@ module Vonage
8
10
  def initialize(config)
9
11
  @config = config
10
12
 
11
- @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 == :rest_host
26
+ raise ArgumentError unless %i[rest_host vonage_host].include?(host)
25
27
 
26
28
  @host = host
27
29
  end
@@ -47,6 +49,7 @@ module Vonage
47
49
  end
48
50
 
49
51
  protected
52
+
50
53
  # :nocov:
51
54
 
52
55
  Get = Net::HTTP::Get
@@ -59,7 +62,7 @@ module Vonage
59
62
  authentication = self.class.authentication.new(@config)
60
63
  authentication.update(params)
61
64
 
62
- uri = URI('https://' + @host + path)
65
+ uri = URI("https://" + @host + path)
63
66
  unless type.const_get(:REQUEST_HAS_BODY) || params.empty?
64
67
  uri.query = Params.encode(params)
65
68
  end
@@ -71,17 +74,20 @@ module Vonage
71
74
  request = type.new(uri)
72
75
 
73
76
  # set headers
74
- request['User-Agent'] = UserAgent.string(@config.app_name, @config.app_version)
75
- request['Accept'] = 'application/json'
76
- self.class.request_headers.each do |key, value|
77
- request[key] = value
78
- end
77
+ request["User-Agent"] = UserAgent.string(
78
+ @config.app_name,
79
+ @config.app_version
80
+ )
81
+ request["Accept"] = "application/json"
82
+ self.class.request_headers.each { |key, value| request[key] = value }
79
83
 
80
84
  # Set BearerToken if needed
81
85
  authentication.update(request)
82
86
 
83
87
  # set body
84
- self.class.request_body.update(request, params) if type.const_get(:REQUEST_HAS_BODY)
88
+ if type.const_get(:REQUEST_HAS_BODY)
89
+ self.class.request_body.update(request, params)
90
+ end
85
91
 
86
92
  request
87
93
  end
@@ -101,16 +107,31 @@ module Vonage
101
107
  end
102
108
 
103
109
  def request(path, params: nil, type: Get, response_class: Response, &block)
104
- auto_advance = !params.nil? && params.key?(:auto_advance) ? params[:auto_advance] : false
105
-
106
- params = params.tap { |params| params.delete(:auto_advance) } if !params.nil? && params.key?(:auto_advance)
110
+ auto_advance =
111
+ (
112
+ if !params.nil? && params.key?(:auto_advance)
113
+ params[:auto_advance]
114
+ else
115
+ false
116
+ end
117
+ )
118
+
119
+ params =
120
+ params.tap { |params| params.delete(:auto_advance) } if !params.nil? &&
121
+ params.key?(:auto_advance)
107
122
 
108
123
  request = build_request(path: path, params: params || {}, type: type)
109
124
 
110
125
  response = make_request!(request, &block)
111
126
 
112
127
  if auto_advance
113
- iterable_request(path, response: response, response_class: response_class, params: params, &block)
128
+ iterable_request(
129
+ path,
130
+ response: response,
131
+ response_class: response_class,
132
+ params: params,
133
+ &block
134
+ )
114
135
  else
115
136
  return if block
116
137
 
@@ -118,22 +139,59 @@ module Vonage
118
139
  end
119
140
  end
120
141
 
142
+ def multipart_post_request(path, filepath:, file_name:, mime_type:, params: {}, override_uri: nil, no_auth: false, response_class: Response, &block)
143
+ authentication = self.class.authentication.new(@config) unless no_auth
144
+
145
+ uri = override_uri ? URI(override_uri) : URI('https://' + @host + path)
146
+
147
+ http = override_uri ? Net::HTTP.new(uri.host, Net::HTTP.https_default_port, p_addr = nil) : @http
148
+ http.use_ssl = true
149
+ http.set_debug_output($stdout)
150
+
151
+ response = File.open(filepath) do |file|
152
+ request = Net::HTTP::Post::Multipart.new(
153
+ uri,
154
+ params.merge(file: Multipart::Post::UploadIO.new(file, mime_type, file_name))
155
+ )
156
+
157
+ request['User-Agent'] = UserAgent.string(@config.app_name, @config.app_version)
158
+
159
+ # Set BearerToken if needed
160
+ authentication.update(request) unless no_auth
161
+
162
+ logger.log_request_info(request)
163
+
164
+ http.request(request, &block)
165
+ end
166
+
167
+ logger.log_response_info(response, @host)
168
+
169
+ return if block
170
+
171
+ logger.debug(response.body) if response.body
172
+
173
+ parse(response, response_class)
174
+ end
175
+
121
176
  def iterable_request(path, response: nil, response_class: nil, params: {}, &block)
122
177
  json_response = ::JSON.parse(response.body)
123
178
  response = parse(response, response_class)
124
179
  remainder = remaining_count(json_response)
125
180
 
126
181
  while remainder > 0
127
- params = { page_size: json_response['page_size'] }
128
-
129
- if json_response['record_index'] && json_response['record_index'] == 0
130
- params[:record_index] = json_response['page_size']
131
- elsif json_response['record_index'] && json_response['record_index'] != 0
132
- params[:record_index] = (json_response['record_index'] + json_response['page_size'])
182
+ params = { page_size: json_response["page_size"] }
183
+
184
+ if json_response["record_index"] && json_response["record_index"] == 0
185
+ params[:record_index] = json_response["page_size"]
186
+ elsif json_response["record_index"] &&
187
+ json_response["record_index"] != 0
188
+ params[:record_index] = (
189
+ json_response["record_index"] + json_response["page_size"]
190
+ )
133
191
  end
134
192
 
135
- if json_response['total_pages']
136
- params[:page] = json_response['page'] + 1
193
+ if json_response["total_pages"]
194
+ params[:page] = json_response["page"] + 1
137
195
  end
138
196
 
139
197
  request = build_request(path: path, type: Get, params: params)
@@ -144,11 +202,15 @@ module Vonage
144
202
  json_response = ::JSON.parse(paginated_response.body)
145
203
  remainder = remaining_count(json_response)
146
204
 
147
- if response.respond_to?('_embedded')
148
- collection_name = collection_name(response['_embedded'])
149
- response['_embedded'][collection_name].push(*next_response['_embedded'][collection_name])
205
+ if response.respond_to?("_embedded")
206
+ collection_name = collection_name(response["_embedded"])
207
+ response["_embedded"][collection_name].push(
208
+ *next_response["_embedded"][collection_name]
209
+ )
150
210
  else
151
- response[collection_name(response)].push(*next_response[collection_name(next_response)])
211
+ response[collection_name(response)].push(
212
+ *next_response[collection_name(next_response)]
213
+ )
152
214
  end
153
215
  end
154
216
 
@@ -156,43 +218,51 @@ module Vonage
156
218
  end
157
219
 
158
220
  def remaining_count(params)
159
- if params.key?('total_pages')
160
- params['total_pages'] - params['page']
161
- elsif params.key?('count')
162
- params['count'] - (params['record_index'] == 0 ? params['page_size'] : (params['record_index'] + params['page_size']))
221
+ if params.key?("total_pages")
222
+ params["total_pages"] - params["page"]
223
+ elsif params.key?("count")
224
+ params["count"] -
225
+ (
226
+ if params["record_index"] == 0
227
+ params["page_size"]
228
+ else
229
+ (params["record_index"] + params["page_size"])
230
+ end
231
+ )
163
232
  else
164
233
  0
165
234
  end
166
235
  end
167
236
 
168
237
  def collection_name(params)
169
- @collection_name ||= case
170
- when params.respond_to?('calls')
171
- 'calls'
172
- when params.respond_to?('users')
173
- 'users'
174
- when params.respond_to?('legs')
175
- 'legs'
176
- when params.respond_to?('data')
177
- 'data'
178
- when params.respond_to?('conversations')
179
- 'conversations'
180
- when params.respond_to?('applications')
181
- 'applications'
182
- when params.respond_to?('records')
183
- 'records'
184
- when params.respond_to?('reports')
185
- 'reports'
186
- when params.respond_to?('networks')
187
- 'networks'
188
- when params.respond_to?('countries')
189
- 'countries'
190
- when params.respond_to?('media')
191
- 'media'
192
- when params.respond_to?('numbers')
193
- 'numbers'
194
- when params.respond_to?('events')
195
- 'events'
238
+ @collection_name ||=
239
+ case
240
+ when params.respond_to?("calls")
241
+ "calls"
242
+ when params.respond_to?("users")
243
+ "users"
244
+ when params.respond_to?("legs")
245
+ "legs"
246
+ when params.respond_to?("data")
247
+ "data"
248
+ when params.respond_to?("conversations")
249
+ "conversations"
250
+ when params.respond_to?("applications")
251
+ "applications"
252
+ when params.respond_to?("records")
253
+ "records"
254
+ when params.respond_to?("reports")
255
+ "reports"
256
+ when params.respond_to?("networks")
257
+ "networks"
258
+ when params.respond_to?("countries")
259
+ "countries"
260
+ when params.respond_to?("media")
261
+ "media"
262
+ when params.respond_to?("numbers")
263
+ "numbers"
264
+ when params.respond_to?("events")
265
+ "events"
196
266
  else
197
267
  params.entity.attributes.keys[0].to_s
198
268
  end
@@ -218,6 +288,19 @@ module Vonage
218
288
  def logger
219
289
  @config.logger
220
290
  end
291
+
292
+ private
293
+
294
+ def set_host
295
+ case self.class.host
296
+ when :rest_host
297
+ @config.rest_host
298
+ when :vonage_host
299
+ @config.vonage_host
300
+ else
301
+ @config.api_host
302
+ end
303
+ end
221
304
  end
222
305
 
223
306
  private_constant :Namespace
@@ -0,0 +1,11 @@
1
+ # typed: true
2
+
3
+ class Vonage::ProactiveConnect::Events::ListResponse < Vonage::Response
4
+ include Enumerable
5
+
6
+ def each
7
+ return enum_for(:each) unless block_given?
8
+
9
+ @entity._embedded.events.each { |item| yield item }
10
+ end
11
+ end
@@ -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,11 @@
1
+ # typed: true
2
+
3
+ class Vonage::ProactiveConnect::Items::ListResponse < Vonage::Response
4
+ include Enumerable
5
+
6
+ def each
7
+ return enum_for(:each) unless block_given?
8
+
9
+ @entity._embedded.items.each { |item| yield item }
10
+ end
11
+ 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