plivo 0.3.19 → 4.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +11 -0
  5. data/AUTHORS.md +4 -0
  6. data/CHANGELOG.md +158 -0
  7. data/Gemfile +10 -0
  8. data/Jenkinsfile +7 -0
  9. data/LICENSE.txt +19 -0
  10. data/README.md +155 -24
  11. data/Rakefile +9 -0
  12. data/ci/config.yml +7 -0
  13. data/examples/conference_bridge.rb +108 -0
  14. data/examples/jwt.rb +32 -0
  15. data/examples/lookup.rb +24 -0
  16. data/examples/multi_party_call.rb +295 -0
  17. data/examples/phlos.rb +55 -0
  18. data/examples/regulatory_compliance.rb +167 -0
  19. data/lib/plivo/base/resource.rb +148 -0
  20. data/lib/plivo/base/resource_interface.rb +108 -0
  21. data/lib/plivo/base/response.rb +38 -0
  22. data/lib/plivo/base.rb +17 -0
  23. data/lib/plivo/base_client.rb +393 -0
  24. data/lib/plivo/exceptions.rb +50 -0
  25. data/lib/plivo/jwt.rb +120 -0
  26. data/lib/plivo/phlo_client.rb +29 -0
  27. data/lib/plivo/resources/accounts.rb +181 -0
  28. data/lib/plivo/resources/addresses.rb +302 -0
  29. data/lib/plivo/resources/applications.rb +258 -0
  30. data/lib/plivo/resources/call_feedback.rb +55 -0
  31. data/lib/plivo/resources/calls.rb +559 -0
  32. data/lib/plivo/resources/conferences.rb +367 -0
  33. data/lib/plivo/resources/endpoints.rb +132 -0
  34. data/lib/plivo/resources/identities.rb +319 -0
  35. data/lib/plivo/resources/lookup.rb +88 -0
  36. data/lib/plivo/resources/media.rb +97 -0
  37. data/lib/plivo/resources/messages.rb +215 -0
  38. data/lib/plivo/resources/multipartycalls.rb +554 -0
  39. data/lib/plivo/resources/nodes.rb +83 -0
  40. data/lib/plivo/resources/numbers.rb +319 -0
  41. data/lib/plivo/resources/phlo_member.rb +64 -0
  42. data/lib/plivo/resources/phlos.rb +55 -0
  43. data/lib/plivo/resources/powerpacks.rb +717 -0
  44. data/lib/plivo/resources/pricings.rb +43 -0
  45. data/lib/plivo/resources/recordings.rb +116 -0
  46. data/lib/plivo/resources/regulatory_compliance.rb +610 -0
  47. data/lib/plivo/resources.rb +25 -0
  48. data/lib/plivo/rest_client.rb +63 -0
  49. data/lib/plivo/utils.rb +294 -0
  50. data/lib/plivo/version.rb +3 -0
  51. data/lib/plivo/xml/break.rb +31 -0
  52. data/lib/plivo/xml/conference.rb +20 -0
  53. data/lib/plivo/xml/cont.rb +13 -0
  54. data/lib/plivo/xml/dial.rb +16 -0
  55. data/lib/plivo/xml/dtmf.rb +13 -0
  56. data/lib/plivo/xml/element.rb +106 -0
  57. data/lib/plivo/xml/emphasis.rb +17 -0
  58. data/lib/plivo/xml/get_digits.rb +15 -0
  59. data/lib/plivo/xml/get_input.rb +16 -0
  60. data/lib/plivo/xml/hangup.rb +12 -0
  61. data/lib/plivo/xml/lang.rb +29 -0
  62. data/lib/plivo/xml/message.rb +13 -0
  63. data/lib/plivo/xml/multipartycall.rb +188 -0
  64. data/lib/plivo/xml/number.rb +13 -0
  65. data/lib/plivo/xml/p.rb +12 -0
  66. data/lib/plivo/xml/phoneme.rb +20 -0
  67. data/lib/plivo/xml/play.rb +13 -0
  68. data/lib/plivo/xml/plivo_xml.rb +19 -0
  69. data/lib/plivo/xml/pre_answer.rb +12 -0
  70. data/lib/plivo/xml/prosody.rb +28 -0
  71. data/lib/plivo/xml/record.rb +17 -0
  72. data/lib/plivo/xml/redirect.rb +13 -0
  73. data/lib/plivo/xml/response.rb +21 -0
  74. data/lib/plivo/xml/s.rb +12 -0
  75. data/lib/plivo/xml/say_as.rb +24 -0
  76. data/lib/plivo/xml/speak.rb +28 -0
  77. data/lib/plivo/xml/sub.rb +16 -0
  78. data/lib/plivo/xml/user.rb +13 -0
  79. data/lib/plivo/xml/w.rb +17 -0
  80. data/lib/plivo/xml/wait.rb +12 -0
  81. data/lib/plivo/xml.rb +39 -0
  82. data/lib/plivo.rb +12 -815
  83. data/plivo.gemspec +44 -0
  84. metadata +181 -41
  85. data/ext/mkrf_conf.rb +0 -9
