nexmo 6.2.0 → 7.1.2
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 +4 -4
- data/README.md +21 -3
- data/lib/nexmo.rb +2 -0
- data/lib/nexmo/abstract_authentication.rb +2 -2
- data/lib/nexmo/account.rb +6 -1
- data/lib/nexmo/alerts.rb +6 -1
- data/lib/nexmo/applications.rb +24 -3
- data/lib/nexmo/applications/list_response.rb +2 -0
- data/lib/nexmo/authentication_error.rb +2 -0
- data/lib/nexmo/basic.rb +2 -0
- data/lib/nexmo/bearer_token.rb +1 -0
- data/lib/nexmo/client.rb +46 -23
- data/lib/nexmo/client_error.rb +2 -0
- data/lib/nexmo/config.rb +49 -9
- data/lib/nexmo/conversations.rb +24 -0
- data/lib/nexmo/conversations/events.rb +1 -0
- data/lib/nexmo/conversations/legs.rb +1 -0
- data/lib/nexmo/conversations/members.rb +1 -0
- data/lib/nexmo/conversations/users.rb +1 -0
- data/lib/nexmo/conversions.rb +4 -0
- data/lib/nexmo/entity.rb +3 -1
- data/lib/nexmo/error.rb +2 -0
- data/lib/nexmo/errors.rb +8 -0
- data/lib/nexmo/files.rb +7 -2
- data/lib/nexmo/form_data.rb +2 -0
- data/lib/nexmo/gsm7.rb +2 -2
- data/lib/nexmo/http.rb +12 -3
- data/lib/nexmo/json.rb +4 -0
- data/lib/nexmo/jwt.rb +5 -1
- data/lib/nexmo/key_secret_params.rb +10 -2
- data/lib/nexmo/keys.rb +7 -1
- data/lib/nexmo/logger.rb +14 -4
- data/lib/nexmo/messages.rb +7 -1
- data/lib/nexmo/namespace.rb +15 -18
- data/lib/nexmo/number_insight.rb +21 -6
- data/lib/nexmo/numbers.rb +2 -1
- data/lib/nexmo/numbers/list_response.rb +2 -0
- data/lib/nexmo/numbers/response.rb +1 -0
- data/lib/nexmo/params.rb +1 -0
- data/lib/nexmo/pricing.rb +2 -1
- data/lib/nexmo/pricing_types.rb +1 -0
- data/lib/nexmo/redact.rb +1 -0
- data/lib/nexmo/response.rb +2 -0
- data/lib/nexmo/secrets.rb +1 -0
- data/lib/nexmo/secrets/list_response.rb +2 -0
- data/lib/nexmo/server_error.rb +2 -0
- data/lib/nexmo/signature.rb +1 -0
- data/lib/nexmo/sms.rb +16 -10
- data/lib/nexmo/tfa.rb +2 -1
- data/lib/nexmo/user_agent.rb +1 -0
- data/lib/nexmo/verify.rb +93 -17
- data/lib/nexmo/version.rb +3 -1
- data/lib/nexmo/{calls.rb → voice.rb} +12 -11
- data/lib/nexmo/{calls → voice}/dtmf.rb +2 -1
- data/lib/nexmo/{calls → voice}/list_response.rb +3 -1
- data/lib/nexmo/{calls → voice}/stream.rb +2 -1
- data/lib/nexmo/{calls → voice}/talk.rb +2 -1
- data/nexmo.gemspec +1 -0
- metadata +22 -11
- data/lib/nexmo/number_insight/response.rb +0 -5
- data/lib/nexmo/sms/response.rb +0 -7
- data/lib/nexmo/verify/response.rb +0 -5
data/lib/nexmo/conversations.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
5
|
class Conversations < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
5
8
|
self.authentication = BearerToken
|
6
9
|
|
7
10
|
self.request_body = JSON
|
@@ -32,6 +35,7 @@ module Nexmo
|
|
32
35
|
#
|
33
36
|
# @see https://developer.nexmo.com/api/conversation#createConversation
|
34
37
|
#
|
38
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Nexmo::Response) }
|
35
39
|
def create(params)
|
36
40
|
request('/beta/conversations', params: params, type: Post)
|
37
41
|
end
|
@@ -62,6 +66,7 @@ module Nexmo
|
|
62
66
|
#
|
63
67
|
# @see https://developer.nexmo.com/api/conversation#replaceConversation
|
64
68
|
#
|
69
|
+
sig { params(params: T.nilable(T::Hash[Symbol, T.untyped])).returns(Nexmo::Response) }
|
65
70
|
def list(params = nil)
|
66
71
|
request('/beta/conversations', params: params)
|
67
72
|
end
|
@@ -77,6 +82,7 @@ module Nexmo
|
|
77
82
|
#
|
78
83
|
# @see https://developer.nexmo.com/api/conversation#retrieveConversation
|
79
84
|
#
|
85
|
+
sig { params(id: String).returns(Nexmo::Response) }
|
80
86
|
def get(id)
|
81
87
|
request('/beta/conversations/' + id)
|
82
88
|
end
|
@@ -109,6 +115,10 @@ module Nexmo
|
|
109
115
|
#
|
110
116
|
# @see https://developer.nexmo.com/api/conversation#replaceConversation
|
111
117
|
#
|
118
|
+
sig { params(
|
119
|
+
id: String,
|
120
|
+
params: T::Hash[Symbol, T.untyped]
|
121
|
+
).returns(Nexmo::Response) }
|
112
122
|
def update(id, params)
|
113
123
|
request('/beta/conversations/' + id, params: params, type: Put)
|
114
124
|
end
|
@@ -124,6 +134,7 @@ module Nexmo
|
|
124
134
|
#
|
125
135
|
# @see https://developer.nexmo.com/api/conversation#deleteConversation
|
126
136
|
#
|
137
|
+
sig { params(id: String).returns(Nexmo::Response) }
|
127
138
|
def delete(id)
|
128
139
|
request('/beta/conversations/' + id, type: Delete)
|
129
140
|
end
|
@@ -155,31 +166,44 @@ module Nexmo
|
|
155
166
|
#
|
156
167
|
# @see https://developer.nexmo.com/api/conversation#recordConversation
|
157
168
|
#
|
169
|
+
sig { params(
|
170
|
+
id: String,
|
171
|
+
params: T::Hash[Symbol, T.untyped]
|
172
|
+
).returns(Nexmo::Response) }
|
158
173
|
def record(id, params)
|
159
174
|
request('/v1/conversations/' + id + '/record', params: params, type: Put)
|
160
175
|
end
|
161
176
|
|
162
177
|
# @return [Events]
|
163
178
|
#
|
179
|
+
sig { returns(T.nilable(Nexmo::Conversations::Events)) }
|
164
180
|
def events
|
181
|
+
@events = T.let(@events, T.nilable(Nexmo::Conversations::Events))
|
182
|
+
@config = T.let(@config, T.nilable(Nexmo::Config))
|
165
183
|
@events ||= Events.new(@config)
|
166
184
|
end
|
167
185
|
|
168
186
|
# @return [Legs]
|
169
187
|
#
|
188
|
+
sig { returns(T.nilable(Nexmo::Conversations::Legs)) }
|
170
189
|
def legs
|
190
|
+
@legs = T.let(@legs, T.nilable(Nexmo::Conversations::Legs))
|
171
191
|
@legs ||= Legs.new(@config)
|
172
192
|
end
|
173
193
|
|
174
194
|
# @return [Members]
|
175
195
|
#
|
196
|
+
sig { returns(T.nilable(Nexmo::Conversations::Members)) }
|
176
197
|
def members
|
198
|
+
@members = T.let(@members, T.nilable(Nexmo::Conversations::Members))
|
177
199
|
@members ||= Members.new(@config)
|
178
200
|
end
|
179
201
|
|
180
202
|
# @return [Users]
|
181
203
|
#
|
204
|
+
sig { returns(T.nilable(Nexmo::Conversations::Users)) }
|
182
205
|
def users
|
206
|
+
@users = T.let(@users, T.nilable(Nexmo::Conversations::Users))
|
183
207
|
@users ||= Users.new(@config)
|
184
208
|
end
|
185
209
|
end
|
data/lib/nexmo/conversions.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
5
|
class Conversions < Namespace
|
6
|
+
extend T::Sig
|
5
7
|
include Keys
|
6
8
|
|
9
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Nexmo::Response) }
|
7
10
|
def track_sms(params)
|
8
11
|
request('/conversions/sms', params: hyphenate(params), type: Post)
|
9
12
|
end
|
10
13
|
|
14
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Nexmo::Response) }
|
11
15
|
def track_voice(params)
|
12
16
|
request('/conversions/voice', params: hyphenate(params), type: Post)
|
13
17
|
end
|
data/lib/nexmo/entity.rb
CHANGED
data/lib/nexmo/error.rb
CHANGED
data/lib/nexmo/errors.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
require 'json'
|
3
4
|
|
4
5
|
module Nexmo
|
5
6
|
module Errors
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig {params(response: T.any(Net::HTTPUnauthorized, Net::HTTPClientError, Net::HTTPServerError, T.untyped)).returns(Nexmo::Error)}
|
6
10
|
def self.parse(response)
|
7
11
|
exception_class = case response
|
8
12
|
when Net::HTTPUnauthorized
|
@@ -20,6 +24,8 @@ module Nexmo
|
|
20
24
|
|
21
25
|
if hash.key?('error_title')
|
22
26
|
hash['error_title']
|
27
|
+
elsif hash.key?('error-code-label')
|
28
|
+
hash['error-code-label']
|
23
29
|
elsif hash.key?('description')
|
24
30
|
hash['description']
|
25
31
|
elsif problem_details?(hash)
|
@@ -30,10 +36,12 @@ module Nexmo
|
|
30
36
|
exception_class.new(message)
|
31
37
|
end
|
32
38
|
|
39
|
+
sig { params(hash: T::Hash[String, T.untyped]).returns(T::Boolean) }
|
33
40
|
def self.problem_details?(hash)
|
34
41
|
hash.key?('title') && hash.key?('detail') && hash.key?('type')
|
35
42
|
end
|
36
43
|
|
44
|
+
sig { params(hash: T::Hash[String, T.untyped]).returns(String) }
|
37
45
|
def self.problem_details_message(hash)
|
38
46
|
"#{hash['title']}. #{hash['detail']} See #{hash['type']} for more info, or email support@nexmo.com if you have any questions."
|
39
47
|
end
|
data/lib/nexmo/files.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
5
|
class Files < Namespace
|
6
|
+
extend T::Sig
|
7
|
+
|
5
8
|
self.authentication = BearerToken
|
6
9
|
|
10
|
+
sig { params(id: String).returns(T.nilable(Nexmo::Response)) }
|
7
11
|
def get(id)
|
8
|
-
request('/v1/files/' + id.split('/').last)
|
12
|
+
request('/v1/files/' + T.must(id.split('/').last))
|
9
13
|
end
|
10
14
|
|
15
|
+
sig { params(id: String, filename: String).returns(T.nilable(Nexmo::Response)) }
|
11
16
|
def save(id, filename)
|
12
|
-
request('/v1/files/' + id.split('/').last) do |response|
|
17
|
+
request('/v1/files/' + T.must(id.split('/').last)) do |response|
|
13
18
|
File.open(filename, 'wb') do |file|
|
14
19
|
response.read_body do |chunk|
|
15
20
|
file.write(chunk)
|
data/lib/nexmo/form_data.rb
CHANGED
data/lib/nexmo/gsm7.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# typed: ignore
|
2
|
+
|
1
3
|
module Nexmo
|
2
4
|
module GSM7
|
3
5
|
CHARACTERS = "\n\f\r !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~ ¡£¤¥§¿ÄÅÆÉÑÖØÜßàäåæçèéìñòöøùüΓΔΘΛΞΠΣΦΨΩ€"
|
@@ -8,6 +10,4 @@ module Nexmo
|
|
8
10
|
REGEXP =~ string
|
9
11
|
end
|
10
12
|
end
|
11
|
-
|
12
|
-
private_constant :GSM7
|
13
13
|
end
|
data/lib/nexmo/http.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
require 'net/http'
|
3
4
|
|
4
5
|
module Nexmo
|
5
6
|
module HTTP
|
6
7
|
class Options
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { params(hash: T::Hash[Symbol, T.untyped]).void }
|
7
11
|
def initialize(hash)
|
8
|
-
|
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
|
9
16
|
|
10
17
|
@hash.each_key do |name|
|
11
18
|
next if defined_options.key?(name)
|
@@ -14,6 +21,7 @@ module Nexmo
|
|
14
21
|
end
|
15
22
|
end
|
16
23
|
|
24
|
+
sig { params(http: Net::HTTP).returns(T::Hash[Symbol, T.untyped]) }
|
17
25
|
def set(http)
|
18
26
|
@hash.each do |name, value|
|
19
27
|
http.public_send(defined_options.fetch(name), value)
|
@@ -22,13 +30,14 @@ module Nexmo
|
|
22
30
|
|
23
31
|
private
|
24
32
|
|
33
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
25
34
|
def defined_options
|
35
|
+
@defined_options = T.let(@defined_options, T.nilable(T::Hash[Symbol, T.untyped]))
|
36
|
+
|
26
37
|
@defined_options ||= Net::HTTP.instance_methods.grep(/\w=\z/).each_with_object({}) do |name, hash|
|
27
38
|
hash[name.to_s.chomp('=').to_sym] = name
|
28
39
|
end
|
29
40
|
end
|
30
41
|
end
|
31
42
|
end
|
32
|
-
|
33
|
-
private_constant :HTTP
|
34
43
|
end
|
data/lib/nexmo/json.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
require 'json'
|
3
4
|
|
4
5
|
module Nexmo
|
5
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 }
|
6
10
|
def self.update(http_request, params)
|
7
11
|
http_request['Content-Type'] = 'application/json'
|
8
12
|
http_request.body = ::JSON.generate(params)
|
data/lib/nexmo/jwt.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
require 'securerandom'
|
3
4
|
require 'openssl'
|
@@ -5,6 +6,8 @@ require 'jwt'
|
|
5
6
|
|
6
7
|
module Nexmo
|
7
8
|
module JWT
|
9
|
+
extend T::Sig
|
10
|
+
|
8
11
|
# Generate an encoded JSON Web Token.
|
9
12
|
#
|
10
13
|
# By default the Nexmo Ruby SDK generates a short lived JWT per request.
|
@@ -30,9 +33,10 @@ module Nexmo
|
|
30
33
|
#
|
31
34
|
# @return [String]
|
32
35
|
#
|
36
|
+
sig { params(payload: T::Hash[T.any(Symbol, String), T.any(String, Integer)], private_key: T.any(OpenSSL::PKey::RSA, String)).returns(String) }
|
33
37
|
def self.generate(payload, private_key)
|
34
38
|
payload[:iat] = iat = Time.now.to_i unless payload.key?(:iat) || payload.key?('iat')
|
35
|
-
payload[:exp] = iat + 60 unless payload.key?(:exp) || payload.key?('exp')
|
39
|
+
payload[:exp] = T.must(iat) + 60 unless payload.key?(:exp) || payload.key?('exp')
|
36
40
|
payload[:jti] = SecureRandom.uuid unless payload.key?(:jti) || payload.key?('jti')
|
37
41
|
|
38
42
|
private_key = OpenSSL::PKey::RSA.new(private_key) unless private_key.respond_to?(:sign)
|
@@ -1,10 +1,18 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
1
3
|
module Nexmo
|
2
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 }
|
3
10
|
def update(object)
|
4
11
|
return unless object.is_a?(Hash)
|
5
12
|
|
6
|
-
|
7
|
-
object[:
|
13
|
+
@config = T.let(@config, T.nilable(Nexmo::Config))
|
14
|
+
object[:api_key] = T.must(@config).api_key
|
15
|
+
object[:api_secret] = T.must(@config).api_secret
|
8
16
|
end
|
9
17
|
end
|
10
18
|
|
data/lib/nexmo/keys.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
5
|
module Keys
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T::Hash[String, T.untyped]) }
|
5
9
|
def hyphenate(hash)
|
6
10
|
hash.transform_keys { |k| k.to_s.tr('_', '-') }
|
7
11
|
end
|
8
12
|
|
13
|
+
sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T::Hash[String, T.untyped]) }
|
9
14
|
def camelcase(hash)
|
10
15
|
hash.transform_keys { |k| k.to_s.gsub(/_(\w)/) { $1.upcase } }
|
11
16
|
end
|
12
17
|
|
13
|
-
ATTRIBUTE_KEYS = Hash.new { |h, k| h[k] = k.split(PATTERN).join('_').downcase.to_sym }
|
18
|
+
ATTRIBUTE_KEYS = T.let(Hash.new { |h, k| h[k] = k.split(PATTERN).join('_').downcase.to_sym }, T::Hash[T.untyped, T.untyped])
|
14
19
|
|
15
20
|
PATTERN = /[\-_]|(?<=\w)(?=[A-Z])/
|
16
21
|
|
@@ -18,6 +23,7 @@ module Nexmo
|
|
18
23
|
|
19
24
|
private_constant :PATTERN
|
20
25
|
|
26
|
+
sig { params(k: T.any(Symbol, String)).returns(Symbol) }
|
21
27
|
def attribute_key(k)
|
22
28
|
return k if k.is_a?(Symbol)
|
23
29
|
|
data/lib/nexmo/logger.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# typed: false
|
1
2
|
# frozen_string_literal: true
|
2
3
|
require 'logger'
|
3
4
|
require 'forwardable'
|
4
5
|
|
5
6
|
module Nexmo
|
6
7
|
class Logger
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { params(logger: T.nilable(T.any(::Logger, Nexmo::Logger))).void }
|
7
11
|
def initialize(logger)
|
8
12
|
@logger = logger || ::Logger.new(nil)
|
9
13
|
end
|
@@ -14,8 +18,11 @@ module Nexmo
|
|
14
18
|
def_delegator :@logger, name, name
|
15
19
|
end
|
16
20
|
|
21
|
+
sig { params(request: T.any(Net::HTTP::Post, Net::HTTP::Get, Net::HTTP::Delete, Net::HTTP::Put)).void }
|
17
22
|
def log_request_info(request)
|
18
|
-
|
23
|
+
@logger = T.let(@logger, T.nilable(T.any(::Logger, Nexmo::Logger)))
|
24
|
+
|
25
|
+
T.must(@logger).info do
|
19
26
|
format('Nexmo API request', {
|
20
27
|
method: request.method,
|
21
28
|
path: request.uri.path
|
@@ -23,8 +30,12 @@ module Nexmo
|
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
33
|
+
sig { params(
|
34
|
+
response: T.any(Net::HTTPOK, Net::HTTPNoContent, Net::HTTPBadRequest, Net::HTTPInternalServerError, Net::HTTPResponse),
|
35
|
+
host: String
|
36
|
+
).void }
|
26
37
|
def log_response_info(response, host)
|
27
|
-
info do
|
38
|
+
T.must(@logger).info do
|
28
39
|
format('Nexmo API response', {
|
29
40
|
host: host,
|
30
41
|
status: response.code,
|
@@ -37,6 +48,7 @@ module Nexmo
|
|
37
48
|
|
38
49
|
private
|
39
50
|
|
51
|
+
sig { params(message: String, hash: T::Hash[Symbol, T.untyped]).returns(String) }
|
40
52
|
def format(message, hash)
|
41
53
|
return message if hash.nil?
|
42
54
|
|
@@ -45,6 +57,4 @@ module Nexmo
|
|
45
57
|
fields.join(' ')
|
46
58
|
end
|
47
59
|
end
|
48
|
-
|
49
|
-
private_constant :Logger
|
50
60
|
end
|
data/lib/nexmo/messages.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
5
|
class Messages < Namespace
|
5
|
-
|
6
|
+
extend T::Sig
|
6
7
|
|
8
|
+
self.host = :rest_host
|
9
|
+
|
10
|
+
sig { params(id: String).returns(Nexmo::Response) }
|
7
11
|
def get(id)
|
8
12
|
request('/search/message', params: {id: id})
|
9
13
|
end
|
10
14
|
|
15
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Nexmo::Response) }
|
11
16
|
def search(params)
|
12
17
|
request('/search/messages', params: params)
|
13
18
|
end
|
14
19
|
|
20
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Nexmo::Response) }
|
15
21
|
def rejections(params)
|
16
22
|
request('/search/rejections', params: params)
|
17
23
|
end
|