plivo 4.62.5 → 4.63.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ab232d10176adbaaf1375e8d53cf04fc9cbca55c
4
- data.tar.gz: b092be2a259e7dd451db35a742951c7291b47094
2
+ SHA256:
3
+ metadata.gz: 3b904e37c728e7361a0e4ad43f9302fc39f09dea88d3ce0c7c7c763b29282f5f
4
+ data.tar.gz: 3df71c5a41b9d3396398046c926cb324013aa8a7046976b6c44b6f4c9bfd1431
5
5
  SHA512:
6
- metadata.gz: d7c2b0e1b7fd3b27ec9634187f5fdafb5b7ede1b11531901b9ba23de9024c0da81c668bddc3897d6c7202ea2065814d809077b83f541e69887e783f66d145022
7
- data.tar.gz: 3c6b3aea56c356103037991df5815d9d12424929ba93a9ef1639c7328ec6d7852961c85c3402260a60b10505a2a6f8d3ea38244a2706c47f54efe9997222fc6d
6
+ metadata.gz: 8878f8bf2f322bbb1640ca403c917864970c9a014675a84a2492f652a855697ab98da486c7b85e70886f075b1a604e143decf8f67e04eb356db42a85ed9b1054
7
+ data.tar.gz: 42f4fe995b8c9d4a054cca33330bdc214e4ba4e2c5b2e91cf4a40e990c8cd50aeb46c3a9ad07201b8125f637d8306e44cab570a05682c5bf58f62294c89f25d2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## [4.63.1](https://github.com/plivo/plivo-ruby/tree/v4.63.1) (2026-04-16)
4
+ **Bug Fix - PhoneNumber Compliance API response mapping**
5
+ - Fixed GET single compliance to unwrap `compliance` wrapper key from API response, making all fields directly accessible on the resource object
6
+ - Fixed List response to remap `compliances` key to `objects` for base class compatibility, returning proper `PhoneNumberCompliance` resource instances
7
+ - Fixed update() to unwrap `compliance` wrapper key from API response, returning the compliance object directly
8
+
9
+ ## [4.63.0](https://github.com/plivo/plivo-ruby/tree/v4.63.0) (2026-04-08)
10
+ **Feature - PhoneNumber Compliance API support**
11
+ - Added `phone_number_compliance_requirements` resource for discovering compliance requirements by country, number type, and user type
12
+ - Added `phone_number_compliances` resource with full CRUD support (create, get, list, update, delete) for compliance applications
13
+ - Added `phone_number_compliance_link` resource for bulk linking phone numbers to accepted compliance applications
14
+ - Added PATCH HTTP method support to `base_client` for compliance application updates
15
+ - Create and update operations support multipart file uploads for compliance documents
16
+
3
17
  ## [4.62.5](https://github.com/plivo/plivo-ruby/tree/v4.62.5) (2026-01-21)
4
18
  **Feature - HA Number support**
5
19
  - Added `ha_enable` optional parameter to PhoneNumber `buy` method
@@ -47,6 +47,7 @@ module Plivo
47
47
  response = case method
