warb 0.1.4 → 1.0.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/.rubocop.yml +5 -12
- data/README.md +9 -32
- data/Rakefile +3 -3
- data/docs/README.md +1 -4
- data/docs/components/README.md +1 -4
- data/docs/messages/README.md +1 -2
- data/docs/messages/flow.md +5 -241
- data/docs/messages/interactive_call_to_action_url.md +9 -9
- data/docs/messages/interactive_list.md +2 -2
- data/docs/messages/interactive_reply_button.md +9 -9
- data/docs/setup.md +1 -45
- data/examples/audio.rb +10 -10
- data/examples/document.rb +34 -34
- data/examples/image.rb +22 -22
- data/examples/interactive_call_to_action_url.rb +46 -46
- data/examples/interactive_list.rb +61 -61
- data/examples/interactive_reply_button.rb +43 -43
- data/examples/location.rb +32 -32
- data/examples/location_request.rb +11 -11
- data/examples/message.rb +8 -8
- data/examples/sticker.rb +10 -10
- data/examples/video.rb +22 -22
- data/examples/webhook.rb +43 -77
- data/lib/warb/client.rb +5 -7
- data/lib/warb/components/action.rb +8 -12
- data/lib/warb/configuration.rb +1 -4
- data/lib/warb/connection.rb +9 -15
- data/lib/warb/dispatcher.rb +3 -4
- data/lib/warb/dispatcher_concern.rb +0 -6
- data/lib/warb/indicator_dispatcher.rb +4 -4
- data/lib/warb/media_dispatcher.rb +10 -10
- data/lib/warb/resources/audio.rb +1 -1
- data/lib/warb/resources/contact.rb +20 -22
- data/lib/warb/resources/document.rb +1 -1
- data/lib/warb/resources/flow.rb +20 -82
- data/lib/warb/resources/image.rb +1 -1
- data/lib/warb/resources/interactive_call_to_action_url.rb +8 -10
- data/lib/warb/resources/interactive_list.rb +5 -7
- data/lib/warb/resources/interactive_reply_button.rb +8 -10
- data/lib/warb/resources/location.rb +1 -11
- data/lib/warb/resources/location_request.rb +3 -5
- data/lib/warb/resources/reaction.rb +1 -1
- data/lib/warb/resources/resource.rb +4 -14
- data/lib/warb/resources/sticker.rb +1 -1
- data/lib/warb/resources/text.rb +3 -31
- data/lib/warb/resources/video.rb +1 -1
- data/lib/warb/utils.rb +1 -3
- data/lib/warb/version.rb +1 -1
- data/lib/warb.rb +31 -67
- metadata +3 -34
- data/docs/components/button.md +0 -62
- data/docs/components/copy_code_button.md +0 -57
- data/docs/components/flow_button.md +0 -102
- data/docs/components/url_button.md +0 -57
- data/docs/messages/template.md +0 -373
- data/docs/resources/README.md +0 -14
- data/docs/resources/currency.md +0 -22
- data/docs/resources/date_time.md +0 -11
- data/docs/resources/text.md +0 -9
- data/lib/warb/category.rb +0 -8
- data/lib/warb/components/button.rb +0 -29
- data/lib/warb/components/component.rb +0 -19
- data/lib/warb/components/copy_code_button.rb +0 -30
- data/lib/warb/components/flow_button.rb +0 -32
- data/lib/warb/components/quick_reply_button.rb +0 -15
- data/lib/warb/components/url_button.rb +0 -30
- data/lib/warb/components/voice_call_button.rb +0 -15
- data/lib/warb/errors.rb +0 -27
- data/lib/warb/language.rb +0 -8
- data/lib/warb/resources/currency.rb +0 -47
- data/lib/warb/resources/date_time.rb +0 -34
- data/lib/warb/resources/helpers/header.rb +0 -35
- data/lib/warb/resources/template.rb +0 -163
- data/lib/warb/resources/validation.rb +0 -30
- data/lib/warb/response.rb +0 -33
- data/lib/warb/response_error_handler.rb +0 -42
- data/lib/warb/template_dispatcher.rb +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 58ff4cfa4904a9a820c4b5906b947b6f5dcbd3e5a3afa76a9e88ed3f83488bb8
|
|
4
|
+
data.tar.gz: 1edcbcef65fd5f128cb0cf475f4b5c6ae8e4e285a4b57335b80818e0487f874a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 43cabbb2bcd395dbbc32eacf0f170e00c5fa913f9edbe4543b9b19f81278648ccae955ac64601182fc468ab02ae81cdb81ae1c07d4601f793dd1645cad28a698
|
|
7
|
+
data.tar.gz: f7ef031988f7c39be607047ebab9e56d627b848527fce0baa5043f1108a93e378e4e7b6d7df853240bcdba9ccb46b0c0c8ba135833fc31fbccaf01175dab9ba6
|
data/.rubocop.yml
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
plugins:
|
|
2
|
-
- rubocop-rspec
|
|
3
|
-
|
|
4
1
|
AllCops:
|
|
5
2
|
TargetRubyVersion: 3.1
|
|
6
|
-
NewCops: enable
|
|
7
|
-
SuggestExtensions: false
|
|
8
|
-
Exclude:
|
|
9
|
-
- examples/**/*
|
|
10
|
-
- bin/*
|
|
11
|
-
Style/Documentation:
|
|
12
|
-
Enabled: false
|
|
13
3
|
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
Style/StringLiterals:
|
|
5
|
+
EnforcedStyle: double_quotes
|
|
6
|
+
|
|
7
|
+
Style/StringLiteralsInInterpolation:
|
|
8
|
+
EnforcedStyle: double_quotes
|
data/README.md
CHANGED
|
@@ -9,16 +9,18 @@ A Ruby Gem focused on wrap all the functionalities and use cases of the WhatsApp
|
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Install the gem and add to the application's Gemfile by executing:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
16
18
|
```
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
19
21
|
|
|
20
|
-
```
|
|
21
|
-
gem
|
|
22
|
+
```bash
|
|
23
|
+
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
22
24
|
```
|
|
23
25
|
|
|
24
26
|
## Configuration
|
|
@@ -88,26 +90,9 @@ Warb.message.dispatch(recipient_number) do |builder|
|
|
|
88
90
|
end
|
|
89
91
|
```
|
|
90
92
|
|
|
91
|
-
### What types of messages can I send?
|
|
92
|
-
|
|
93
|
-
Warb implements the main types of WhatsApp messages, you can follow the message types [`here`](docs/messages/README.md#messages-types)
|
|
94
|
-
|
|
95
|
-
examples:
|
|
96
|
-
|
|
97
|
-
```ruby
|
|
98
|
-
|
|
99
|
-
warb = Warb.new(...)
|
|
100
|
-
|
|
101
|
-
warb.message.dispatch(...)
|
|
102
|
-
warb.audio.dispatch(...)
|
|
103
|
-
warb.video.dispatch(...)
|
|
104
|
-
warb.image.dispatch(...)
|
|
105
|
-
...
|
|
106
|
-
```
|
|
107
|
-
|
|
108
93
|
### Find all usage examples
|
|
109
94
|
|
|
110
|
-
We suggest heading to the
|
|
95
|
+
We suggest heading to the `examples/` directory, where you'll find documentation files with plenty of usage examples, organized by **Resources** (**Resources** are the types of messages you can send via WhatsApp using Warb).
|
|
111
96
|
|
|
112
97
|
You can also check the [`docs`](docs/README.md) for a more structured overview of the available resources and their usage.
|
|
113
98
|
|
|
@@ -124,14 +109,6 @@ To enable this kind of flow, you’ll need to know **when** a message is receive
|
|
|
124
109
|
> ⚠️ **Note:** This gem **does not** provide built-in support for webhooks.
|
|
125
110
|
> However, you can look at [`examples/webhook.rb`](examples/webhook.rb) for a starting point on how to implement it. Also, check the [official documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/payload-examples) for more details if you get stuck.
|
|
126
111
|
|
|
127
|
-
## Deploy
|
|
128
|
-
|
|
129
|
-
```
|
|
130
|
-
git tag v0.0.2
|
|
131
|
-
git push origin main --tags
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
|
|
135
112
|
## Development
|
|
136
113
|
|
|
137
114
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rspec/core/rake_task"
|
|
5
5
|
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
|
7
7
|
|
|
8
|
-
require
|
|
8
|
+
require "rubocop/rake_task"
|
|
9
9
|
|
|
10
10
|
RuboCop::RakeTask.new
|
|
11
11
|
|
data/docs/README.md
CHANGED
|
@@ -10,7 +10,4 @@ Refer to [webhook](webhook.md) for more details on how to setup a webhook to get
|
|
|
10
10
|
Refer to [messages](./messages/README.md) for more details on how to send messages using Warb.
|
|
11
11
|
|
|
12
12
|
## Components
|
|
13
|
-
Refer to [components](./components/README.md) for more details on how Warb components work.
|
|
14
|
-
|
|
15
|
-
## Resources
|
|
16
|
-
Refer to [resources](./resources/README.md) for more details on resources.
|
|
13
|
+
Refer to [components](./components/README.md) for more details on how Warb components work.
|
data/docs/components/README.md
CHANGED
|
@@ -18,7 +18,4 @@ Here is a table of available components, and where they can be used:
|
|
|
18
18
|
| `Warb::Components::ReplyButtonAction` | [Interactive Reply Button](../messages/interactive_reply_button.md) | [Reply Button Action](./reply_button_action) |
|
|
19
19
|
| `Warb::Components::Row` | [Interactive List](../messages/interactive_list.md) | [Row](./row.md) |
|
|
20
20
|
| `Warb::Components::ListAction` | [Interactive List](../messages/interactive_list.md) | [List Action](./list_action.md) |
|
|
21
|
-
| `Warb::Components::Section` | [Interactive List](../messages/interactive_list.md) | [Section](./section.md) |
|
|
22
|
-
| `Warb::Components::Button` | [Template](../messages/template.md) | [Button](./button.md) |
|
|
23
|
-
| `Warb::Components::UrlButton` | [Template](../messages/template.md) | [UrlButton](./url_button.md) |
|
|
24
|
-
| `Warb::Components::CopyCodeButton` | [Template](../messages/template.md) | [CopyCodeButton](./copy_code_button.md) |
|
|
21
|
+
| `Warb::Components::Section` | [Interactive List](../messages/interactive_list.md) | [Section](./section.md) |
|
data/docs/messages/README.md
CHANGED
|
@@ -71,10 +71,9 @@ Messages are sent using a helper dispatcher and its resource class. Here is a li
|
|
|
71
71
|
| Video | `Warb::Resources::Video` | `video` | [Video Message](./video.md) |
|
|
72
72
|
| Special Dispatchers |
|
|
73
73
|
| Indicator | `Warb::Resources::Indicator` | `indicator` | [Indicator Message](./indicator.md) |
|
|
74
|
-
| Template | `Warb::Resources::Template` | `template` | [Template Message](./template.md) |
|
|
75
74
|
|
|
76
75
|
> Simple Dispatcher doesn't offer any additional functionality, they just send messages.
|
|
77
76
|
|
|
78
77
|
> Media Dispatchers, aside from sending messages, also provide methods to upload and download media files.
|
|
79
78
|
|
|
80
|
-
> Special Dispatchers are used for specific purposes, such as sending indicators
|
|
79
|
+
> Special Dispatchers are used for specific purposes, such as sending indicators or reactions.
|
data/docs/messages/flow.md
CHANGED
|
@@ -1,248 +1,12 @@
|
|
|
1
1
|
# Flow
|
|
2
2
|
|
|
3
|
-
Flow is a special type of
|
|
4
|
-
With ```Warb.flow``` you can send static (navigate) or dynamic (data exchange) flows, both in draft and published modes.
|
|
3
|
+
Flow is a special type of message. We can summarize it simply as a form.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
Business Account + Developer Account
|
|
8
|
-
Verified Business to send flows in production WhatsApp (unverified accounts can only test in Meta’s Flow editor)
|
|
9
|
-
For dynamic flows: endpoint + encryption configured in Meta (to handle user responses)
|
|
5
|
+
At this point of writing, this gem only supports sending existing flows, and it can only send flows which are in draft.
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
##### Send a static draft flow:
|
|
14
|
-
```ruby
|
|
15
|
-
Warb.flow.dispatch(recipient_number, flow_id: "0000000000000000", mode: "draft", screen: "INITIAL", body: "Open flow")
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
##### Send a dynamic draft flow:
|
|
19
|
-
```ruby
|
|
20
|
-
Warb.flow.dispatch(recipient_number,
|
|
21
|
-
flow_id: "0000000000000000",
|
|
22
|
-
mode: "draft",
|
|
23
|
-
flow_action: "data_exchange",
|
|
24
|
-
body: "Open flow"
|
|
25
|
-
)
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
##### Send a dynamic published flow with custom header, body, and footer:
|
|
29
|
-
```ruby
|
|
30
|
-
Warb.flow.dispatch(recipient_number) do |flow|
|
|
31
|
-
flow.flow_id = "0000000000000000"
|
|
32
|
-
flow.flow_action = "data_exchange"
|
|
33
|
-
flow.mode = "published"
|
|
34
|
-
flow.body = "Hello! Please follow the instructions."
|
|
35
|
-
flow.footer = "Need help? Reply to this message."
|
|
36
|
-
|
|
37
|
-
flow.header = {
|
|
38
|
-
type: "document",
|
|
39
|
-
document: {
|
|
40
|
-
link: "https://example.com/contract.pdf",
|
|
41
|
-
filename: "contract.pdf"
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
flow.flow_cta = "Sign"
|
|
46
|
-
end
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Dispatching Flow Messages
|
|
7
|
+
To send flows, you can do as following:
|
|
50
8
|
```ruby
|
|
51
|
-
Warb.flow.dispatch(recipient_number,
|
|
9
|
+
Warb.flow.dispatch(recipient_number, flow_id: "flow_id", screen: "screen")
|
|
52
10
|
```
|
|
53
|
-
##### Parameters
|
|
54
|
-
| Attribute | Type | Required | Description |
|
|
55
|
-
| ------------- | -------- | ---------------------------------- | ----------------------------------------------------------- |
|
|
56
|
-
| `flow_id` | `String` | Yes | The ID of the Flow created in Meta. |
|
|
57
|
-
| `body` | `String` | Yes | Body text shown in the Flow message. |
|
|
58
|
-
| `flow_action` | `String` | No | `"navigate"` (default) or `"data_exchange"`. |
|
|
59
|
-
| `mode` | `String` | Yes if `flow mode == 'draft'` | `"published"` (default) or `"draft"`. |
|
|
60
|
-
| `screen` | `String` | Yes if `flow_action == "navigate"` | Initial screen to navigate to. |
|
|
61
|
-
| `flow_cta` | `String` | No | Label for the button that opens the Flow. |
|
|
62
|
-
| `flow_token` | `String` | No | Token for dynamic flows (encryption/validation). |
|
|
63
|
-
| `data` | `Hash` | No | Prefill data for navigate flows. |
|
|
64
|
-
| `header` | `Hash` | No | Optional header (see below). |
|
|
65
|
-
| `footer` | `String` | No | Optional footer text. |
|
|
66
|
-
|
|
67
|
-
### Supported Headers
|
|
68
|
-
|
|
69
|
-
You must provide exactly one of the following header types:
|
|
70
11
|
|
|
71
|
-
|
|
72
|
-
```ruby
|
|
73
|
-
{ type: "text", text: "Flow title" }
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
##### Image
|
|
77
|
-
```ruby
|
|
78
|
-
{ type: "image", image: { id: "MEDIA_ID" } }
|
|
79
|
-
# or
|
|
80
|
-
{ type: "image", image: { link: "https://example.com/img.jpg" } }
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
##### Video
|
|
84
|
-
```ruby
|
|
85
|
-
{ type: "video", video: { id: "MEDIA_ID" } }
|
|
86
|
-
# or
|
|
87
|
-
{ type: "video", video: { link: "https://example.com/video.mp4" } }
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
##### Document
|
|
91
|
-
```ruby
|
|
92
|
-
{ type: "document", document: { id: "MEDIA_ID" } }
|
|
93
|
-
# or
|
|
94
|
-
{ type: "document", document: { link: "https://example.com/file.pdf", filename: "file.pdf" } }
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
##### Note:
|
|
98
|
-
|
|
99
|
-
id must be obtained from a media upload (Warb.image/video/document.upload).
|
|
100
|
-
|
|
101
|
-
link must be a public URL. For documents, filename is required to determine preview capabilities.
|
|
102
|
-
|
|
103
|
-
### Modes and Actions
|
|
104
|
-
##### mode
|
|
105
|
-
|
|
106
|
-
"published" (default): Published flow. Allows customizing header, body, footer, and flow_cta.
|
|
107
|
-
|
|
108
|
-
"draft": Draft flow. Usable via Meta Flow editor and sometimes on WhatsApp, but some elements (like body text and CTA) may be restricted.
|
|
109
|
-
|
|
110
|
-
##### flow_action
|
|
111
|
-
|
|
112
|
-
"navigate" (default) → static flow
|
|
113
|
-
Requires screen, can include initial data:
|
|
114
|
-
```ruby
|
|
115
|
-
Warb.flow.dispatch(recipient_number,
|
|
116
|
-
flow_id: "0000000000000000",
|
|
117
|
-
screen: "INITIAL",
|
|
118
|
-
body: "Continue",
|
|
119
|
-
data: { prefill: { name: "Alice", email: "alice@example.com" } }
|
|
120
|
-
)
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
"data_exchange" → dynamic flow
|
|
124
|
-
No flow_action_payload (omitted automatically):
|
|
125
|
-
```ruby
|
|
126
|
-
Warb.flow.dispatch(recipient_number,
|
|
127
|
-
flow_id: "0000000000000000",
|
|
128
|
-
flow_action: "data_exchange",
|
|
129
|
-
body: "Fill the form",
|
|
130
|
-
)
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Block Building
|
|
134
|
-
|
|
135
|
-
You can also build flows using a block:
|
|
136
|
-
```ruby
|
|
137
|
-
Warb.flow.dispatch(recipient_number) do |flow|
|
|
138
|
-
flow.flow_id = "0000000000000000"
|
|
139
|
-
flow.flow_action = "data_exchange"
|
|
140
|
-
flow.mode = "published"
|
|
141
|
-
flow.body = "We need some information"
|
|
142
|
-
|
|
143
|
-
flow.header = { type: "text", text: "Registration" }
|
|
144
|
-
flow.footer = "Thanks!"
|
|
145
|
-
|
|
146
|
-
flow.flow_cta = "Open"
|
|
147
|
-
end
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Validations
|
|
151
|
-
|
|
152
|
-
Before sending, the gem enforces:
|
|
153
|
-
|
|
154
|
-
flow_id is required → raises ArgumentError: flow_id is required
|
|
155
|
-
|
|
156
|
-
body is required → raises ArgumentError: body is required for flow message
|
|
157
|
-
|
|
158
|
-
If flow_action == "navigate" then screen is required →
|
|
159
|
-
raises ArgumentError: screen is required for flow_action=navigate
|
|
160
|
-
|
|
161
|
-
The Meta API may return additional errors (invalid parameters, missing fields, etc.), which are raised as Warb::BadRequest, Warb::RequestError, etc.
|
|
162
|
-
|
|
163
|
-
Example Scenarios
|
|
164
|
-
1) Static / Draft
|
|
165
|
-
```ruby
|
|
166
|
-
Warb.flow.dispatch(recipient_number,
|
|
167
|
-
flow_id: "0000000000000000",
|
|
168
|
-
screen: "INITIAL",
|
|
169
|
-
mode: "draft",
|
|
170
|
-
body: "Open flow"
|
|
171
|
-
)
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
2) Dynamic / Draft
|
|
175
|
-
```ruby
|
|
176
|
-
Warb.flow.dispatch(recipient_number,
|
|
177
|
-
flow_id: "0000000000000000",
|
|
178
|
-
flow_action: "data_exchange",
|
|
179
|
-
mode: "draft",
|
|
180
|
-
body: "Fill the form"
|
|
181
|
-
)
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
3) Dynamic / Published with Document Header
|
|
185
|
-
```ruby
|
|
186
|
-
Warb.flow.dispatch(recipient_number) do |flow|
|
|
187
|
-
flow.flow_id = "0000000000000000"
|
|
188
|
-
flow.flow_action = "data_exchange"
|
|
189
|
-
flow.mode = "published"
|
|
190
|
-
flow.body = "Please review and sign the document."
|
|
191
|
-
flow.footer = "Reply if you need assistance."
|
|
192
|
-
flow.flow_cta = "Sign"
|
|
193
|
-
|
|
194
|
-
flow.header = {
|
|
195
|
-
type: "document",
|
|
196
|
-
document: {
|
|
197
|
-
link: "https://www.thecampusqdl.com/uploads/files/pdf_sample_2.pdf",
|
|
198
|
-
filename: "pdf_sample_2.pdf"
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
end
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
4) Static / Published with Image Header (id) and Prefill Data
|
|
205
|
-
```ruby
|
|
206
|
-
image_id = Warb.image.upload(file_path: "banner.jpg", file_type: "image/jpeg")
|
|
207
|
-
|
|
208
|
-
Warb.flow.dispatch(recipient_number) do |flow|
|
|
209
|
-
flow.flow_id = "0000000000000000"
|
|
210
|
-
flow.mode = "published"
|
|
211
|
-
flow.body = "Open and check your data"
|
|
212
|
-
|
|
213
|
-
flow.header = { type: "image", image: { id: image_id } }
|
|
214
|
-
|
|
215
|
-
flow.screen = "INITIAL"
|
|
216
|
-
flow.data = { prefill: { name: "John", email: "john@example.com" } }
|
|
217
|
-
end
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### Generated Payload (Reference)
|
|
221
|
-
|
|
222
|
-
Example payload produced by the gem:
|
|
223
|
-
```ruby
|
|
224
|
-
{
|
|
225
|
-
"type": "interactive",
|
|
226
|
-
"interactive": {
|
|
227
|
-
"type": "flow",
|
|
228
|
-
"header": { ... },
|
|
229
|
-
"body": { "text": "..." },
|
|
230
|
-
"footer": { "text": "..." },
|
|
231
|
-
"action": {
|
|
232
|
-
"name": "flow",
|
|
233
|
-
"parameters": {
|
|
234
|
-
"flow_message_version": "3",
|
|
235
|
-
"flow_id": "....",
|
|
236
|
-
"flow_action": "navigate" | "data_exchange",
|
|
237
|
-
"mode": "published" | "draft",
|
|
238
|
-
"flow_cta": "Open",
|
|
239
|
-
"flow_token": "TOKEN",
|
|
240
|
-
"flow_action_payload": {
|
|
241
|
-
"screen": "INITIAL",
|
|
242
|
-
"data": { "prefill": { ... } }
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
```
|
|
12
|
+
`flow_id` must be the ID of the flow and `screen` must be the ID of the first screen of the flow.
|
|
@@ -28,7 +28,7 @@ Warb.interactive_call_to_action_url.dispatch(recipient_number) do |message|
|
|
|
28
28
|
message.footer = "footer"
|
|
29
29
|
|
|
30
30
|
# for header, there's a helper method to create a text header
|
|
31
|
-
message.
|
|
31
|
+
message.set_text_header("Check this out!")
|
|
32
32
|
|
|
33
33
|
# and for action, you can use the build_action method to create a CTA action`
|
|
34
34
|
message.build_action(button_text: "Click Here") do |action|
|
|
@@ -37,7 +37,7 @@ Warb.interactive_call_to_action_url.dispatch(recipient_number) do |message|
|
|
|
37
37
|
end
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
Aside from the text header, you can also set an image, video, or document as header using the respective methods, `
|
|
40
|
+
Aside from the text header, you can also set an image, video, or document as header using the respective methods, `set_image_header`, `set_video_header`, and `set_document_header`.
|
|
41
41
|
|
|
42
42
|
Here is an example of using an image as header:
|
|
43
43
|
|
|
@@ -47,7 +47,7 @@ Warb.interactive_call_to_action_url.dispatch(recipient_number) do |message|
|
|
|
47
47
|
message.footer = "footer"
|
|
48
48
|
|
|
49
49
|
# set an image as header
|
|
50
|
-
message.
|
|
50
|
+
message.set_image_header(link: "https://example.com/image.jpg")
|
|
51
51
|
|
|
52
52
|
# the build_action method also returns the built action
|
|
53
53
|
action = message.build_action do |action|
|
|
@@ -68,7 +68,7 @@ Warb.interactive_call_to_action_url.dispatch(recipient_number) do |message|
|
|
|
68
68
|
|
|
69
69
|
# set a document as header
|
|
70
70
|
# for documents, you can also pass a filename. its extension will be used to determine the MIME type
|
|
71
|
-
message.
|
|
71
|
+
message.set_document_header(link: "https://example.com/document.pdf", filename: "document.pdf")
|
|
72
72
|
|
|
73
73
|
message.build_action(url: "https://example.com", button_text: "Click here")
|
|
74
74
|
end
|
|
@@ -86,11 +86,11 @@ Here is a summary of the fields you can set in the `dispatch` method of the `int
|
|
|
86
86
|
For header, as seen above, you can set it using the following instance methods:
|
|
87
87
|
| Method | Named Parameters | Positional Parameters | Respective Resource Class |
|
|
88
88
|
|-----------------------|--------------------|------------------------|-----------------------------|
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
89
|
+
| `set_text_header` | - | the content header | `Warb::Resources::Text` |
|
|
90
|
+
| `set_image_header` | `link` | - | `Warb::Resources::Image` |
|
|
91
|
+
| `set_video_header` | `link` | - | `Warb::Resources::Video` |
|
|
92
|
+
| `set_document_header` | `link`, `filename` | - | `Warb::Resources::Document` |
|
|
93
93
|
|
|
94
94
|
Under the hood, the set header methods will create the respective resource object and call its `build_header` method to prepare the header for sending.
|
|
95
95
|
|
|
96
|
-
For the action, the `build_action` instance method will create a `Warb::Components::CTAAction` and return it
|
|
96
|
+
For the action, the `build_action` instance method will create a `Warb::Components::CTAAction` and return it
|
|
@@ -77,7 +77,7 @@ Warb.interactive_list.dispatch(recipient_number) do |message|
|
|
|
77
77
|
message.body = "Choose your preferred language"
|
|
78
78
|
message.footer = "You can change it later"
|
|
79
79
|
|
|
80
|
-
message.
|
|
80
|
+
message.set_text_header("Language Selection")
|
|
81
81
|
|
|
82
82
|
message.build_action(button_text: "Select") do |action|
|
|
83
83
|
section = action.add_section(title: nil)
|
|
@@ -108,7 +108,7 @@ Warb.interactive_list.dispatch(recipient_number) do |message|
|
|
|
108
108
|
message.body = "Choose your preferred language"
|
|
109
109
|
message.footer = "You can change it later"
|
|
110
110
|
|
|
111
|
-
message.
|
|
111
|
+
message.set_text_header("Language Selection")
|
|
112
112
|
|
|
113
113
|
message.build_action(button_text: "Select") do |action|
|
|
114
114
|
action.add_section(title: "American Languages") do |american_section|
|
|
@@ -23,7 +23,7 @@ Or you can use the block building strategy to simplify the process:
|
|
|
23
23
|
|
|
24
24
|
```ruby
|
|
25
25
|
Warb.interactive_reply_button.dispatch(recipient_number) do |message|
|
|
26
|
-
message.
|
|
26
|
+
message.set_image_header(media_id: "1341834336894773")
|
|
27
27
|
|
|
28
28
|
message.body = "Select a Language:"
|
|
29
29
|
message.footer = nil
|
|
@@ -38,23 +38,23 @@ or you can build the action with the buttons texts directly, passing them to the
|
|
|
38
38
|
|
|
39
39
|
```ruby
|
|
40
40
|
Warb.interactive_reply_button.dispatch(recipient_number, action: action) do |message|
|
|
41
|
-
message.
|
|
41
|
+
message.set_text_header(content: "Options")
|
|
42
42
|
message.body = "Select a Language:"
|
|
43
43
|
message.footer = nil
|
|
44
44
|
message.build_action(buttons_texts: ["Português", "English", "Español"])
|
|
45
45
|
end
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
Aside from text and image headers, you can also set a video or document as header using the respective methods, `
|
|
48
|
+
Aside from text and image headers, you can also set a video or document as header using the respective methods, `set_video_header` and `set_document_header`.
|
|
49
49
|
|
|
50
|
-
For text header, `
|
|
50
|
+
For text header, `set_text_header` receives a string, while for image, video, and document headers, you can pass a `media_id` or a `link` to the media file.
|
|
51
51
|
For header, as seen above, you can set it using the following instance methods:
|
|
52
52
|
| Method | Named Parameters | Positional Parameters | Respective Resource Class |
|
|
53
53
|
|-----------------------|--------------------------------|------------------------|-----------------------------|
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
54
|
+
| `set_text_header` | - | the content header | `Warb::Resources::Text` |
|
|
55
|
+
| `set_image_header` | `link`, `media_id` | - | `Warb::Resources::Image` |
|
|
56
|
+
| `set_video_header` | `link`, `media_id` | - | `Warb::Resources::Video` |
|
|
57
|
+
| `set_document_header` | `link`, `media_id`, `filename` | - | `Warb::Resources::Document` |
|
|
58
58
|
|
|
59
59
|
Either `link` or `media_id` can be used, but not both at the same time.
|
|
60
60
|
|
|
@@ -64,4 +64,4 @@ If you're using a `media_id`, it must be obtained from a previous upload using t
|
|
|
64
64
|
|
|
65
65
|
The `filename` for the document header is optional, but if provided, it will be used to determine the MIME type of the document.
|
|
66
66
|
|
|
67
|
-
For the `action` of the message, you can use the [`Warb::Components::ReplyButtonAction`](../components/reply_button_action.md) class to build the action with the buttons texts.
|
|
67
|
+
For the `action` of the message, you can use the [`Warb::Components::ReplyButtonAction`](../components/reply_button_action.md) class to build the action with the buttons texts.
|
data/docs/setup.md
CHANGED
|
@@ -43,48 +43,4 @@ Warb.setup do |config|
|
|
|
43
43
|
end
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
Also, note that calling `Warb.setup` multiple times **WILL NOT** override the previous configuration, so you can use it to change the global configuration at any time.
|
|
47
|
-
|
|
48
|
-
## Phone numbers (quality monitoring)
|
|
49
|
-
|
|
50
|
-
You can fetch all phone numbers attached to your WhatsApp Business Account (WABA) and their quality/operational signals.
|
|
51
|
-
|
|
52
|
-
Requirements: make sure you have configured a business_id in your global setup (this method uses the business context, not the sender/phone context).
|
|
53
|
-
```ruby
|
|
54
|
-
Warb.setup do |config|
|
|
55
|
-
config.access_token = "ACCESS_TOKEN"
|
|
56
|
-
config.business_id = "BUSINESS_ID" # <-- required here
|
|
57
|
-
config.sender_id = "SENDER_ID" # still used for message dispatch
|
|
58
|
-
end
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
#### Global usage
|
|
62
|
-
```ruby
|
|
63
|
-
phones = Warb.list_phone_numbers
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
#### Sample response (unwrapped data array):
|
|
67
|
-
```ruby
|
|
68
|
-
=> [
|
|
69
|
-
{
|
|
70
|
-
"verified_name" => "Test",
|
|
71
|
-
"code_verification_status" => "NOT_VERIFIED",
|
|
72
|
-
"display_phone_number" => "00000000000",
|
|
73
|
-
"quality_rating" => "GREEN",
|
|
74
|
-
"platform_type" => "CLOUD_API",
|
|
75
|
-
"throughput" => { "level" => "STANDARD" },
|
|
76
|
-
"webhook_configuration" => { "application" => "https://example.com/" },
|
|
77
|
-
"id" => "(phone_number_id)"
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
#### Notes
|
|
83
|
-
|
|
84
|
-
This method returns the data array directly. If you need paging cursors, call the raw client:
|
|
85
|
-
```ruby
|
|
86
|
-
raw = Warb.client.get("phone_numbers", {}, endpoint_prefix: :business_id)
|
|
87
|
-
raw.body # => { "data" => [...], "paging" => { "cursors" => {...} } }
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Non-2xx responses raise Warb::RequestError (or subclasses), so you can rescue them in your app.
|
|
46
|
+
Also, note that calling `Warb.setup` multiple times **WILL NOT** override the previous configuration, so you can use it to change the global configuration at any time.
|
data/examples/audio.rb
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "../lib/warb"
|
|
4
4
|
|
|
5
5
|
# Configure your variables here
|
|
6
6
|
|
|
7
|
-
access_token =
|
|
8
|
-
business_id =
|
|
9
|
-
sender_id =
|
|
10
|
-
recipient_number =
|
|
7
|
+
access_token = ""
|
|
8
|
+
business_id = ""
|
|
9
|
+
sender_id = ""
|
|
10
|
+
recipient_number = ""
|
|
11
11
|
|
|
12
|
-
audio_link =
|
|
12
|
+
audio_link = ""
|
|
13
13
|
|
|
14
14
|
# We recommend testing one section at a time, as it can be overwhelming to see all the messages at once.
|
|
15
15
|
# So you can comment out the sections you don't want to test.
|
|
@@ -25,8 +25,8 @@ warb_from_setup = Warb.setup do |config|
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# To send audio using its ID, you may need to retrieve it first, which can be retrieved this way
|
|
28
|
-
file_path =
|
|
29
|
-
file_type =
|
|
28
|
+
file_path = "" # fill this in with the file path pointing to wherever the audio is located
|
|
29
|
+
file_type = "" # fill this in with the mimetype of the audio to be uploaded
|
|
30
30
|
# allow values for file_type: audio/aac, audio/amr, audio/mpeg, audio/mp4 or audio/ogg
|
|
31
31
|
audio_id = warb_from_setup.audio.upload(file_path: file_path, file_type: file_type)
|
|
32
32
|
# if you already have an audio id, you can simply replace the above line with such id
|
|
@@ -53,8 +53,8 @@ warb_from_new = Warb.new(
|
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
# Same as stated above, if you need an audio id, you can upload it this way
|
|
56
|
-
file_path =
|
|
57
|
-
file_type =
|
|
56
|
+
file_path = "" # fill this in with the file path pointing to wherever the audio is located
|
|
57
|
+
file_type = "" # fill this in with the mimetype of the audio to be uploaded
|
|
58
58
|
# allow values for file_type: audio/aac, audio/amr, audio/mpeg, audio/mp4 or audio/ogg
|
|
59
59
|
audio_id = warb_from_setup.audio.upload(file_path: file_path, file_type: file_type)
|
|
60
60
|
# if you already have an audio id, you can simply replace the above line with such id
|