whatsapp_sdk 0.0.1 → 0.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.
@@ -15,13 +15,19 @@ module WhatsappSdk
15
15
  end
16
16
  end
17
17
 
18
+ # Send a text message.
19
+ #
20
+ # @param sender_id [Integer] Sender' phone number.
21
+ # @param recipient_number [Integer] Recipient' Phone number.
22
+ # @param message [String] Text to send.
23
+ # @return [WhatsappSdk::Api::Response] Response object.
18
24
  def send_text(sender_id:, recipient_number:, message:)
19
25
  params = {
20
26
  messaging_product: "whatsapp",
21
27
  to: recipient_number,
22
- recepient_type: "individual",
28
+ recipient_type: "individual",
23
29
  type: "text",
24
- "text": { body: message }
30
+ text: { body: message }
25
31
  }
26
32
 
27
33
  response = send_request(
@@ -29,20 +35,32 @@ module WhatsappSdk
29
35
  params: params
30
36
  )
31
37
 
32
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
38
+ WhatsappSdk::Api::Response.new(
39
+ response: response,
40
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
41
+ )
33
42
  end
34
43
 
44
+ # Send location.
45
+ #
46
+ # @param sender_id [Integer] Sender' phone number.
47
+ # @param recipient_number [Integer] Recipient' Phone number.
48
+ # @param longitude [Float] Location longitude.
49
+ # @param latitude [Float] Location latitude.
50
+ # @param name [String] Location name.
51
+ # @param address [String] Location address.
52
+ # @return [WhatsappSdk::Api::Response] Response object.
35
53
  def send_location(sender_id:, recipient_number:, longitude:, latitude:, name:, address:)
36
54
  params = {
37
55
  messaging_product: "whatsapp",
38
56
  to: recipient_number,
39
- recepient_type: "individual",
57
+ recipient_type: "individual",
40
58
  type: "location",
41
- "location": {
42
- "longitude": longitude,
43
- "latitude": latitude,
44
- "name": name,
45
- "address": address
59
+ location: {
60
+ longitude: longitude,
61
+ latitude: latitude,
62
+ name: name,
63
+ address: address
46
64
  }
47
65
  }
48
66
 
@@ -51,16 +69,27 @@ module WhatsappSdk
51
69
  params: params
52
70
  )
53
71
 
54
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
72
+ WhatsappSdk::Api::Response.new(
73
+ response: response,
74
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
75
+ )
55
76
  end
56
77
 
78
+ # Send an image.
79
+ #
80
+ # @param sender_id [Integer] Sender' phone number.
81
+ # @param recipient_number [Integer] Recipient' Phone number.
82
+ # @param image_id [Integer] Image ID.
83
+ # @param link [String] Image link.
84
+ # @param caption [String] Image caption.
85
+ # @return [WhatsappSdk::Api::Response] Response object.
57
86
  def send_image(sender_id:, recipient_number:, image_id: nil, link: nil, caption: "")
58
87
  raise MissingArgumentError, "image_id or link is required" if !image_id && !link
59
88
 
60
89
  params = {
61
90
  messaging_product: "whatsapp",
62
91
  to: recipient_number,
63
- recepient_type: "individual",
92
+ recipient_type: "individual",
64
93
  type: "image"
65
94
  }
66
95
  params[:image] = if link
@@ -74,16 +103,26 @@ module WhatsappSdk
74
103
  params: params
75
104
  )
76
105
 
77
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
106
+ WhatsappSdk::Api::Response.new(
107
+ response: response,
108
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
109
+ )
78
110
  end
79
111
 
112
+ # Send an audio.
113
+ #
114
+ # @param sender_id [Integer] Sender' phone number.
115
+ # @param recipient_number [Integer] Recipient' Phone number.
116
+ # @param audio_id [Integer] Audio ID.
117
+ # @param link [String] Audio link.
118
+ # @return [WhatsappSdk::Api::Response] Response object.
80
119
  def send_audio(sender_id:, recipient_number:, audio_id: nil, link: nil)