@@ -0,0 +1,108 @@
1
+ module Plivo
2
+ module Base
3
+ class ResourceInterface
4
+ include Plivo::Utils
5
+ def initialize(client, resource_list_json = nil)
6
+ configure_client(client)
7
+ configure_resource_uri
8
+ parse_and_set(resource_list_json) if resource_list_json
9
+ @_is_voice_request = false
10
+ end
11
+
12
+ private
13
+
14
+ def configure_client(client)
15
+ valid_param?(:client, client, [RestClient, Phlo], true)
16
+ @_client = client
17
+ end
18
+
19
+ def configure_resource_uri
20
+ to_join = ['', 'v1', 'Account', @_client.auth_id, @_name, '']
21
+ to_join = ['', 'v1', 'Account', ''] if @_name == 'Account'
22
+ to_join = ['', 'v1', @_name, ''] if @_name == 'phlo'
23
+ @_resource_uri = to_join.join('/')
24
+ end
25
+
26
+ def parse_and_set(resource_list_json)
27
+ return unless resource_list_json
28
+
29
+ valid_param?(:resource_list_json, resource_list_json, Hash, true)
30
+
31
+ resource_list_json.each do |k, v|
32
+ if k == 'objects'
33
+ parse_and_set_list(resource_list_json['objects'])
34
+ elsif k == 'meta'
35
+ @_meta = resource_list_json['meta']
36
+ else
37
+ instance_variable_set("@#{k}", v)
38
+ self.class.send(:attr_reader, k)
39
+ end
40
+ end
41
+ end
42
+
43
+ def perform_get(identifier, params = nil)
44
+ valid_param?(:identifier, identifier, [String, Symbol], true)
45
+ response_json = @_client.send_request(@_resource_uri + identifier.to_s + '/', 'GET', params, nil, false, is_voice_request: @_is_voice_request)
46
+ @_resource_type.new(@_client, resource_json: response_json)
47
+ end
48
+
49
+ def perform_get_without_identifier(params)
50
+ valid_param?(:params, params, Hash, true)
51
+ response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
52
+ @_resource_type.new(@_client, resource_json: response_json)
53
+ end
54
+
55
+ def perform_create(params, use_multipart_conn=false)
56
+ Response.new(
57
+ @_client.send_request(@_resource_uri, 'POST', params, nil, use_multipart_conn, is_voice_request: @_is_voice_request),
58
+ @_identifier_string
59
+ )
60
+ end
61
+
62
+ def perform_submit(identifier, params = nil)
63
+ valid_param?(:identifier, identifier, [String, Symbol], true)
64
+ response_json = @_client.send_request(@_resource_uri + identifier.to_s + '/Submit/', 'POST', params, nil, false, is_voice_request: @_is_voice_request)
65
+ @_resource_type.new(@_client, resource_json: response_json)
66
+ end
67
+
68
+ def perform_post(params)
69
+ response_json = @_client.send_request(@_resource_uri, 'POST', params, nil, false, is_voice_request: @_is_voice_request)
70
+
71
+ parse_and_set(response_json)
72
+ self
73
+ end
74
+
75
+ def parse_and_set_list(list_json)
76
+ return unless list_json
77
+ valid_param?(:list_json, list_json, Array, false)
78
+ @_resource_list = list_json.map do |resource|
79
+ @_resource_type.new(@_client, resource_json: resource)
80
+ end
81
+ end
82
+
83
+ def perform_list(params = nil)
84
+ response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
85
+ parse_and_set(response_json)
86
+ {
87
+ api_id: @api_id,
88
+ meta: @_meta,
89
+ objects: @_resource_list
90
+ }
91
+ end
92
+
93
+ def perform_action(action = nil, method = 'GET', params = nil, parse = false)
94
+ resource_path = action ? @_resource_uri + action + '/' : @_resource_uri
95
+ response = @_client.send_request(resource_path, method, params, nil, false, is_voice_request: @_is_voice_request)
96
+ parse ? parse_and_set(response) : self
97
+ method == 'POST' ? parse_and_set(params) : self
98
+ self
99
+ end
100
+
101
+ def perform_list_without_object(params = nil)
102
+ response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
103
+ parse_and_set(response_json)
104
+ response_json
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,38 @@
1
+ module Plivo
2
+ module Base
3
+ ##
4
+ # A class to provide a blanket response based on what is
5
+ # being received from Plivo servers.
6
+ #
7
+ # This will be used only during POST and DELETE requests.
8
+ class Response
9
+ ##
10
+ # Instantiating a new instance requires a response_hash
11
+ # The id_symbol should contain a Symbol that represents
12
+ # the identifier of the resource for which this response
13
+ # is being generated for.
14
+
15
+ def initialize(response_hash, id_symbol = nil)
16
+ return unless response_hash
17
+
18
+ response_hash.each do |k, v|
19
+ instance_variable_set("@#{k}", v)
20
+ self.class.send(:attr_reader, k)
21
+ end
22
+ return unless id_symbol && response_hash.key?(id_symbol)
23
+
24
+ self.class.send(:attr_reader, :id)
25
+ @id = response_hash[id_symbol]
26
+ end
27
+
28
+ def to_s
29
+ h = self.instance_variables.map do |attribute|
30
+ key = attribute.to_s.gsub('@','')
31
+ [key, self.instance_variable_get(attribute)]
32
+ end.to_h
33
+ h.to_s
34
+ end
35
+
36
+ end
37
+ end
38
+ end
data/lib/plivo/base.rb ADDED
@@ -0,0 +1,17 @@
1
+ require_relative 'base/resource_interface'
2
+ require_relative 'base/resource'
3
+ require_relative 'base/response'
4
+
5
+ module Plivo
6
+ module Base
7
+ PLIVO_API_URL = 'https://api.plivo.com'.freeze
8
+
9
+ API_VOICE = 'https://voice.plivo.com'.freeze
10
+ API_VOICE_FALLBACK_1 = 'https://voice-usw1.plivo.com'.freeze
11
+ API_VOICE_FALLBACK_2 = 'https://voice-use1.plivo.com'.freeze
12
+
13
+ CALLINSIGHTS_API_URL = 'https://stats.plivo.com'.freeze
14
+ PHLO_API_URL = 'https://phlorunner.plivo.com'.freeze
15
+ LOOKUP_API_URL = 'https://lookup.plivo.com'.freeze
16
+ end
17
+ end
@@ -0,0 +1,393 @@
1
+ require 'json'
2
+ require 'faraday'
3
+ require 'faraday_middleware'
4
+
5
+ require_relative 'exceptions'
6
+ require_relative 'utils'
7
+ require_relative 'resources'
8
+ require_relative 'base'
9
+
10
+ module Plivo
11
+ # Core client, used for all API requests
12
+ include Utils
13
+ class BaseClient
14
+ # Base stuff
15
+ attr_reader :headers, :auth_credentials
16
+ @@voice_retry_count = 0
17
+ def initialize(auth_id = nil, auth_token = nil, proxy_options = nil, timeout=5)
18
+ configure_credentials(auth_id, auth_token)
19
+ configure_proxies(proxy_options)
20
+ configure_timeout(timeout)
21
+ configure_headers
22
+ configure_connection
23
+ end
24
+
25
+ def auth_id
26
+ @auth_credentials[:auth_id]
27
+ end
28
+
29
+ def process_response(method, response)
30
+ handle_response_exceptions(response)
31
+ if method == 'DELETE'
32
+ if !([200, 204].include? response[:status])
33
+ raise Exceptions::PlivoRESTError, "Resource at #{response[:url]} "\
34
+ 'couldn\'t be deleted'
35
+ end
36
+ elsif !([200, 201, 202, 204, 207].include? response[:status])
37
+ raise Exceptions::PlivoRESTError, "Received #{response[:status]} for #{method}"
38
+ end
39
+ @@voice_retry_count = 0
40
+ response[:body]
41
+ end
42
+
43
+ def send_request(resource_path, method = 'GET', data = {}, timeout = nil, use_multipart_conn = false, options = nil)
44
+ timeout ||= @timeout
45
+
46
+ if options[:is_voice_request] == true
47
+ response = case method
48
+ when 'GET' then send_get(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
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 'DELETE' then send_delete(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
51
+ else raise_invalid_request("#{method} not supported by Plivo, yet")
52
+ end
53
+
54
+ if response.status >= 500
55
+ @@voice_retry_count += 1
56
+ if @@voice_retry_count > 2
57
+ return process_response(method, response.to_hash)
58
+ end
59
+ is_voice_request = true
60
+ send_request(resource_path, method, data, timeout, use_multipart_conn, is_voice_request: is_voice_request)
61
+ else
62
+ process_response(method, response.to_hash)
63
+ end
64
+ elsif options[:is_lookup_request] == true
65
+ response = case method
66
+ when 'GET' then send_get(resource_path, data, timeout, is_lookup_request: options[:is_lookup_request])
67
+ else raise_invalid_request("#{method} not supported by Plivo, yet")
68
+ end
69
+ process_response(method, response.to_hash)
70
+ else
71
+ response = case method
72
+ when 'GET' then send_get(resource_path, data, timeout)
73
+ when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn)
74
+ when 'DELETE' then send_delete(resource_path, data, timeout)
75
+ else raise_invalid_request("#{method} not supported by Plivo, yet")
76
+ end
77
+
78
+ process_response(method, response.to_hash)
79
+ end
80
+ end
81
+
82
+ private
83
+
84
+ def auth_token
85
+ @auth_credentials[:auth_token]
86
+ end
87
+
88
+ def configure_credentials(auth_id, auth_token)
89
+ # Fetches and sets the right credentials
90
+ auth_id ||= ENV['PLIVO_AUTH_ID']
91
+ auth_token ||= ENV['PLIVO_AUTH_TOKEN']
92
+
93
+ raise Exceptions::AuthenticationError, 'Couldn\'t find auth credentials' unless
94
+ auth_id && auth_token
95
+
96
+ raise Exceptions::AuthenticationError, "Invalid auth_id: '#{auth_id}'" unless
97
+ Utils.valid_account?(auth_id)
98
+
99
+ @auth_credentials = {
100
+ auth_id: auth_id,
101
+ auth_token: auth_token
102
+ }
103
+ end
104
+
105
+ def configure_proxies(proxy_dict)
106
+ @proxy_hash = nil
107
+ return unless proxy_dict
108
+
109
+ @proxy_hash = {
110
+ uri: "#{proxy_dict[:proxy_host]}:#{proxy_dict[:proxy_port]}",
111
+ user: proxy_dict[:proxy_user],
112
+ password: proxy_dict[:proxy_pass]
113
+ }
114
+ end
115
+
116
+ def configure_timeout(timeout)
117
+ @timeout = timeout
118
+ end
119
+
120
+ def user_agent
121
+ "plivo-ruby/#{Plivo::VERSION} (Ruby #{RUBY_VERSION})"
122
+ end
123
+
124
+ def configure_headers
125
+ @headers = {
126
+ 'User-Agent' => user_agent,
127
+ 'Content-Type' => 'application/json',
128
+ 'Accept' => 'application/json'
129
+ }
130
+ end
131
+
132
+
133
+ def configure_connection
134
+ @conn = Faraday.new(@base_uri) do |faraday|
135
+ faraday.headers = @headers
136
+
137
+ # DANGER: Basic auth should always come after headers, else
138
+ # The headers will replace the basic_auth
139
+
140
+ faraday.basic_auth(auth_id, auth_token)
141
+
142
+ faraday.proxy=@proxy_hash if @proxy_hash
143
+ faraday.response :json, content_type: /\bjson$/
144
+ faraday.adapter Faraday.default_adapter
145
+ end
146
+
147
+ @voice_conn_no_retry = Faraday.new(@voice_base_uri) do |faraday|
148
+ faraday.headers = @headers
149
+
150
+ # DANGER: Basic auth should always come after headers, else
151
+ # The headers will replace the basic_auth
152
+
153
+ faraday.basic_auth(auth_id, auth_token)
154
+
155
+ faraday.proxy=@proxy_hash if @proxy_hash
156
+ faraday.response :json, content_type: /\bjson$/
157
+ faraday.adapter Faraday.default_adapter
158
+ end
159
+
160
+ @voice_conn_retry_1 = Faraday.new(@voice_base_uri_fallback_1) do |faraday|
161
+ faraday.headers = @headers
162
+
163
+ # DANGER: Basic auth should always come after headers, else
164
+ # The headers will replace the basic_auth
165
+
166
+ faraday.basic_auth(auth_id, auth_token)
167
+
168
+ faraday.proxy=@proxy_hash if @proxy_hash
169
+ faraday.response :json, content_type: /\bjson$/
170
+ faraday.adapter Faraday.default_adapter
171
+ end
172
+
173
+ @voice_conn_retry_2 = Faraday.new(@voice_base_uri_fallback_2) do |faraday|
174
+ faraday.headers = @headers
175
+
176
+ # DANGER: Basic auth should always come after headers, else
177
+ # The headers will replace the basic_auth
178
+
179
+ faraday.basic_auth(auth_id, auth_token)
180
+
181
+ faraday.proxy=@proxy_hash if @proxy_hash
182
+ faraday.response :json, content_type: /\bjson$/
183
+ faraday.adapter Faraday.default_adapter
184
+ end
185
+
186
+ @callinsights_conn = Faraday.new(@callinsights_base_uri) do |faraday|
187
+ faraday.headers = @headers
188
+
189
+ # DANGER: Basic auth should always come after headers, else
190
+ # The headers will replace the basic_auth
191
+
192
+ faraday.basic_auth(auth_id, auth_token)
193
+
194
+ faraday.proxy=@proxy_hash if @proxy_hash
195
+ faraday.response :json, content_type: /\bjson$/
196
+ faraday.adapter Faraday.default_adapter
197
+ end
198
+
199
+ @lookup_conn = Faraday.new(@lookup_base_uri) do |faraday|
200
+ faraday.headers = @headers
201
+
202
+ # DANGER: Basic auth should always come after headers, else
203
+ # The headers will replace the basic_auth
204
+
205
+ faraday.basic_auth(auth_id, auth_token)
206
+
207
+ faraday.proxy=@proxy_hash if @proxy_hash
208
+ faraday.response :json, content_type: /\bjson$/
209
+ faraday.adapter Faraday.default_adapter
210
+ end
211
+ end
212
+
213
+ def send_get(resource_path, data, timeout, options = nil)
214
+ if options
215
+ if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
216
+ response = @voice_conn_no_retry.get do |req|
217
+ req.url resource_path, data
218
+ req.options.timeout = timeout if timeout
219
+ end
220
+ elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
221
+ response = @voice_conn_retry_1.get do |req|
222
+ req.url resource_path, data
223
+ req.options.timeout = timeout if timeout
224
+ end
225
+ elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
226
+ response = @voice_conn_retry_2.get do |req|
227
+ req.url resource_path, data
228
+ req.options.timeout = timeout if timeout
229
+ end
230
+ elsif options[:is_lookup_request] == true
231
+ response = @lookup_conn.get do |req|
232
+ req.url resource_path, data
233
+ req.options.timeout = timeout if timeout
234
+ end
235
+ end
236
+ else
237
+ response = @conn.get do |req|
238
+ req.url resource_path, data
239
+ req.options.timeout = timeout if timeout
240
+ end
241
+ end
242
+ response
243
+ end
244
+
245
+ def send_post(resource_path, data, timeout, use_multipart_conn, options = nil)
246
+ if use_multipart_conn
247
+ multipart_conn = Faraday.new(@base_uri) do |faraday|
248
+ faraday.headers = {
249
+ 'User-Agent' => @headers['User-Agent'],
250
+ 'Accept' => @headers['Accept']
251
+ }
252
+
253
+ # DANGER: Basic auth should always come after headers, else
254
+ # The headers will replace the basic_auth
255
+
256
+ faraday.request :multipart
257
+ faraday.request :url_encoded
258
+ faraday.basic_auth(auth_id, auth_token)
259
+
260
+ faraday.proxy=@proxy_hash if @proxy_hash
261
+ faraday.response :json, content_type: /\bjson$/
262
+ faraday.adapter Faraday.default_adapter
263
+ end
264
+
265
+ response = multipart_conn.post do |req|
266
+ req.url resource_path
267
+ req.options.timeout = timeout if timeout
268
+ req.body = data
269
+ puts req
270
+ end
271
+ else
272
+ if !data.nil? && (data.has_key? 'is_callinsights_request')
273
+ callinsight_base_url = data['callinsight_base_url']
274
+ resource_path = data['request_url']
275
+ data.delete('is_callinsights_request')
276
+ data.delete('request_url')
277
+
278
+ response = @callinsights_conn.post do |req|
279
+ req.url resource_path
280
+ req.options.timeout = timeout if timeout
281
+ req.body = JSON.generate(data) if data
282
+ end
283
+ elsif options
284
+ if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
285
+ response = @voice_conn_no_retry.post do |req|
286
+ req.url resource_path
287
+ req.options.timeout = timeout if timeout
288
+ req.body = JSON.generate(data) if data
289
+ end
290
+ elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
291
+ response = @voice_conn_retry_1.post do |req|
292
+ req.url resource_path
293
+ req.options.timeout = timeout if timeout
294
+ req.body = JSON.generate(data) if data
295
+ end
296
+ elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
297
+ response = @voice_conn_retry_2.post do |req|
298
+ req.url resource_path
299
+ req.options.timeout = timeout if timeout
300
+ req.body = JSON.generate(data) if data
301
+ end
302
+ end
303
+ else
304
+ response = @conn.post do |req|
305
+ req.url resource_path
306
+ req.options.timeout = timeout if timeout
307
+ req.body = JSON.generate(data) if data
308
+ end
309
+ end
310
+ end
311
+ response
312
+ end
313
+
314
+ def send_delete(resource_path, data, timeout, options = nil)
315
+ if options
316
+ if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
317
+ response = @voice_conn_no_retry.delete do |req|
318
+ req.url resource_path
319
+ req.options.timeout = timeout if timeout
320
+ req.body = JSON.generate(data) if data
321
+ end
322
+ elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
323
+ response = @voice_conn_retry_1.delete do |req|
324
+ req.url resource_path
325
+ req.options.timeout = timeout if timeout
326
+ req.body = JSON.generate(data) if data
327
+ end
328
+ elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
329
+ response = @voice_conn_retry_2.delete do |req|
330
+ req.url resource_path
331
+ req.options.timeout = timeout if timeout
332
+ req.body = JSON.generate(data) if data
333
+ end
334
+ end
335
+ else
336
+ response = @conn.delete do |req|
337
+ req.url resource_path
338
+ req.options.timeout = timeout if timeout
339
+ req.body = JSON.generate(data) if data
340
+ end
341
+ end
342
+ response
343
+ end
344
+
345
+ def handle_response_exceptions(response)
346
+ exception_mapping = {
347
+ 400 => [
348
+ Exceptions::ValidationError,
349
+ 'A parameter is missing or is invalid while accessing resource'
350
+ ],
351
+ 401 => [
352
+ Exceptions::AuthenticationError,
353
+ 'Failed to authenticate while accessing resource'
354
+ ],
355
+ 404 => [
356
+ Exceptions::ResourceNotFoundError,
357
+ 'Resource not found'
358
+ ],
359
+ 405 => [
360
+ Exceptions::InvalidRequestError,
361
+ 'HTTP method used is not allowed to access resource'
362
+ ],
363
+ 409 => [
364
+ Exceptions::InvalidRequestError,
365
+ 'Conflict'
366
+ ],
367
+ 422 => [
368
+ Exceptions::InvalidRequestError,
369
+ 'Unprocessable Entity'
370
+ ],
371
+ 500 => [
372
+ Exceptions::PlivoServerError,
373
+ 'A server error occurred while accessing resource'
374
+ ]
375
+ }
376
+
377
+ response_json = response[:body]
378
+ return unless exception_mapping.key? response[:status]
379
+
380
+ exception_now = exception_mapping[response[:status]]
381
+ error_message = if (response_json.is_a? Hash) && (response_json.key? 'error')
382
+ response_json['error']
383
+ else
384
+ exception_now[1] + " at: #{response[:url]}"
385
+ end
386
+ if error_message.is_a?(Hash) && error_message.key?('error')
387
+ error_message = error_message['error']
388
+ end
389
+
390
+ raise exception_now[0], error_message.to_s
391
+ end
392
+ end
393
+ end
@@ -0,0 +1,50 @@
1
+ module Plivo
2
+ ##
3
+ # The exceptions module that helps in passing on errors to the user in a better way.
4
+ module Exceptions
5
+ ##
6
+ # This is Plivo's base error and will be raised when there is an unknown
7
+ # error that is not covered by other errors.
8
+ PlivoRESTError = Class.new(StandardError)
9
+
10
+ ##
11
+ # This will be raised when A parameter is missing or is invalid while
12
+ # accessing resource.
13
+ ValidationError = Class.new(PlivoRESTError)
14
+ # 'A parameter is missing or is invalid while accessing resource'
15
+
16
+ ##
17
+ # This will be raised when there is an an error authenticating the request.
18
+ #
19
+ # It is because there were no authentication credentials found or passed
20
+ # or the auth credentials that were found or passed were incorrect.
21
+ AuthenticationError = Class.new(PlivoRESTError)
22
+
23
+ ##
24
+ # This will be raised when one or more parameters passed to Plivo servers
25
+ # is invalid.
26
+ #
27
+ # More specific error message will be displayed wherever possible.
28
+ InvalidRequestError = Class.new(PlivoRESTError)
29
+
30
+ ##
31
+ # This will be raised when there is a server error on the Plivo end.
32
+ #
33
+ # This is rarely encountered. You might want to catch this error and
34
+ # retry the request if needed.
35
+ #
36
+ # If retrying doesn't help, please contact https://support.plivo.com
37
+ # immediately.
38
+ PlivoServerError = Class.new(PlivoRESTError)
39
+
40
+ ##
41
+ # This will be raised when there is an XML generation error.
42
+ #
43
+ # Usually, the reason why this error is raised will be included.
44
+ PlivoXMLError = Class.new(PlivoRESTError)
45
+
46
+ ##
47
+ # This will be raised when there is an authentication error
48
+ ResourceNotFoundError = Class.new(PlivoRESTError)
49
+ end
50
+ end