whatsapp_sdk 0.0.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,32 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "data_response"
4
+
3
5
  module WhatsappSdk
4
6
  module Api
5
7
  module Responses
6
- class ErrorResponse
7
- attr_reader :code, :subcode, :message, :type, :data, :fbtrace_id
8
+ class ErrorResponse < DataResponse
9
+ attr_accessor :error, :status
8
10
 
9
- def initialize(code:, subcode:, message:, type:, data:, fbtrace_id:)
10
- @code = code
11
- @subcode = subcode
12
- @message = message
13
- @type = type
14
- @data = data
15
- @fbtrace_id = fbtrace_id
11
+ def initialize(response:)
12
+ @error = response["error"]
13
+ @status = response["status"]
14
+ super(response)
16
15
  end
17
16
 
18
17
  def self.build_from_response(response:)
19
- error_response = response["error"]
20
- return unless error_response
18
+ return unless response["error"]
21
19
 
22
- new(
23
- code: error_response["code"],
24
- subcode: error_response["error_subcode"],
25
- message: error_response["message"],
26
- type: error_response["type"],
27
- data: error_response["data"],
28
- fbtrace_id: error_response["fbtrace_id"]
29
- )
20
+ new(response: response)
30
21
  end
31
22
  end
32
23
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "data_response"
4
+
5
+ module WhatsappSdk
6
+ module Api
7
+ module Responses
8
+ class MediaDataResponse < DataResponse
9
+ attr_accessor :id, :url, :mime_type, :sha256, :file_size, :messaging_product
10
+
11
+ def initialize(response)
12
+ @id = response["id"]
13
+ @messaging_product = response["messaging_product"]
14
+ @url = response["url"]
15
+ @mime_type = response["mime_type"]
16
+ @sha256 = response["sha256"]
17
+ @file_size = response["file_size"]
18
+ super(response)
19
+ end
20
+
21
+ def self.build_from_response(response:)
22
+ return unless response["id"]
23
+
24
+ new(response)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "error_response"
4
+
5
+ module WhatsappSdk
6
+ module Api
7
+ module Responses
8
+ class MessageErrorResponse < ErrorResponse
9
+ attr_reader :code, :subcode, :message, :type, :data, :fbtrace_id
10
+
11
+ def initialize(response:)
12
+ @code = response["code"]
13
+ @subcode = response["error_subcode"]
14
+ @message = response["message"]
15
+ @type = response["type"]
16
+ @data = response["data"]
17
+ @fbtrace_id = response["fbtrace_id"]
18
+ super(response: response)
19
+ end
20
+
21
+ def self.build_from_response(response:)
22
+ error_response = response["error"]
23
+ return unless error_response
24
+
25
+ new(response: error_response)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -8,11 +8,11 @@ require_relative "../../resource/contact_response"
8
8
  module WhatsappSdk
9
9
  module Api
10
10
  module Responses
11
- class MessageDataResponse < DataResponse
12
- attr_reader :sucess
11
+ class ReadMessageDataResponse < DataResponse
12
+ attr_reader :success
13
13
 
14
14
  def initialize(response:)
15
- @sucess = response["sucess"]
15
+ @success = response["success"]
16
16
  super(response)
17
17
  end
