whatsapp_sdk 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/CONTRIBUTING.MD +30 -0
- data/Gemfile.lock +5 -33
- data/README.md +73 -24
- data/config/api_versions.yml +32 -0
- data/example.rb +80 -42
- data/lib/whatsapp_sdk/api/api_configuration.rb +2 -2
- data/lib/whatsapp_sdk/api/business_profile.rb +34 -3
- data/lib/whatsapp_sdk/api/client.rb +38 -11
- data/lib/whatsapp_sdk/api/medias.rb +7 -4
- data/lib/whatsapp_sdk/api/messages.rb +2 -1
- data/lib/whatsapp_sdk/api/request.rb +7 -2
- data/lib/whatsapp_sdk/configuration.rb +31 -3
- data/lib/whatsapp_sdk/resource/business_profile.rb +15 -0
- data/lib/whatsapp_sdk/resource/media_types.rb +2 -0
- data/lib/whatsapp_sdk/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53c16bc6791e7862e5e35d1324792e0c0cea54a171e2f861f3e834ec3751e196
|
4
|
+
data.tar.gz: 610c042ac0cf2c095251c2bef1768776260a1d47e93898dd69c410609e6e722a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fdce7569dbb71b96744ee296feb1e90ee5c5300e82ce860550d0e1c3c4c9521ddc88c2ce7f5924c41f0559b17e7d301e9b81c1c0a78e881abc42bcae8102bd1
|
7
|
+
data.tar.gz: cab5e1753ee9ef35b05f7409ceb42af407cd6242dffa4a975a9f511bef417b05cc0cb221b7195508fcb53e7e912c9c5a24ff49eaa4c3df65cda199d16567a11e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# v 0.12.0
|
4
|
+
- Added ability to specify logger @chahmedejaz [#129](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/129)
|
5
|
+
- Allow download of unsupported media types @dvuckovic [#128](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/128)
|
6
|
+
- Allow users to specify the API version. @conr [#126](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/126)
|
7
|
+
- Use http multipart only when is needed. @ignacio-chiazzo [#123](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/123)
|
8
|
+
- Validate Vertical on BusinessProfile update API. @ignacio-chiazzo [#120](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/120)
|
9
|
+
- Added ability to specify fields param in the busines profile API. @ignacio-chiazzo [#119](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/119)
|
10
|
+
|
3
11
|
# v 0.11.0
|
4
12
|
- Bumped API version to v19. @paulomcnally https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/116
|
5
13
|
|
data/CONTRIBUTING.MD
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk) This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
2
|
+
|
3
|
+
If you want a feature implemented in the gem, please open an issue, and we will look as soon as we can.
|
4
|
+
|
5
|
+
Do you want to contribute and are unsure where to start? Ping me on Twitter, and I will help you!
|
6
|
+
|
7
|
+
### Getting started
|
8
|
+
|
9
|
+
Clone the project and ensure tests are passing locally.
|
10
|
+
|
11
|
+
```console
|
12
|
+
bundle install
|
13
|
+
bundle exec rake test
|
14
|
+
```
|
15
|
+
|
16
|
+
#### Configure an App and enable WhatsApp
|
17
|
+
|
18
|
+
Follow the steps in the [Readme#set-up-a-meta-app](/README.md#set-up-a-meta-app)
|
19
|
+
|
20
|
+
#### Architecture
|
21
|
+
|
22
|
+
The main logic lives under `/lib`. There, you can find API classes (Medias, Messages, PhoneNumbers, etc.) and Resources (Button, Address, etc.).
|
23
|
+
Each API class inherits from `Request`, which contains the helper methods to make HTTP requests to Meta.
|
24
|
+
|
25
|
+
If you are new to the code, a good place to start is looking at [closed PRs](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pulls?q=is%3Apr+is%3Aclosed). Here are some helpful PRs:
|
26
|
+
- [Added a new Templates API](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/90)
|
27
|
+
- [Added an error when the user entered a bad input](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/89/files)
|
28
|
+
- [Change on Faraday configuration](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/123/files).
|
29
|
+
|
30
|
+
Do you want to contribute and are unsure where to start? Ping me on Twitter, and I will help you!
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
whatsapp_sdk (0.
|
4
|
+
whatsapp_sdk (0.12.0)
|
5
5
|
faraday (~> 2)
|
6
6
|
faraday-multipart (~> 1)
|
7
7
|
sorbet-runtime (~> 0.5)
|
@@ -17,8 +17,7 @@ GEM
|
|
17
17
|
coderay (1.1.3)
|
18
18
|
crack (0.4.5)
|
19
19
|
rexml
|
20
|
-
|
21
|
-
faraday (2.7.12)
|
20
|
+
faraday (2.8.1)
|
22
21
|
base64
|
23
22
|
faraday-net_http (>= 2.0, < 3.1)
|
24
23
|
ruby2_keywords (>= 0.0.4)
|
@@ -29,8 +28,7 @@ GEM
|
|
29
28
|
method_source (1.0.0)
|
30
29
|
minitest (5.16.1)
|
31
30
|
mocha (1.14.0)
|
32
|
-
multipart-post (2.
|
33
|
-
netrc (0.11.0)
|
31
|
+
multipart-post (2.4.0)
|
34
32
|
parallel (1.22.1)
|
35
33
|
parser (3.1.2.0)
|
36
34
|
ast (~> 2.4.1)
|
@@ -42,11 +40,6 @@ GEM
|
|
42
40
|
public_suffix (5.0.0)
|
43
41
|
rainbow (3.1.1)
|
44
42
|
rake (12.3.3)
|
45
|
-
rbi (0.0.15)
|
46
|
-
ast
|
47
|
-
parser (>= 2.6.4.0)
|
48
|
-
sorbet-runtime (>= 0.5.9204)
|
49
|
-
unparser
|
50
43
|
regexp_parser (2.5.0)
|
51
44
|
rexml (3.2.5)
|
52
45
|
rubocop (1.30.1)
|
@@ -75,39 +68,18 @@ GEM
|
|
75
68
|
sorbet-static (0.5.10346-universal-darwin-19)
|
76
69
|
sorbet-static (0.5.10346-universal-darwin-21)
|
77
70
|
sorbet-static (0.5.10346-x86_64-linux)
|
78
|
-
sorbet-static-and-runtime (0.5.10346)
|
79
|
-
sorbet (= 0.5.10346)
|
80
|
-
sorbet-runtime (= 0.5.10346)
|
81
71
|
spoom (1.1.12)
|
82
72
|
sorbet (>= 0.5.9204)
|
83
73
|
sorbet-runtime (>= 0.5.9204)
|
84
74
|
thor (>= 0.19.2)
|
85
|
-
tapioca (0.
|
86
|
-
bundler (>= 1.17.3)
|
87
|
-
netrc (>= 0.11.0)
|
88
|
-
parallel (>= 1.21.0)
|
89
|
-
pry (>= 0.12.2)
|
90
|
-
rbi (~> 0.0.0, >= 0.0.14)
|
91
|
-
sorbet-static-and-runtime (>= 0.5.9204)
|
92
|
-
spoom (~> 1.1.0, >= 1.1.11)
|
93
|
-
thor (>= 1.2.0)
|
94
|
-
yard-sorbet
|
75
|
+
tapioca (0.0.1)
|
95
76
|
thor (1.2.1)
|
96
77
|
unicode-display_width (2.2.0)
|
97
|
-
unparser (0.6.5)
|
98
|
-
diff-lcs (~> 1.3)
|
99
|
-
parser (>= 3.1.0)
|
100
78
|
webmock (3.18.1)
|
101
79
|
addressable (>= 2.8.0)
|
102
80
|
crack (>= 0.3.2)
|
103
81
|
hashdiff (>= 0.4.0, < 2.0.0)
|
104
|
-
|
105
|
-
yard (0.9.28)
|
106
|
-
webrick (~> 1.7.0)
|
107
|
-
yard-sorbet (0.7.0)
|
108
|
-
sorbet-runtime (>= 0.5)
|
109
|
-
yard (>= 0.9)
|
110
|
-
zeitwerk (2.6.12)
|
82
|
+
zeitwerk (2.6.13)
|
111
83
|
|
112
84
|
PLATFORMS
|
113
85
|
arm64-darwin-21
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Ruby Whatsapp SDK
|
2
|
+
|
2
3
|
[![Gem Version](https://badge.fury.io/rb/whatsapp_sdk.svg)](https://badge.fury.io/rb/whatsapp_sdk)
|
3
4
|
[![CircleCI](https://circleci.com/gh/circleci/circleci-docs.svg?style=svg)](https://circleci.com/gh/ignacio-chiazzo/ruby_whatsapp_sdk)
|
4
5
|
<a href="https://codeclimate.com/github/ignacio-chiazzo/ruby_whatsapp_sdk/maintainability"><img src="https://api.codeclimate.com/v1/badges/169cce95450272e4ad7d/maintainability" /></a>
|
@@ -6,7 +7,6 @@
|
|
6
7
|
The SDK provides a set of operations and classes to use the Whatsapp API.
|
7
8
|
Send stickers, messages, audio, videos, locations, react and reply to messages or just ask for the phone numbers through this library in a few steps!
|
8
9
|
|
9
|
-
|
10
10
|
## Demo
|
11
11
|
|
12
12
|
https://user-images.githubusercontent.com/11672878/173238826-6fc0a6f8-d0ee-4eae-8947-7dfd3b8b3446.mov
|
@@ -35,21 +35,37 @@ There are three primary resources, `Messages`, `Media` and `PhoneNumbers`. `Mess
|
|
35
35
|
|
36
36
|
To use `Messages`, `Media` or `PhoneNumbers`, you need to initialize the `Client` that contains auth information. There are two ways to do it.
|
37
37
|
|
38
|
-
1
|
39
|
-
|
38
|
+
1. Use an initializer
|
39
|
+
|
40
|
+
Note:
|
41
|
+
Optionally, you can specify the desired API version to use (defaults to the latest version if omitted).
|
42
|
+
Available API version can be found [here](https://developers.facebook.com/docs/graph-api/changelog/versions).
|
43
|
+
|
40
44
|
```ruby
|
41
45
|
# config/initializers/whatsapp_sdk.rb
|
42
46
|
WhatsappSdk.configure do |config|
|
43
47
|
config.access_token = ACCESS_TOKEN
|
48
|
+
config.api_version = API_VERSION
|
49
|
+
config.logger = Logger.new(STDOUT) # optional, Faraday logger to attach
|
50
|
+
config.logger_options = { bodies: true } # optional, they are all valid logger_options for Faraday
|
44
51
|
end
|
45
52
|
```
|
53
|
+
More Details on Faraday Logger Options are [here](https://lostisland.github.io/faraday/#/middleware/included/logging?id=logging).
|
54
|
+
|
46
55
|
OR 2) Create a `Client` instance and pass it to the `Messages`, `Medias` or `PhoneNumbers` instance like this:
|
47
56
|
|
57
|
+
**Without Logger:**
|
48
58
|
```ruby
|
49
59
|
client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>") # replace this with a valid access token
|
50
60
|
messages_api = WhatsappSdk::Api::Messages.new(client)
|
51
61
|
```
|
52
|
-
|
62
|
+
**With Logger:**
|
63
|
+
```ruby
|
64
|
+
logger = Logger.new(STDOUT)
|
65
|
+
logger_options = { bodies: true }
|
66
|
+
client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>", "<API VERSION>", logger, logger_options) # replace this with a valid access token
|
67
|
+
messages_api = WhatsappSdk::Api::Messages.new(client)
|
68
|
+
```
|
53
69
|
Each API operation returns a `WhatsappSdk::Api::Response` that contains `data` and `error` and a couple of helpful functions such as `ok?` and `error?`. There are three types of responses `WhatsappSdk::Api::MessageDataResponse`, `WhatsappSdk::Api::PhoneNumberDataResponse` and `WhatsappSdk::Api::PhoneNumbersDataResponse`. Each of them contains different attributes.
|
54
70
|
|
55
71
|
## Set up a Meta app
|
@@ -68,7 +84,7 @@ Each API operation returns a `WhatsappSdk::Api::Response` that contains `data` a
|
|
68
84
|
|
69
85
|
Try sending a message to your phone in the UI.
|
70
86
|
|
71
|
-
<details><summary>4) Copy the ACCESS_TOKEN, the SENDER_ID, the BUSINESS_ID and the
|
87
|
+
<details><summary>4) Copy the ACCESS_TOKEN, the SENDER_ID, the BUSINESS_ID and the RECIPIENT_NUMBER</summary>
|
72
88
|
<img width="1010" alt="Screen Shot 2022-09-05 at 11 13 24 AM" src="https://user-images.githubusercontent.com/11672878/188480634-369f8de1-b851-4735-86de-f49e96f78d8c.png">
|
73
89
|
</details>
|
74
90
|
|
@@ -76,11 +92,12 @@ Try sending a message to your phone in the UI.
|
|
76
92
|
|
77
93
|
<details><summary>5) Use the GEM to interact with Whatsapp</summary>
|
78
94
|
|
79
|
-
Example:
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
95
|
+
Example:
|
96
|
+
|
97
|
+
1. Install the gem by running `gem install whatsapp_sdk` in the gem.
|
98
|
+
2. Open the irb terminal by running `irb`
|
99
|
+
3. `require "whatsapp_sdk"`
|
100
|
+
4. Set up the `ACCESS_TOKEN`, the `SENDER_ID`, the `BUSINESS_ID` and the `RECIPIENT_NUMBER` in variables.
|
84
101
|
|
85
102
|
```ruby
|
86
103
|
ACCESS_TOKEN = "EAAZAvvr0DZBs0BABRLF8zohP5Epc6pyNu"
|
@@ -89,7 +106,7 @@ SENDER_ID = 1234567891011
|
|
89
106
|
RECIPIENT_NUMBER = 12398765432
|
90
107
|
```
|
91
108
|
|
92
|
-
5
|
109
|
+
5. Configure the Client by running
|
93
110
|
|
94
111
|
```ruby
|
95
112
|
WhatsappSdk.configure do |config|
|
@@ -97,15 +114,17 @@ WhatsappSdk.configure do |config|
|
|
97
114
|
end
|
98
115
|
```
|
99
116
|
|
100
|
-
6
|
117
|
+
6. Try the Phone Numbers API or Messages API
|
101
118
|
|
102
119
|
Phone Numbers API
|
120
|
+
|
103
121
|
```ruby
|
104
122
|
phone_numbers_api = WhatsappSdk::Api::PhoneNumbers.new
|
105
123
|
registered_number = phone_numbers_api.registered_number(SENDER_ID)
|
106
124
|
```
|
107
125
|
|
108
126
|
Messages API
|
127
|
+
|
109
128
|
```ruby
|
110
129
|
messages_api = WhatsappSdk::Api::Messages.new
|
111
130
|
message_sent = messages_api.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER,
|
@@ -117,6 +136,7 @@ Check the [example.rb file](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk
|
|
117
136
|
</details>
|
118
137
|
|
119
138
|
## Operations
|
139
|
+
|
120
140
|
First, create the client and then create an instance `WhatsappSdk::Api::Messages` that requires a client as a param like this:
|
121
141
|
|
122
142
|
```ruby
|
@@ -132,6 +152,7 @@ Note: Remember to initialize the client first!
|
|
132
152
|
## APIs
|
133
153
|
|
134
154
|
### Templates
|
155
|
+
|
135
156
|
<details>
|
136
157
|
|
137
158
|
```ruby
|
@@ -142,25 +163,30 @@ templates_api.templates(business_id: BUSINESS_ID)
|
|
142
163
|
new_template = templates_api.create(
|
143
164
|
business_id: BUSINESS_ID, name: "seasonal_promotion", language: "en_US", category: "MARKETING",
|
144
165
|
components_json: components_json, allow_category_change: true
|
145
|
-
)
|
166
|
+
)
|
146
167
|
|
147
168
|
# Delete a template
|
148
169
|
templates_api.delete(business_id: BUSINESS_ID, name: "my_name") # delete by name
|
149
170
|
```
|
171
|
+
|
150
172
|
</details>
|
151
173
|
|
152
174
|
### Business Profile API
|
175
|
+
|
153
176
|
<details>
|
154
177
|
|
155
178
|
Get the details of your business
|
179
|
+
|
156
180
|
```ruby
|
157
181
|
business_profile = business_profile_api.details(123456)
|
158
182
|
```
|
159
183
|
|
160
184
|
Update the details of your business
|
185
|
+
|
161
186
|
```ruby
|
162
187
|
business_profile_api.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } )
|
163
188
|
```
|
189
|
+
|
164
190
|
</details>
|
165
191
|
|
166
192
|
### Phone numbers API
|
@@ -168,45 +194,55 @@ business_profile_api.update(phone_number_id: SENDER_ID, params: { about: "A very
|
|
168
194
|
<details>
|
169
195
|
|
170
196
|
Get the list of phone numbers registered
|
197
|
+
|
171
198
|
```ruby
|
172
199
|
phone_numbers_api.registered_numbers(123456) # accepts a business_id
|
173
200
|
```
|
174
201
|
|
175
202
|
Get the a phone number by id
|
203
|
+
|
176
204
|
```ruby
|
177
205
|
phone_numbers_api.registered_numbers(123456) # accepts a phone_number_id
|
178
206
|
```
|
179
207
|
|
180
208
|
Register a phone number
|
209
|
+
|
181
210
|
```ruby
|
182
211
|
phone_numbers_api.register_number(phone_number_id, pin)
|
183
212
|
```
|
184
213
|
|
185
214
|
Deregister a phone number
|
215
|
+
|
186
216
|
```ruby
|
187
217
|
phone_numbers_api.deregister_number(phone_number_id)
|
188
218
|
```
|
219
|
+
|
189
220
|
</details>
|
190
221
|
|
191
222
|
### Media API
|
223
|
+
|
192
224
|
<details>
|
193
225
|
|
194
226
|
Upload a media
|
227
|
+
|
195
228
|
```ruby
|
196
229
|
medias_api.upload(sender_id: SENDER_ID, file_path: "tmp/whatsapp.png", type: "image/png")
|
197
230
|
```
|
198
231
|
|
199
232
|
Get a media
|
233
|
+
|
200
234
|
```ruby
|
201
235
|
media = medias_api.media(media_id: MEDIA_ID)
|
202
236
|
```
|
203
237
|
|
204
238
|
Download media
|
239
|
+
|
205
240
|
```ruby
|
206
241
|
medias_api.download(url: MEDIA_URL, file_path: 'tmp/downloaded_whatsapp.png', media_type: "image/png")
|
207
242
|
```
|
208
243
|
|
209
244
|
Delete a media
|
245
|
+
|
210
246
|
```ruby
|
211
247
|
medias_api.delete(media_id: MEDIA_ID)
|
212
248
|
```
|
@@ -214,6 +250,7 @@ medias_api.delete(media_id: MEDIA_ID)
|
|
214
250
|
</details>
|
215
251
|
|
216
252
|
### Messages API
|
253
|
+
|
217
254
|
<details>
|
218
255
|
|
219
256
|
**Send a text message**
|
@@ -223,6 +260,7 @@ messages_api.send_text(sender_id: 1234, recipient_number: 112345678, message: "h
|
|
223
260
|
```
|
224
261
|
|
225
262
|
**Read a message**
|
263
|
+
|
226
264
|
```ruby
|
227
265
|
messages_api.read_message(sender_id: 1234, message_id: "wamid.HBgLMTM0M12345678910=")
|
228
266
|
```
|
@@ -230,7 +268,7 @@ messages_api.read_message(sender_id: 1234, message_id: "wamid.HBgLMTM0M123456789
|
|
230
268
|
Note: To get the `message_id` you can set up [Webhooks](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components) that will listen and fire an event when a message is received.
|
231
269
|
|
232
270
|
**Send a reaction to message**
|
233
|
-
To send a reaction to a message, you need to obtain the
|
271
|
+
To send a reaction to a message, you need to obtain the message id and look for the emoji's unicode you want to use.
|
234
272
|
|
235
273
|
```ruby
|
236
274
|
messages_api.send_reaction(sender_id: 123_123, recipient_number: 56_789, message_id: "12345", emoji: "\u{1f550}")
|
@@ -256,6 +294,7 @@ messages_api.send_location(
|
|
256
294
|
|
257
295
|
**Send an image message**
|
258
296
|
It could use a link or an image_id.
|
297
|
+
|
259
298
|
```ruby
|
260
299
|
# with a link
|
261
300
|
messages_api.send_image(
|
@@ -270,6 +309,7 @@ messages_api.send_image(
|
|
270
309
|
|
271
310
|
**Send an audio message**
|
272
311
|
It could use a link or an audio_id.
|
312
|
+
|
273
313
|
```ruby
|
274
314
|
# with a link
|
275
315
|
messages_api.send_audio(sender_id: 123123, recipient_number: 56789, link: "audio_link")
|
@@ -280,6 +320,7 @@ messages_api.send_audio(sender_id: 123123, recipient_number: 56789, audio_id: "1
|
|
280
320
|
|
281
321
|
**Send a document message**
|
282
322
|
It could use a link or a document_id.
|
323
|
+
|
283
324
|
```ruby
|
284
325
|
# with a link
|
285
326
|
messages_api.send_document(
|
@@ -294,6 +335,7 @@ messages_api.send_document(
|
|
294
335
|
|
295
336
|
**Send a sticker message**
|
296
337
|
It could use a link or a sticker_id.
|
338
|
+
|
297
339
|
```ruby
|
298
340
|
# with a link
|
299
341
|
messages_api.send_sticker(sender_id: 123123, recipient_number: 56789, link: "link")
|
@@ -310,7 +352,8 @@ contacts = [create_contact(params)]
|
|
310
352
|
messages_api.send_contacts(sender_id: 123123, recipient_number: 56789, contacts: contacts)
|
311
353
|
```
|
312
354
|
|
313
|
-
|
355
|
+
Alternatively, you could pass a plain json like this:
|
356
|
+
|
314
357
|
```ruby
|
315
358
|
messages_api.send_contacts(sender_id: 123123, recipient_number: 56789, contacts_json: {...})
|
316
359
|
```
|
@@ -328,7 +371,7 @@ date_time = WhatsappSdk::Resource::DateTime.new(fallback_value: "2020-01-01T00:0
|
|
328
371
|
image = WhatsappSdk::Resource::Media.new(type: "image", link: "http(s)://URL")
|
329
372
|
|
330
373
|
parameter_image = WhatsappSdk::Resource::ParameterObject.new(type: WhatsappSdk::Resource::ParameterObject::Type::Image, image: image)
|
331
|
-
# You can also use a plain string as type e.g.
|
374
|
+
# You can also use a plain string as type e.g.
|
332
375
|
# parameter_image = WhatsappSdk::Resource::ParameterObject.new(type: "image", image: image)
|
333
376
|
parameter_text = WhatsappSdk::Resource::ParameterObject.new(type: WhatsappSdk::Resource::ParameterObject::Type::Text, text: "TEXT_STRING")
|
334
377
|
parameter_currency = WhatsappSdk::Resource::ParameterObject.new(type: WhatsappSdk::Resource::ParameterObject::Type::Currency, currency: currency)
|
@@ -366,7 +409,8 @@ button_component2 = WhatsappSdk::Resource::Component.new(
|
|
366
409
|
|
367
410
|
</details>
|
368
411
|
|
369
|
-
|
412
|
+
Alternatively, you could pass a plain json like this:
|
413
|
+
|
370
414
|
```ruby
|
371
415
|
@messages_api.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [{...}])
|
372
416
|
```
|
@@ -421,9 +465,11 @@ messages_api.send_interactive_list_messages(
|
|
421
465
|
interactive: interactive_list_messages
|
422
466
|
)
|
423
467
|
```
|
468
|
+
|
424
469
|
</details>
|
425
470
|
|
426
|
-
|
471
|
+
Alternatively, you could pass a plain json like this:
|
472
|
+
|
427
473
|
```ruby
|
428
474
|
messages_api.send_interactive_list_messages(
|
429
475
|
sender_id: 12_345, recipient_number: 1234567890
|
@@ -477,17 +523,19 @@ messages_api.send_interactive_reply_buttons(
|
|
477
523
|
interactive: interactive_reply_buttons
|
478
524
|
)
|
479
525
|
```
|
526
|
+
|
480
527
|
</details>
|
481
528
|
|
482
529
|
Alternative, you could pass a plain json like this:
|
530
|
+
|
483
531
|
```ruby
|
484
532
|
messages_api.send_interactive_reply_buttons(
|
485
533
|
sender_id: 12_345, recipient_number: 1234567890
|
486
534
|
interactive_json: {...}
|
487
535
|
)
|
488
536
|
```
|
489
|
-
</details>
|
490
537
|
|
538
|
+
</details>
|
491
539
|
|
492
540
|
## Examples
|
493
541
|
|
@@ -500,11 +548,11 @@ Visit [the example file](/example.rb) with examples to call the API in a single
|
|
500
548
|
|
501
549
|
## Troubleshooting
|
502
550
|
|
503
|
-
- If the API response is `success`,
|
551
|
+
- If the API response is `success`, but the message is not delivered, ensure the device you're sending the message to is using a supported Whatsapp version. [Check documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/support/troubleshooting#message-not-delivered). Try also replying a message to the number you are registered on your Whatsapp.
|
504
552
|
- Ensure your Meta App uses an API version greater than or equal to `v.14`.
|
505
553
|
- Ensure that the Panel in the Facebook dashboard doesn't display any errors.
|
506
554
|
|
507
|
-
Note: Sometimes the messages are delayed; see [Meta documentation](https://developers.facebook.com/docs/whatsapp/on-premises/guides/send-message-performance#delays).
|
555
|
+
Note: Sometimes the messages are delayed; see [Meta documentation](https://developers.facebook.com/docs/whatsapp/on-premises/guides/send-message-performance#delays).
|
508
556
|
|
509
557
|
## Development
|
510
558
|
|
@@ -513,22 +561,23 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
513
561
|
Run ' bundle exec rake install ' to install this gem onto your local machine. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
514
562
|
|
515
563
|
### Run all the tests
|
564
|
+
|
516
565
|
- **Unit tests:** Run `rake test`
|
517
566
|
- **Sorbet Typecheck:** run `srb tc`
|
518
567
|
- **Linters:** `bundle exec rubocop`
|
519
568
|
|
520
|
-
|
521
569
|
To update the Cloud API version update the version in `lib/whatsapp_sdk/api/api_configuration.rb`. Check the [Cloud API changelog for API udpates](https://developers.facebook.com/docs/whatsapp/business-platform/changelog#api-error-response-behavior).
|
522
570
|
|
523
571
|
## Contributing
|
524
572
|
|
525
573
|
Bug reports and pull requests are welcome on GitHub at [https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk) This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
526
574
|
|
527
|
-
If you want a feature to be implemented in the gem, please, open an issue and we will take a look as soon as we can.
|
528
|
-
|
575
|
+
If you want a feature to be implemented in the gem, please, open an issue and we will take a look as soon as we can.
|
529
576
|
|
530
577
|
Do you want to contribute and are unsure where to start? Ping me on Twitter, and I will help you!
|
531
578
|
|
579
|
+
Check [Contributing](/CONTRIBUTING.MD) file.
|
580
|
+
|
532
581
|
## License
|
533
582
|
|
534
583
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -0,0 +1,32 @@
|
|
1
|
+
- v19.0
|
2
|
+
- v18.0
|
3
|
+
- v17.0
|
4
|
+
- v16.0
|
5
|
+
- v15.0
|
6
|
+
- v14.0
|
7
|
+
- v13.0
|
8
|
+
- v12.0
|
9
|
+
- v11.0
|
10
|
+
- v10.0
|
11
|
+
- v9.0
|
12
|
+
- v8.0
|
13
|
+
- v7.0
|
14
|
+
- v6.0
|
15
|
+
- v5.0
|
16
|
+
- v4.0
|
17
|
+
- v3.3
|
18
|
+
- v3.2
|
19
|
+
- v3.1
|
20
|
+
- v3.0
|
21
|
+
- v2.12
|
22
|
+
- v2.11
|
23
|
+
- v2.10
|
24
|
+
- v2.9
|
25
|
+
- v2.8
|
26
|
+
- v2.7
|
27
|
+
- v2.6
|
28
|
+
- v2.5
|
29
|
+
- v2.4
|
30
|
+
- v2.3
|
31
|
+
- v2.2
|
32
|
+
- v2.1
|
data/example.rb
CHANGED
@@ -33,6 +33,8 @@ if ACCESS_TOKEN == "<TODO replace>"
|
|
33
33
|
exit
|
34
34
|
end
|
35
35
|
|
36
|
+
puts "\n\n\n\n\n\n *************** Starting calling the Cloud API *************** \n"
|
37
|
+
|
36
38
|
################# Initialize Client #################
|
37
39
|
WhatsappSdk.configure do |config|
|
38
40
|
config.access_token = ACCESS_TOKEN
|
@@ -46,6 +48,14 @@ def print_message_sent(message_response)
|
|
46
48
|
puts "Error: #{message_response.error&.to_s}"
|
47
49
|
end
|
48
50
|
end
|
51
|
+
|
52
|
+
def print_data_or_error(response, identifier)
|
53
|
+
if response.error?
|
54
|
+
return "Error: #{response.error&.to_s}"
|
55
|
+
end
|
56
|
+
|
57
|
+
return identifier
|
58
|
+
end
|
49
59
|
##################################################
|
50
60
|
|
51
61
|
|
@@ -56,12 +66,13 @@ business_profile_api = WhatsappSdk::Api::BusinessProfile.new
|
|
56
66
|
templates_api = WhatsappSdk::Api::Templates.new
|
57
67
|
|
58
68
|
############################## Templates API ##############################
|
59
|
-
|
60
69
|
## Get list of templates
|
61
|
-
templates_api.templates(business_id: BUSINESS_ID)
|
70
|
+
templates = templates_api.templates(business_id: BUSINESS_ID)
|
71
|
+
puts "GET Templates list : #{print_data_or_error(templates, templates.data&.templates.map { |r| r.template.name })}"
|
62
72
|
|
63
73
|
## Get message templates namespace
|
64
|
-
templates_api.get_message_template_namespace(business_id: BUSINESS_ID)
|
74
|
+
template_namespace = templates_api.get_message_template_namespace(business_id: BUSINESS_ID)
|
75
|
+
puts "GET template by namespace: #{print_data_or_error(template_namespace, template_namespace.data&.id)}"
|
65
76
|
|
66
77
|
# Create a template
|
67
78
|
components_json = [
|
@@ -97,6 +108,7 @@ new_template = templates_api.create(
|
|
97
108
|
business_id: BUSINESS_ID, name: "seasonal_promotion", language: "ka", category: "MARKETING",
|
98
109
|
components_json: components_json, allow_category_change: true
|
99
110
|
)
|
111
|
+
puts "GET template by namespace: #{print_data_or_error(template_namespace, template_namespace.data&.id)}"
|
100
112
|
|
101
113
|
# Update a template
|
102
114
|
components_json = [
|
@@ -112,66 +124,83 @@ components_json = [
|
|
112
124
|
]
|
113
125
|
}
|
114
126
|
]
|
115
|
-
templates_api.update(template_id: "1624560287967996", category: "UTILITY")
|
127
|
+
updated_template = templates_api.update(template_id: "1624560287967996", category: "UTILITY")
|
128
|
+
puts "UPDATE template by id: #{print_data_or_error(updated_template, updated_template.data&.id)}"
|
116
129
|
|
117
130
|
## Delete a template
|
118
|
-
templates_api.delete(business_id: BUSINESS_ID, name: "seasonal_promotion") # delete by name
|
131
|
+
delete_template = templates_api.delete(business_id: BUSINESS_ID, name: "seasonal_promotion") # delete by name
|
132
|
+
puts "DELETE template by id: #{print_data_or_error(delete_template, delete_template.data&.id) }"
|
119
133
|
# templates_api.delete(business_id: BUSINESS_ID, name: "name2", hsm_id: "243213188351928") # delete by name and id
|
120
134
|
|
121
135
|
############################## Business API ##############################
|
122
136
|
business_profile = business_profile_api.details(SENDER_ID)
|
123
|
-
|
137
|
+
puts "DELETE Business Profile by id: #{print_data_or_error(delete_template, business_profile.data&.id) }"
|
138
|
+
|
139
|
+
updated_bp = business_profile_api.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } )
|
140
|
+
puts "UPDATE Business Profile by id: #{print_data_or_error(updated_bp, updated_bp.data&.id) }"
|
124
141
|
|
125
142
|
############################## Phone Numbers API ##############################
|
126
143
|
registered_number = phone_numbers_api.registered_number(SENDER_ID)
|
144
|
+
puts "GET Registered number: #{print_data_or_error(registered_number, registered_number.data&.id)}"
|
145
|
+
|
127
146
|
registered_numbers = phone_numbers_api.registered_numbers(BUSINESS_ID)
|
147
|
+
puts "GET Registered numbers: #{print_data_or_error(registered_number, registered_numbers.data&.phone_numbers.map(&:id))}"
|
128
148
|
|
129
149
|
############################## Media API ##############################
|
130
150
|
|
131
151
|
##### Image #####
|
132
152
|
# upload a Image
|
133
153
|
uploaded_media = medias_api.upload(sender_id: SENDER_ID, file_path: "tmp/whatsapp.png", type: "image/png")
|
134
|
-
|
135
|
-
puts "Uploaded media id: #{media_id}"
|
154
|
+
puts "Uploaded media id: #{print_data_or_error(uploaded_media, uploaded_media.data&.id)}"
|
136
155
|
|
137
156
|
# get a media Image
|
138
|
-
|
139
|
-
|
157
|
+
if uploaded_media.data&.id
|
158
|
+
media = medias_api.media(media_id: uploaded_media.data&.id)
|
159
|
+
puts "GET Media id: #{print_data_or_error(media, media.data&.id)}"
|
140
160
|
|
141
|
-
# download media Image
|
142
|
-
download_image = medias_api.download(url: media.url, file_path: 'tmp/downloaded_image.png', media_type: "image/png")
|
143
|
-
puts "Downloaded: #{download_image.data.success?}"
|
161
|
+
# download media Image
|
162
|
+
download_image = medias_api.download(url: media.data.url, file_path: 'tmp/downloaded_image.png', media_type: "image/png")
|
163
|
+
puts "Downloaded: #{print_data_or_error(download_image, download_image.data.success?)}"
|
144
164
|
|
145
|
-
# delete a media
|
146
|
-
deleted_media = medias_api.delete(media_id: media
|
147
|
-
puts "
|
165
|
+
# delete a media
|
166
|
+
deleted_media = medias_api.delete(media_id: media.data.id)
|
167
|
+
puts "DELETE: #{print_data_or_error(deleted_media, deleted_media.data.success?)}"
|
168
|
+
end
|
148
169
|
|
149
170
|
#### Audio ####
|
150
171
|
# upload an audio
|
151
172
|
uploaded_media = medias_api.upload(sender_id: SENDER_ID, file_path: "tmp/downloaded_audio.ogg", type: "audio/ogg")
|
173
|
+
puts "Uploaded media id: #{print_data_or_error(uploaded_media, uploaded_media.data&.id)}"
|
174
|
+
|
175
|
+
if uploaded_media.data&.id
|
176
|
+
media_id = uploaded_media.data&.id
|
152
177
|
media_id = uploaded_media.data&.id
|
178
|
+
puts "Uploaded media id: #{media_id}"
|
179
|
+
media_id = uploaded_media.data&.id
|
153
180
|
puts "Uploaded media id: #{media_id}"
|
154
181
|
|
155
|
-
# get a media audio
|
156
|
-
media = medias_api.media(media_id: media_id)
|
157
|
-
puts "Media
|
182
|
+
# get a media audio
|
183
|
+
media = medias_api.media(media_id: media_id)
|
184
|
+
puts "GET Media id: #{print_data_or_error(media, media.data&.id)}"
|
158
185
|
|
159
|
-
# get a media audio
|
160
|
-
audio_link = media.url
|
161
|
-
download_image = medias_api.download(url: audio_link, file_path: 'tmp/downloaded_audio2.ogg', media_type: "audio/ogg")
|
162
|
-
puts "
|
186
|
+
# get a media audio
|
187
|
+
audio_link = media.data.url
|
188
|
+
download_image = medias_api.download(url: audio_link, file_path: 'tmp/downloaded_audio2.ogg', media_type: "audio/ogg")
|
189
|
+
puts "Download Media Audio: #{print_data_or_error(download_image, download_image.data.success?)}"
|
190
|
+
end
|
163
191
|
|
164
192
|
############################## Messages API ##############################
|
165
193
|
|
166
194
|
######### SEND A TEXT MESSAGE
|
167
|
-
message_sent = messages_api.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER,
|
168
|
-
message: "Hey there! it's Whatsapp Ruby SDK")
|
195
|
+
message_sent = messages_api.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message: "Hey there! it's Whatsapp Ruby SDK")
|
169
196
|
print_message_sent(message_sent)
|
170
197
|
|
171
198
|
######### React to a message
|
172
199
|
message_id = message_sent.data.messages.first.id
|
173
|
-
messages_api.send_reaction(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message_id: message_id, emoji: "\u{1f550}")
|
174
|
-
messages_api.send_reaction(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message_id: message_id, emoji: "⛄️")
|
200
|
+
reaction_1_sent = messages_api.send_reaction(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message_id: message_id, emoji: "\u{1f550}")
|
201
|
+
reaction_2_sent = messages_api.send_reaction(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message_id: message_id, emoji: "⛄️")
|
202
|
+
puts "Message Reaction 1: #{print_data_or_error(reaction_1_sent, reaction_1_sent.data&.messages.first&.id)}"
|
203
|
+
puts "Message Reaction 2: #{print_data_or_error(reaction_2_sent, reaction_2_sent.data&.messages.first&.id)}"
|
175
204
|
|
176
205
|
######### Reply to a message
|
177
206
|
message_to_reply_id = message_sent.data.messages.first.id
|
@@ -190,40 +219,49 @@ print_message_sent(location_sent)
|
|
190
219
|
|
191
220
|
######### SEND AN IMAGE
|
192
221
|
# Send an image with a link
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
222
|
+
if media.data&.id
|
223
|
+
image_sent = messages_api.send_image(
|
224
|
+
sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: media.data.url, caption: "Ignacio Chiazzo Profile"
|
225
|
+
)
|
226
|
+
print_message_sent(image_sent)
|
227
|
+
|
228
|
+
# Send an image with an id
|
229
|
+
messages_api.send_image(
|
230
|
+
sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, image_id: media.data.id, caption: "Ignacio Chiazzo Profile"
|
231
|
+
)
|
232
|
+
print_message_sent(image_sent)
|
233
|
+
end
|
202
234
|
|
203
235
|
######### SEND AUDIOS
|
204
236
|
## with a link
|
205
|
-
messages_api.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "audio_link")
|
237
|
+
audio_sent = messages_api.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "audio_link")
|
238
|
+
print_message_sent(audio_sent)
|
206
239
|
|
207
240
|
## with an audio id
|
208
|
-
messages_api.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, audio_id: "1234")
|
241
|
+
audio_sent = messages_api.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, audio_id: "1234")
|
242
|
+
print_message_sent(audio_sent)
|
209
243
|
|
210
244
|
######### SEND DOCUMENTS
|
211
245
|
## with a link
|
212
|
-
messages_api.send_document(
|
246
|
+
document_sent = messages_api.send_document(
|
213
247
|
sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "document_link", caption: "Ignacio Chiazzo"
|
214
248
|
)
|
249
|
+
print_message_sent(document_sent)
|
215
250
|
|
216
251
|
## with a document id
|
217
|
-
messages_api.send_document(
|
252
|
+
document_sent = messages_api.send_document(
|
218
253
|
sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, document_id: "1234", caption: "Ignacio Chiazzo"
|
219
254
|
)
|
255
|
+
print_message_sent(document_sent)
|
220
256
|
|
221
257
|
######### SEND STICKERS
|
222
258
|
## with a link
|
223
|
-
messages_api.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "link")
|
259
|
+
sticker_sent = messages_api.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "link")
|
260
|
+
print_message_sent(sticker_sent)
|
224
261
|
|
225
262
|
## with a sticker_id
|
226
|
-
messages_api.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, sticker_id: "1234")
|
263
|
+
sticker_sent = messages_api.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, sticker_id: "1234")
|
264
|
+
print_message_sent(sticker_sent)
|
227
265
|
|
228
266
|
######### SEND A TEMPLATE
|
229
267
|
# Note: The template must have been created previously.
|
@@ -6,8 +6,8 @@ module WhatsappSdk
|
|
6
6
|
module ApiConfiguration
|
7
7
|
extend T::Sig
|
8
8
|
|
9
|
-
|
10
|
-
API_URL = T.let("https://graph.facebook.com
|
9
|
+
DEFAULT_API_VERSION = T.let("v19.0", String)
|
10
|
+
API_URL = T.let("https://graph.facebook.com", String)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -3,21 +3,42 @@
|
|
3
3
|
|
4
4
|
require_relative "request"
|
5
5
|
require_relative "response"
|
6
|
+
require_relative "../resource/business_profile"
|
6
7
|
|
7
8
|
module WhatsappSdk
|
8
9
|
module Api
|
9
10
|
class BusinessProfile < Request
|
10
11
|
DEFAULT_FIELDS = 'about,address,description,email,profile_picture_url,websites,vertical'
|
11
12
|
|
13
|
+
class InvalidVertical < StandardError
|
14
|
+
extend T::Sig
|
15
|
+
|
16
|
+
sig { returns(String) }
|
17
|
+
attr_accessor :message
|
18
|
+
|
19
|
+
sig { params(vertical: String).void }
|
20
|
+
def initialize(vertical:)
|
21
|
+
@message = "invalid vertical #{vertical}. See the supported types in the official documentation " \
|
22
|
+
"https://developers.facebook.com/docs/whatsapp/cloud-api/reference/business-profiles"
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
12
27
|
# Get the details of business profile.
|
13
28
|
#
|
14
29
|
# @param phone_number_id [Integer] Phone Number Id.
|
15
30
|
# @return [Api::Response] Response object.
|
16
|
-
sig { params(phone_number_id: Integer).returns(Api::Response) }
|
17
|
-
def details(phone_number_id)
|
31
|
+
sig { params(phone_number_id: Integer, fields: T.nilable(T::Array[String])).returns(Api::Response) }
|
32
|
+
def details(phone_number_id, fields: nil)
|
33
|
+
fields = if fields
|
34
|
+
fields.join(',')
|
35
|
+
else
|
36
|
+
DEFAULT_FIELDS
|
37
|
+
end
|
38
|
+
|
18
39
|
response = send_request(
|
19
40
|
http_method: "get",
|
20
|
-
endpoint: "#{phone_number_id}/whatsapp_business_profile?fields=#{
|
41
|
+
endpoint: "#{phone_number_id}/whatsapp_business_profile?fields=#{fields}"
|
21
42
|
)
|
22
43
|
|
23
44
|
Api::Response.new(
|
@@ -39,6 +60,7 @@ module WhatsappSdk
|
|
39
60
|
def update(phone_number_id:, params:)
|
40
61
|
# this is a required field
|
41
62
|
params[:messaging_product] = 'whatsapp'
|
63
|
+
return raise InvalidVertical.new(vertical: params[:vertical]) unless valid_vertical?(params)
|
42
64
|
|
43
65
|
response = send_request(
|
44
66
|
http_method: "post",
|
@@ -51,6 +73,15 @@ module WhatsappSdk
|
|
51
73
|
data_class_type: Api::Responses::SuccessResponse
|
52
74
|
)
|
53
75
|
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
sig { params(params: T::Hash[T.untyped, T.untyped]).returns(T::Boolean) }
|
80
|
+
def valid_vertical?(params)
|
81
|
+
return true unless params[:vertical]
|
82
|
+
|
83
|
+
WhatsappSdk::Resource::BusinessProfile::VERTICAL_VALUES.include?(params[:vertical])
|
84
|
+
end
|
54
85
|
end
|
55
86
|
end
|
56
87
|
end
|
@@ -3,15 +3,35 @@
|
|
3
3
|
|
4
4
|
require "faraday"
|
5
5
|
require "faraday/multipart"
|
6
|
+
require "yaml"
|
6
7
|
|
7
8
|
module WhatsappSdk
|
8
9
|
module Api
|
9
10
|
class Client
|
10
11
|
extend T::Sig
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
API_VERSIONS = T.let(YAML.load_file("config/api_versions.yml"), T::Array[String])
|
14
|
+
|
15
|
+
sig do
|
16
|
+
params(
|
17
|
+
access_token: String,
|
18
|
+
api_version: String,
|
19
|
+
logger: T.nilable(T.any(Logger, T.class_of(Logger))),
|
20
|
+
logger_options: Hash
|
21
|
+
).void
|
22
|
+
end
|
23
|
+
def initialize(
|
24
|
+
access_token,
|
25
|
+
api_version = ApiConfiguration::DEFAULT_API_VERSION,
|
26
|
+
logger = nil,
|
27
|
+
logger_options = {}
|
28
|
+
)
|
14
29
|
@access_token = access_token
|
30
|
+
@logger = logger
|
31
|
+
@logger_options = logger_options
|
32
|
+
|
33
|
+
validate_api_version(api_version)
|
34
|
+
@api_version = api_version
|
15
35
|
end
|
16
36
|
|
17
37
|
sig do
|
@@ -20,13 +40,14 @@ module WhatsappSdk
|
|
20
40
|
full_url: T.nilable(String),
|
21
41
|
http_method: String,
|
22
42
|
params: T::Hash[T.untyped, T.untyped],
|
23
|
-
headers: T::Hash[T.untyped, T.untyped]
|
43
|
+
headers: T::Hash[T.untyped, T.untyped],
|
44
|
+
multipart: T::Boolean
|
24
45
|
).returns(T.nilable(T::Hash[T.untyped, T.untyped]))
|
25
46
|
end
|
26
|
-
def send_request(endpoint: "", full_url: nil, http_method: "post", params: {}, headers: {})
|
27
|
-
url = full_url || ApiConfiguration::API_URL
|
47
|
+
def send_request(endpoint: "", full_url: nil, http_method: "post", params: {}, headers: {}, multipart: false)
|
48
|
+
url = full_url || "#{ApiConfiguration::API_URL}/#{@api_version}/"
|
28
49
|
|
29
|
-
faraday_request = T.unsafe(faraday(url))
|
50
|
+
faraday_request = T.unsafe(faraday(url: url, multipart: multipart))
|
30
51
|
|
31
52
|
response = faraday_request.public_send(http_method, endpoint, request_params(params, headers), headers)
|
32
53
|
|
@@ -69,15 +90,21 @@ module WhatsappSdk
|
|
69
90
|
params
|
70
91
|
end
|
71
92
|
|
72
|
-
sig { params(url: String).returns(Faraday::Connection) }
|
73
|
-
def faraday(url)
|
93
|
+
sig { params(url: String, multipart: T::Boolean).returns(Faraday::Connection) }
|
94
|
+
def faraday(url:, multipart: false)
|
74
95
|
::Faraday.new(url) do |client|
|
75
|
-
client.request
|
76
|
-
client.request
|
77
|
-
client.adapter
|
96
|
+
client.request(:multipart) if multipart
|
97
|
+
client.request(:url_encoded)
|
98
|
+
client.adapter(::Faraday.default_adapter)
|
78
99
|
client.headers['Authorization'] = "Bearer #{@access_token}" unless @access_token.nil?
|
100
|
+
client.response(:logger, @logger, @logger_options) unless @logger.nil?
|
79
101
|
end
|
80
102
|
end
|
103
|
+
|
104
|
+
sig { params(api_version: String).void }
|
105
|
+
def validate_api_version(api_version)
|
106
|
+
raise ArgumentError, "Invalid API version: #{api_version}" unless API_VERSIONS.include?(api_version)
|
107
|
+
end
|
81
108
|
end
|
82
109
|
end
|
83
110
|
end
|
@@ -64,12 +64,15 @@ module WhatsappSdk
|
|
64
64
|
#
|
65
65
|
# @param url URL.
|
66
66
|
# @param file_path [String] The file_path to download the media e.g. "tmp/downloaded_image.png".
|
67
|
-
# @param media_type [String] The media type e.g. "audio/mp4". See
|
68
|
-
# documentation https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#supported-media-types
|
67
|
+
# @param media_type [String] The media type e.g. "audio/mp4". See possible types in the official
|
68
|
+
# documentation https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#supported-media-types,
|
69
|
+
# but note that the API may allow more depending on the client.
|
69
70
|
# @return [Api::Response] Response object.
|
70
71
|
sig { params(url: String, file_path: String, media_type: String).returns(Api::Response) }
|
71
72
|
def download(url:, file_path:, media_type:)
|
72
|
-
|
73
|
+
# Allow download of unsupported media types, since Cloud API may decide to let it through.
|
74
|
+
# https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/discussions/127
|
75
|
+
# raise InvalidMediaTypeError.new(media_type: media_type) unless valid_media_type?(media_type)
|
73
76
|
|
74
77
|
content_type_header = map_media_type_to_content_type_header(media_type)
|
75
78
|
|
@@ -104,7 +107,7 @@ module WhatsappSdk
|
|
104
107
|
type: type
|
105
108
|
}
|
106
109
|
|
107
|
-
response = send_request(http_method: "post", endpoint: "#{sender_id}/media", params: params)
|
110
|
+
response = send_request(http_method: "post", endpoint: "#{sender_id}/media", params: params, multipart: true)
|
108
111
|
|
109
112
|
Api::Response.new(
|
110
113
|
response: response,
|
@@ -14,9 +14,14 @@ module WhatsappSdk
|
|
14
14
|
@client.download_file(url: url, content_type_header: content_type_header, file_path: file_path)
|
15
15
|
end
|
16
16
|
|
17
|
-
def send_request(endpoint: nil, full_url: nil, http_method: "post", params: {}, headers: {})
|
17
|
+
def send_request(endpoint: nil, full_url: nil, http_method: "post", params: {}, headers: {}, multipart: false)
|
18
18
|
@client.send_request(
|
19
|
-
http_method: http_method,
|
19
|
+
http_method: http_method,
|
20
|
+
full_url: full_url,
|
21
|
+
endpoint: endpoint,
|
22
|
+
params: params,
|
23
|
+
headers: headers,
|
24
|
+
multipart: multipart
|
20
25
|
)
|
21
26
|
end
|
22
27
|
end
|
@@ -5,23 +5,51 @@ module WhatsappSdk
|
|
5
5
|
# This module allows client instantiating the client as a singleton like the following example:
|
6
6
|
# WhatsappSdk.configure do |config|
|
7
7
|
# config.access_token = ACCESS_TOKEN
|
8
|
+
# config.api_version = API_VERSION
|
8
9
|
# end
|
9
10
|
#
|
10
11
|
# The gem have access to the client through WhatsappSdk.configuration.client
|
11
12
|
class Configuration
|
12
13
|
extend T::Sig
|
13
14
|
|
15
|
+
logger_or_subclass_or_nil = T.nilable(T.any(Logger, T.class_of(Logger)))
|
16
|
+
|
14
17
|
sig { returns(String) }
|
15
18
|
attr_accessor :access_token
|
16
19
|
|
17
|
-
sig {
|
18
|
-
|
20
|
+
sig { returns(String) }
|
21
|
+
attr_accessor :api_version
|
22
|
+
|
23
|
+
# loggers like ActiveSupport::Logger (Rails.logger) is a subclass of Logger
|
24
|
+
sig { returns(logger_or_subclass_or_nil) }
|
25
|
+
attr_accessor :logger
|
26
|
+
|
27
|
+
sig { returns(Hash) }
|
28
|
+
attr_accessor :logger_options
|
29
|
+
|
30
|
+
sig do
|
31
|
+
params(
|
32
|
+
access_token: String,
|
33
|
+
api_version: String,
|
34
|
+
logger: logger_or_subclass_or_nil,
|
35
|
+
logger_options: Hash
|
36
|
+
).void
|
37
|
+
end
|
38
|
+
def initialize(
|
39
|
+
access_token = "",
|
40
|
+
api_version = Api::ApiConfiguration::DEFAULT_API_VERSION,
|
41
|
+
logger = nil,
|
42
|
+
logger_options = {}
|
43
|
+
)
|
19
44
|
@access_token = access_token
|
45
|
+
@api_version = api_version
|
46
|
+
@logger = logger
|
47
|
+
@logger_options = logger_options
|
20
48
|
end
|
21
49
|
|
22
50
|
sig { returns(Api::Client) }
|
23
51
|
def client
|
24
|
-
Api::Client.new(access_token)
|
52
|
+
Api::Client.new(access_token, api_version, logger, logger_options)
|
25
53
|
end
|
26
54
|
end
|
27
55
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class BusinessProfile
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
VERTICAL_VALUES = %w[
|
10
|
+
UNDEFINED OTHER AUTO BEAUTY APPAREL EDU ENTERTAIN EVENT_PLAN FINANCE GROCERY
|
11
|
+
GOVT HOTEL HEALTH NONPROFIT PROF_SERVICES RETAIL TRAVEL RESTAURANT NOT_A_BIZ
|
12
|
+
].freeze
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -13,6 +13,8 @@ module WhatsappSdk
|
|
13
13
|
# The content-type header matches with the media type using Internet Assigned Numbers Authority (IANA).
|
14
14
|
# Media type list defined by IANA https://www.iana.org/assignments/media-types/media-types.xhtml
|
15
15
|
#
|
16
|
+
# NOTE: Cloud API may decide to allow more media types to be downloaded, since the support differs depending on
|
17
|
+
# the used client.
|
16
18
|
|
17
19
|
AUDIO_TYPES = %w[audio/aac audio/mp4 audio/mpeg audio/amr audio/ogg].freeze
|
18
20
|
DOCUMENT_TYPES = %w[
|
data/lib/whatsapp_sdk/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whatsapp_sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ignacio-chiazzo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -142,6 +142,7 @@ files:
|
|
142
142
|
- ".travis.yml"
|
143
143
|
- CHANGELOG.md
|
144
144
|
- CODE_OF_CONDUCT.md
|
145
|
+
- CONTRIBUTING.MD
|
145
146
|
- Gemfile
|
146
147
|
- Gemfile.lock
|
147
148
|
- LICENSE.txt
|
@@ -150,6 +151,7 @@ files:
|
|
150
151
|
- bin/console
|
151
152
|
- bin/setup
|
152
153
|
- bin/tapioca
|
154
|
+
- config/api_versions.yml
|
153
155
|
- example.rb
|
154
156
|
- lib/whatsapp_sdk.rb
|
155
157
|
- lib/whatsapp_sdk/api/api_configuration.rb
|
@@ -179,6 +181,7 @@ files:
|
|
179
181
|
- lib/whatsapp_sdk/error.rb
|
180
182
|
- lib/whatsapp_sdk/resource/address.rb
|
181
183
|
- lib/whatsapp_sdk/resource/address_type.rb
|
184
|
+
- lib/whatsapp_sdk/resource/business_profile.rb
|
182
185
|
- lib/whatsapp_sdk/resource/button_parameter.rb
|
183
186
|
- lib/whatsapp_sdk/resource/component.rb
|
184
187
|
- lib/whatsapp_sdk/resource/contact.rb
|
@@ -249,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
249
252
|
- !ruby/object:Gem::Version
|
250
253
|
version: '0'
|
251
254
|
requirements: []
|
252
|
-
rubygems_version: 3.
|
255
|
+
rubygems_version: 3.1.6
|
253
256
|
signing_key:
|
254
257
|
specification_version: 4
|
255
258
|
summary: Use the Ruby Whatsapp SDK to communicate with Whatsapp API using the Cloud
|