48
48
  when 'GET' then send_get(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
49
49
  when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
50
+ when 'PATCH' then send_patch(resource_path, data, timeout, use_multipart_conn, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
50
51
  when 'DELETE' then send_delete(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
51
52
  else raise_invalid_request("#{method} not supported by Plivo, yet")
52
53
  end
@@ -64,6 +65,7 @@ module Plivo
64
65
  elsif options[:is_lookup_request] == true
65
66
  response = case method
66
67
  when 'GET' then send_get(resource_path, data, timeout, is_lookup_request: options[:is_lookup_request])
68
+ when 'PATCH' then send_patch(resource_path, data, timeout, use_multipart_conn, is_lookup_request: options[:is_lookup_request])
67
69
  else raise_invalid_request("#{method} not supported by Plivo, yet")
68
70
  end
69
71
  process_response(method, response.to_hash)
@@ -71,6 +73,7 @@ module Plivo
71
73
  response = case method
72
74
  when 'GET' then send_get(resource_path, data, timeout)
73
75
  when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn)
76
+ when 'PATCH' then send_patch(resource_path, data, timeout, use_multipart_conn)
74
77
  when 'DELETE' then send_delete(resource_path, data, timeout)
75
78
  else raise_invalid_request("#{method} not supported by Plivo, yet")
76
79
  end
@@ -311,6 +314,41 @@ module Plivo
311
314
  response
312
315
  end
313
316
 
317
+ def send_patch(resource_path, data, timeout, use_multipart_conn, options = nil)
318
+ if use_multipart_conn
319
+ multipart_conn = Faraday.new(@base_uri) do |faraday|
320
+ faraday.headers = {
321
+ 'User-Agent' => @headers['User-Agent'],
322
+ 'Accept' => @headers['Accept']
323
+ }
324
+
325
+ # DANGER: Basic auth should always come after headers, else
326
+ # The headers will replace the basic_auth
327
+
328
+ faraday.request :multipart
329
+ faraday.request :url_encoded
330
+ faraday.headers['Authorization'] = "Basic #{Base64.strict_encode64("#{auth_id}:#{auth_token}")}"
331
+
332
+ faraday.proxy=@proxy_hash if @proxy_hash
333
+ faraday.response :json, content_type: /\bjson$/
334
+ faraday.adapter Faraday.default_adapter
335
+ end
336
+
337
+ response = multipart_conn.patch do |req|
338
+ req.url resource_path
339
+ req.options.timeout = timeout if timeout
340
+ req.body = data
341
+ end
342
+ else
343
+ response = @conn.patch do |req|
344
+ req.url resource_path
345
+ req.options.timeout = timeout if timeout
346
+ req.body = JSON.generate(data) if data
347
+ end
348
+ end
349
+ response
350
+ end
351
+
314
352
  def send_delete(resource_path, data, timeout, options = nil)
315
353
  if options
316
354
  if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
@@ -0,0 +1,260 @@
1
+ module Plivo
2
+ module Resources
3
+ include Plivo::Utils
4
+
5
+ class PhoneNumberComplianceRequirement < Base::Resource
6
+ def initialize(client, options = nil)
7
+ @_name = 'PhoneNumber/Compliance/Requirements'
8
+ @_identifier_string = 'requirement_id'
9
+ super
10
+ end
11
+
12
+ def to_s
13
+ {
14
+ api_id: @api_id,
15
+ requirement_id: @requirement_id,
16
+ country_iso: @country_iso,
17
+ number_type: @number_type,
18
+ user_type: @user_type,
19
+ document_types: @document_types
20
+ }.delete_if { |key, value| value.nil? }.to_s
21
+ end
22
+ end
23
+
24
+ class PhoneNumberComplianceRequirementsInterface < Base::ResourceInterface
25
+ def initialize(client, resource_list_json = nil)
26
+ @_name = 'PhoneNumber/Compliance/Requirements'
27
+ @_resource_type = PhoneNumberComplianceRequirement
28
+ @_identifier_string = 'requirement_id'
29
+ super
30
+ end
31
+
32
+ ##
33
+ # Get phone number compliance requirements
34
+ # @param [Hash] options
35
+ # @option options [String] :country_iso
36
+ # @option options [String] :number_type
37
+ # @option options [String] :user_type
38
+ # @return [PhoneNumberComplianceRequirement]
39
+ def get(options = nil)
40
+ params = {}
41
+ if options
42
+ valid_param?(:options, options, Hash, true)
43
+ %i[country_iso number_type user_type].each do |param|
44
+ if options.key?(param) &&
45
+ valid_param?(param, options[param], [String, Symbol], false)
46
+ params[param] = options[param]
47
+ end
48
+ end
49
+ end
50
+ perform_get_without_identifier(params)
51
+ end
52
+ end
53
+
54
+ class PhoneNumberCompliance < Base::Resource
55
+ def initialize(client, options = nil)
56
+ @_name = 'PhoneNumber/Compliance'
57
+ @_identifier_string = 'compliance_id'
58
+ super
59
+ end
60
+
61
+ def update(params)
62
+ unless @id
63
+ raise_invalid_request("Cannot update a #{@_name} resource "\
64
+ 'without an identifier')
65
+ end
66
+
67
+ response_json = @_client.send_request(@_resource_uri, 'PATCH', params, nil, true, is_voice_request: false)
68
+
69
+ # Unwrap compliance wrapper if present (API returns {api_id, message, compliance: {...}})
70
+ compliance_data = response_json['compliance'] || response_json
71
+ compliance_data['api_id'] = response_json['api_id'] if response_json['api_id']
72
+ # Include message from response so callers can access update status via resp.message
73
+ compliance_data['message'] = response_json['message'] if response_json['message']
74
+ parse_and_set(compliance_data)
75
+ self
76
+ end
77
+
78
+ def delete
79
+ perform_delete
80
+ end
81
+
82
+ def to_s
83
+ {
84
+ api_id: @api_id,
85
+ compliance_id: @compliance_id,
86
+ alias: @alias,
87
+ status: @status,
88
+ country_iso: @country_iso,
89
+ number_type: @number_type,
90
+ user_type: @user_type,
91
+ created_at: @created_at,
92
+ updated_at: @updated_at
93
+ }.delete_if { |key, value| value.nil? }.to_s
94
+ end
95
+ end
96
+
97
+ class PhoneNumberCompliancesInterface < Base::ResourceInterface
98
+ def initialize(client, resource_list_json = nil)
99
+ @_name = 'PhoneNumber/Compliance'
100
+ @_resource_type = PhoneNumberCompliance
101
+ @_identifier_string = 'compliance_id'
102
+ super
103
+ end
104
+
105
+ ##
106
+ # Create a phone number compliance application
107
+ # @param [Hash] data_hash - compliance data (country_iso, number_type, alias, end_user, documents, etc.)
108
+ # @param [Array] documents - list of local file paths for document uploads (optional)
109
+ # @return [Response]
110
+ def create(data_hash, documents = nil)
111
+ params = { data: JSON.generate(data_hash) }
112
+ if documents
113
+ documents.each_with_index do |filepath, index|
114
+ file_extension = filepath.split('.')[-1]
115
+ content_type = case file_extension
116
+ when 'jpeg', 'jpg' then 'image/jpeg'
117
+ when 'png' then 'image/png'
118
+ when 'pdf' then 'application/pdf'
119
+ else raise_invalid_request("#{file_extension} is not supported")
120
+ end
121
+ params["documents[#{index}].file"] = Faraday::UploadIO.new(filepath, content_type)
122
+ end
123
+ end
124
+ perform_create(params, true)
125
+ end
126
+
127
+ ##
128
+ # Get a phone number compliance application
129
+ # @param [String] compliance_id
130
+ # @param [Hash] options
131
+ # @option options [String] :expand
132
+ # @return [PhoneNumberCompliance]
133
+ def get(compliance_id, options = nil)
134
+ valid_param?(:compliance_id, compliance_id, [String, Symbol], true)
135
+ params = {}
136
+ if options
137
+ valid_param?(:options, options, Hash, true)
138
+ if options.key?(:expand) &&
139
+ valid_param?(:expand, options[:expand], [String, Symbol], false)
140
+ params[:expand] = options[:expand]
141
+ end
142
+ end
143
+ response_json = @_client.send_request(@_resource_uri + compliance_id.to_s + '/', 'GET', params, nil, false, is_voice_request: false)
144
+ # Extract the compliance wrapper returned by the API
145
+ compliance_data = response_json['compliance'] || response_json
146
+ compliance_data['api_id'] = response_json['api_id'] if response_json['api_id']
147
+ @_resource_type.new(@_client, resource_json: compliance_data)
148
+ end
149
+
150
+ ##
151
+ # List phone number compliance applications
152
+ # @param [Hash] options
153
+ # @option options [Int] :limit
154
+ # @option options [Int] :offset
155
+ # @option options [String] :status
156
+ # @option options [String] :country_iso
157
+ # @option options [String] :number_type
158
+ # @option options [String] :user_type
159
+ # @option options [String] :alias
160
+ # @option options [String] :expand
161
+ # @return [Hash]
162
+ def list(options = nil)
163
+ params = {}
164
+ if options
165
+ valid_param?(:options, options, Hash, true)
166
+
167
+ %i[status country_iso number_type user_type alias expand].each do |param|
168
+ if options.key?(param) &&
169
+ valid_param?(param, options[param], [String, Symbol], false)
170
+ params[param] = options[param]
171
+ end
172
+ end
173
+
174
+ %i[offset limit].each do |param|
175
+ if options.key?(param) && valid_param?(param, options[param],
176
+ [Integer], false)
177
+ params[param] = options[param]
178
+ end
179
+ end
180
+
181
+ raise_invalid_request("Offset can't be negative") if options.key?(:offset) && options[:offset] < 0
182
+
183
+ if options.key?(:limit) && (options[:limit] > 20 || options[:limit] <= 0)
184
+ raise_invalid_request('The maximum number of results that can be '\
185
+ "fetched is 20. limit can't be more than 20 or less than 1")
186
+ end
187
+ end
188
+
189
+ response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: false)
190
+
191
+ # Remap 'compliances' to 'objects' for base class compatibility
192
+ if response_json.key?('compliances')
193
+ response_json['objects'] = response_json.delete('compliances')
194
+ end
195
+
196
+ parse_and_set(response_json)
197
+ {
198
+ api_id: @api_id,
199
+ meta: @_meta,
200
+ objects: @_resource_list
201
+ }
202
+ end
203
+
204
+ ##
205
+ # Update a phone number compliance application
206
+ # @param [String] compliance_id
207
+ # @param [Hash] data_hash - compliance data to update
208
+ # @param [Array] documents - list of local file paths for document uploads (optional)
209
+ # @return [PhoneNumberCompliance]
210
+ def update(compliance_id, data_hash, documents = nil)
211
+ valid_param?(:compliance_id, compliance_id, [String, Symbol], true)
212
+
213
+ params = { data: JSON.generate(data_hash) }
214
+ if documents
215
+ documents.each_with_index do |filepath, index|
216
+ file_extension = filepath.split('.')[-1]
217
+ content_type = case file_extension
218
+ when 'jpeg', 'jpg' then 'image/jpeg'
219
+ when 'png' then 'image/png'
220
+ when 'pdf' then 'application/pdf'
221
+ else raise_invalid_request("#{file_extension} is not supported")
222
+ end
223
+ params["documents[#{index}].file"] = Faraday::UploadIO.new(filepath, content_type)
224
+ end
225
+ end
226
+
227
+ PhoneNumberCompliance.new(@_client,
228
+ resource_id: compliance_id).update(params)
229
+ end
230
+
231
+ ##
232
+ # Delete a phone number compliance application
233
+ # @param [String] compliance_id
234
+ def delete(compliance_id)
235
+ valid_param?(:compliance_id, compliance_id, [String, Symbol], true)
236
+ PhoneNumberCompliance.new(@_client,
237
+ resource_id: compliance_id).delete
238
+ end
239
+ end
240
+
241
+ class PhoneNumberComplianceLinkInterface < Base::ResourceInterface
242
+ def initialize(client, resource_list_json = nil)
243
+ @_name = 'PhoneNumber/Compliance/Link'
244
+ @_resource_type = PhoneNumberCompliance
245
+ @_identifier_string = 'compliance_id'
246
+ super
247
+ end
248
+
249
+ ##
250
+ # Link numbers to compliance applications
251
+ # @param [Array] numbers - list of hashes with 'number' and 'compliance_application_id'
252
+ # @return [Response]
253
+ def create(numbers)
254
+ valid_param?(:numbers, numbers, Array, true)
255
+ params = { numbers: numbers }
256
+ perform_create(params)
257
+ end
258
+ end
259
+ end
260
+ end
@@ -22,6 +22,7 @@ require_relative 'resources/campaign'
22
22
  require_relative 'resources/profile'
23
23
  require_relative 'resources/lookup'
24
24
  require_relative 'resources/regulatory_compliance'
25
+ require_relative 'resources/phone_number_compliance'
25
26
  require_relative 'resources/multipartycalls'
26
27
  require_relative 'resources/verify_session'
27
28
  require_relative 'resources/tollfree_verification'
@@ -22,6 +22,7 @@ module Plivo
22
22
  attr_reader :tollfree_verifications
23
23
  attr_reader :verify_caller_id
24
24
  attr_reader :maskingsession
25
+ attr_reader :phone_number_compliance_requirements, :phone_number_compliances, :phone_number_compliance_link
25
26
 
26
27
  def initialize(auth_id = nil, auth_token = nil, proxy_options = nil, timeout = 5)
27
28
  configure_base_uri
@@ -69,6 +70,9 @@ module Plivo
69
70
  @compliance_documents = Resources::ComplianceDocumentsInterface.new(self)
70
71
  @compliance_requirements = Resources::ComplianceRequirementsInterface.new(self)
71
72
  @compliance_applications = Resources::ComplianceApplicationsInterface.new(self)
73
+ @phone_number_compliance_requirements = Resources::PhoneNumberComplianceRequirementsInterface.new(self)
74
+ @phone_number_compliances = Resources::PhoneNumberCompliancesInterface.new(self)
75
+ @phone_number_compliance_link = Resources::PhoneNumberComplianceLinkInterface.new(self)
72
76
  @verify_session = Resources::SessionInterface.new(self)
73
77
  @tollfree_verifications = Resources::TollfreeVerificationsInterface.new(self)
74
78
  @verify_caller_id = Resources::VerifyCallerIdInterface.new(self)
data/lib/plivo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Plivo
2
- VERSION = "4.62.5".freeze
2
+ VERSION = "4.63.1".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plivo
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.62.5
4
+ version: 4.63.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Plivo SDKs Team
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-21 00:00:00.000000000 Z
11
+ date: 2026-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -190,6 +190,7 @@ files:
190
190
  - lib/plivo/resources/numbers.rb
191
191
  - lib/plivo/resources/phlo_member.rb
192
192
  - lib/plivo/resources/phlos.rb
193
+ - lib/plivo/resources/phone_number_compliance.rb
193
194
  - lib/plivo/resources/powerpacks.rb
194
195
  - lib/plivo/resources/pricings.rb
195
196
  - lib/plivo/resources/profile.rb
@@ -241,7 +242,7 @@ homepage: https://github.com/plivo/plivo-ruby
241
242
  licenses:
242
243
  - MIT
243
244
  metadata: {}
244
- post_install_message:
245
+ post_install_message:
245
246
  rdoc_options: []
246
247
  require_paths:
247
248
  - lib
@@ -256,9 +257,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
256
257
  - !ruby/object:Gem::Version
257
258
  version: '0'
258
259
  requirements: []
259
- rubyforge_project:
260
- rubygems_version: 2.6.14.4
261
- signing_key:
260
+ rubygems_version: 3.4.19
261
+ signing_key:
262
262
  specification_version: 4
263
263
  summary: A Ruby SDK to make voice calls & send SMS using Plivo and to generate Plivo
264
264
  XML