warb 1.0.0 → 1.0.1
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 +12 -5
- data/README.md +32 -9
- data/Rakefile +3 -3
- data/docs/README.md +4 -1
- data/docs/components/README.md +4 -1
- data/docs/components/button.md +62 -0
- data/docs/components/copy_code_button.md +57 -0
- data/docs/components/flow_button.md +102 -0
- data/docs/components/url_button.md +57 -0
- data/docs/messages/README.md +2 -1
- data/docs/messages/flow.md +241 -5
- 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/messages/template.md +373 -0
- data/docs/resources/README.md +14 -0
- data/docs/resources/currency.md +22 -0
- data/docs/resources/date_time.md +11 -0
- data/docs/resources/text.md +9 -0
- data/docs/setup.md +45 -1
- 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 +77 -43
- data/lib/warb/category.rb +8 -0
- data/lib/warb/client.rb +7 -5
- data/lib/warb/components/action.rb +12 -8
- data/lib/warb/components/button.rb +29 -0
- data/lib/warb/components/component.rb +19 -0
- data/lib/warb/components/copy_code_button.rb +30 -0
- data/lib/warb/components/flow_button.rb +32 -0
- data/lib/warb/components/quick_reply_button.rb +15 -0
- data/lib/warb/components/url_button.rb +30 -0
- data/lib/warb/components/voice_call_button.rb +15 -0
- data/lib/warb/configuration.rb +4 -1
- data/lib/warb/connection.rb +15 -9
- data/lib/warb/dispatcher.rb +4 -3
- data/lib/warb/dispatcher_concern.rb +6 -0
- data/lib/warb/errors.rb +27 -0
- data/lib/warb/indicator_dispatcher.rb +4 -4
- data/lib/warb/language.rb +8 -0
- data/lib/warb/media_dispatcher.rb +10 -10
- data/lib/warb/resources/audio.rb +1 -1
- data/lib/warb/resources/contact.rb +22 -20
- data/lib/warb/resources/currency.rb +47 -0
- data/lib/warb/resources/date_time.rb +34 -0
- data/lib/warb/resources/document.rb +1 -1
- data/lib/warb/resources/flow.rb +82 -20
- data/lib/warb/resources/helpers/header.rb +35 -0
- data/lib/warb/resources/image.rb +1 -1
- data/lib/warb/resources/interactive_call_to_action_url.rb +10 -8
- data/lib/warb/resources/interactive_list.rb +7 -5
- data/lib/warb/resources/interactive_reply_button.rb +10 -8
- data/lib/warb/resources/location.rb +11 -1
- data/lib/warb/resources/location_request.rb +5 -3
- data/lib/warb/resources/reaction.rb +1 -1
- data/lib/warb/resources/resource.rb +14 -4
- data/lib/warb/resources/sticker.rb +1 -1
- data/lib/warb/resources/template.rb +163 -0
- data/lib/warb/resources/text.rb +31 -3
- data/lib/warb/resources/validation.rb +30 -0
- data/lib/warb/resources/video.rb +1 -1
- data/lib/warb/response.rb +33 -0
- data/lib/warb/response_error_handler.rb +42 -0
- data/lib/warb/template_dispatcher.rb +21 -0
- data/lib/warb/utils.rb +3 -1
- data/lib/warb/version.rb +1 -1
- data/lib/warb.rb +67 -31
- metadata +34 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c7750b641ab09a5a2ecc79e894e4047a98af4602aebd98aad2edcdf61018142b
|
|
4
|
+
data.tar.gz: d9b0255c4f0a2c4bc6a6965f21459d971390b7722c4ffec3d2d7c533c649f611
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d20edff3caa1f062d3c718cebd66dbf1a56392d51148ebe718fa25da9ec2869f8b1af2b82a515250740d5a6ce426064ee85b4db28f14bb27d13f99c919fe7d8a
|
|
7
|
+
data.tar.gz: 6507de0abb32ef0df3e4d37c1736209d6c85fb76fc890d352be7a9a71f0902f102a5b75f6b3ae11782eaf91e1797c7f10802f691c16e3412e93df8de4e4baddc
|
data/.rubocop.yml
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
plugins:
|
|
2
|
+
- rubocop-rspec
|
|
3
|
+
|
|
1
4
|
AllCops:
|
|
2
5
|
TargetRubyVersion: 3.1
|
|
6
|
+
NewCops: enable
|
|
7
|
+
SuggestExtensions: false
|
|
8
|
+
Exclude:
|
|
9
|
+
- examples/**/*
|
|
10
|
+
- bin/*
|
|
11
|
+
Style/Documentation:
|
|
12
|
+
Enabled: false
|
|
3
13
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Style/StringLiteralsInInterpolation:
|
|
8
|
-
EnforcedStyle: double_quotes
|
|
14
|
+
RSpec/NestedGroups:
|
|
15
|
+
Enabled: false
|
data/README.md
CHANGED
|
@@ -9,18 +9,16 @@ A Ruby Gem focused on wrap all the functionalities and use cases of the WhatsApp
|
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Add `warb` to your bundle
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
14
|
+
```ruby
|
|
15
|
+
bundle add warb
|
|
18
16
|
```
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
or add it manually to your Gemfile if you prefer.
|
|
21
19
|
|
|
22
|
-
```
|
|
23
|
-
gem
|
|
20
|
+
```ruby
|
|
21
|
+
gem 'warb'
|
|
24
22
|
```
|
|
25
23
|
|
|
26
24
|
## Configuration
|
|
@@ -90,9 +88,26 @@ Warb.message.dispatch(recipient_number) do |builder|
|
|
|
90
88
|
end
|
|
91
89
|
```
|
|
92
90
|
|
|
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
|
+
|
|
93
108
|
### Find all usage examples
|
|
94
109
|
|
|
95
|
-
We suggest heading to the `examples
|
|
110
|
+
We suggest heading to the [`examples`](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).
|
|
96
111
|
|
|
97
112
|
You can also check the [`docs`](docs/README.md) for a more structured overview of the available resources and their usage.
|
|
98
113
|
|
|
@@ -109,6 +124,14 @@ To enable this kind of flow, you’ll need to know **when** a message is receive
|
|
|
109
124
|
> ⚠️ **Note:** This gem **does not** provide built-in support for webhooks.
|
|
110
125
|
> 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.
|
|
111
126
|
|
|
127
|
+
## Deploy
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
git tag v0.0.2
|
|
131
|
+
git push origin main --tags
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
|
|
112
135
|
## Development
|
|
113
136
|
|
|
114
137
|
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,4 +10,7 @@ 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.
|
|
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.
|
data/docs/components/README.md
CHANGED
|
@@ -18,4 +18,7 @@ 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) |
|
|
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) |
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
`Warb::Components::Button` is a component that represents a generic button used in template messages. It's part of the Components module, which contains reusable parts of complex structures.
|
|
4
|
+
|
|
5
|
+
It represents a generic button, which can be set with the following attributes:
|
|
6
|
+
|
|
7
|
+
## Attributes
|
|
8
|
+
| Attribute | Type | Required | Description |
|
|
9
|
+
|--------------|-----------|----------|-----------------------------------------------|
|
|
10
|
+
| `index` | `Integer` | Yes | An identifier or position for the button. |
|
|
11
|
+
| `sub_type` | `String` | Yes | A more specific classification for the button |
|
|
12
|
+
|
|
13
|
+
## Common Button Types
|
|
14
|
+
| Button Type | Template Instance Method | Params |
|
|
15
|
+
|---------------|------------------------------|------------------------------------------|
|
|
16
|
+
| `quick_reply` | `add_quick_reply_button` | `index` |
|
|
17
|
+
| `voice_call` | `add_voice_call_button` | `index` |
|
|
18
|
+
| `url` | `add_dynamic_url_button` | `index`, `text` |
|
|
19
|
+
| `copy_code` | `add_copy_code_button` | `index`, `coupon_code` |
|
|
20
|
+
| `flow` | `add_flow_button` | `index`, `flow_token`, `flow_action_data`|
|
|
21
|
+
|
|
22
|
+
Please, refer to our [templates messaging documentation](../messages/template.md) for more info. You can check the methods to insert a button in the "Adding Buttons" section.
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### Quick Reply button
|
|
27
|
+
```ruby
|
|
28
|
+
quick_reply = Warb::Components::Button.new(index: 0, sub_type: "quick_reply")
|
|
29
|
+
quick_reply.to_h
|
|
30
|
+
=> {
|
|
31
|
+
type: "button",
|
|
32
|
+
sub_type: "quick_reply",
|
|
33
|
+
index: 0
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Voice Call button
|
|
38
|
+
```ruby
|
|
39
|
+
voice_call = Warb::Components::Button.new(index: 1, sub_type: "voice_call")
|
|
40
|
+
voice_call.to_h
|
|
41
|
+
=> {
|
|
42
|
+
type: "button",
|
|
43
|
+
sub_type: "voice_call",
|
|
44
|
+
index: 1
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage in Templates
|
|
49
|
+
|
|
50
|
+
Buttons are typically used within template messages. Here's how to add them:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
template = Warb::Resources::Template.new(name: "my_template", language: "en_US")
|
|
54
|
+
|
|
55
|
+
# Add a quick reply button
|
|
56
|
+
template.add_quick_reply_button(index: 0)
|
|
57
|
+
|
|
58
|
+
# Add a voice call button
|
|
59
|
+
template.add_voice_call_button(index: 1)
|
|
60
|
+
|
|
61
|
+
# The buttons will be included in the template's build_payload (as components)
|
|
62
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# CopyCodeButton
|
|
2
|
+
|
|
3
|
+
`Warb::Components::CopyCodeButton` is a component used in template messages for copy code buttons.
|
|
4
|
+
|
|
5
|
+
## Attributes
|
|
6
|
+
| Attribute | Type | Required | Description |
|
|
7
|
+
|----------------|-----------|----------|-----------------------------------------------|
|
|
8
|
+
| `index` | `Integer` | Yes | An identifier or position for the button. |
|
|
9
|
+
| `sub_type` | `String` | Yes | Always "copy_code" for this button type |
|
|
10
|
+
| `coupon_code` | `String` | No | The coupon code to be copied when button is pressed |
|
|
11
|
+
|
|
12
|
+
## Examples
|
|
13
|
+
|
|
14
|
+
### Basic copy code button
|
|
15
|
+
```ruby
|
|
16
|
+
copy_button = Warb::Components::CopyCodeButton.new(index: 0, sub_type: "copy_code", coupon_code: "SAVE20")
|
|
17
|
+
copy_button.to_h
|
|
18
|
+
=> {
|
|
19
|
+
type: "button",
|
|
20
|
+
sub_type: "copy_code",
|
|
21
|
+
index: 0,
|
|
22
|
+
parameters: [
|
|
23
|
+
{
|
|
24
|
+
type: "coupon_code",
|
|
25
|
+
coupon_code: "SAVE20"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Copy code button without coupon code
|
|
32
|
+
```ruby
|
|
33
|
+
copy_button = Warb::Components::CopyCodeButton.new(index: 1, sub_type: "copy_code")
|
|
34
|
+
copy_button.to_h
|
|
35
|
+
=> {
|
|
36
|
+
type: "button",
|
|
37
|
+
sub_type: "copy_code",
|
|
38
|
+
index: 1
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage in Templates
|
|
43
|
+
|
|
44
|
+
Copy code buttons are typically added to templates using the `add_copy_code_button` method:
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
template = Warb::Resources::Template.new(name: "my_template", language: "en_US")
|
|
48
|
+
|
|
49
|
+
# Add a copy code button
|
|
50
|
+
template.add_copy_code_button(index: 0, coupon_code: "SAVE20")
|
|
51
|
+
|
|
52
|
+
# Or using a block for more complex configuration
|
|
53
|
+
template.add_copy_code_button do |button|
|
|
54
|
+
button.index = 0
|
|
55
|
+
button.coupon_code = "SAVE20"
|
|
56
|
+
end
|
|
57
|
+
```
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# FlowButton
|
|
2
|
+
|
|
3
|
+
```Warb::Components::FlowButton``` is a component used in template messages for flow buttons.
|
|
4
|
+
This button type allows you to link a template directly with a WhatsApp Flow experience.
|
|
5
|
+
|
|
6
|
+
## Attributes
|
|
7
|
+
| Attribute | Type | Required | Description |
|
|
8
|
+
| ------------------ | --------- | -------- |-----------------------------------------------------------------|
|
|
9
|
+
| `index` | `Integer` | Yes | An identifier or position for the button in the template. |
|
|
10
|
+
| `sub_type` | `String` | Yes | Always `"flow"` for this button type. |
|
|
11
|
+
| `flow_token` | `String` | No | If not set, the API defaults to `"unused"`. |
|
|
12
|
+
| `flow_action_data` | `Hash` | No | A key-value payload passed to the flow as pre-filled form data. |
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## Examples
|
|
17
|
+
###### Basic Flow button with token
|
|
18
|
+
```ruby
|
|
19
|
+
flow_button = Warb::Components::FlowButton.new(
|
|
20
|
+
index: 0,
|
|
21
|
+
sub_type: "flow",
|
|
22
|
+
flow_token: "TOKEN_123"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
flow_button.to_h
|
|
26
|
+
=> {
|
|
27
|
+
type: "button",
|
|
28
|
+
sub_type: "flow",
|
|
29
|
+
index: 0,
|
|
30
|
+
parameters: [
|
|
31
|
+
{
|
|
32
|
+
type: "action",
|
|
33
|
+
action: {
|
|
34
|
+
flow_token: "TOKEN_123"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
##### Flow button with token and action data
|
|
42
|
+
```ruby
|
|
43
|
+
flow_button = Warb::Components::FlowButton.new(
|
|
44
|
+
index: 1,
|
|
45
|
+
sub_type: "flow",
|
|
46
|
+
flow_token: "TOKEN_ABC",
|
|
47
|
+
flow_action_data: { name: "John", cpf: "11122233344" }
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
flow_button.to_h
|
|
51
|
+
=> {
|
|
52
|
+
type: "button",
|
|
53
|
+
sub_type: "flow",
|
|
54
|
+
index: 1,
|
|
55
|
+
parameters: [
|
|
56
|
+
{
|
|
57
|
+
type: "action",
|
|
58
|
+
action: {
|
|
59
|
+
flow_token: "TOKEN_ABC",
|
|
60
|
+
flow_action_data: { name: "John", cpf: "11122233344" }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
##### Flow button without optional fields
|
|
68
|
+
```ruby
|
|
69
|
+
flow_button = Warb::Components::FlowButton.new(index: 2, sub_type: "flow")
|
|
70
|
+
flow_button.to_h
|
|
71
|
+
=> {
|
|
72
|
+
type: "button",
|
|
73
|
+
sub_type: "flow",
|
|
74
|
+
index: 2,
|
|
75
|
+
parameters: [
|
|
76
|
+
{
|
|
77
|
+
type: "action",
|
|
78
|
+
action: {}
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
### Usage in Templates
|
|
84
|
+
|
|
85
|
+
Flow buttons are typically added to templates using the add_flow_button method:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
template = Warb::Resources::Template.new(name: "my_template", language: "en_US")
|
|
89
|
+
|
|
90
|
+
# Add a flow button with token
|
|
91
|
+
template.add_flow_button(index: 0, flow_token: "TOKEN_123")
|
|
92
|
+
|
|
93
|
+
# Add a flow button with token and action data
|
|
94
|
+
template.add_flow_button(index: 1, flow_token: "TOKEN_ABC", flow_action_data: { name: "Jane", dob: "1990-01-01" })
|
|
95
|
+
|
|
96
|
+
# Or using a block for more complex configuration
|
|
97
|
+
template.add_flow_button do |button|
|
|
98
|
+
button.index = 0
|
|
99
|
+
button.flow_token = "TOKEN_DYNAMIC"
|
|
100
|
+
button.flow_action_data = { email: "user@example.com" }
|
|
101
|
+
end
|
|
102
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# UrlButton
|
|
2
|
+
|
|
3
|
+
`Warb::Components::UrlButton` is a component used in template messages, for dynamic url or auth code buttons.
|
|
4
|
+
|
|
5
|
+
## Attributes
|
|
6
|
+
| Attribute | Type | Required | Description |
|
|
7
|
+
|--------------|-----------|----------|-----------------------------------------------|
|
|
8
|
+
| `index` | `Integer` | Yes | An identifier or position for the button. |
|
|
9
|
+
| `sub_type` | `String` | Yes | Always "url" for this button type |
|
|
10
|
+
| `text` | `String` | No | The URL suffix or text parameter for the button |
|
|
11
|
+
|
|
12
|
+
## Examples
|
|
13
|
+
|
|
14
|
+
### Basic URL button
|
|
15
|
+
```ruby
|
|
16
|
+
url_button = Warb::Components::UrlButton.new(index: 0, sub_type: "url", text: "example.com")
|
|
17
|
+
url_button.to_h
|
|
18
|
+
=> {
|
|
19
|
+
type: "button",
|
|
20
|
+
sub_type: "url",
|
|
21
|
+
index: 0,
|
|
22
|
+
parameters: [
|
|
23
|
+
{
|
|
24
|
+
type: "text",
|
|
25
|
+
text: "example.com"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### URL button without text parameter
|
|
32
|
+
```ruby
|
|
33
|
+
url_button = Warb::Components::UrlButton.new(index: 1, sub_type: "url")
|
|
34
|
+
url_button.to_h
|
|
35
|
+
=> {
|
|
36
|
+
type: "button",
|
|
37
|
+
sub_type: "url",
|
|
38
|
+
index: 1
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage in Templates
|
|
43
|
+
|
|
44
|
+
URL buttons are typically added to templates using the `add_dynamic_url_button` method:
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
template = Warb::Resources::Template.new(name: "my_template", language: "en_US")
|
|
48
|
+
|
|
49
|
+
# Add a dynamic URL button
|
|
50
|
+
template.add_dynamic_url_button(index: 0, text: "example.com")
|
|
51
|
+
|
|
52
|
+
# Or using a block for more complex configuration
|
|
53
|
+
template.add_dynamic_url_button do |button|
|
|
54
|
+
button.index = 0
|
|
55
|
+
button.text = "example.com"
|
|
56
|
+
end
|
|
57
|
+
```
|
data/docs/messages/README.md
CHANGED
|
@@ -71,9 +71,10 @@ 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) |
|
|
74
75
|
|
|
75
76
|
> Simple Dispatcher doesn't offer any additional functionality, they just send messages.
|
|
76
77
|
|
|
77
78
|
> Media Dispatchers, aside from sending messages, also provide methods to upload and download media files.
|
|
78
79
|
|
|
79
|
-
> Special Dispatchers are used for specific purposes, such as sending indicators or
|
|
80
|
+
> Special Dispatchers are used for specific purposes, such as sending indicators, reactions or templates.
|
data/docs/messages/flow.md
CHANGED
|
@@ -1,12 +1,248 @@
|
|
|
1
1
|
# Flow
|
|
2
2
|
|
|
3
|
-
Flow is a special type of
|
|
3
|
+
Flow is a special type of interactive WhatsApp message that provides a "form-like" experience.
|
|
4
|
+
With ```Warb.flow``` you can send static (navigate) or dynamic (data exchange) flows, both in draft and published modes.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Prerequisites (Meta)
|
|
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)
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
### Quick Examples
|
|
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
|
|
8
50
|
```ruby
|
|
9
|
-
Warb.flow.dispatch(recipient_number,
|
|
51
|
+
Warb.flow.dispatch(recipient_number, **params, &block)
|
|
10
52
|
```
|
|
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:
|
|
11
70
|
|
|
12
|
-
|
|
71
|
+
##### Text
|
|
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
|
+
```
|