vonage 7.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +190 -0
  3. data/README.md +191 -0
  4. data/lib/vonage.rb +29 -0
  5. data/lib/vonage/abstract_authentication.rb +9 -0
  6. data/lib/vonage/account.rb +61 -0
  7. data/lib/vonage/alerts.rb +72 -0
  8. data/lib/vonage/applications.rb +148 -0
  9. data/lib/vonage/applications/list_response.rb +11 -0
  10. data/lib/vonage/authentication_error.rb +6 -0
  11. data/lib/vonage/basic.rb +13 -0
  12. data/lib/vonage/bearer_token.rb +14 -0
  13. data/lib/vonage/client.rb +134 -0
  14. data/lib/vonage/client_error.rb +6 -0
  15. data/lib/vonage/config.rb +208 -0
  16. data/lib/vonage/conversations.rb +210 -0
  17. data/lib/vonage/conversations/events.rb +73 -0
  18. data/lib/vonage/conversations/legs.rb +30 -0
  19. data/lib/vonage/conversations/members.rb +104 -0
  20. data/lib/vonage/conversations/users.rb +93 -0
  21. data/lib/vonage/conversions.rb +19 -0
  22. data/lib/vonage/entity.rb +51 -0
  23. data/lib/vonage/error.rb +6 -0
  24. data/lib/vonage/errors.rb +51 -0
  25. data/lib/vonage/files.rb +26 -0
  26. data/lib/vonage/form_data.rb +11 -0
  27. data/lib/vonage/gsm7.rb +13 -0
  28. data/lib/vonage/http.rb +43 -0
  29. data/lib/vonage/json.rb +17 -0
  30. data/lib/vonage/jwt.rb +43 -0
  31. data/lib/vonage/key_secret_params.rb +20 -0
  32. data/lib/vonage/keys.rb +51 -0
  33. data/lib/vonage/logger.rb +60 -0
  34. data/lib/vonage/messages.rb +25 -0
  35. data/lib/vonage/namespace.rb +118 -0
  36. data/lib/vonage/number_insight.rb +140 -0
  37. data/lib/vonage/numbers.rb +196 -0
  38. data/lib/vonage/numbers/list_response.rb +11 -0
  39. data/lib/vonage/numbers/response.rb +8 -0
  40. data/lib/vonage/params.rb +27 -0
  41. data/lib/vonage/pricing.rb +30 -0
  42. data/lib/vonage/pricing_types.rb +18 -0
  43. data/lib/vonage/redact.rb +37 -0
  44. data/lib/vonage/response.rb +25 -0
  45. data/lib/vonage/secrets.rb +85 -0
  46. data/lib/vonage/secrets/list_response.rb +11 -0
  47. data/lib/vonage/server_error.rb +6 -0
  48. data/lib/vonage/signature.rb +53 -0
  49. data/lib/vonage/sms.rb +121 -0
  50. data/lib/vonage/tfa.rb +14 -0
  51. data/lib/vonage/user_agent.rb +16 -0
  52. data/lib/vonage/verify.rb +253 -0
  53. data/lib/vonage/version.rb +5 -0
  54. data/lib/vonage/voice.rb +250 -0
  55. data/lib/vonage/voice/dtmf.rb +26 -0
  56. data/lib/vonage/voice/list_response.rb +11 -0
  57. data/lib/vonage/voice/stream.rb +44 -0
  58. data/lib/vonage/voice/talk.rb +48 -0
  59. data/vonage.gemspec +26 -0
  60. metadata +155 -0