81
120
  raise MissingArgumentError, "audio_id or link is required" if !audio_id && !link
82
121
 
83
122
  params = {
84
123
  messaging_product: "whatsapp",
85
124
  to: recipient_number,
86
- recepient_type: "individual",
125
+ recipient_type: "individual",
87
126
  type: "audio"
88
127
  }
89
128
  params[:audio] = link ? { link: link } : { id: audio_id }
@@ -93,16 +132,27 @@ module WhatsappSdk
93
132
  params: params
94
133
  )
95
134
 
96
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
135
+ WhatsappSdk::Api::Response.new(
136
+ response: response,
137
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
138
+ )
97
139
  end
98
140
 
141
+ # Send a video.
142
+ #
143
+ # @param sender_id [Integer] Sender' phone number.
144
+ # @param recipient_number [Integer] Recipient' Phone number.
145
+ # @param video_id [Integer] Video ID.
146
+ # @param link [String] Image link.
147
+ # @param caption [String] Image caption.
148
+ # @return [WhatsappSdk::Api::Response] Response object.
99
149
  def send_video(sender_id:, recipient_number:, video_id: nil, link: nil, caption: "")
100
150
  raise MissingArgumentError, "video_id or link is required" if !video_id && !link
101
151
 
102
152
  params = {
103
153
  messaging_product: "whatsapp",
104
154
  to: recipient_number,
105
- recepient_type: "individual",
155
+ recipient_type: "individual",
106
156
  type: "video"
107
157
  }
108
158
  params[:video] = if link
@@ -116,16 +166,27 @@ module WhatsappSdk
116
166
  params: params
117
167
  )
118
168
 
119
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
169
+ WhatsappSdk::Api::Response.new(
170
+ response: response,
171
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
172
+ )
120
173
  end
121
174
 
175
+ # Send a document.
176
+ #
177
+ # @param sender_id [Integer] Sender' phone number.
178
+ # @param recipient_number [Integer] Recipient' Phone number.
179
+ # @param document_id [Integer] document ID.
180
+ # @param link [String] Image link.
181
+ # @param caption [String] Image caption.
182
+ # @return [WhatsappSdk::Api::Response] Response object.
122
183
  def send_document(sender_id:, recipient_number:, document_id: nil, link: nil, caption: "")
123
184
  raise MissingArgumentError, "document or link is required" if !document_id && !link
124
185
 
125
186
  params = {
126
187
  messaging_product: "whatsapp",
127
188
  to: recipient_number,
128
- recepient_type: "individual",
189
+ recipient_type: "individual",
129
190
  type: "document"
130
191
  }
131
192
  params[:document] = if link
@@ -139,16 +200,25 @@ module WhatsappSdk
139
200
  params: params
140
201
  )
141
202
 
142
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
203
+ WhatsappSdk::Api::Response.new(
204
+ response: response,
205
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
206
+ )
143
207
  end
144
208
 
209
+ # Send a document.
210
+ #
211
+ # @param sender_id [Integer] Sender' phone number.
212
+ # @param recipient_number [Integer] Recipient' Phone number.
213
+ # @param link [String] Image link.
214
+ # @return [WhatsappSdk::Api::Response] Response object.
145
215
  def send_sticker(sender_id:, recipient_number:, sticker_id: nil, link: nil)
146
216
  raise MissingArgumentError, "sticker or link is required" if !sticker_id && !link
147
217
 
148
218
  params = {
149
219
  messaging_product: "whatsapp",
150
220
  to: recipient_number,
151
- recepient_type: "individual",
221
+ recipient_type: "individual",
152
222
  type: "sticker"
153
223
  }
154
224
  params[:sticker] = link ? { link: link } : { id: sticker_id }
@@ -158,14 +228,25 @@ module WhatsappSdk
158
228
  params: params
159
229
  )
160
230
 
161
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
231
+ WhatsappSdk::Api::Response.new(
232
+ response: response,
233
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
234
+ )
162
235
  end
163
236
 
