nexmo 4.8.0 → 5.0.0.pre1

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.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class Conversions < Namespace
5
+ include Keys
6
+
7
+ def track_sms(params)
8
+ request('/conversions/sms', params: hyphenate(params), type: Post)
9
+ end
10
+
11
+ def track_voice(params)
12
+ request('/conversions/voice', params: hyphenate(params), type: Post)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ module Nexmo
2
+ class Entity
3
+ def initialize(**kwargs)
4
+ @attributes = kwargs
5
+ end
6
+
7
+ def []=(key, value)
8
+ name = self.class.attribute_names[key]
9
+
10
+ @attributes[name] = value
11
+ end
12
+
13
+ def respond_to_missing?(name, include_private = false)
14
+ @attributes.key?(name) or super
15
+ end
16
+
17
+ def method_missing(name, *args)
18
+ return super unless @attributes.key?(name)
19
+
20
+ @attributes[name]
21
+ end
22
+
23
+ def ==(entity)
24
+ entity.class == self.class && entity.attributes == @attributes
25
+ end
26
+
27
+ def to_h
28
+ @attributes
29
+ end
30
+
31
+ attr_reader :attributes
32
+
33
+ protected :attributes
34
+
35
+ private
36
+
37
+ def self.attribute_names
38
+ @attribute_names ||= Hash.new do |hash, key|
39
+ hash[key] = attribute_name(key)
40
+ end
41
+ end
42
+
43
+ def self.attribute_name(key)
44
+ return key if key.is_a?(Symbol)
45
+
46
+ key.split(PATTERN).join(UNDERSCORE).downcase.to_sym
47
+ end
48
+
49
+ PATTERN = /[\-_]|(?<=\w)(?=[A-Z])/
50
+
51
+ UNDERSCORE = '_'
52
+ end
53
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class Files < Namespace
5
+ def get(id)
6
+ request('/v1/files/' + id.split('/').last)
7
+ end
8
+
9
+ def save(id, filename)
10
+ request('/v1/files/' + id.split('/').last) do |response|
11
+ File.open(filename, 'wb') do |file|
12
+ response.read_body do |chunk|
13
+ file.write(chunk)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def authorization_header?
22
+ true
23
+ end
24
+ end
25
+ end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require 'securerandom'
2
3
  require 'openssl'
3
4
  require 'jwt'
4
5
 
5
6
  module Nexmo
6
7
  module JWT
7
- def self.auth_token(payload, private_key)
8
+ def self.generate(payload, private_key)
8
9
  payload[:iat] = iat = Time.now.to_i unless payload.key?(:iat) || payload.key?('iat')
9
10
  payload[:exp] = iat + 60 unless payload.key?(:exp) || payload.key?('exp')