18
18
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "data_response"
4
+
5
+ module WhatsappSdk
6
+ module Api
7
+ module Responses
8
+ class SuccessResponse < DataResponse
9
+ def initialize(response:)
10
+ @success = response["success"]
11
+ super(response)
12
+ end
13
+
14
+ def self.build_from_response(response:)
15
+ return unless response["success"]
16
+
17
+ new(response: response)
18
+ end
19
+
20
+ def success?
21
+ @success
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhatsappSdk
4
+ # This module allows client instantiating the client as a singleton like the following example:
5
+ # WhatsappSdk.configure do |config|
6
+ # config.access_token = ACCESS_TOKEN
7
+ # end
8
+ #
9
+ # The gem have access to the client through WhatsappSdk.configuration.client
10
+
11
+ class << self
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure
17
+ yield(configuration)
18
+ end
19
+ end
20
+
21
+ class Configuration
22
+ attr_accessor :access_token
23
+
24
+ def initialize(access_token = nil)
25
+ @access_token = access_token
26
+ end
27
+
28
+ def client
29
+ return unless access_token
30
+
31
+ WhatsappSdk::Api::Client.new(access_token)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhatsappSdk
4
+ module Resource
5
+ class ButtonParameter
6
+ class InvalidType < StandardError
7
+ attr_accessor :message
8
+
9
+ def initialize(type)
10
+ @message = "invalid type #{type}. type should be text or payload"
11
+ super
12
+ end
13
+ end
14
+
15
+ # Returns the button parameter type.
16
+ #
17
+ # @returns type [String] Valid options are payload and text.
18
+ attr_accessor :type
19
+
20
+ module Type
21
+ TEXT = "text"
22
+ PAYLOAD = "payload"
23
+
24
+ VALID_TYPES = [PAYLOAD, TEXT].freeze
25
+ end
26
+
27
+ # Required for quick_reply buttons.
28
+ # Returns the button payload. Developer-defined payload that is returned when the button is clicked
29
+ # in addition to the display text on the button.
30
+ #
31
+ # @returns payload [String]
32
+ attr_accessor :payload
33
+
34
+ # Required for URL buttons.
35
+ # Developer-provided suffix that is appended to the predefined prefix URL in the template.
36
+ #
37
+ # @returns text [String]
38
+ attr_accessor :text
39
+
40
+ def initialize(type:, payload: nil, text: nil)
41
+ @type = type
42
+ @payload = payload
43
+ @text = text
44
+ validate
45
+ end
46
+
47
+ def to_json(*_args)
48
+ json = {
49
+ type: type
50
+ }
51
+ json[:payload] = payload if payload
52
+ json[:text] = text if text
53
+ json
54
+ end
55
+
56
+ private
57
+
58
+ def validate
59
+ return if Type::VALID_TYPES.include?(type)
60
+
61
+ raise InvalidType, type
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhatsappSdk
4
+ module Resource
5
+ class Component
6
+ class InvalidField < StandardError
7
+ attr_reader :field, :message
8
+
9
+ def initialize(field, message)
10
+ @field = field
11
+ @message = message
12
+ super(message)
13
+ end
14
+ end
15
+
16
+ module Type
17
+ HEADER = 'header'
18
+ BODY = 'body'
19
+ BUTTON = 'button'
20
+ end
21
+
22
+ module Subtype
23
+ QUICK_REPLY = "quick_reply"
24
+ URL = "url"
25
+ end
26
+
27
+ # Returns the Component type.
28
+ #
29
+ # @returns type [String]. Supported Options are header, body and button.
30
+ attr_accessor :type
31
+
32
+ # Returns the parameters of the component. For button type, it's required.
33
+ #
34
+ # @returns parameter [Array<ButtonParameter, ParameterObject>] .
35
+ attr_accessor :parameters
36
+
37
+ # Returns the Type of button to create. Required when type=button. Not used for the other types.
38
+ # Supported Options
39
+ # quick_reply: Refers to a previously created quick reply button
40
+ # that allows for the customer to return a predefined message.
41
+ # url: Refers to a previously created button that allows the customer to visit the URL generated by
42
+ # appending the text parameter to the predefined prefix URL in the template.
43
+ #
44
+ # @returns subtype [String]. Valid options are quick_reply and url.
45
+ attr_accessor :sub_type
46
+
47
+ # Required when type=button. Not used for the other types.
48
+ # Position index of the button. You can have up to 3 buttons using index values of 0 to 2.
49
+ #
50
+ # @returns index [Integer].
51
+ attr_accessor :index
52
+
53
+ def add_parameter(parameter)
54
+ @parameters << parameter
55
+ end
56
+
57
+ def initialize(type:, parameters: [], sub_type: nil, index: nil)
58
+ @parameters = parameters
59
+ @type = type
60
+ @sub_type = sub_type
61
+ @index = index.nil? && type == Type::BUTTON ? 0 : index
62
+ validate_fields
63
+ end
64
+
65
+ def to_json(*_args)
66
+ json = {
67
+ type: type,
68
+ parameters: parameters.map(&:to_json)
69
+ }
70
+ json[:sub_type] = sub_type if sub_type
71
+ json[:index] = index if index
72
+ json
73
+ end
74
+
75
+ private
76
+
77
+ def validate_fields
78
+ return if type == Type::BUTTON
79
+ raise InvalidField.new(:sub_type, 'sub_type is not required when type is not button') if sub_type
80
+
81
+ raise InvalidField.new(:index, 'index is not required when type is not button') if index
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhatsappSdk
4
+ module Resource
5
+ class Currency
6
+ # Returns default text if localization fails.
7
+ #
8
+ # @returns fallback_value [String].
9
+ attr_accessor :fallback_value
10
+
11
+ # Currency code as defined in ISO 4217.
12
+ #
13
+ # @returns code [String].
14
+ attr_accessor :code
15
+
16
+ # Amount multiplied by 1000.
17
+ #
18
+ # @returns code [Float].
19
+ attr_accessor :amount
20
+
21
+ def initialize(fallback_value:, code:, amount:)
22
+ @fallback_value = fallback_value
23
+ @code = code
24
+ @amount = amount
25
+ end
26
+
27
+ def to_json(*_args)
28
+ {
29
+ fallback_value: fallback_value,
30
+ code: code,
31
+ amount_1000: amount
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhatsappSdk
4
+ module Resource
5
+ class DateTime
6
+ # Returns default text if localization fails.
7
+ #
8
+ # @returns fallback_value [String].
9
+ attr_accessor :fallback_value
10
+
11
+ def initialize(fallback_value:)
12
+ @fallback_value = fallback_value
13
+ end
14
+
15
+ def to_json(*_args)
16
+ {
17
+ fallback_value: fallback_value
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhatsappSdk
4
+ module Resource
5
+ class Media
6
+ class InvalidMedia < StandardError
7
+ attr_reader :field, :message
8
+
9
+ def initialize(field, message)
10
+ @field = field
11
+ @message = message
12
+ super(message)
13
+ end
14
+ end
15
+
16
+ # Returns media id.
17
+ #
18
+ # @returns id [String].
19
+ attr_accessor :id
20
+
21
+ module Type
22
+ AUDIO = 'audio'
23
+ DOCUMENT = 'document'
24
+ IMAGE = 'image'
25
+ VIDEO = 'video'
26
+ STICKER = 'sticker'
27
+
28
+ VALID_TYPES = [AUDIO, DOCUMENT, IMAGE, VIDEO, STICKER].freeze
29
+ end
30
+
31
+ # @returns type [String]. Valid options ar audio, document, image, video and sticker.
32
+ attr_accessor :type
33
+
34
+ # The protocol and URL of the media to be sent. Use only with HTTP/HTTPS URLs.
35
+ # Do not use this field when the message type is set to text.
36
+ #
37
+ # @returns link [String].
38
+ attr_accessor :link
39
+
40
+ # Describes the specified document or image media.
41
+ #
42
+ # @returns caption [String].
43
+ attr_accessor :caption
44
+
45
+ # Describes the filename for the specific document. Use only with document media.
46
+ #
47
+ # @returns filename [String].
48
+ attr_accessor :filename
49
+
50
+ def initialize(type:, id: nil, link: nil, caption: nil, filename: nil)
51
+ @type = type
52
+ @id = id
53
+ @link = link
54
+ @caption = caption
55
+ @filename = filename
56
+ validate_media
57
+ end
58
+
59
+ def to_json(*_args)
60
+ json = {}
61
+ json[:id] = id unless id.nil?
62
+ json[:link] = link unless link.nil?
63
+ json[:caption] = caption unless caption.nil?
64
+ json[:filename] = filename unless filename.nil?
65
+ json
66
+ end
67
+
68
+ private
69
+
70
+ def validate_media
71
+ unless Type::VALID_TYPES.include?(type)
72
+ raise InvalidMedia.new(:type, "invalid type. type should be audio, document, image, video or sticker")
73
+ end
74
+ if filename && (type != Type::DOCUMENT)
75
+ raise InvalidMedia.new(:filename, "filename can only be used with document")
76
+ end
77
+
78
+ if caption && !(type == Type::DOCUMENT || type == Type::IMAGE)
79
+ raise InvalidMedia.new(:caption, "caption can only be used with document or image")
80
+ end
81
+
82
+ true
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WhatsappSdk
4
+ module Resource
5
+ class ParameterObject
6
+ class InvalidType < StandardError
7
+ attr_accessor :message
8
+
9
+ def initialize(type)
10
+ @message = "invalid type #{type}. type should be text, currency, date_time, image, document or video"
11
+ super
12
+ end
13
+ end
14
+
15
+ class MissingValue < StandardError
16
+ attr_reader :field, :message
17
+
18
+ def initialize(field, message)
19
+ @field = field
20
+ @message = message
21
+ super(message)
22
+ end
23
+ end
24
+
25
+ # Returns the parameter type.
26
+ #
27
+ # @returns type [String] Valid options are text, currency, date_time, image, document, video.
28
+ attr_accessor :type
29
+
30
+ module Type
31
+ TEXT = "text"
32
+ CURRENCY = "currency"
33
+ DATE_TIME = "date_time"
34
+ IMAGE = "image"
35
+ DOCUMENT = "document"
36
+ VIDEO = "video"
37
+
38
+ VALID_TYPES = [TEXT, CURRENCY, DATE_TIME, IMAGE, DOCUMENT, VIDEO].freeze
39
+ end
40
+
41
+ # Returns Text string if the parameter object type is text.
42
+ # For the header component, the character limit is 60 characters.
43
+ # For the body component, the character limit is 1024 characters.
44
+ #
45
+ # @returns text [String]
46
+ attr_accessor :text
47
+
48
+ # Returns Currency if the parameter object type is currency.
49
+ #
50
+ # @returns currency [Currency]
51
+ attr_accessor :currency
52
+
53
+ # Returns date_time if the parameter object type is date_time.
54
+ #
55
+ # @returns date_time [DateTime]
56
+ attr_accessor :date_time
57
+
58
+ # Returns image if the parameter object type is image.
59
+ #
60
+ # @returns image [Media]
61
+ attr_accessor :image
62
+
63
+ # Returns document if the parameter object type is document.
64
+ #
65
+ # @returns document [Media]
66
+ attr_accessor :document
67
+
68
+ # Returns video if the parameter object type is video.
69
+ #
70
+ # @returns video [Media]
71
+ attr_accessor :video
72
+
73
+ def initialize(type:, text: nil, currency: nil, date_time: nil, image: nil, document: nil, video: nil)
74
+ @type = type
75
+ @text = text
76
+ @currency = currency
77
+ @date_time = date_time
78
+ @image = image
79
+ @document = document
80
+ @video = video
81
+ validate
82
+ end
83
+
84
+ def to_json(*_args)
85
+ json = { type: type }
86
+ json[type.to_sym] = case type
87
+ when "text"
88
+ text
89
+ when "currency"
90
+ currency.to_json
91
+ when "date_time"
92
+ date_time.to_json
93
+ when "image"
94
+ image.to_json
95
+ when "document"
96
+ document.to_json
97
+ when "video"
98
+ video.to_json
99
+ else
100
+ raise "Invalid type: #{type}"
101
+ end
102
+
103
+ json
104
+ end
105
+
106
+ private
107
+
108
+ def validate
109
+ validate_attributes
110
+ validate_type
111
+ end
112
+
113
+ def validate_type
114
+ return if Type::VALID_TYPES.include?(type)
115
+
116
+ raise InvalidType, type
117
+ end
118
+
119
+ def validate_attributes
120
+ [
121
+ [:text, text],
122
+ [:currency, currency],
123
+ [:date_time, date_time],
124
+ [:image, image],
125
+ [:document, document],
126
+ [:video, video]
127
+ ].each do |type_sym, value|
128
+ next unless type == type_sym
129
+ raise MissingValue.new(type, "#{type} is required when the type is #{type}") if value.nil?
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
data/lib/whatsapp_sdk.rb CHANGED
@@ -1,24 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Configuration
4
+ require_relative "whatsapp_sdk/configuration"
5
+
3
6
  # APIs
4
7
  require_relative "whatsapp_sdk/api/phone_numbers"
5
8
  require_relative "whatsapp_sdk/api/messages"
9
+ require_relative "whatsapp_sdk/api/medias"
6
10
  require_relative "whatsapp_sdk/api/client"
7
11
 
8
12
  # APIs responses
9
13
  require_relative "whatsapp_sdk/api/responses/message_data_response"
10
14
  require_relative "whatsapp_sdk/api/responses/phone_number_data_response"
11
15
  require_relative "whatsapp_sdk/api/responses/phone_numbers_data_response"
12
- require_relative "whatsapp_sdk/api/responses/error_response"
16
+ require_relative "whatsapp_sdk/api/responses/message_error_response"
13
17
  require_relative "whatsapp_sdk/api/responses/data_response"
18
+ require_relative "whatsapp_sdk/api/responses/read_message_data_response"
19
+ require_relative "whatsapp_sdk/api/responses/media_data_response"
20
+ require_relative "whatsapp_sdk/api/responses/success_response"
21
+ require_relative "whatsapp_sdk/api/responses/error_response"
14
22
 
15
23
  # Resources
16
24
  require_relative "whatsapp_sdk/resource/address"
25
+ require_relative "whatsapp_sdk/resource/button_parameter"
26
+ require_relative "whatsapp_sdk/resource/component"
17
27
  require_relative "whatsapp_sdk/resource/contact_response"
18
28
  require_relative "whatsapp_sdk/resource/contact"
29
+ require_relative "whatsapp_sdk/resource/currency"
30
+ require_relative "whatsapp_sdk/resource/date_time"
19
31
  require_relative "whatsapp_sdk/resource/email"
32
+ require_relative "whatsapp_sdk/resource/media"
20
33
  require_relative "whatsapp_sdk/resource/message"
21
34
  require_relative "whatsapp_sdk/resource/name"
22
35
  require_relative "whatsapp_sdk/resource/org"
36
+ require_relative "whatsapp_sdk/resource/parameter_object"
23
37
  require_relative "whatsapp_sdk/resource/phone_number"
24
38
  require_relative "whatsapp_sdk/resource/url"
data/tmp/whatsapp.png ADDED
Binary file