flow_chat 0.8.2 → 0.9.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/.cliff.toml +74 -0
- data/.github/workflows/ci.yml +2 -3
- data/.github/workflows/release.yml +56 -0
- data/.standard.yml +4 -0
- data/CHANGELOG.md +22 -0
- data/CLAUDE.md +327 -0
- data/CONTRIBUTING.md +134 -0
- data/Gemfile +1 -0
- data/README.md +290 -105
- data/Rakefile +5 -1
- data/SECURITY.md +42 -349
- data/docs/architecture.md +510 -0
- data/docs/async-background-processing.md +298 -0
- data/docs/configuration.md +556 -226
- data/docs/factory-pattern.md +355 -0
- data/docs/gateway-context-variables.md +171 -0
- data/docs/gateway-development.md +723 -0
- data/docs/getting-started.md +429 -0
- data/docs/instrumentation.md +264 -153
- data/docs/platforms/telegram.md +1013 -0
- data/docs/platforms/ussd.md +693 -0
- data/docs/platforms/whatsapp.md +1395 -0
- data/docs/testing.md +243 -365
- data/examples/custom_session_id_example.rb +119 -0
- data/examples/http_controller.rb +11 -11
- data/examples/intercom_configuration_example.rb +118 -0
- data/examples/intercom_controller.rb +194 -0
- data/examples/multi_tenant_whatsapp_controller.rb +4 -4
- data/examples/ussd_controller.rb +9 -9
- data/examples/whatsapp_controller.rb +2 -2
- data/flow_chat.gemspec +4 -0
- data/lib/flow_chat/{base_app.rb → app.rb} +16 -9
- data/lib/flow_chat/async_job.rb +176 -0
- data/lib/flow_chat/config.rb +10 -30
- data/lib/flow_chat/{base_executor.rb → executor.rb} +6 -11
- data/lib/flow_chat/factory.rb +94 -0
- data/lib/flow_chat/gateway_async_support.rb +106 -0
- data/lib/flow_chat/generic_async_job.rb +30 -0
- data/lib/flow_chat/http/gateway/simple.rb +81 -33
- data/lib/flow_chat/http/renderer.rb +3 -3
- data/lib/flow_chat/instrumentation/setup.rb +1 -1
- data/lib/flow_chat/instrumentation.rb +23 -0
- data/lib/flow_chat/intercom/client.rb +155 -0
- data/lib/flow_chat/intercom/configuration.rb +149 -0
- data/lib/flow_chat/intercom/gateway/intercom_api.rb +396 -0
- data/lib/flow_chat/intercom/renderer.rb +71 -0
- data/lib/flow_chat/phone_number_util.rb +37 -35
- data/lib/flow_chat/processor.rb +188 -0
- data/lib/flow_chat/renderers/markdown_support.rb +58 -0
- data/lib/flow_chat/session/middleware.rb +25 -9
- data/lib/flow_chat/telegram/client.rb +240 -0
- data/lib/flow_chat/telegram/configuration.rb +118 -0
- data/lib/flow_chat/telegram/gateway/bot_api.rb +300 -0
- data/lib/flow_chat/telegram/middleware/choice_mapper.rb +35 -0
- data/lib/flow_chat/telegram/renderer.rb +125 -0
- data/lib/flow_chat/telegram.rb +7 -0
- data/lib/flow_chat/ussd/gateway/nalo.rb +24 -4
- data/lib/flow_chat/ussd/middleware/pagination.rb +9 -5
- data/lib/flow_chat/ussd/renderer.rb +1 -1
- data/lib/flow_chat/version.rb +1 -1
- data/lib/flow_chat/whatsapp/client.rb +144 -13
- data/lib/flow_chat/whatsapp/configuration.rb +1 -1
- data/lib/flow_chat/whatsapp/gateway/cloud_api.rb +132 -96
- data/lib/flow_chat/whatsapp/id_generator.rb +124 -0
- data/lib/flow_chat/whatsapp/middleware/choice_mapper.rb +147 -0
- data/lib/flow_chat/whatsapp/renderer.rb +145 -11
- data/lib/flow_chat.rb +11 -1
- data/lib/tasks/release.rake +165 -0
- metadata +84 -25
- data/docs/flows.md +0 -320
- data/docs/http-gateway-protocol.md +0 -432
- data/docs/images/simulator.png +0 -0
- data/docs/media.md +0 -153
- data/docs/sessions.md +0 -433
- data/docs/ussd-setup.md +0 -322
- data/docs/whatsapp-setup.md +0 -162
- data/examples/whatsapp_message_job.rb +0 -113
- data/lib/flow_chat/base_processor.rb +0 -146
- data/lib/flow_chat/http/app.rb +0 -6
- data/lib/flow_chat/http/middleware/executor.rb +0 -24
- data/lib/flow_chat/http/processor.rb +0 -33
- data/lib/flow_chat/session/rails_session_store.rb +0 -68
- data/lib/flow_chat/ussd/app.rb +0 -6
- data/lib/flow_chat/ussd/gateway/nsano.rb +0 -96
- data/lib/flow_chat/ussd/middleware/executor.rb +0 -24
- data/lib/flow_chat/ussd/processor.rb +0 -39
- data/lib/flow_chat/whatsapp/app.rb +0 -29
- data/lib/flow_chat/whatsapp/middleware/executor.rb +0 -24
- data/lib/flow_chat/whatsapp/processor.rb +0 -32
- data/lib/flow_chat/whatsapp/send_job_support.rb +0 -79
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
# FlowChat HTTP Gateway Protocol Specification
|
|
2
|
-
|
|
3
|
-
**Version:** 1.0
|
|
4
|
-
**Date:** 2025-06-27
|
|
5
|
-
**Status:** Stable
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
The FlowChat HTTP Gateway Protocol defines a simple JSON-based request/response format for building conversational flows over HTTP. It enables any HTTP endpoint to participate in FlowChat's conversation framework with session management, media support, and interactive elements.
|
|
10
|
-
|
|
11
|
-
## Protocol Design
|
|
12
|
-
|
|
13
|
-
The protocol is designed to be:
|
|
14
|
-
- **Simple**: Easy to implement with any web framework
|
|
15
|
-
- **Stateless**: Each request contains all necessary context
|
|
16
|
-
- **Flexible**: Supports various response types and media
|
|
17
|
-
- **Extensible**: Can be enhanced without breaking compatibility
|
|
18
|
-
|
|
19
|
-
## Request Format
|
|
20
|
-
|
|
21
|
-
### HTTP Method
|
|
22
|
-
All requests use **POST** method.
|
|
23
|
-
|
|
24
|
-
### Headers
|
|
25
|
-
```
|
|
26
|
-
Content-Type: application/json
|
|
27
|
-
Accept: application/json
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Request Body
|
|
31
|
-
```json
|
|
32
|
-
{
|
|
33
|
-
"session_id": "string",
|
|
34
|
-
"user_id": "string",
|
|
35
|
-
"input": "string",
|
|
36
|
-
"simulator_mode": boolean
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
#### Request Fields
|
|
41
|
-
|
|
42
|
-
| Field | Type | Required | Description |
|
|
43
|
-
|-------|------|----------|-------------|
|
|
44
|
-
| `session_id` | string | Yes | Unique identifier for the conversation session |
|
|
45
|
-
| `user_id` | string | Yes | Unique identifier for the user (phone number, email, etc.) |
|
|
46
|
-
| `input` | string | Yes | User's input message (empty string for initial request) |
|
|
47
|
-
| `simulator_mode` | boolean | No | Indicates if request is from FlowChat simulator |
|
|
48
|
-
|
|
49
|
-
#### Example Request
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"session_id": "sess_abc123",
|
|
53
|
-
"user_id": "+256700123456",
|
|
54
|
-
"input": "1",
|
|
55
|
-
"simulator_mode": true
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Response Format
|
|
60
|
-
|
|
61
|
-
### HTTP Status Codes
|
|
62
|
-
- **200 OK**: Successful response with flow continuation
|
|
63
|
-
- **400 Bad Request**: Invalid request format
|
|
64
|
-
- **500 Internal Server Error**: Server processing error
|
|
65
|
-
|
|
66
|
-
### Response Body
|
|
67
|
-
```json
|
|
68
|
-
{
|
|
69
|
-
"type": "string",
|
|
70
|
-
"message": "string",
|
|
71
|
-
"choices": "object|null",
|
|
72
|
-
"media": "object|null"
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
#### Response Fields
|
|
77
|
-
|
|
78
|
-
| Field | Type | Required | Description |
|
|
79
|
-
|-------|------|----------|-------------|
|
|
80
|
-
| `type` | string | Yes | Response type: `prompt`, `text`, or `terminal` |
|
|
81
|
-
| `message` | string | Yes | Text message to display to user |
|
|
82
|
-
| `choices` | object | No | Interactive choices for user selection |
|
|
83
|
-
| `media` | object | No | Media content (images, videos, etc.) |
|
|
84
|
-
|
|
85
|
-
## Response Types
|
|
86
|
-
|
|
87
|
-
### 1. Prompt Response
|
|
88
|
-
Interactive response expecting user input with optional choices.
|
|
89
|
-
|
|
90
|
-
```json
|
|
91
|
-
{
|
|
92
|
-
"type": "prompt",
|
|
93
|
-
"message": "Welcome! Please choose an option:",
|
|
94
|
-
"choices": {
|
|
95
|
-
"1": "View Profile",
|
|
96
|
-
"2": "Send Message",
|
|
97
|
-
"3": "Settings"
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
**Behavior**: Session continues, awaiting user input.
|
|
103
|
-
|
|
104
|
-
### 2. Text Response
|
|
105
|
-
Simple informational message.
|
|
106
|
-
|
|
107
|
-
```json
|
|
108
|
-
{
|
|
109
|
-
"type": "text",
|
|
110
|
-
"message": "Processing your request..."
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**Behavior**: Session continues, awaiting user input.
|
|
115
|
-
|
|
116
|
-
### 3. Terminal Response
|
|
117
|
-
Final message that ends the conversation session.
|
|
118
|
-
|
|
119
|
-
```json
|
|
120
|
-
{
|
|
121
|
-
"type": "terminal",
|
|
122
|
-
"message": "Thank you for using our service. Goodbye!"
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**Behavior**: Session ends, no further input expected.
|
|
127
|
-
|
|
128
|
-
## Choices Format
|
|
129
|
-
|
|
130
|
-
Choices enable interactive menu-driven flows. They can be provided in two formats:
|
|
131
|
-
|
|
132
|
-
### Simple Format
|
|
133
|
-
```json
|
|
134
|
-
{
|
|
135
|
-
"choices": {
|
|
136
|
-
"1": "Option One",
|
|
137
|
-
"2": "Option Two",
|
|
138
|
-
"3": "Option Three"
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Object Format
|
|
144
|
-
```json
|
|
145
|
-
{
|
|
146
|
-
"choices": {
|
|
147
|
-
"choice1": {
|
|
148
|
-
"key": "1",
|
|
149
|
-
"value": "Option One"
|
|
150
|
-
},
|
|
151
|
-
"choice2": {
|
|
152
|
-
"key": "2",
|
|
153
|
-
"value": "Option Two"
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
**Key Guidelines:**
|
|
160
|
-
- Keys should be simple (numbers, single letters)
|
|
161
|
-
- Values should be descriptive text
|
|
162
|
-
- Maximum 10 choices recommended for usability
|
|
163
|
-
- Empty choices object `{}` means free-form input expected
|
|
164
|
-
|
|
165
|
-
## Media Support
|
|
166
|
-
|
|
167
|
-
The protocol supports various media types in responses.
|
|
168
|
-
|
|
169
|
-
### Image Media
|
|
170
|
-
```json
|
|
171
|
-
{
|
|
172
|
-
"media": {
|
|
173
|
-
"type": "image",
|
|
174
|
-
"url": "https://example.com/image.jpg",
|
|
175
|
-
"caption": "Optional image caption"
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Video Media
|
|
181
|
-
```json
|
|
182
|
-
{
|
|
183
|
-
"media": {
|
|
184
|
-
"type": "video",
|
|
185
|
-
"url": "https://example.com/video.mp4",
|
|
186
|
-
"caption": "Optional video caption"
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Document Media
|
|
192
|
-
```json
|
|
193
|
-
{
|
|
194
|
-
"media": {
|
|
195
|
-
"type": "document",
|
|
196
|
-
"url": "https://example.com/document.pdf",
|
|
197
|
-
"filename": "report.pdf",
|
|
198
|
-
"caption": "Download the full report"
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### Audio Media
|
|
204
|
-
```json
|
|
205
|
-
{
|
|
206
|
-
"media": {
|
|
207
|
-
"type": "audio",
|
|
208
|
-
"url": "https://example.com/audio.mp3",
|
|
209
|
-
"caption": "Voice message"
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
**Media Guidelines:**
|
|
215
|
-
- URLs must be publicly accessible
|
|
216
|
-
- HTTPS URLs recommended for security
|
|
217
|
-
- Include appropriate file extensions
|
|
218
|
-
- Captions are optional but recommended for accessibility
|
|
219
|
-
|
|
220
|
-
## Session Management
|
|
221
|
-
|
|
222
|
-
### Session Lifecycle
|
|
223
|
-
1. **Initialization**: First request has empty `input` field
|
|
224
|
-
2. **Continuation**: Subsequent requests include user input
|
|
225
|
-
3. **Termination**: Response with `type: "terminal"` ends session
|
|
226
|
-
|
|
227
|
-
### Session State
|
|
228
|
-
The protocol is stateless from HTTP perspective. Session state must be managed by the endpoint implementation using:
|
|
229
|
-
- Database storage
|
|
230
|
-
- In-memory cache
|
|
231
|
-
- External session stores
|
|
232
|
-
- Cookies/tokens (if supported)
|
|
233
|
-
|
|
234
|
-
### Session ID Format
|
|
235
|
-
- Must be unique across all sessions
|
|
236
|
-
- Recommended: UUID, random string, or timestamped identifier
|
|
237
|
-
- Length: 8-64 characters
|
|
238
|
-
- Characters: alphanumeric, hyphens, underscores
|
|
239
|
-
|
|
240
|
-
## Error Handling
|
|
241
|
-
|
|
242
|
-
### Client Errors (4xx)
|
|
243
|
-
```json
|
|
244
|
-
{
|
|
245
|
-
"type": "terminal",
|
|
246
|
-
"message": "Invalid request format. Please try again later."
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### Server Errors (5xx)
|
|
251
|
-
```json
|
|
252
|
-
{
|
|
253
|
-
"type": "terminal",
|
|
254
|
-
"message": "Service temporarily unavailable. Please try again later."
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### Validation Errors
|
|
259
|
-
```json
|
|
260
|
-
{
|
|
261
|
-
"type": "prompt",
|
|
262
|
-
"message": "Invalid selection. Please choose from the available options:",
|
|
263
|
-
"choices": {
|
|
264
|
-
"1": "Option A",
|
|
265
|
-
"2": "Option B"
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## Implementation Examples
|
|
271
|
-
|
|
272
|
-
### Basic Flow Handler
|
|
273
|
-
```ruby
|
|
274
|
-
def handle_http_webhook
|
|
275
|
-
data = JSON.parse(request.body.read)
|
|
276
|
-
|
|
277
|
-
session_id = data['session_id']
|
|
278
|
-
user_id = data['user_id']
|
|
279
|
-
input = data['input']
|
|
280
|
-
|
|
281
|
-
response = case input.downcase.strip
|
|
282
|
-
when '', 'start'
|
|
283
|
-
{
|
|
284
|
-
type: 'prompt',
|
|
285
|
-
message: 'Welcome! What would you like to do?',
|
|
286
|
-
choices: {
|
|
287
|
-
'1' => 'View Account',
|
|
288
|
-
'2' => 'Make Payment',
|
|
289
|
-
'3' => 'Get Help'
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
when '1'
|
|
293
|
-
{
|
|
294
|
-
type: 'text',
|
|
295
|
-
message: "Account Balance: $150.00\nLast Transaction: -$25.00"
|
|
296
|
-
}
|
|
297
|
-
when '2'
|
|
298
|
-
{
|
|
299
|
-
type: 'prompt',
|
|
300
|
-
message: 'Enter payment amount:',
|
|
301
|
-
choices: {}
|
|
302
|
-
}
|
|
303
|
-
when '3'
|
|
304
|
-
{
|
|
305
|
-
type: 'terminal',
|
|
306
|
-
message: 'For help, call 1-800-HELP or visit our website.'
|
|
307
|
-
}
|
|
308
|
-
else
|
|
309
|
-
{
|
|
310
|
-
type: 'prompt',
|
|
311
|
-
message: 'Please select a valid option:',
|
|
312
|
-
choices: {
|
|
313
|
-
'1' => 'View Account',
|
|
314
|
-
'2' => 'Make Payment',
|
|
315
|
-
'3' => 'Get Help'
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
render json: response
|
|
321
|
-
end
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### With Media Support
|
|
325
|
-
```ruby
|
|
326
|
-
def handle_media_flow
|
|
327
|
-
# ... input parsing ...
|
|
328
|
-
|
|
329
|
-
case input
|
|
330
|
-
when 'show_chart'
|
|
331
|
-
{
|
|
332
|
-
type: 'prompt',
|
|
333
|
-
message: 'Here is your sales chart:',
|
|
334
|
-
media: {
|
|
335
|
-
type: 'image',
|
|
336
|
-
url: generate_chart_url(user_id),
|
|
337
|
-
caption: 'Monthly sales data'
|
|
338
|
-
},
|
|
339
|
-
choices: {
|
|
340
|
-
'0' => 'Back to menu'
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
end
|
|
344
|
-
end
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
## Security Considerations
|
|
348
|
-
|
|
349
|
-
### Input Validation
|
|
350
|
-
- Always validate and sanitize user input
|
|
351
|
-
- Check session_id format and existence
|
|
352
|
-
- Validate user_id against expected format
|
|
353
|
-
- Limit input length to prevent abuse
|
|
354
|
-
|
|
355
|
-
### Authentication
|
|
356
|
-
- Implement endpoint authentication if needed
|
|
357
|
-
- Validate session ownership
|
|
358
|
-
- Use HTTPS for sensitive data
|
|
359
|
-
- Consider rate limiting
|
|
360
|
-
|
|
361
|
-
### Data Protection
|
|
362
|
-
- Don't log sensitive user input
|
|
363
|
-
- Encrypt session data if stored
|
|
364
|
-
- Use secure session identifiers
|
|
365
|
-
- Implement proper CORS headers
|
|
366
|
-
|
|
367
|
-
## Best Practices
|
|
368
|
-
|
|
369
|
-
### Response Design
|
|
370
|
-
1. **Keep messages concise** - Users prefer short, clear text
|
|
371
|
-
2. **Limit choices** - Maximum 5-7 options for better UX
|
|
372
|
-
3. **Use clear labels** - Make choice text descriptive
|
|
373
|
-
4. **Provide fallbacks** - Handle invalid input gracefully
|
|
374
|
-
5. **End flows properly** - Always provide terminal responses
|
|
375
|
-
|
|
376
|
-
### Session Management
|
|
377
|
-
1. **Set timeouts** - Expire inactive sessions
|
|
378
|
-
2. **Clean up data** - Remove old session data
|
|
379
|
-
3. **Handle duplicates** - Manage duplicate session IDs
|
|
380
|
-
4. **Log activities** - Track session flow for debugging
|
|
381
|
-
|
|
382
|
-
### Error Handling
|
|
383
|
-
1. **Fail gracefully** - Provide helpful error messages
|
|
384
|
-
2. **Log errors** - Capture errors for debugging
|
|
385
|
-
3. **Retry logic** - Handle temporary failures
|
|
386
|
-
4. **Fallback flows** - Provide alternative paths
|
|
387
|
-
|
|
388
|
-
## Protocol Extensions
|
|
389
|
-
|
|
390
|
-
### Custom Fields
|
|
391
|
-
Implementations may include additional fields in requests/responses:
|
|
392
|
-
|
|
393
|
-
```json
|
|
394
|
-
{
|
|
395
|
-
"type": "prompt",
|
|
396
|
-
"message": "Hello!",
|
|
397
|
-
"choices": {...},
|
|
398
|
-
"metadata": {
|
|
399
|
-
"flow_version": "1.2",
|
|
400
|
-
"user_lang": "en"
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
### Future Enhancements
|
|
406
|
-
- Rich media support (carousels, buttons)
|
|
407
|
-
- Location sharing
|
|
408
|
-
- File uploads
|
|
409
|
-
- Real-time messaging
|
|
410
|
-
- Multi-turn conversations
|
|
411
|
-
|
|
412
|
-
## Compliance
|
|
413
|
-
|
|
414
|
-
### HTTP Standards
|
|
415
|
-
- Follows HTTP/1.1 and HTTP/2 specifications
|
|
416
|
-
- Uses standard status codes and headers
|
|
417
|
-
- Supports CORS for cross-origin requests
|
|
418
|
-
|
|
419
|
-
### JSON Standards
|
|
420
|
-
- Follows RFC 7159 JSON specification
|
|
421
|
-
- Uses UTF-8 encoding
|
|
422
|
-
- Validates JSON schema on input
|
|
423
|
-
|
|
424
|
-
## Version History
|
|
425
|
-
|
|
426
|
-
| Version | Date | Changes |
|
|
427
|
-
|---------|------|---------|
|
|
428
|
-
| 1.0 | 2025-06-27 | Initial specification |
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
For implementation questions or protocol clarifications, please refer to the FlowChat documentation or contact the development team.
|
data/docs/images/simulator.png
DELETED
|
Binary file
|
data/docs/media.md
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
# Media Support
|
|
2
|
-
|
|
3
|
-
FlowChat supports rich media attachments for enhanced conversational experiences with automatic cross-platform optimization.
|
|
4
|
-
|
|
5
|
-
## Supported Media Types
|
|
6
|
-
|
|
7
|
-
- **📷 Images** (`type: :image`) - Photos, screenshots, diagrams
|
|
8
|
-
- **📄 Documents** (`type: :document`) - PDFs, forms, receipts
|
|
9
|
-
- **🎥 Videos** (`type: :video`) - Tutorials, demos, explanations
|
|
10
|
-
- **🎵 Audio** (`type: :audio`) - Voice messages, recordings
|
|
11
|
-
- **😊 Stickers** (`type: :sticker`) - Fun visual elements
|
|
12
|
-
|
|
13
|
-
## Basic Usage
|
|
14
|
-
|
|
15
|
-
```ruby
|
|
16
|
-
class ProductFlow < FlowChat::Flow
|
|
17
|
-
def main_page
|
|
18
|
-
# Text input with context image
|
|
19
|
-
feedback = app.screen(:feedback) do |prompt|
|
|
20
|
-
prompt.ask "What do you think of our new product?",
|
|
21
|
-
media: {
|
|
22
|
-
type: :image,
|
|
23
|
-
url: "https://cdn.example.com/products/new_product.jpg"
|
|
24
|
-
}
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Send informational media
|
|
28
|
-
app.say "Thanks for your feedback! Here's what's coming next:",
|
|
29
|
-
media: {
|
|
30
|
-
type: :video,
|
|
31
|
-
url: "https://videos.example.com/roadmap.mp4"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
# Document with filename
|
|
35
|
-
app.say "Here's your receipt:",
|
|
36
|
-
media: {
|
|
37
|
-
type: :document,
|
|
38
|
-
url: "https://api.example.com/receipt.pdf",
|
|
39
|
-
filename: "receipt.pdf"
|
|
40
|
-
}
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Media Hash Format
|
|
46
|
-
|
|
47
|
-
```ruby
|
|
48
|
-
{
|
|
49
|
-
type: :image, # Required: :image, :document, :audio, :video, :sticker
|
|
50
|
-
url: "https://...", # Required: URL to the media file OR WhatsApp media ID
|
|
51
|
-
filename: "doc.pdf" # Optional: Only for documents
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Using WhatsApp Media IDs
|
|
56
|
-
|
|
57
|
-
For better performance and to avoid external dependencies, you can upload files to WhatsApp and use the media ID:
|
|
58
|
-
|
|
59
|
-
```ruby
|
|
60
|
-
# Upload a file first
|
|
61
|
-
client = FlowChat::Whatsapp::Client.new(config)
|
|
62
|
-
media_id = client.upload_media('path/to/image.jpg', 'image/jpeg')
|
|
63
|
-
|
|
64
|
-
# Then use the media ID in your flow
|
|
65
|
-
app.screen(:product_demo) do |prompt|
|
|
66
|
-
prompt.ask "What do you think?",
|
|
67
|
-
media: {
|
|
68
|
-
type: :image,
|
|
69
|
-
url: media_id # Use the media ID instead of URL
|
|
70
|
-
}
|
|
71
|
-
end
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## WhatsApp Client Media Methods
|
|
75
|
-
|
|
76
|
-
The WhatsApp client provides methods for uploading and sending media:
|
|
77
|
-
|
|
78
|
-
```ruby
|
|
79
|
-
client = FlowChat::Whatsapp::Client.new(config)
|
|
80
|
-
|
|
81
|
-
# Upload media and get media ID
|
|
82
|
-
media_id = client.upload_media('image.jpg', 'image/jpeg')
|
|
83
|
-
media_id = client.upload_media(file_io, 'image/jpeg', 'photo.jpg')
|
|
84
|
-
|
|
85
|
-
# Send media directly
|
|
86
|
-
client.send_image("+1234567890", "https://example.com/image.jpg", "Caption")
|
|
87
|
-
client.send_image("+1234567890", media_id, "Caption")
|
|
88
|
-
|
|
89
|
-
# Send document with MIME type and filename
|
|
90
|
-
client.send_document("+1234567890", "https://example.com/doc.pdf", "Your receipt", "receipt.pdf", "application/pdf")
|
|
91
|
-
|
|
92
|
-
# Send other media types
|
|
93
|
-
client.send_video("+1234567890", "https://example.com/video.mp4", "Demo video", "video/mp4")
|
|
94
|
-
client.send_audio("+1234567890", "https://example.com/audio.mp3", "audio/mpeg")
|
|
95
|
-
client.send_sticker("+1234567890", "https://example.com/sticker.webp", "image/webp")
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Cross-Platform Behavior
|
|
99
|
-
|
|
100
|
-
### WhatsApp Experience
|
|
101
|
-
- Media is sent directly to the chat
|
|
102
|
-
- Prompt text becomes the media caption
|
|
103
|
-
- Rich, native messaging experience
|
|
104
|
-
|
|
105
|
-
### USSD Experience
|
|
106
|
-
- Media URL is included in text message
|
|
107
|
-
- Graceful degradation with clear media indicators
|
|
108
|
-
- Users can access media via the provided link
|
|
109
|
-
|
|
110
|
-
```ruby
|
|
111
|
-
# This code works on both platforms:
|
|
112
|
-
app.screen(:help) do |prompt|
|
|
113
|
-
prompt.ask "Describe your issue:",
|
|
114
|
-
media: {
|
|
115
|
-
type: :image,
|
|
116
|
-
url: "https://support.example.com/help_example.jpg"
|
|
117
|
-
}
|
|
118
|
-
end
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
**WhatsApp Result:** Image sent with caption "Describe your issue:"
|
|
122
|
-
|
|
123
|
-
**USSD Result:**
|
|
124
|
-
```
|
|
125
|
-
📷 Image: https://support.example.com/help_example.jpg
|
|
126
|
-
|
|
127
|
-
Describe your issue:
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Advanced Examples
|
|
131
|
-
|
|
132
|
-
### Dynamic Media Based on User Context
|
|
133
|
-
|
|
134
|
-
```ruby
|
|
135
|
-
class SupportFlow < FlowChat::Flow
|
|
136
|
-
def show_help
|
|
137
|
-
user_level = determine_user_level
|
|
138
|
-
|
|
139
|
-
help_media = case user_level
|
|
140
|
-
when :beginner
|
|
141
|
-
{ type: :video, url: "https://help.example.com/beginner_guide.mp4" }
|
|
142
|
-
when :advanced
|
|
143
|
-
{ type: :document, url: "https://help.example.com/advanced_manual.pdf", filename: "advanced_manual.pdf" }
|
|
144
|
-
else
|
|
145
|
-
{ type: :image, url: "https://help.example.com/quick_reference.jpg" }
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
app.say "Here's help tailored for you:", media: help_media
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
See [examples/whatsapp_media_examples.rb](../examples/whatsapp_media_examples.rb) for complete media implementation examples.
|