10
11
  payload[:jti] = SecureRandom.uuid unless payload.key?(:jti) || payload.key?('jti')
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ module Keys
5
+ if {}.respond_to?(:transform_keys)
6
+ def hyphenate(hash)
7
+ hash.transform_keys { |k| hyphenate_key(k) }
8
+ end
9
+
10
+ def camelcase(hash)
11
+ hash.transform_keys { |k| camelcase_key(k) }
12
+ end
13
+ else
14
+ def hyphenate(hash)
15
+ hash.each_with_object({}) { |(k, v), h| h[hyphenate_key(k)] = v }
16
+ end
17
+
18
+ def camelcase(hash)
19
+ hash.each_with_object({}) { |(k, v), h| h[camelcase_key(k)] = v }
20
+ end
21
+ end
22
+
23
+ def hyphenate_key(k)
24
+ k.to_s.tr('_', '-')
25
+ end
26
+
27
+ def camelcase_key(k)
28
+ k.to_s.gsub(/_(\w)/) { $1.upcase }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class Messages < Namespace
5
+ def get(id)
6
+ request('/search/message', params: {id: id})
7
+ end
8
+
9
+ def search(params)
10
+ request('/search/messages', params: params)
11
+ end
12
+
13
+ def rejections(params)
14
+ request('/search/rejections', params: params)
15
+ end
16
+
17
+ private
18
+
19
+ def host
20
+ 'rest.nexmo.com'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,83 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module Nexmo
5
+ class Namespace
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ private
11
+
12
+ Get = Net::HTTP::Get
13
+ Put = Net::HTTP::Put
14
+ Post = Net::HTTP::Post
15
+ Delete = Net::HTTP::Delete
16
+
17
+ def host
18
+ 'api.nexmo.com'
19
+ end
20
+
21
+ def authorization_header?
22
+ false
23
+ end
24
+
25
+ def request(path, params: nil, type: Get, &block)
26
+ uri = URI('https://' + host + path)
27
+
28
+ unless authorization_header?
29
+ params ||= {}
30
+ params[:api_key] = @client.api_key
31
+ params[:api_secret] = @client.api_secret
32
+ end
33
+
34
+ unless type::REQUEST_HAS_BODY || params.nil? || params.empty?
35
+ uri.query = Params.encode(params)
36
+ end
37
+
38
+ message = type.new(uri.request_uri)
39
+
40
+ if type::REQUEST_HAS_BODY
41
+ message['Content-Type'] = 'application/json'
42
+ message.body = JSON.generate(params)
43
+ end
44
+
45
+ message['Authorization'] = @client.authorization if authorization_header?
46
+ message['User-Agent'] = @client.user_agent
47
+
48
+ http = Net::HTTP.new(uri.host, Net::HTTP.https_default_port)
49
+ http.use_ssl = true
50
+
51
+ response = http.request(message)
52
+
53
+ parse(response, &block)
54
+ end
55
+
56
+ def parse(response, &block)
57
+ case response
58
+ when Net::HTTPNoContent
59
+ :no_content
60
+ when Net::HTTPSuccess
61
+ parse_success(response, &block)
62
+ when Net::HTTPUnauthorized
63
+ raise AuthenticationError, "#{response.code} response from #{host}"
64
+ when Net::HTTPClientError
65
+ raise ClientError, "#{response.code} response from #{host}"
66
+ when Net::HTTPServerError
67
+ raise ServerError, "#{response.code} response from #{host}"
68
+ else
69
+ raise Error, "#{response.code} response from #{host}"
70
+ end
71
+ end
72
+
73
+ def parse_success(response)
74
+ if response['Content-Type'].split(';').first == 'application/json'
75
+ JSON.parse(response.body, object_class: Nexmo::Entity)
76
+ elsif block_given?
77
+ yield response
78
+ else
79
+ response.body
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class NumberInsight < Namespace
5
+ def basic(params)
6
+ request('/ni/basic/json', params: params)
7
+ end
8
+
9
+ def standard(params)
10
+ request('/ni/standard/json', params: params)
11
+ end
12
+
13
+ def advanced(params)
14
+ request('/ni/advanced/json', params: params)
15
+ end
16
+
17
+ def advanced_async(params)
18
+ request('/ni/advanced/async/json', params: params)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class Numbers < Namespace
5
+ include Keys
6
+
7
+ def list(params)
8
+ request('/account/numbers', params: params)
9
+ end
10
+
11
+ def search(params)
12
+ request('/number/search', params: params)
13
+ end
14
+
15
+ def buy(params)
16
+ request('/number/buy', params: params, type: Post)
17
+ end
18
+
19
+ def cancel(params)
20
+ request('/number/cancel', params: params, type: Post)
21
+ end
22
+
23
+ def update(params)
24
+ request('/number/update', params: camelcase(params), type: Post)
25
+ end
26
+
27
+ private
28
+
29
+ def host
30
+ 'rest.nexmo.com'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class Pricing < Namespace
5
+ def initialize(client, type: nil)
6
+ raise ArgumentError if type.nil?
7
+
8
+ @client, @type = client, type
9
+ end
10
+
11
+ attr_reader :type
12
+
13
+ def get(country)
14
+ request('/get-pricing/outbound/' + @type, params: {country: country})
15
+ end
16
+
17
+ def list
18
+ request('/get-full-pricing/outbound/' + @type)
19
+ end
20
+
21
+ def prefix(prefix)
22
+ request('/get-prefix-pricing/outbound/' + @type, params: {prefix: prefix})
23
+ end
24
+
25
+ private
26
+
27
+ def host
28
+ 'rest.nexmo.com'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class PricingTypes
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ def sms
10
+ @sms ||= Pricing.new(@client, type: 'sms')
11
+ end
12
+
13
+ def voice
14
+ @voice ||= Pricing.new(@client, type: 'voice')
15
+ end
16
+ end
17
+ end
@@ -2,7 +2,7 @@ require 'digest/md5'
2
2
  require 'jwt'
3
3
 
4
4
  module Nexmo
5
- module Signature
5
+ class Signature
6
6
  def self.check(params, secret)
7
7
  params = params.dup
8
8
 
@@ -11,6 +11,14 @@ module Nexmo
11
11
  secure_compare(signature, digest(params, secret))
12
12
  end
13
13
 
14
+ def initialize(client)
15
+ @client = client
16
+ end
17
+
18
+ def check(params)
19
+ self.class.check(params, @client.signature_secret)
20
+ end
21
+
14
22
  private
15
23
 
16
24
  if defined?(::JWT::SecurityUtils) # ruby-jwt v2
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class SMS < Namespace
5
+ include Keys
6
+
7
+ def send(params)
8
+ request('/sms/json', params: hyphenate(params), type: Post)
9
+ end
10
+
11
+ private
12
+
13
+ def host
14
+ 'rest.nexmo.com'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ module UserAgent
5
+ def self.string(app_name, app_version)
6
+ identifiers = []
7
+ identifiers << 'nexmo-ruby/' + VERSION
8
+ identifiers << 'ruby/' + RUBY_VERSION
9
+ identifiers << app_name + '/' + app_version if app_name && app_version
10
+ identifiers.join(' ')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nexmo
4
+ class Verify < Namespace
5
+ alias_method :http_request, :request
6
+
7
+ def request(params)
8
+ http_request('/verify/json', params: params, type: Post)
9
+ end
10
+
11
+ def check(params)
12
+ http_request('/verify/check/json', params: params, type: Post)
13
+ end
14
+
15
+ def search(params)
16
+ http_request('/verify/search/json', params: params)
17
+ end
18
+
19
+ def control(params)
20
+ http_request('/verify/control/json', params: params, type: Post)
21
+ end
22
+
23
+ def cancel(id)
24
+ control(request_id: id, cmd: 'cancel')
25
+ end
26
+
27
+ def trigger_next_event(id)
28
+ control(request_id: id, cmd: 'trigger_next_event')
29
+ end
30
+ end
31
+ end