vonage 7.2.0

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.
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