237
+ # Send contacts.
238
+ # You can either send contacts objects or contacts as JSON.
239
+ #
240
+ # @param sender_id [Integer] Sender' phone number.
241
+ # @param recipient_number [Integer] Recipient' Phone number.
242
+ # @param contacts [Array<Contact>] Contacts.
243
+ # @param contacts_json [Json] Contacts.
244
+ # @return [WhatsappSdk::Api::Response] Response object.
164
245
  def send_contacts(sender_id:, recipient_number:, contacts: nil, contacts_json: {})
165
246
  params = {
166
247
  messaging_product: "whatsapp",
167
248
  to: recipient_number,
168
- recepient_type: "individual",
249
+ recipient_type: "individual",
169
250
  type: "contacts"
170
251
  }
171
252
  params[:contacts] = contacts ? contacts.map(&:to_h) : contacts_json
@@ -175,7 +256,10 @@ module WhatsappSdk
175
256
  params: params
176
257
  )
177
258
 
178
- WhatsappSdk::Api::Response.new(response: response, class_type: WhatsappSdk::Api::Responses::MessageDataResponse)
259
+ WhatsappSdk::Api::Response.new(
260
+ response: response,
261
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
262
+ )
179
263
  end
180
264
 
181
265
  def send_interactive_button
@@ -190,6 +274,69 @@ module WhatsappSdk
190
274
  # TODO: https://developers.facebook.com/docs/whatsapp_sdk/cloud-api/reference/messages#contacts-object
191
275
  end
192
276
 
277
+ # Mark a message as read.
278
+ #
279
+ # @param sender_id [Integer] Sender' phone number.
280
+ # @param message_id [Integer] Message ID.
281
+ # @return [WhatsappSdk::Api::Response] Response object.
282
+ def read_message(sender_id:, message_id:)
283
+ params = {
284
+ messaging_product: "whatsapp",
285
+ status: "read",
286
+ message_id: message_id
287
+ }
288
+
289
+ response = send_request(
290
+ endpoint: endpoint(sender_id),
291
+ params: params
292
+ )
293
+
294
+ WhatsappSdk::Api::Response.new(
295
+ response: response,
296
+ data_class_type: WhatsappSdk::Api::Responses::ReadMessageDataResponse
297
+ )
298
+ end
299
+
300
+ # Send template
301
+ #
302
+ # @param sender_id [Integer] Sender' phone number.
303
+ # @param recipient_number [Integer] Recipient' Phone number.
304
+ # @param name [String] the template's name.
305
+ # @param language [String] template language.
306
+ # @param components [Component] Component.
307
+ # @param components_json [Json] The component as a Json. If you pass components_json, you can't pass components.
308
+ # @return [WhatsappSdk::Api::Response] Response object.
309
+ def send_template(sender_id:, recipient_number:, name:, language:, components: nil, components_json: nil)
310
+ raise MissingArgumentError, "components or components_json is required" if !components && !components_json
311
+
312
+ params = {
313
+ messaging_product: "whatsapp",
314
+ recipient_type: "individual",
315
+ to: recipient_number,
316
+ type: "template",
317
+ template: {
318
+ name: name
319
+ }
320
+ }
321
+
322
+ params[:template][:language] = { code: language } if language
323
+ params[:template][:components] = if components.nil?
324
+ components_json
325
+ else
326
+ components.map(&:to_json)
327
+ end
328
+
329
+ response = send_request(
330
+ endpoint: endpoint(sender_id),
331
+ params: params
332
+ )
333
+
334
+ WhatsappSdk::Api::Response.new(
335
+ response: response,
336
+ data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
337
+ )
338
+ end
339
+
193
340
  private
194
341
 
195
342
  def endpoint(sender_id)
@@ -6,24 +6,36 @@ require_relative "response"
6
6
  module WhatsappSdk
7
7
  module Api
8
8
  class PhoneNumbers < Request
9
+ # Get list of registered numbers.
10
+ #
11
+ # @param business_id [Integer] Business Id.
12
+ # @return [WhatsappSdk::Api::Response] Response object.
9
13
  def registered_numbers(business_id)
