whatsapp_sdk 0.3.0 → 0.4.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +21 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
  4. data/.github/workflows/codeql-analysis.yml +72 -0
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +14 -0
  7. data/CHANGELOG.md +8 -1
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +48 -1
  10. data/README.md +107 -33
  11. data/Rakefile +1 -0
  12. data/bin/tapioca +30 -0
  13. data/example.rb +23 -20
  14. data/lib/version.rb +2 -1
  15. data/lib/whatsapp_sdk/api/client.rb +14 -3
  16. data/lib/whatsapp_sdk/api/medias.rb +12 -3
  17. data/lib/whatsapp_sdk/api/messages.rb +72 -14
  18. data/lib/whatsapp_sdk/api/phone_numbers.rb +3 -0
  19. data/lib/whatsapp_sdk/api/request.rb +2 -2
  20. data/lib/whatsapp_sdk/api/response.rb +17 -1
  21. data/lib/whatsapp_sdk/api/responses/data_response.rb +10 -3
  22. data/lib/whatsapp_sdk/api/responses/error_response.rb +8 -1
  23. data/lib/whatsapp_sdk/api/responses/media_data_response.rb +26 -7
  24. data/lib/whatsapp_sdk/api/responses/message_data_response.rb +20 -3
  25. data/lib/whatsapp_sdk/api/responses/message_error_response.rb +26 -7
  26. data/lib/whatsapp_sdk/api/responses/phone_number_data_response.rb +18 -5
  27. data/lib/whatsapp_sdk/api/responses/phone_numbers_data_response.rb +9 -1
  28. data/lib/whatsapp_sdk/api/responses/read_message_data_response.rb +10 -3
  29. data/lib/whatsapp_sdk/api/responses/success_response.rb +5 -1
  30. data/lib/whatsapp_sdk/configuration.rb +7 -14
  31. data/lib/whatsapp_sdk/error.rb +1 -0
  32. data/lib/whatsapp_sdk/resource/address.rb +30 -6
  33. data/lib/whatsapp_sdk/resource/address_type.rb +15 -0
  34. data/lib/whatsapp_sdk/resource/button_parameter.rb +19 -23
  35. data/lib/whatsapp_sdk/resource/component.rb +45 -13
  36. data/lib/whatsapp_sdk/resource/contact.rb +30 -1
  37. data/lib/whatsapp_sdk/resource/contact_response.rb +9 -1
  38. data/lib/whatsapp_sdk/resource/currency.rb +9 -1
  39. data/lib/whatsapp_sdk/resource/date_time.rb +7 -1
  40. data/lib/whatsapp_sdk/resource/email.rb +9 -5
  41. data/lib/whatsapp_sdk/resource/media.rb +44 -15
  42. data/lib/whatsapp_sdk/resource/message.rb +5 -0
  43. data/lib/whatsapp_sdk/resource/name.rb +28 -1
  44. data/lib/whatsapp_sdk/resource/org.rb +13 -1
  45. data/lib/whatsapp_sdk/resource/parameter_object.rb +82 -39
  46. data/lib/whatsapp_sdk/resource/phone_number.rb +12 -5
  47. data/lib/whatsapp_sdk/resource/url.rb +9 -5
  48. data/lib/whatsapp_sdk.rb +19 -33
  49. data/sorbet/config +6 -0
  50. data/sorbet/rbi/annotations/faraday.rbi +17 -0
  51. data/sorbet/rbi/annotations/mocha.rbi +34 -0
  52. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  53. data/sorbet/rbi/gems/faraday-multipart@1.0.4.rbi +270 -0
  54. data/sorbet/rbi/gems/faraday-net_http@2.0.3.rbi +182 -0
  55. data/sorbet/rbi/gems/faraday@2.3.0.rbi +2494 -0
  56. data/sorbet/rbi/gems/method_source@1.0.0.rbi +272 -0
  57. data/sorbet/rbi/gems/minitest@5.16.1.rbi +1459 -0
  58. data/sorbet/rbi/gems/mocha@1.14.0.rbi +60 -0
  59. data/sorbet/rbi/gems/multipart-post@2.2.3.rbi +239 -0
  60. data/sorbet/rbi/gems/netrc@0.11.0.rbi +150 -0
  61. data/sorbet/rbi/gems/oj@3.13.14.rbi +589 -0
  62. data/sorbet/rbi/gems/zeitwerk@2.6.0.rbi +867 -0
  63. data/sorbet/rbi/todo.rbi +8 -0
  64. data/sorbet/shims/request.rbi +10 -0
  65. data/sorbet/tapioca/config.yml +13 -0
  66. data/sorbet/tapioca/require.rb +5 -0
  67. data/whatsapp_sdk.gemspec +5 -1
  68. metadata +67 -2
