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,11 @@
1
+ # typed: ignore
2
+
3
+ class Vonage::Numbers::ListResponse < Vonage::Response
4
+ include Enumerable
5
+
6
+ def each
7
+ return enum_for(:each) unless block_given?
8
+
9
+ @entity.numbers.each { |item| yield item }
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ class Vonage::Numbers::Response < Vonage::Response
5
+ def success?
6
+ error_code == '200'
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ # typed: ignore
2
+ # frozen_string_literal: true
3
+ require 'cgi'
4
+
5
+ module Vonage
6
+ module Params
7
+ def self.encode(params)
8
+ params.flat_map { |k, vs| Array(vs).map { |v| "#{escape(k)}=#{escape(v)}" } }.join('&')
9
+ end
10
+
11
+ def self.join(string, params)
12
+ encoded = encode(params)
13
+
14
+ return encoded if string.nil?
15
+
16
+ string + '&' + encoded
17
+ end
18
+
19
+ def self.escape(component)
20
+ CGI.escape(component.to_s)
21
+ end
22
+
23
+ private_class_method :escape
24
+ end
25
+
26
+ private_constant :Params
27
+ end
@@ -0,0 +1,30 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Pricing < Namespace
6
+ self.host = :rest_host
7
+
8
+ def initialize(config, type: nil)
9
+ raise ArgumentError if type.nil?
10
+
11
+ @type = type
12
+
13
+ super config
14
+ end
15
+
16
+ attr_reader :type
17
+
18
+ def get(country)
19
+ request('/account/get-pricing/outbound/' + @type, params: {country: country})
20
+ end
21
+
22
+ def list
23
+ request('/account/get-full-pricing/outbound/' + @type)
24
+ end
25
+
26
+ def prefix(prefix)
27
+ request('/account/get-prefix-pricing/outbound/' + @type, params: {prefix: prefix})
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class PricingTypes
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def sms
11
+ @sms ||= Pricing.new(@config, type: 'sms')
12
+ end
13
+
14
+ def voice
15
+ @voice ||= Pricing.new(@config, type: 'voice')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Redact < Namespace
6
+ extend T::Sig
7
+
8
+ self.authentication = Basic
9
+
10
+ self.request_body = JSON
11
+
12
+ # Redact a specific message.
13
+ #
14
+ # @example
15
+ # response = client.redact.transaction(id: '00A0B0C0', product: 'sms')
16
+ #
17
+ # @option params [required, String] :id
18
+ # The transaction ID to redact.
19
+ #
20
+ # @option params [required, String] :product
21
+ # Product name that the ID provided relates to.
22
+ #
23
+ # @option params [required, String] :type
24
+ # Required if redacting SMS data.
25
+ #
26
+ # @param [Hash] params
27
+ #
28
+ # @return [Response]
29
+ #
30
+ # @see https://developer.nexmo.com/api/redact#redact-message
31
+ #
32
+ sig { params(params: T::Hash[Symbol, T.untyped]).returns(Vonage::Response) }
33
+ def transaction(params)
34
+ request('/v1/redact/transaction', params: params, type: Post)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ # typed: true
2
+
3
+ module Vonage
4
+ class Response
5
+ def initialize(entity=nil, http_response=nil)
6
+ @entity = entity
7
+
8
+ @http_response = http_response
9
+ end
10
+
11
+ attr_reader :http_response
12
+
13
+ def respond_to_missing?(name, include_private = false)
14
+ return super if @entity.nil?
15
+
16
+ @entity.respond_to?(name)
17
+ end
18
+
19
+ def method_missing(name, *args)
20
+ return super if @entity.nil?
21
+
22
+ @entity.public_send(name, *args)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,85 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Secrets < Namespace
6
+ self.authentication = Basic
7
+
8
+ self.request_body = JSON
9
+
10
+ # Create API Secret.
11
+ #
12
+ # @example
13
+ # response = client.secrets.create(secret: 'T0ps3cr3t')
14
+ #
15
+ # @option params [required, String] :secret
16
+ # The new secret must follow these rules:
17
+ # - minimum 8 characters
18
+ # - maximum 25 characters
19
+ # - minimum 1 lower case character
20
+ # - minimum 1 upper case character
21
+ # - minimum 1 digit
22
+ #
23
+ # @param [Hash] params
24
+ #
25
+ # @return [Response]
26
+ #
27
+ # @see https://developer.nexmo.com/api/account#createAPISecret
28
+ #
29
+ def create(params)
30
+ request('/accounts/' + account_id + '/secrets', params: params, type: Post)
31
+ end
32
+
33
+ # Retrieve API Secrets.
34
+ #
35
+ # @example
36
+ # response = client.secrets.list
37
+ # response.each do |item|
38
+ # puts "#{item.created_at} #{item.id}"
39
+ # end
40
+ #
41
+ # @return [ListResponse]
42
+ #
43
+ # @see https://developer.nexmo.com/api/account#retrieveAPISecrets
44
+ #
45
+ def list
46
+ request('/accounts/' + account_id + '/secrets', response_class: ListResponse)
47
+ end
48
+
49
+ # Retrieve one API Secret.
50
+ #
51
+ # @example
52
+ # response = client.secrets.get(secret_id)
53
+ #
54
+ # @param [String] secret_id
55
+ #
56
+ # @return [Response]
57
+ #
58
+ # @see https://developer.nexmo.com/api/account#retrieveAPISecret
59
+ #
60
+ def get(secret_id)
61
+ request('/accounts/' + account_id + '/secrets/' + secret_id)
62
+ end
63
+
64
+ # Revoke an API Secret.
65
+ #
66
+ # @example
67
+ # response = client.secrets.revoke(secret_id)
68
+ #
69
+ # @param [String] secret_id
70
+ #
71
+ # @return [Response]
72
+ #
73
+ # @see https://developer.nexmo.com/api/account#revokeAPISecret
74
+ #
75
+ def revoke(secret_id)
76
+ request('/accounts/' + account_id + '/secrets/' + secret_id, type: Delete)
77
+ end
78
+
79
+ private
80
+
81
+ def account_id
82
+ @config.api_key
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,11 @@
1
+ # typed: ignore
2
+
3
+ class Vonage::Secrets::ListResponse < Vonage::Response
4
+ include Enumerable
5
+
6
+ def each
7
+ return enum_for(:each) unless block_given?
8
+
9
+ @entity._embedded.secrets.each { |item| yield item }
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ # typed: strong
2
+
3
+ module Vonage
4
+ class ServerError < Error
5
+ end
6
+ end
@@ -0,0 +1,53 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'openssl'
4
+ require 'digest/md5'
5
+ require 'jwt'
6
+
7
+ module Vonage
8
+ class Signature
9
+ def initialize(config)
10
+ @config = config
11
+ end
12
+
13
+ # Check webhook request signature.
14
+ #
15
+ # @example
16
+ # client = Vonage::Client.new
17
+ # client.config.signature_secret = 'secret'
18
+ # client.config.signature_method = 'sha512'
19
+ #
20
+ # if client.signature.check(request.GET)
21
+ # # valid signature
22
+ # else
23
+ # # invalid signature
24
+ # end
25
+ #
26
+ # @param [Hash] params
27
+ #
28
+ # @see https://developer.nexmo.com/concepts/guides/signing-messages
29
+ #
30
+ def check(params, signature_method: @config.signature_method)
31
+ params = params.dup
32
+
33
+ signature = params.delete('sig')
34
+
35
+ ::JWT::SecurityUtils.secure_compare(signature, digest(params, signature_method))
36
+ end
37
+
38
+ private
39
+
40
+ def digest(params, signature_method)
41
+ digest_string = params.sort.map { |k, v| "&#{k}=#{v.tr('&=', '_')}" }.join
42
+
43
+ case signature_method
44
+ when 'md5', 'sha1', 'sha256', 'sha512'
45
+ OpenSSL::HMAC.hexdigest(signature_method, @config.signature_secret, digest_string).upcase
46
+ when 'md5hash'
47
+ Digest::MD5.hexdigest("#{digest_string}#{@config.signature_secret}")
48
+ else
49
+ raise ArgumentError, "Unknown signature algorithm: #{signature_method}. Expected: md5hash, md5, sha1, sha256, or sha512."
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,121 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class SMS < Namespace
6
+ extend T::Sig
7
+ include Keys
8
+
9
+ self.host = :rest_host
10
+
11
+ # Send an outbound SMS from your Vonage account.
12
+ #
13
+ # @example
14
+ # response = client.sms.send(from: 'Ruby', to: '447700900000', text: 'Hello world')
15
+ #
16
+ # puts "Sent message id=#{response.messages.first.message_id}"
17
+ #
18
+ # @option params [required, String] :from
19
+ # The name or number the message should be sent from.
20
+ # Alphanumeric senderID's are not supported in all countries, see [Global Messaging](https://developer.nexmo.com/messaging/sms/guides/global-messaging#country-specific-features) for more details.
21
+ # If alphanumeric, spaces will be ignored. Numbers are specified in E.164 format.
22
+ #
23
+ # @option params [required, String] :to
24
+ # The number that the message should be sent to.
25
+ # Numbers are specified in E.164 format.
26
+ #
27
+ # @option params [String] :text
28
+ # The body of the message being sent.
29
+ # If your message contains characters that can be encoded according to the GSM Standard and Extended tables then you can set the **:type** to `text`.
30
+ # If your message contains characters outside this range, then you will need to set the **:type** to `unicode`.
31
+ #
32
+ # @option params [Integer] :ttl
33
+ # The duration in milliseconds the delivery of an SMS will be attempted.
34
+ # By default Vonage attempt delivery for 72 hours, however the maximum effective value depends on the operator and is typically 24 - 48 hours.
35
+ # We recommend this value should be kept at its default or at least 30 minutes.
36
+ #
37
+ # @option params [Boolean] :status_report_req
38
+ # Boolean indicating if you like to receive a [Delivery Receipt](https://developer.nexmo.com/messaging/sms/building-blocks/receive-a-delivery-receipt).
39
+ #
40
+ # @option params [String] :callback
41
+ # The webhook endpoint the delivery receipt for this sms is sent to.
42
+ # This parameter overrides the webhook endpoint you set in Dashboard.
43
+ #
44
+ # @option params [Integer] :message_class
45
+ # The Data Coding Scheme value of the message.
46
+ #
47
+ # @option params [String] :type
48
+ # The format of the message body.
49
+ #
50
+ # @option params [String] :vcard
51
+ # A business card in [vCard format](https://en.wikipedia.org/wiki/VCard).
52
+ # Depends on **:type** option having the value `vcard`.
53
+ #
54
+ # @option params [String] :vcal
55
+ # A calendar event in [vCal format](https://en.wikipedia.org/wiki/VCal).
56
+ # Depends on **:type** option having the value `vcal`.
57
+ #
58
+ # @option params [String] :body
59
+ # Hex encoded binary data.
60
+ # Depends on **:type** option having the value `binary`.
61
+ #
62
+ # @option params [String] :udh
63
+ # Your custom Hex encoded [User Data Header](https://en.wikipedia.org/wiki/User_Data_Header).
64
+ # Depends on **:type** option having the value `binary`.
65
+ #
66
+ # @option params [Integer] :protocol_id
67
+ # The value of the [protocol identifier](https://en.wikipedia.org/wiki/GSM_03.40#Protocol_Identifier) to use.
68
+ # Ensure that the value is aligned with **:udh**.
69
+ #
70
+ # @option params [String] :title
71
+ # The title for a wappush SMS.
72
+ # Depends on **:type** option having the value `wappush`.
73
+ #
74
+ # @option params [String] :url
75
+ # The URL of your website.
76
+ # Depends on **:type** option having the value `wappush`.
77
+ #
78
+ # @option params [String] :validity
79
+ # The availability for an SMS in milliseconds.
80
+ # Depends on **:type** option having the value `wappush`.
81
+ #
82
+ # @option params [String] :client_ref
83
+ # You can optionally include your own reference of up to 40 characters.
84
+ #
85
+ # @option params [String] :account_ref
86
+ # An optional string used to identify separate accounts using the SMS endpoint for billing purposes.
87
+ # To use this feature, please email [support@nexmo.com](mailto:support@nexmo.com).
88
+ #
89
+ # @param [Hash] params
90
+ #
91
+ # @return [Response]
92
+ #
93
+ # @see https://developer.nexmo.com/api/sms#send-an-sms
94
+ #
95
+ sig { params(params: T::Hash[Symbol, T.untyped]).returns(Vonage::Response) }
96
+ def send(params)
97
+ if unicode?(params.fetch(:text)) && params[:type] != 'unicode'
98
+ message = 'Sending unicode text SMS without setting the type parameter to "unicode". ' \
99
+ 'See https://developer.nexmo.com/messaging/sms for details, ' \
100
+ 'or email support@nexmo.com if you have any questions.'
101
+
102
+ logger.warn(message)
103
+ end
104
+
105
+ response = request('/sms/json', params: hyphenate(params), type: Post)
106
+
107
+ unless response.messages.first.status == '0'
108
+ raise Error, response.messages.first[:error_text]
109
+ end
110
+
111
+ response
112
+ end
113
+
114
+ private
115
+
116
+ sig { params(text: String).returns(T::Boolean) }
117
+ def unicode?(text)
118
+ !Vonage::GSM7.encoded?(text)
119
+ end
120
+ end
121
+ end