whatsapp_sdk 0.11.0 → 0.12.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.
- 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
|
[](https://badge.fury.io/rb/whatsapp_sdk)
|
|
3
4
|
[](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
|