data/example.rb CHANGED
@@ -48,16 +48,17 @@ messages_api = WhatsappSdk::Api::Messages.new
48
48
  phone_numbers_api = WhatsappSdk::Api::PhoneNumbers.new
49
49
 
50
50
  ############################## Phone Numbers API ##############################
51
- phone_numbers_api.registered_number(SENDER_ID)
52
- phone_numbers_api.registered_numbers(BUSINESS_ID)
51
+ registered_number = phone_numbers_api.registered_number(SENDER_ID)
52
+ registered_numbers = phone_numbers_api.registered_numbers(BUSINESS_ID)
53
53
  ############################## Media API ##############################
54
54
 
55
55
  # upload a media
56
56
  uploaded_media = medias_api.upload(sender_id: SENDER_ID, file_path: "tmp/whatsapp.png", type: "image/png")
57
- puts "Uploaded media id: #{uploaded_media.data&.id}"
57
+ media_id = uploaded_media.data&.id
58
+ puts "Uploaded media id: #{media_id}"
58
59
 
59
60
  # get a media
60
- media = medias_api.media(media_id: uploaded_media.data&.id).data
61
+ media = medias_api.media(media_id: media_id).data
61
62
  puts "Media info: #{media.raw_data_response}"
62
63
 
63
64
  # download media
@@ -131,12 +132,12 @@ puts response_with_object
131
132
 
132
133
  # Send a template with components.Remember to create the template first.
133
134
  header_component = WhatsappSdk::Resource::Component.new(
134
- type: WhatsappSdk::Resource::Component::Type::HEADER
135
+ type: WhatsappSdk::Resource::Component::Type::Header
135
136
  )
136
137
 
137
138
  image = WhatsappSdk::Resource::Media.new(type: "image", link: "http(s)://URL", caption: "caption")
138
139
  document = WhatsappSdk::Resource::Media.new(type: "document", link: "http(s)://URL", filename: "txt.rb")
139
- video = WhatsappSdk::Resource::Media.new(type: "video", id: 123)
140
+ video = WhatsappSdk::Resource::Media.new(type: "video", id: "123")
140
141
 