@@ -0,0 +1,19 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Conversions < Namespace
6
+ extend T::Sig
7
+ include Keys
8
+
9
+ sig { params(params: T::Hash[Symbol, T.untyped]).returns(Vonage::Response) }
10
+ def track_sms(params)
11
+ request('/conversions/sms', params: hyphenate(params), type: Post)
12
+ end
13
+
14
+ sig { params(params: T::Hash[Symbol, T.untyped]).returns(Vonage::Response) }
15
+ def track_voice(params)
16
+ request('/conversions/voice', params: hyphenate(params), type: Post)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,51 @@
1
+ # typed: true
2
+
3
+ module Vonage
4
+ class Entity
5
+ include Keys
6
+
7
+ def initialize(attributes = nil)
8
+ @attributes = attributes || {}
9
+ end
10
+
11
+ def [](key)
12
+ @attributes[attribute_key(key)]
13
+ end
14
+
15
+ def []=(key, value)
16
+ @attributes[attribute_key(key)] = value
17
+ end
18
+
19
+ def respond_to_missing?(name, include_private = false)
20
+ @attributes.key?(name) or super
21
+ end
22
+
23
+ def method_missing(name, *args)
24
+ return super unless @attributes.key?(name)
25
+
26
+ @attributes[name]
27
+ end
28
+
29
+ def ==(entity)
30
+ entity.class == self.class && entity.attributes == @attributes
31
+ end
32
+
33
+ def to_h
34
+ @attributes
35
+ end
36
+
37
+ attr_reader :attributes
38
+
39
+ protected :attributes
40
+
41
+ def each_pair(&block)
42
+ return to_enum(:each_pair) unless block
43
+
44
+ @attributes.each_pair(&block)
45
+ end
46
+
47
+ alias_method :each, :each_pair
48
+
49
+ include Enumerable
50
+ end
51
+ end
@@ -0,0 +1,6 @@
1
+ # typed: strong
2
+
3
+ module Vonage
4
+ class Error < StandardError
5
+ end
6
+ end
@@ -0,0 +1,51 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+ require 'json'
4
+
5
+ module Vonage
6
+ module Errors
7
+ extend T::Sig
8
+
9
+ sig {params(response: T.any(Net::HTTPUnauthorized, Net::HTTPClientError, Net::HTTPServerError, T.untyped)).returns(Vonage::Error)}
10
+ def self.parse(response)
11
+ exception_class = case response
12
+ when Net::HTTPUnauthorized
13
+ AuthenticationError
14
+ when Net::HTTPClientError
15
+ ClientError
16
+ when Net::HTTPServerError
17
+ ServerError
18
+ else
19
+ Error
20
+ end
21
+
22
+ message = if response.content_type == 'application/json'
23
+ hash = ::JSON.parse(response.body)
24
+
25
+ if hash.key?('error_title')
26
+ hash['error_title']
27
+ elsif hash.key?('error-code-label')
28
+ hash['error-code-label']
29
+ elsif hash.key?('description')
30
+ hash['description']
31
+ elsif problem_details?(hash)
32
+ problem_details_message(hash)
33
+ end
34
+ end
35
+
36
+ exception_class.new(message)
37
+ end
38
+
39
+ sig { params(hash: T::Hash[String, T.untyped]).returns(T::Boolean) }
40
+ def self.problem_details?(hash)
41
+ hash.key?('title') && hash.key?('detail') && hash.key?('type')
42
+ end
43
+
44
+ sig { params(hash: T::Hash[String, T.untyped]).returns(String) }
45
+ def self.problem_details_message(hash)
46
+ "#{hash['title']}. #{hash['detail']} See #{hash['type']} for more info, or email support@nexmo.com if you have any questions."
47
+ end
48
+ end
49
+
50
+ private_constant :Errors
51
+ end
@@ -0,0 +1,26 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Files < Namespace
6
+ extend T::Sig
7
+
8
+ self.authentication = BearerToken
9
+
10
+ sig { params(id: String).returns(T.nilable(Vonage::Response)) }
11
+ def get(id)
12
+ request('/v1/files/' + T.must(id.split('/').last))
13
+ end
14
+
15
+ sig { params(id: String, filename: String).returns(T.nilable(Vonage::Response)) }
16
+ def save(id, filename)
17
+ request('/v1/files/' + T.must(id.split('/').last)) do |response|
18
+ File.open(filename, 'wb') do |file|
19
+ response.read_body do |chunk|
20
+ file.write(chunk)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ # typed: ignore
2
+
3
+ module Vonage
4
+ module FormData
5
+ def self.update(http_request, params)
6
+ http_request.form_data = params
7
+ end
8
+ end
9
+
10
+ private_constant :FormData
11
+ end
@@ -0,0 +1,13 @@
1
+ # typed: ignore
2
+
3
+ module Vonage
4
+ module GSM7
5
+ CHARACTERS = "\n\f\r !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~ ¡£¤¥§¿ÄÅÆÉÑÖØÜßàäåæçèéìñòöøùüΓΔΘΛΞΠΣΦΨΩ€"
6
+
7
+ REGEXP = /\A[#{Regexp.escape(CHARACTERS)}]*\z/
8
+
9
+ def self.encoded?(string)
10
+ REGEXP =~ string
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,43 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+ require 'net/http'
4
+
5
+ module Vonage
6
+ module HTTP
7
+ class Options
8
+ extend T::Sig
9
+
10
+ sig { params(hash: T::Hash[Symbol, T.untyped]).void }
11
+ def initialize(hash)
12
+ raise ArgumentError, 'hash parameter cannot be empty or nil' if hash == {} || hash.nil?
13
+
14
+ @hash = T.let(@hash, T::Hash[Symbol, T.untyped]) if defined? @hash
15
+ @hash = hash
16
+
17
+ @hash.each_key do |name|
18
+ next if defined_options.key?(name)
19
+
20
+ raise ArgumentError, "#{name.inspect} is not a valid option"
21
+ end
22
+ end
23
+
24
+ sig { params(http: Net::HTTP).returns(T::Hash[Symbol, T.untyped]) }
25
+ def set(http)
26
+ @hash.each do |name, value|
27
+ http.public_send(defined_options.fetch(name), value)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ sig { returns(T::Hash[Symbol, T.untyped]) }
34
+ def defined_options
35
+ @defined_options = T.let(@defined_options, T.nilable(T::Hash[Symbol, T.untyped]))
36
+
37
+ @defined_options ||= Net::HTTP.instance_methods.grep(/\w=\z/).each_with_object({}) do |name, hash|
38
+ hash[name.to_s.chomp('=').to_sym] = name
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+ require 'json'
4
+
5
+ module Vonage
6
+ module JSON
7
+ extend T::Sig
8
+
9
+ sig { params(http_request: T.any(Net::HTTP::Put, Net::HTTP::Post), params: T::Hash[Symbol, T.untyped]).void }
10
+ def self.update(http_request, params)
11
+ http_request['Content-Type'] = 'application/json'
12
+ http_request.body = ::JSON.generate(params)
13
+ end
14
+ end
15
+
16
+ private_constant :JSON
17
+ end
@@ -0,0 +1,43 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+ require 'securerandom'
4
+ require 'openssl'
5
+ require 'nexmo-jwt'
6
+
7
+ module Vonage
8
+ class JWT
9
+ # Generate an encoded JSON Web Token.
10
+ #
11
+ # By default the Vonage Ruby SDK generates a short lived JWT per request.
12
+ #
13
+ # To generate a long lived JWT for multiple requests or to specify JWT claims
14
+ # directly call {Vonage::JWT.generate} to generate a token, and set the token
15
+ # attribute on the client object.
16
+ #
17
+ # Documentation for the Vonage Ruby JWT generator gem can be found at
18
+ # https://www.rubydoc.info/github/Nexmo/nexmo-jwt-ruby
19
+ #
20
+ # @example
21
+ # claims = {
22
+ # application_id: application_id,
23
+ # ttl: 800,
24
+ # subject: 'My_Subject'
25
+ # }
26
+ #
27
+ # private_key = File.read('path/to/private.key')
28
+ #
29
+ # client.config.token = Vonage::JWT.generate(claims, private_key)
30
+ #
31
+ # @param [Hash] payload
32
+ # @param [String, OpenSSL::PKey::RSA] private_key
33
+ #
34
+ # @return [String]
35
+ #
36
+ def self.generate(payload, private_key = nil)
37
+ raise "Expecting 'private_key' in either the payload or as a separate parameter" if !payload[:private_key] && !private_key
38
+
39
+ payload[:private_key] = private_key if private_key && !payload[:private_key]
40
+ @token = Nexmo::JWTBuilder.new(payload).jwt.generate
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ # typed: strict
2
+
3
+ module Vonage
4
+ class KeySecretParams < AbstractAuthentication
5
+ extend T::Sig
6
+
7
+ sig { params(
8
+ object: T.any(T::Hash[T.untyped, T.untyped], URI::HTTPS, Net::HTTP::Post, Net::HTTP::Get)
9
+ ).void }
10
+ def update(object)
11
+ return unless object.is_a?(Hash)
12
+
13
+ @config = T.let(@config, T.nilable(Vonage::Config))
14
+ object[:api_key] = T.must(@config).api_key
15
+ object[:api_secret] = T.must(@config).api_secret
16
+ end
17
+ end
18
+
19
+ private_constant :KeySecretParams
20
+ end
@@ -0,0 +1,51 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ module Keys
6
+ extend T::Sig
7
+
8
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T::Hash[String, T.untyped]) }
9
+ def hyphenate(hash)
10
+ hash.transform_keys { |k| k.to_s.tr('_', '-') }
11
+ end
12
+
13
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T::Hash[T.untyped, T.untyped]) }
14
+ def camelcase(hash)
15
+ exceptions = [
16
+ 'dr_call_back_url',
17
+ 'mo_http_url',
18
+ 'mo_smpp_sys_type',
19
+ 'mo_call_back_url',
20
+ 'voice_callback_type',
21
+ 'voice_callback_value',
22
+ 'voice_status_callback',
23
+ 'messages_callback_value',
24
+ 'messages_callback_type'
25
+ ]
26
+ hash.transform_keys do |k|
27
+ if exceptions.include?(k.to_s)
28
+ next k.to_s.gsub(/_(\w)/) { $1.upcase.to_s }
29
+ end
30
+ k
31
+ end
32
+ end
33
+
34
+ ATTRIBUTE_KEYS = T.let(Hash.new { |h, k| h[k] = k.split(PATTERN).join('_').downcase.to_sym }, T::Hash[T.untyped, T.untyped])
35
+
36
+ PATTERN = /[\-_]|(?<=\w)(?=[A-Z])/
37
+
38
+ private_constant :ATTRIBUTE_KEYS
39
+
40
+ private_constant :PATTERN
41
+
42
+ sig { params(k: T.any(Symbol, String)).returns(Symbol) }
43
+ def attribute_key(k)
44
+ return k if k.is_a?(Symbol)
45
+
46
+ ATTRIBUTE_KEYS[k]
47
+ end
48
+ end
49
+
50
+ private_constant :Keys
51
+ end
@@ -0,0 +1,60 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+ require 'logger'
4
+ require 'forwardable'
5
+
6
+ module Vonage
7
+ class Logger
8
+ extend T::Sig
9
+
10
+ sig { params(logger: T.nilable(T.any(::Logger, Vonage::Logger))).void }
11
+ def initialize(logger)
12
+ @logger = logger || ::Logger.new(nil)
13
+ end
14
+
15
+ extend Forwardable
16
+
17
+ ::Logger::Severity.constants.map(&:downcase).each do |name|
18
+ def_delegator :@logger, name, name
19
+ end
20
+
21
+ sig { params(request: T.any(Net::HTTP::Post, Net::HTTP::Get, Net::HTTP::Delete, Net::HTTP::Put)).void }
22
+ def log_request_info(request)
23
+ @logger = T.let(@logger, T.nilable(T.any(::Logger, Vonage::Logger)))
24
+
25
+ T.must(@logger).info do
26
+ format('Vonage API request', {
27
+ method: request.method,
28
+ path: request.uri.path
29
+ })
30
+ end
31
+ end
32
+
33
+ sig { params(
34
+ response: T.any(Net::HTTPOK, Net::HTTPNoContent, Net::HTTPBadRequest, Net::HTTPInternalServerError, Net::HTTPResponse),
35
+ host: String
36
+ ).void }
37
+ def log_response_info(response, host)
38
+ T.must(@logger).info do
39
+ format('Vonage API response', {
40
+ host: host,
41
+ status: response.code,
42
+ type: response.content_type,
43
+ length: response.content_length,
44
+ trace_id: response['x-Vonage-trace-id']
45
+ })
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ sig { params(message: String, hash: T::Hash[Symbol, T.untyped]).returns(String) }
52
+ def format(message, hash)
53
+ return message if hash.nil?
54
+
55
+ fields = hash.map { |key, value| "#{key}=#{value}" if value }.compact
56
+ fields.unshift(message)
57
+ fields.join(' ')
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,25 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Messages < Namespace
6
+ extend T::Sig
7
+
8
+ self.host = :rest_host
9
+
10
+ sig { params(id: String).returns(Vonage::Response) }
11
+ def get(id)
12
+ request('/search/message', params: {id: id})
13
+ end
14
+
15
+ sig { params(params: T::Hash[Symbol, T.untyped]).returns(Vonage::Response) }
16
+ def search(params)
17
+ request('/search/messages', params: params)
18
+ end
19
+
20
+ sig { params(params: T::Hash[Symbol, T.untyped]).returns(Vonage::Response) }
21
+ def rejections(params)
22
+ request('/search/rejections', params: params)
23
+ end
24
+ end
25
+ end