10
14
  response = send_request(
11
15
  http_method: "get",
12
16
  endpoint: "#{business_id}/phone_numbers"
13
17
  )
14
18
 
15
- WhatsappSdk::Api::Response.new(response: response,
16
- class_type: WhatsappSdk::Api::Responses::PhoneNumbersDataResponse)
19
+ WhatsappSdk::Api::Response.new(
20
+ response: response,
21
+ data_class_type: WhatsappSdk::Api::Responses::PhoneNumbersDataResponse
22
+ )
17
23
  end
18
24
 
25
+ # Get the registered number id.
26
+ #
27
+ # @param phone_number_id [Integer] The registered number we want to retrieve.
28
+ # @return [WhatsappSdk::Api::Response] Response object.
19
29
  def registered_number(phone_number_id)
20
30
  response = send_request(
21
31
  http_method: "get",
22
32
  endpoint: phone_number_id.to_s
23
33
  )
24
34
 
25
- WhatsappSdk::Api::Response.new(response: response,
26
- class_type: WhatsappSdk::Api::Responses::PhoneNumberDataResponse)
35
+ WhatsappSdk::Api::Response.new(
36
+ response: response,
37
+ data_class_type: WhatsappSdk::Api::Responses::PhoneNumberDataResponse
38
+ )
27
39
  end
28
40
  end
29
41
  end
@@ -10,8 +10,14 @@ module WhatsappSdk
10
10
  @client = client
11
11
  end
12
12
 
13
- def send_request(endpoint:, http_method: "post", params: {})
14
- @client.send_request(http_method: http_method, endpoint: endpoint, params: params)
13
+ def download_file(url, path_to_file_name = nil)
14
+ @client.download_file(url, path_to_file_name)
15
+ end
16
+
17
+ def send_request(endpoint: nil, full_url: nil, http_method: "post", params: {})
18
+ @client.send_request(
19
+ http_method: http_method, full_url: full_url, endpoint: endpoint, params: params
20
+ )
15
21
  end
16
22
  end
17
23
  end
@@ -3,28 +3,25 @@
3
3
  require_relative "responses/message_data_response"
4
4
  require_relative "responses/phone_number_data_response"
5
5
  require_relative "responses/phone_numbers_data_response"
6
- require_relative "responses/error_response"
6
+ require_relative "responses/read_message_data_response"
7
+ require_relative "responses/message_error_response"
7
8
 
8
9
  module WhatsappSdk
9
10
  module Api
10
11
  class Response
11
12
  attr_accessor :error, :data
12
13
 
13
- CLASS_TYPE = {
14
- message_data_response: Responses::MessageDataResponse,
15
- phone_number_data_response: Responses::PhoneNumberDataResponse,
16
- phone_numbers_data_response: Responses::PhoneNumbersDataResponse
17
- }.freeze
18
-
19
- def initialize(response:, class_type:)
20
- @data = class_type.build_from_response(response: response)
21
- @error = Responses::ErrorResponse.build_from_response(response: response)
14
+ def initialize(response:, data_class_type:, error_class_type: Responses::MessageErrorResponse)
15
+ @data = data_class_type.build_from_response(response: response)
16
+ @error = error_class_type.build_from_response(response: response)
22
17
  end
23
18
 
19
+ # @return [Boolean] Whether or not the response is successful.
24
20
  def ok?
25
21
  @error.nil?
26
22
  end
27
23
 
24
+ # @return [Boolean] Whether or not the response has an error.
28
25
  def error?
29
26
  !!@error
30
27
  end
@@ -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
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../request"
4
+ require_relative "data_response"
5
+ require_relative "../../resource/message"
6
+ require_relative "../../resource/contact_response"
7
+
8
+ module WhatsappSdk
9
+ module Api
10
+ module Responses
11
+ class ReadMessageDataResponse < DataResponse
12
+ attr_reader :success
13
+
14
+ def initialize(response:)
15
+ @success = response["success"]
16
+ super(response)
17
+ end
18
+
19
+ def self.build_from_response(response:)
20
+ return if response["error"]
21
+
22
+ new(response: response)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -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,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