141
142
  parameter_image = WhatsappSdk::Resource::ParameterObject.new(
142
143
  type: "image",
@@ -165,7 +166,7 @@ header_component.add_parameter(parameter_document)
165
166
  header_component.to_json
166
167
 
167
168
  body_component = WhatsappSdk::Resource::Component.new(
168
- type: WhatsappSdk::Resource::Component::Type::BODY
169
+ type: WhatsappSdk::Resource::Component::Type::Body
169
170
  )
170
171
  body_component.add_parameter(parameter_text)
171
172
  body_component.add_parameter(parameter_image)
@@ -173,19 +174,21 @@ body_component.add_parameter(parameter_video)
173
174
  body_component.add_parameter(parameter_document)
174
175
  body_component.to_json
175
176
 
176
- # button_component_1 = WhatsappSdk::Resource::Component.new(
177
- # type: WhatsappSdk::Resource::Component::Type::BUTTON,
178
- # index: 0,
179
- # sub_type: WhatsappSdk::Resource::Component::Subtype::QUICK_REPLY,
180
- # parameters: [WhatsappSdk::Resource::ButtonParameter.new(type: "payload", payload: "payload")]
181
- # )
182
-
183
- # button_component_2 = WhatsappSdk::Resource::Component.new(
184
- # type: WhatsappSdk::Resource::Component::Type::BUTTON,
185
- # index: 1,
186
- # sub_type: WhatsappSdk::Resource::Component::Subtype::QUICK_REPLY,
187
- # parameters: [WhatsappSdk::Resource::ButtonParameter.new(type: "payload", payload: "payload")]
188
- # )
177
+ button_component_1 = WhatsappSdk::Resource::Component.new(
178
+ type: WhatsappSdk::Resource::Component::Type::Button,
179
+ index: 0,
180
+ sub_type: WhatsappSdk::Resource::Component::Subtype::QuickReply,
181
+ parameters: [WhatsappSdk::Resource::ButtonParameter.new(type: WhatsappSdk::Resource::ButtonParameter::Type::Payload,
182
+ payload: "payload")]
183
+ )
184
+
185
+ button_component_2 = WhatsappSdk::Resource::Component.new(
186
+ type: WhatsappSdk::Resource::Component::Type::Button,
187
+ index: 1,
188
+ sub_type: WhatsappSdk::Resource::Component::Subtype::QuickReply,
189
+ parameters: [WhatsappSdk::Resource::ButtonParameter.new(type: WhatsappSdk::Resource::ButtonParameter::Type::Payload,
190
+ payload: "payload")]
191
+ )
189
192
 
190
193
  # Send a template with component_json
191
194
  response_with_json = messages_api.send_template(
data/lib/version.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  module WhatsappSdk
4
- VERSION = "0.3.0"
5
+ VERSION = "0.4.0"
5
6
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require "faraday"
4
5
  require "oj"
@@ -6,20 +7,29 @@ require "oj"
6
7
  module WhatsappSdk
7
8
  module Api
8
9
  class Client
9
- API_VERSION = "v14.0"
10
- API_CLIENT = "https://graph.facebook.com/#{API_VERSION}/"
10
+ extend T::Sig
11
11
 
12
+ API_VERSION = T.let("v14.0", String)
13
+ API_CLIENT = T.let("https://graph.facebook.com/#{API_VERSION}/", String)
14
+
15
+ sig { params(access_token: String).void }
12
16
  def initialize(access_token)
13
17
  @access_token = access_token
14
18
  end
15
19
 
20
+ sig do
21
+ params(
22
+ endpoint: String, full_url: T.nilable(String), http_method: String, params: T::Hash[T.untyped, T.untyped]
23
+ ).returns(T::Hash[T.untyped, T.untyped])
24
+ end
16
25
  def send_request(endpoint: "", full_url: nil, http_method: "post", params: {})
17
26
  url = full_url || API_CLIENT
18
27
 
19
- response = faraday(url).public_send(http_method, endpoint, params)
28
+ response = T.unsafe(faraday(url)).public_send(http_method, endpoint, params)
20
29
  Oj.load(response.body)
21
30
  end
22
31
 
32
+ sig { params(url: String, path_to_file_name: T.nilable(String)).returns(Net::HTTPResponse) }
23
33
  def download_file(url, path_to_file_name = nil)
24
34
  uri = URI.parse(url)
25
35
  request = Net::HTTP::Get.new(uri)
@@ -37,6 +47,7 @@ module WhatsappSdk
37
47
 
38
48
  private
39
49
 
50
+ sig { params(url: String).returns(Faraday::Connection) }
40
51
  def faraday(url)
41
52
  ::Faraday.new(url) do |client|
42
53
  client.request :multipart
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require "faraday"
4
5
  require "faraday/multipart"
@@ -12,8 +13,12 @@ module WhatsappSdk
12
13
  module Api
13
14
  class Medias < Request
14
15
  class FileNotFoundError < StandardError
16
+ extend T::Sig
17
+
18
+ sig { returns(String) }
15
19
  attr_reader :file_path
16
20
 
21
+ sig { params(file_path: String).void }
17
22
  def initialize(file_path)
18
23
  @file_path = file_path
19
24
  super("Couldn't find file_path: #{file_path}")
@@ -22,8 +27,9 @@ module WhatsappSdk
22
27
 
23
28
  # Get Media by ID.
24
29
  #
25
- # @param media_id [Integer] Media Id.
30
+ # @param media_id [String] Media Id.
26
31
  # @return [WhatsappSdk::Api::Response] Response object.
32
+ sig { params(media_id: String).returns(WhatsappSdk::Api::Response) }
27
33
  def media(media_id:)
28
34
  response = send_request(
29
35
  http_method: "get",
@@ -38,9 +44,10 @@ module WhatsappSdk
38
44
 
39
45
  # Download Media by URL.
40
46
  #
41
- # @param media_id [Integer] Media Id.
47
+ # @param url URL.
42
48
  # @param file_path [String] The file_path to download the media e.g. "tmp/downloaded_image.png".
43
49
  # @return [WhatsappSdk::Api::Response] Response object.
50
+ sig { params(url: String, file_path: String).returns(WhatsappSdk::Api::Response) }
44
51
  def download(url:, file_path:)
45
52
  response = download_file(url, file_path)
46
53
 
@@ -64,6 +71,7 @@ module WhatsappSdk
64
71
  # see the official documentation https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#supported-media-types.
65
72
  #
66
73
  # @return [WhatsappSdk::Api::Response] Response object.
74
+ sig { params(sender_id: Integer, file_path: String, type: String).returns(WhatsappSdk::Api::Response) }
67
75
  def upload(sender_id:, file_path:, type:)
68
76
  raise FileNotFoundError, file_path unless File.file?(file_path)
69
77
 
@@ -83,8 +91,9 @@ module WhatsappSdk
83
91
 
84
92
  # Delete a Media by ID.
85
93
  #
86
- # @param media_id [Integer] Media Id.
94
+ # @param media_id [String] Media Id.
87
95
  # @return [WhatsappSdk::Api::Response] Response object.
96
+ sig { params(media_id: String).returns(WhatsappSdk::Api::Response) }
88
97
  def delete(media_id:)
89
98
  response = send_request(
90
99
  http_method: "delete",
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require_relative "request"
4
5
  require_relative "response"
@@ -6,9 +7,15 @@ require_relative "response"
6
7
  module WhatsappSdk
7
8
  module Api
8
9
  class Messages < Request
10
+ extend T::Sig
11
+
9
12
  class MissingArgumentError < StandardError
13
+ extend T::Sig
14
+
15
+ sig { returns(String) }
10
16
  attr_reader :message
11
17
 
18
+ sig { params(message: String).void }
12
19
  def initialize(message)
13
20
  @message = message
14
21
  super(message)
@@ -21,6 +28,7 @@ module WhatsappSdk
21
28
  # @param recipient_number [Integer] Recipient' Phone number.
22
29
  # @param message [String] Text to send.
23
30
  # @return [WhatsappSdk::Api::Response] Response object.
31
+ sig { params(sender_id: Integer, recipient_number: Integer, message: String).returns(WhatsappSdk::Api::Response) }
24
32
  def send_text(sender_id:, recipient_number:, message:)
25
33
  params = {
26
34
  messaging_product: "whatsapp",
@@ -50,6 +58,12 @@ module WhatsappSdk
50
58
  # @param name [String] Location name.
51
59
  # @param address [String] Location address.
52
60
  # @return [WhatsappSdk::Api::Response] Response object.
61
+ sig do
62
+ params(
63
+ sender_id: Integer, recipient_number: Integer,
64
+ longitude: Float, latitude: Float, name: String, address: String
65
+ ).returns(WhatsappSdk::Api::Response)
66
+ end
53
67
  def send_location(sender_id:, recipient_number:, longitude:, latitude:, name:, address:)
54
68
  params = {
55
69
  messaging_product: "whatsapp",
@@ -79,10 +93,16 @@ module WhatsappSdk
79
93
  #
80
94
  # @param sender_id [Integer] Sender' phone number.
81
95
  # @param recipient_number [Integer] Recipient' Phone number.
82
- # @param image_id [Integer] Image ID.
96
+ # @param image_id [String] Image ID.
83
97
  # @param link [String] Image link.
84
98
  # @param caption [String] Image caption.
85
99
  # @return [WhatsappSdk::Api::Response] Response object.
100
+ sig do
101
+ params(
102
+ sender_id: Integer, recipient_number: Integer, image_id: T.nilable(String),
103
+ link: T.nilable(String), caption: T.nilable(String)
104
+ ).returns(WhatsappSdk::Api::Response)
105
+ end
86
106
  def send_image(sender_id:, recipient_number:, image_id: nil, link: nil, caption: "")
87
107
  raise MissingArgumentError, "image_id or link is required" if !image_id && !link
88
108
 
@@ -113,9 +133,14 @@ module WhatsappSdk
113
133
  #
114
134
  # @param sender_id [Integer] Sender' phone number.
115
135
  # @param recipient_number [Integer] Recipient' Phone number.
116
- # @param audio_id [Integer] Audio ID.
136
+ # @param audio_id [String] Audio ID.
117
137
  # @param link [String] Audio link.
118
138
  # @return [WhatsappSdk::Api::Response] Response object.
139
+ sig do
140
+ params(
141
+ sender_id: Integer, recipient_number: Integer, audio_id: T.nilable(String), link: T.nilable(String)
142
+ ).returns(WhatsappSdk::Api::Response)
143
+ end
119
144
  def send_audio(sender_id:, recipient_number:, audio_id: nil, link: nil)
120
145
  raise MissingArgumentError, "audio_id or link is required" if !audio_id && !link
121
146
 
@@ -142,10 +167,16 @@ module WhatsappSdk
142
167
  #
143
168
  # @param sender_id [Integer] Sender' phone number.
144
169
  # @param recipient_number [Integer] Recipient' Phone number.
145
- # @param video_id [Integer] Video ID.
170
+ # @param video_id [String] Video ID.
146
171
  # @param link [String] Image link.
147
172
  # @param caption [String] Image caption.
148
173
  # @return [WhatsappSdk::Api::Response] Response object.
174
+ sig do
175
+ params(
176
+ sender_id: Integer, recipient_number: Integer,
177
+ video_id: T.nilable(String), link: T.nilable(String), caption: String
178
+ ).returns(WhatsappSdk::Api::Response)
179
+ end
149
180
  def send_video(sender_id:, recipient_number:, video_id: nil, link: nil, caption: "")
150
181
  raise MissingArgumentError, "video_id or link is required" if !video_id && !link
151
182
 
@@ -176,10 +207,16 @@ module WhatsappSdk
176
207
  #
177
208
  # @param sender_id [Integer] Sender' phone number.
178
209
  # @param recipient_number [Integer] Recipient' Phone number.
179
- # @param document_id [Integer] document ID.
210
+ # @param document_id [String] document ID.
180
211
  # @param link [String] Image link.
181
212
  # @param caption [String] Image caption.
182
213
  # @return [WhatsappSdk::Api::Response] Response object.
214
+ sig do
215
+ params(
216
+ sender_id: Integer, recipient_number: Integer,
217
+ document_id: T.nilable(String), link: T.nilable(String), caption: String
218
+ ).returns(WhatsappSdk::Api::Response)
219
+ end
183
220
  def send_document(sender_id:, recipient_number:, document_id: nil, link: nil, caption: "")
184
221
  raise MissingArgumentError, "document or link is required" if !document_id && !link
185
222
 
@@ -210,8 +247,14 @@ module WhatsappSdk
210
247
  #
211
248
  # @param sender_id [Integer] Sender' phone number.
212
249
  # @param recipient_number [Integer] Recipient' Phone number.
250
+ # @param sticker_id [String] The sticker ID.
213
251
  # @param link [String] Image link.
214
252
  # @return [WhatsappSdk::Api::Response] Response object.
253
+ sig do
254
+ params(
255
+ sender_id: Integer, recipient_number: Integer, sticker_id: T.nilable(String), link: T.nilable(String)
256
+ ).returns(WhatsappSdk::Api::Response)
257
+ end
215
258
  def send_sticker(sender_id:, recipient_number:, sticker_id: nil, link: nil)
216
259
  raise MissingArgumentError, "sticker or link is required" if !sticker_id && !link
217
260
 
@@ -219,7 +262,7 @@ module WhatsappSdk
219
262
  messaging_product: "whatsapp",
220
263
  to: recipient_number,
221
264
  recipient_type: "individual",
222
- type: "sticker"
265
+ type: Resource::Media::Type::Sticker
223
266
  }
224
267
  params[:sticker] = link ? { link: link } : { id: sticker_id }
225
268
 
@@ -242,6 +285,12 @@ module WhatsappSdk
242
285
  # @param contacts [Array<Contact>] Contacts.
243
286
  # @param contacts_json [Json] Contacts.
244
287
  # @return [WhatsappSdk::Api::Response] Response object.
288
+ sig do
289
+ params(
290
+ sender_id: Integer, recipient_number: Integer,
291
+ contacts: T.nilable(T::Array[WhatsappSdk::Resource::Contact]), contacts_json: T::Hash[T.untyped, T.untyped]
292
+ ).returns(WhatsappSdk::Api::Response)
293
+ end
245
294
  def send_contacts(sender_id:, recipient_number:, contacts: nil, contacts_json: {})
246
295
  params = {
247
296
  messaging_product: "whatsapp",
@@ -262,23 +311,24 @@ module WhatsappSdk
262
311
  )
263
312
  end
264
313
 
265
- def send_interactive_button
266
- # TODO: https://developers.facebook.com/docs/whatsapp_sdk/cloud-api/reference/messages#contacts-object
267
- end
314
+ # def send_interactive_button
315
+ # # TODO: https://developers.facebook.com/docs/whatsapp_sdk/cloud-api/reference/messages#contacts-object
316
+ # end
268
317
 
269
- def send_interactive_reply_buttons
270
- # TODO: https://developers.facebook.com/docs/whatsapp_sdk/cloud-api/reference/messages#contacts-object
271
- end
318
+ # def send_interactive_reply_buttons
319
+ # # TODO: https://developers.facebook.com/docs/whatsapp_sdk/cloud-api/reference/messages#contacts-object
320
+ # end
272
321
 
273
- def send_interactive_section
274
- # TODO: https://developers.facebook.com/docs/whatsapp_sdk/cloud-api/reference/messages#contacts-object
275
- end
322
+ # def send_interactive_section
323
+ # # TODO: https://developers.facebook.com/docs/whatsapp_sdk/cloud-api/reference/messages#contacts-object
324
+ # end
276
325
 
277
326
  # Mark a message as read.
278
327
  #
279
328
  # @param sender_id [Integer] Sender' phone number.
280
329
  # @param message_id [Integer] Message ID.
281
330
  # @return [WhatsappSdk::Api::Response] Response object.
331
+ sig { params(sender_id: Integer, message_id: String).returns(WhatsappSdk::Api::Response) }
282
332
  def read_message(sender_id:, message_id:)
283
333
  params = {
284
334
  messaging_product: "whatsapp",
@@ -306,6 +356,13 @@ module WhatsappSdk
306
356
  # @param components [Component] Component.
307
357
  # @param components_json [Json] The component as a Json. If you pass components_json, you can't pass components.
308
358
  # @return [WhatsappSdk::Api::Response] Response object.
359
+ sig do
360
+ params(
361
+ sender_id: Integer, recipient_number: Integer, name: String, language: String,
362
+ components: T.nilable(T::Array[WhatsappSdk::Resource::Component]),
363
+ components_json: T.nilable(T::Array[T::Hash[T.untyped, T.untyped]])
364
+ ).returns(WhatsappSdk::Api::Response)
365
+ end
309
366
  def send_template(sender_id:, recipient_number:, name:, language:, components: nil, components_json: nil)
310
367
  raise MissingArgumentError, "components or components_json is required" if !components && !components_json
311
368
 
@@ -339,6 +396,7 @@ module WhatsappSdk
339
396
 
340
397
  private
341
398
 
399
+ sig { params(sender_id: Integer).returns(String) }
342
400
  def endpoint(sender_id)
343
401
  "#{sender_id}/messages"
344
402
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require_relative "request"
4
5
  require_relative "response"
@@ -10,6 +11,7 @@ module WhatsappSdk
10
11
  #
11
12
  # @param business_id [Integer] Business Id.
12
13
  # @return [WhatsappSdk::Api::Response] Response object.
14
+ sig { params(business_id: Integer).returns(WhatsappSdk::Api::Response) }
13
15
  def registered_numbers(business_id)
14
16
  response = send_request(
15
17
  http_method: "get",
@@ -26,6 +28,7 @@ module WhatsappSdk
26
28
  #
27
29
  # @param phone_number_id [Integer] The registered number we want to retrieve.
28
30
  # @return [WhatsappSdk::Api::Response] Response object.
31
+ sig { params(phone_number_id: Integer).returns(WhatsappSdk::Api::Response) }
29
32
  def registered_number(phone_number_id)
30
33
  response = send_request(
31
34
  http_method: "get",
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
 
3
4
  module WhatsappSdk
4
5
  module Api
5
6
  class Request
6
- API_VERSION = "v13.0"
7
- API_CLIENT = "https://graph.facebook.com/#{API_VERSION}/"
7
+ extend T::Sig
8
8
 
9
9
  def initialize(client = WhatsappSdk.configuration.client)
10
10
  @client = client
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require_relative "responses/message_data_response"
4
5
  require_relative "responses/phone_number_data_response"
@@ -9,19 +10,34 @@ require_relative "responses/message_error_response"
9
10
  module WhatsappSdk
10
11
  module Api
11
12
  class Response
12
- attr_accessor :error, :data
13
+ extend T::Sig
13
14
 
15
+ sig { returns(T.nilable(WhatsappSdk::Api::Responses::ErrorResponse)) }
16
+ attr_accessor :error
17
+
18
+ sig { returns(T.nilable(WhatsappSdk::Api::Responses::DataResponse)) }
19
+ attr_accessor :data
20
+
21
+ sig do
22
+ params(
23
+ response: T::Hash[T.untyped, T.untyped],
24
+ data_class_type: T.class_of(WhatsappSdk::Api::Responses::DataResponse),
25
+ error_class_type: T.class_of(WhatsappSdk::Api::Responses::ErrorResponse)
26
+ ).void
27
+ end
14
28
  def initialize(response:, data_class_type:, error_class_type: Responses::MessageErrorResponse)
15
29
  @data = data_class_type.build_from_response(response: response)
16
30
  @error = error_class_type.build_from_response(response: response)
17
31
  end
18
32
 
19
33
  # @return [Boolean] Whether or not the response is successful.
34
+ sig { returns(T::Boolean) }
20
35
  def ok?
21
36
  @error.nil?
22
37
  end
23
38
 
24
39
  # @return [Boolean] Whether or not the response has an error.
40
+ sig { returns(T::Boolean) }
25
41
  def error?
26
42
  !!@error
27
43
  end
@@ -1,18 +1,25 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  module WhatsappSdk
4
5
  module Api
5
6
  module Responses
6
7
  class DataResponse
8
+ extend ::T::Sig
9
+ extend ::T::Helpers
10
+
11
+ abstract!
12
+
13
+ sig { returns(T::Hash[T.untyped, T.untyped]) }
7
14
  attr_reader :raw_data_response
8
15
 
16
+ sig { params(response: T::Hash[T.untyped, T.untyped]).void }
9
17
  def initialize(response)
10
18
  @raw_data_response = response
11
19
  end
12
20
 
13
- def self.build_from_response(response:) # rubocop:disable Lint/UnusedMethodArgument:
14
- raise NotImplemented
15
- end
21
+ sig { abstract.params(response: T::Hash[T.untyped, T.untyped]).returns(T.nilable(DataResponse)) }
22
+ def self.build_from_response(response:); end
16
23
  end
17
24
  end
18
25
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require_relative "data_response"
4
5
 
@@ -6,14 +7,20 @@ module WhatsappSdk
6
7
  module Api
7
8
  module Responses
8
9
  class ErrorResponse < DataResponse
9
- attr_accessor :error, :status
10
+ sig { returns(T.nilable(T::Boolean)) }
11
+ attr_accessor :error
10
12
 
13
+ sig { returns(T.nilable(Integer)) }
14
+ attr_accessor :status
15
+
16
+ sig { params(response: T::Hash[T.untyped, T.untyped]).void }
11
17
  def initialize(response:)
12
18
  @error = response["error"]
13
19
  @status = response["status"]
14
20
  super(response)
15
21
  end
16
22
 
23
+ sig { override.params(response: T::Hash[T.untyped, T.untyped]).returns(T.nilable(ErrorResponse)) }
17
24
  def self.build_from_response(response:)
18
25
  return unless response["error"]
19
26
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require_relative "data_response"
4
5
 
@@ -6,18 +7,36 @@ module WhatsappSdk
6
7
  module Api
7
8
  module Responses
8
9
  class MediaDataResponse < DataResponse
9
- attr_accessor :id, :url, :mime_type, :sha256, :file_size, :messaging_product
10
+ sig { returns(String) }
11
+ attr_accessor :id
10
12
 
13
+ sig { returns(T.nilable(String)) }
14
+ attr_accessor :url
15
+
16
+ sig { returns(T.nilable(String)) }
17
+ attr_accessor :mime_type
18
+
19
+ sig { returns(T.nilable(String)) }
20
+ attr_accessor :sha256
21
+
22
+ sig { returns(T.nilable(Integer)) }
23
+ attr_accessor :file_size
24
+
25
+ sig { returns(T.nilable(String)) }
26
+ attr_accessor :messaging_product
27
+
28
+ sig { params(response: T::Hash[T.untyped, T.untyped]).void }
11
29
  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"]
30
+ @id = T.let(response["id"], String)
31
+ @messaging_product = T.let(response["messaging_product"], T.nilable(String))
32
+ @url = T.let(response["url"], T.nilable(String))
33
+ @mime_type = T.let(response["mime_type"], T.nilable(String))
34
+ @sha256 = T.let(response["sha256"], T.nilable(String))
35
+ @file_size = T.let(response["file_size"], T.nilable(Integer))
18
36
  super(response)
19
37
  end
20
38
 
39
+ sig { override.params(response: T::Hash[T.untyped, T.untyped]).returns(T.nilable(MediaDataResponse)) }
21
40
  def self.build_from_response(response:)
22
41
  return unless response["id"]
23
42
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  require_relative "../request"
4
5
  require_relative "data_response"
@@ -9,14 +10,28 @@ module WhatsappSdk
9
10
  module Api
10
11
  module Responses
11
12
  class MessageDataResponse < DataResponse
12
- attr_reader :contacts, :messages
13
+ extend T::Sig
13
14
 
15
+ sig { returns(T::Array[::WhatsappSdk::Resource::ContactResponse]) }
16
+ attr_reader :contacts
17
+
18
+ sig { returns(T::Array[::WhatsappSdk::Resource::Message]) }
19
+ attr_reader :messages
20
+
21
+ sig { params(response: T::Hash[T.untyped, T.untyped]).void }
14
22
  def initialize(response:)
15
- @contacts = response["contacts"]&.map { |contact_json| parse_contact(contact_json) }
16
- @messages = response["messages"]&.map { |contact_json| parse_message(contact_json) }
23
+ @contacts = T.let(
24
+ response["contacts"]&.map { |contact_json| parse_contact(contact_json) },
25
+ T::Array[::WhatsappSdk::Resource::ContactResponse]
26
+ )
27
+ @messages = T.let(
28
+ response["messages"]&.map { |contact_json| parse_message(contact_json) },
29
+ T::Array[::WhatsappSdk::Resource::Message]
30
+ )
17
31
  super(response)
18
32
  end
19
33
 
34
+ sig { override.params(response: T::Hash[T.untyped, T.untyped]).returns(T.nilable(MessageDataResponse)) }
20
35
  def self.build_from_response(response:)
21
36
  return unless response["messages"]
22
37
 
@@ -25,10 +40,12 @@ module WhatsappSdk
25
40
 
26
41
  private
27
42
 
43
+ sig { params(message_json: T::Hash[T.untyped, T.untyped]).returns(::WhatsappSdk::Resource::Message) }
28
44
  def parse_message(message_json)
29
45
  ::WhatsappSdk::Resource::Message.new(id: message_json["id"])
30
46
  end
31
47
 
48
+ sig { params(contact_json: T::Hash[T.untyped, T.untyped]).returns(::WhatsappSdk::Resource::ContactResponse) }
32
49
  def parse_contact(contact_json)
33
50
  ::WhatsappSdk::Resource::ContactResponse.new(input: contact_json["input"], wa_id: contact_json["wa_id"])
34
51
  end