flow_chat 0.4.0 โ 0.4.2
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/Gemfile +1 -0
- data/README.md +408 -102
- data/examples/initializer.rb +1 -1
- data/examples/media_prompts_examples.rb +27 -0
- data/examples/multi_tenant_whatsapp_controller.rb +60 -64
- data/examples/ussd_controller.rb +17 -11
- data/examples/whatsapp_controller.rb +11 -12
- data/examples/whatsapp_media_examples.rb +404 -0
- data/examples/whatsapp_message_job.rb +111 -0
- data/lib/flow_chat/base_processor.rb +8 -4
- data/lib/flow_chat/config.rb +37 -0
- data/lib/flow_chat/session/cache_session_store.rb +5 -5
- data/lib/flow_chat/simulator/controller.rb +78 -0
- data/lib/flow_chat/simulator/views/simulator.html.erb +1982 -0
- data/lib/flow_chat/ussd/gateway/nsano.rb +1 -1
- data/lib/flow_chat/ussd/processor.rb +1 -2
- data/lib/flow_chat/ussd/prompt.rb +39 -5
- data/lib/flow_chat/version.rb +1 -1
- data/lib/flow_chat/whatsapp/app.rb +8 -2
- data/lib/flow_chat/whatsapp/client.rb +435 -0
- data/lib/flow_chat/whatsapp/configuration.rb +50 -12
- data/lib/flow_chat/whatsapp/gateway/cloud_api.rb +113 -115
- data/lib/flow_chat/whatsapp/middleware/executor.rb +1 -1
- data/lib/flow_chat/whatsapp/processor.rb +1 -11
- data/lib/flow_chat/whatsapp/prompt.rb +125 -84
- data/lib/flow_chat/whatsapp/send_job_support.rb +79 -0
- data/lib/flow_chat/whatsapp/template_manager.rb +7 -7
- metadata +8 -3
- data/lib/flow_chat/ussd/simulator/controller.rb +0 -51
- data/lib/flow_chat/ussd/simulator/views/simulator.html.erb +0 -239
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 004e0d3a8a9c9da83dfd6386b6e7684b7fea2b69daab7645e28d9a4767e80819
|
4
|
+
data.tar.gz: 85cf51f944ebb00aa7498106f88d60bfbdf060dcfe62762e3ab5a83784cff9f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5a716d3345118c334899299367e1b7ef082e54651d75d7d92a24f01f03ea36a1e55df916aa14b6ddd0e75b353a0a37be08b0ce2681082df4f0d9768dc10a525
|
7
|
+
data.tar.gz: d533c33058573554f5c340460999c6d3b08332800ef33b521a0111ca44e8b4d10d4aa559e5d4f23f6575cffc86e8fa10d0e0850cefec5e18f075397ccb3d449d
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,8 +8,9 @@ FlowChat is a Rails framework designed for building sophisticated conversational
|
|
8
8
|
- โ
**Input Validation & Transformation** - Built-in validation and data conversion
|
9
9
|
- ๐ **Middleware Architecture** - Flexible request processing pipeline
|
10
10
|
- ๐ฑ **USSD Gateway Support** - Currently supports Nalo gateways
|
11
|
-
- ๐ฌ **WhatsApp Integration** - Full WhatsApp Cloud API support with
|
12
|
-
-
|
11
|
+
- ๐ฌ **WhatsApp Integration** - Full WhatsApp Cloud API support with multiple processing modes
|
12
|
+
- ๐ง **Reusable WhatsApp Client** - Standalone client for out-of-band messaging
|
13
|
+
- ๐งช **Built-in Testing Tools** - Unified simulator for both USSD and WhatsApp testing
|
13
14
|
|
14
15
|
## Architecture Overview
|
15
16
|
|
@@ -154,17 +155,54 @@ custom_config.business_account_id = "your_specific_business_account_id"
|
|
154
155
|
|
155
156
|
# Use in processor
|
156
157
|
processor = FlowChat::Whatsapp::Processor.new(self) do |config|
|
157
|
-
config.
|
158
|
-
config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
|
158
|
+
config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, custom_config
|
159
159
|
config.use_session_store FlowChat::Session::CacheSessionStore
|
160
160
|
end
|
161
161
|
```
|
162
162
|
|
163
163
|
๐ก **Tip**: See [examples/multi_tenant_whatsapp_controller.rb](examples/multi_tenant_whatsapp_controller.rb) for comprehensive multi-tenant and per-setup configuration examples.
|
164
164
|
|
165
|
-
### 2.
|
165
|
+
### 2. Choose Message Handling Mode
|
166
166
|
|
167
|
+
FlowChat offers three WhatsApp message handling modes. Configure them in an initializer:
|
168
|
+
|
169
|
+
**Create an initializer** `config/initializers/flowchat.rb`:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
# config/initializers/flowchat.rb
|
173
|
+
|
174
|
+
# Configure WhatsApp message handling mode
|
175
|
+
FlowChat::Config.whatsapp.message_handling_mode = :inline # or :background, :simulator
|
176
|
+
FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
|
177
|
+
```
|
178
|
+
|
179
|
+
**Inline Mode (Default)** - Process messages synchronously:
|
167
180
|
```ruby
|
181
|
+
# config/initializers/flowchat.rb
|
182
|
+
FlowChat::Config.whatsapp.message_handling_mode = :inline
|
183
|
+
|
184
|
+
# app/controllers/whatsapp_controller.rb
|
185
|
+
class WhatsappController < ApplicationController
|
186
|
+
skip_forgery_protection
|
187
|
+
|
188
|
+
def webhook
|
189
|
+
processor = FlowChat::Whatsapp::Processor.new(self) do |config|
|
190
|
+
config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
|
191
|
+
config.use_session_store FlowChat::Session::CacheSessionStore
|
192
|
+
end
|
193
|
+
|
194
|
+
processor.run WelcomeFlow, :main_page
|
195
|
+
end
|
196
|
+
end
|
197
|
+
```
|
198
|
+
|
199
|
+
**Background Mode** - Process flows synchronously, send responses asynchronously:
|
200
|
+
```ruby
|
201
|
+
# config/initializers/flowchat.rb
|
202
|
+
FlowChat::Config.whatsapp.message_handling_mode = :background
|
203
|
+
FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
|
204
|
+
|
205
|
+
# app/controllers/whatsapp_controller.rb
|
168
206
|
class WhatsappController < ApplicationController
|
169
207
|
skip_forgery_protection
|
170
208
|
|
@@ -179,6 +217,28 @@ class WhatsappController < ApplicationController
|
|
179
217
|
end
|
180
218
|
```
|
181
219
|
|
220
|
+
**Simulator Mode** - Return response data instead of sending via WhatsApp API:
|
221
|
+
```ruby
|
222
|
+
# config/initializers/flowchat.rb
|
223
|
+
FlowChat::Config.whatsapp.message_handling_mode = :simulator
|
224
|
+
|
225
|
+
# app/controllers/whatsapp_controller.rb
|
226
|
+
class WhatsappController < ApplicationController
|
227
|
+
skip_forgery_protection
|
228
|
+
|
229
|
+
def webhook
|
230
|
+
processor = FlowChat::Whatsapp::Processor.new(self) do |config|
|
231
|
+
config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
|
232
|
+
config.use_session_store FlowChat::Session::CacheSessionStore
|
233
|
+
end
|
234
|
+
|
235
|
+
processor.run WelcomeFlow, :main_page
|
236
|
+
end
|
237
|
+
end
|
238
|
+
```
|
239
|
+
|
240
|
+
๐ก **See [examples/README_whatsapp_modes.md](examples/README_whatsapp_modes.md) for detailed mode explanations and use cases.**
|
241
|
+
|
182
242
|
### 3. Add WhatsApp Route
|
183
243
|
|
184
244
|
```ruby
|
@@ -299,6 +359,86 @@ end
|
|
299
359
|
|
300
360
|
For detailed WhatsApp setup instructions, see [WhatsApp Integration Guide](docs/whatsapp_setup.md).
|
301
361
|
|
362
|
+
## ๐ง Reusable WhatsApp Client
|
363
|
+
|
364
|
+
FlowChat provides a standalone WhatsApp client for out-of-band messaging:
|
365
|
+
|
366
|
+
```ruby
|
367
|
+
# Initialize client
|
368
|
+
config = FlowChat::Whatsapp::Configuration.from_credentials
|
369
|
+
client = FlowChat::Whatsapp::Client.new(config)
|
370
|
+
|
371
|
+
# Send text message
|
372
|
+
client.send_text("+1234567890", "Hello, World!")
|
373
|
+
|
374
|
+
# Send interactive buttons
|
375
|
+
client.send_buttons(
|
376
|
+
"+1234567890",
|
377
|
+
"Choose an option:",
|
378
|
+
[
|
379
|
+
{ id: 'option1', title: 'Option 1' },
|
380
|
+
{ id: 'option2', title: 'Option 2' }
|
381
|
+
]
|
382
|
+
)
|
383
|
+
|
384
|
+
# Send interactive list
|
385
|
+
client.send_list(
|
386
|
+
"+1234567890",
|
387
|
+
"Select from menu:",
|
388
|
+
[
|
389
|
+
{
|
390
|
+
title: "Services",
|
391
|
+
rows: [
|
392
|
+
{ id: 'service1', title: 'Service 1', description: 'Description 1' },
|
393
|
+
{ id: 'service2', title: 'Service 2', description: 'Description 2' }
|
394
|
+
]
|
395
|
+
}
|
396
|
+
]
|
397
|
+
)
|
398
|
+
|
399
|
+
# Handle media
|
400
|
+
media_url = client.get_media_url("media_id_123")
|
401
|
+
media_content = client.download_media("media_id_123")
|
402
|
+
```
|
403
|
+
|
404
|
+
### Out-of-Band Messaging Service Example
|
405
|
+
|
406
|
+
```ruby
|
407
|
+
class NotificationService
|
408
|
+
def initialize
|
409
|
+
@config = FlowChat::Whatsapp::Configuration.from_credentials
|
410
|
+
@client = FlowChat::Whatsapp::Client.new(@config)
|
411
|
+
end
|
412
|
+
|
413
|
+
def send_order_confirmation(phone_number, order_id, items, total)
|
414
|
+
item_list = items.map { |item| "โข #{item[:name]} x#{item[:quantity]}" }.join("\n")
|
415
|
+
|
416
|
+
@client.send_buttons(
|
417
|
+
phone_number,
|
418
|
+
"โ
Order Confirmed!\n\nOrder ##{order_id}\n\n#{item_list}\n\nTotal: $#{total}",
|
419
|
+
[
|
420
|
+
{ id: 'track_order', title: '๐ฆ Track Order' },
|
421
|
+
{ id: 'contact_support', title: '๐ฌ Contact Support' }
|
422
|
+
]
|
423
|
+
)
|
424
|
+
end
|
425
|
+
|
426
|
+
def send_appointment_reminder(phone_number, appointment)
|
427
|
+
@client.send_buttons(
|
428
|
+
phone_number,
|
429
|
+
"๐ฅ Appointment Reminder\n\n#{appointment[:service]} with #{appointment[:provider]}\n๐
#{appointment[:date]}\n๐ #{appointment[:time]}",
|
430
|
+
[
|
431
|
+
{ id: 'confirm', title: 'โ
Confirm' },
|
432
|
+
{ id: 'reschedule', title: '๐
Reschedule' },
|
433
|
+
{ id: 'cancel', title: 'โ Cancel' }
|
434
|
+
]
|
435
|
+
)
|
436
|
+
end
|
437
|
+
end
|
438
|
+
```
|
439
|
+
|
440
|
+
๐ก **See [examples/whatsapp_controller_modes.rb](examples/whatsapp_controller_modes.rb) for comprehensive usage examples.**
|
441
|
+
|
302
442
|
## Cross-Platform Compatibility
|
303
443
|
|
304
444
|
FlowChat provides a unified API that works across both USSD and WhatsApp platforms, with graceful degradation for platform-specific features:
|
@@ -321,6 +461,135 @@ FlowChat provides a unified API that works across both USSD and WhatsApp platfor
|
|
321
461
|
|
322
462
|
This design allows you to write flows once and deploy them on both platforms, with WhatsApp users getting enhanced interactive features automatically.
|
323
463
|
|
464
|
+
## ๐ฑ Media Support
|
465
|
+
|
466
|
+
FlowChat supports rich media attachments for enhanced conversational experiences. Media can be attached to `ask()` and `say()` prompts, with automatic cross-platform optimization.
|
467
|
+
|
468
|
+
### Supported Media Types
|
469
|
+
|
470
|
+
- **๐ท Images** (`type: :image`) - Photos, screenshots, diagrams
|
471
|
+
- **๐ Documents** (`type: :document`) - PDFs, forms, receipts
|
472
|
+
- **๐ฅ Videos** (`type: :video`) - Tutorials, demos, explanations
|
473
|
+
- **๐ต Audio** (`type: :audio`) - Voice messages, recordings
|
474
|
+
- **๐ Stickers** (`type: :sticker`) - Fun visual elements
|
475
|
+
|
476
|
+
### Basic Usage
|
477
|
+
|
478
|
+
```ruby
|
479
|
+
class ProductFlow < FlowChat::Flow
|
480
|
+
def main_page
|
481
|
+
# โ
Text input with context image
|
482
|
+
feedback = app.screen(:feedback) do |prompt|
|
483
|
+
prompt.ask "What do you think of our new product?",
|
484
|
+
media: {
|
485
|
+
type: :image,
|
486
|
+
url: "https://cdn.example.com/products/new_product.jpg"
|
487
|
+
}
|
488
|
+
end
|
489
|
+
|
490
|
+
# โ
Send informational media
|
491
|
+
app.say "Thanks for your feedback! Here's what's coming next:",
|
492
|
+
media: {
|
493
|
+
type: :video,
|
494
|
+
url: "https://videos.example.com/roadmap.mp4"
|
495
|
+
}
|
496
|
+
|
497
|
+
# โ
Document with filename
|
498
|
+
app.say "Here's your receipt:",
|
499
|
+
media: {
|
500
|
+
type: :document,
|
501
|
+
url: "https://api.example.com/receipt.pdf",
|
502
|
+
filename: "receipt.pdf"
|
503
|
+
}
|
504
|
+
end
|
505
|
+
end
|
506
|
+
```
|
507
|
+
|
508
|
+
### Media Hash Format
|
509
|
+
|
510
|
+
```ruby
|
511
|
+
{
|
512
|
+
type: :image, # Required: :image, :document, :audio, :video, :sticker
|
513
|
+
url: "https://...", # Required: URL to the media file OR WhatsApp media ID
|
514
|
+
filename: "doc.pdf" # Optional: Only for documents
|
515
|
+
}
|
516
|
+
```
|
517
|
+
|
518
|
+
### Using WhatsApp Media IDs
|
519
|
+
|
520
|
+
For better performance and to avoid external dependencies, you can upload files to WhatsApp and use the media ID:
|
521
|
+
|
522
|
+
```ruby
|
523
|
+
# Upload a file first
|
524
|
+
client = FlowChat::Whatsapp::Client.new(config)
|
525
|
+
media_id = client.upload_media('path/to/image.jpg', 'image/jpeg')
|
526
|
+
|
527
|
+
# Then use the media ID in your flow
|
528
|
+
app.screen(:product_demo) do |prompt|
|
529
|
+
prompt.ask "What do you think?",
|
530
|
+
media: {
|
531
|
+
type: :image,
|
532
|
+
url: media_id # Use the media ID instead of URL
|
533
|
+
}
|
534
|
+
end
|
535
|
+
```
|
536
|
+
|
537
|
+
### Client Media Methods
|
538
|
+
|
539
|
+
The WhatsApp client provides methods for uploading and sending media:
|
540
|
+
|
541
|
+
```ruby
|
542
|
+
client = FlowChat::Whatsapp::Client.new(config)
|
543
|
+
|
544
|
+
# Upload media and get media ID
|
545
|
+
media_id = client.upload_media('image.jpg', 'image/jpeg')
|
546
|
+
media_id = client.upload_media(file_io, 'image/jpeg', 'photo.jpg')
|
547
|
+
|
548
|
+
# Send media directly
|
549
|
+
client.send_image("+1234567890", "https://example.com/image.jpg", "Caption")
|
550
|
+
client.send_image("+1234567890", media_id, "Caption")
|
551
|
+
|
552
|
+
# Send document with MIME type and filename
|
553
|
+
client.send_document("+1234567890", "https://example.com/doc.pdf", "Your receipt", "receipt.pdf", "application/pdf")
|
554
|
+
|
555
|
+
# Send other media types
|
556
|
+
client.send_video("+1234567890", "https://example.com/video.mp4", "Demo video", "video/mp4")
|
557
|
+
client.send_audio("+1234567890", "https://example.com/audio.mp3", "audio/mpeg")
|
558
|
+
client.send_sticker("+1234567890", "https://example.com/sticker.webp", "image/webp")
|
559
|
+
```
|
560
|
+
|
561
|
+
### Cross-Platform Behavior
|
562
|
+
|
563
|
+
**WhatsApp Experience:**
|
564
|
+
- Media is sent directly to the chat
|
565
|
+
- Prompt text becomes the media caption
|
566
|
+
- Rich, native messaging experience
|
567
|
+
|
568
|
+
**USSD Experience:**
|
569
|
+
- Media URL is included in text message
|
570
|
+
- Graceful degradation with clear media indicators
|
571
|
+
- Users can access media via the provided link
|
572
|
+
|
573
|
+
```ruby
|
574
|
+
# This code works on both platforms:
|
575
|
+
app.screen(:help) do |prompt|
|
576
|
+
prompt.ask "Describe your issue:",
|
577
|
+
media: {
|
578
|
+
type: :image,
|
579
|
+
url: "https://support.example.com/help_example.jpg"
|
580
|
+
}
|
581
|
+
end
|
582
|
+
```
|
583
|
+
|
584
|
+
**WhatsApp Result:** Image sent with caption "Describe your issue:"
|
585
|
+
|
586
|
+
**USSD Result:**
|
587
|
+
```
|
588
|
+
Describe your issue:
|
589
|
+
|
590
|
+
๐ท Image: https://support.example.com/help_example.jpg
|
591
|
+
```
|
592
|
+
|
324
593
|
## Core Concepts
|
325
594
|
|
326
595
|
### Flows and Screens
|
@@ -460,6 +729,68 @@ app.screen(:credit_card) do |prompt|
|
|
460
729
|
end
|
461
730
|
```
|
462
731
|
|
732
|
+
### Background Job Support
|
733
|
+
|
734
|
+
For high-volume WhatsApp applications, use background response delivery:
|
735
|
+
|
736
|
+
```ruby
|
737
|
+
# app/jobs/whatsapp_message_job.rb
|
738
|
+
class WhatsappMessageJob < ApplicationJob
|
739
|
+
include FlowChat::Whatsapp::SendJobSupport
|
740
|
+
|
741
|
+
def perform(send_data)
|
742
|
+
perform_whatsapp_send(send_data)
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
# config/initializers/flowchat.rb
|
747
|
+
FlowChat::Config.whatsapp.message_handling_mode = :background
|
748
|
+
FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
|
749
|
+
|
750
|
+
# config/application.rb
|
751
|
+
config.active_job.queue_adapter = :sidekiq
|
752
|
+
```
|
753
|
+
|
754
|
+
**The `SendJobSupport` module provides:**
|
755
|
+
- โ
**Automatic config resolution** - Resolves named configurations automatically
|
756
|
+
- โ
**Response delivery** - Handles sending responses to WhatsApp
|
757
|
+
- โ
**Error handling** - Comprehensive error handling with user notifications
|
758
|
+
- โ
**Retry logic** - Built-in exponential backoff retry
|
759
|
+
- โ
**Extensible** - Override methods for custom behavior
|
760
|
+
|
761
|
+
**How it works:**
|
762
|
+
1. **Controller receives webhook** - WhatsApp message arrives
|
763
|
+
2. **Flow processes synchronously** - Maintains controller context and session state
|
764
|
+
3. **Response queued for delivery** - Only the sending is moved to background
|
765
|
+
4. **Job sends response** - Background job handles API call to WhatsApp
|
766
|
+
|
767
|
+
**Advanced job with custom callbacks:**
|
768
|
+
|
769
|
+
```ruby
|
770
|
+
class AdvancedWhatsappMessageJob < ApplicationJob
|
771
|
+
include FlowChat::Whatsapp::SendJobSupport
|
772
|
+
|
773
|
+
def perform(send_data)
|
774
|
+
perform_whatsapp_send(send_data)
|
775
|
+
end
|
776
|
+
|
777
|
+
private
|
778
|
+
|
779
|
+
# Override for custom success handling
|
780
|
+
def on_whatsapp_send_success(send_data, result)
|
781
|
+
Rails.logger.info "Successfully sent WhatsApp message to #{send_data[:msisdn]}"
|
782
|
+
UserEngagementTracker.track_message_sent(phone: send_data[:msisdn])
|
783
|
+
end
|
784
|
+
|
785
|
+
# Override for custom error handling
|
786
|
+
def on_whatsapp_send_error(error, send_data)
|
787
|
+
ErrorTracker.notify(error, user_phone: send_data[:msisdn])
|
788
|
+
end
|
789
|
+
end
|
790
|
+
```
|
791
|
+
|
792
|
+
๐ก **See [examples/whatsapp_message_job.rb](examples/whatsapp_message_job.rb) for complete job implementation examples.**
|
793
|
+
|
463
794
|
### Middleware Configuration
|
464
795
|
|
465
796
|
FlowChat uses a **middleware architecture** to process USSD requests through a configurable pipeline. Each request flows through multiple middleware layers in a specific order.
|
@@ -694,27 +1025,79 @@ class ProcessorMiddlewareTest < Minitest::Test
|
|
694
1025
|
end
|
695
1026
|
```
|
696
1027
|
|
697
|
-
###
|
1028
|
+
### FlowChat Unified Simulator
|
698
1029
|
|
699
|
-
Use the built-in simulator for interactive testing:
|
1030
|
+
Use the built-in unified simulator for interactive testing of both USSD and WhatsApp flows:
|
700
1031
|
|
701
1032
|
```ruby
|
702
|
-
class
|
703
|
-
include FlowChat::
|
1033
|
+
class SimulatorController < ApplicationController
|
1034
|
+
include FlowChat::Simulator::Controller
|
1035
|
+
|
1036
|
+
def index
|
1037
|
+
flowchat_simulator
|
1038
|
+
end
|
704
1039
|
|
705
1040
|
protected
|
706
1041
|
|
707
|
-
def
|
708
|
-
|
1042
|
+
def configurations
|
1043
|
+
{
|
1044
|
+
production_ussd: {
|
1045
|
+
name: "Production USSD",
|
1046
|
+
icon: "๐ญ",
|
1047
|
+
processor_type: "ussd",
|
1048
|
+
provider: "nalo",
|
1049
|
+
endpoint: "/ussd",
|
1050
|
+
color: "#28a745"
|
1051
|
+
},
|
1052
|
+
staging_whatsapp: {
|
1053
|
+
name: "Staging WhatsApp",
|
1054
|
+
icon: "๐งช",
|
1055
|
+
processor_type: "whatsapp",
|
1056
|
+
provider: "cloud_api",
|
1057
|
+
endpoint: "/whatsapp/webhook",
|
1058
|
+
color: "#17a2b8"
|
1059
|
+
},
|
1060
|
+
local_ussd: {
|
1061
|
+
name: "Local USSD",
|
1062
|
+
icon: "๐ป",
|
1063
|
+
processor_type: "ussd",
|
1064
|
+
provider: "nalo",
|
1065
|
+
endpoint: "http://localhost:3000/ussd",
|
1066
|
+
color: "#6f42c1"
|
1067
|
+
}
|
1068
|
+
}
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
def default_config_key
|
1072
|
+
:local_ussd
|
709
1073
|
end
|
710
1074
|
|
711
|
-
def
|
712
|
-
|
1075
|
+
def default_phone_number
|
1076
|
+
"+254712345678"
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
def default_contact_name
|
1080
|
+
"John Doe"
|
713
1081
|
end
|
714
1082
|
end
|
715
1083
|
```
|
716
1084
|
|
717
|
-
Add to routes and visit `http://localhost:3000/
|
1085
|
+
Add to routes and visit `http://localhost:3000/simulator`.
|
1086
|
+
|
1087
|
+
**Key Features:**
|
1088
|
+
- ๐ **Platform Toggle** - Switch between USSD and WhatsApp modes with configuration selection
|
1089
|
+
- ๐ฑ **USSD Mode** - Classic green-screen terminal simulation with provider support (Nalo, Nsano)
|
1090
|
+
- ๐ฌ **WhatsApp Mode** - Full WhatsApp interface with interactive buttons, lists, and rich messaging
|
1091
|
+
- โ๏ธ **Multi-Environment** - Support for different configurations (local, staging, production)
|
1092
|
+
- ๐จ **Modern UI** - Beautiful, responsive interface with real-time status indicators
|
1093
|
+
- ๐ **Request Logging** - View all HTTP requests and responses in real-time
|
1094
|
+
- ๐ง **Developer Tools** - Character counts, connection status, and comprehensive error handling
|
1095
|
+
|
1096
|
+
The simulator automatically adapts its interface based on the selected configuration:
|
1097
|
+
- **USSD**: Shows traditional terminal-style interface with character limits and pagination
|
1098
|
+
- **WhatsApp**: Displays realistic WhatsApp chat interface with support for interactive elements
|
1099
|
+
|
1100
|
+
๐ก **Tip**: See [examples/simulator_controller.rb](examples/simulator_controller.rb) for advanced configurations including multi-tenant support and environment-specific endpoints.
|
718
1101
|
|
719
1102
|
## Best Practices
|
720
1103
|
|
@@ -783,97 +1166,20 @@ def main_page
|
|
783
1166
|
end
|
784
1167
|
```
|
785
1168
|
|
786
|
-
|
787
|
-
|
788
|
-
### Cache Configuration
|
1169
|
+
### 5. Choose the Right WhatsApp Mode
|
789
1170
|
|
790
|
-
|
1171
|
+
Configure the appropriate mode in your initializer:
|
791
1172
|
|
792
1173
|
```ruby
|
793
|
-
# config/
|
794
|
-
FlowChat::Config.cache = Rails.cache
|
795
|
-
|
796
|
-
# Or use a specific cache store
|
797
|
-
FlowChat::Config.cache = ActiveSupport::Cache::MemoryStore.new
|
798
|
-
|
799
|
-
# For Redis (requires redis gem)
|
800
|
-
FlowChat::Config.cache = ActiveSupport::Cache::RedisCacheStore.new(url: "redis://localhost:6379/1")
|
801
|
-
```
|
802
|
-
|
803
|
-
๐ก **Tip**: See [examples/initializer.rb](examples/initializer.rb) for a complete configuration example.
|
804
|
-
|
805
|
-
### Session Storage Options
|
806
|
-
|
807
|
-
Configure different session storage backends:
|
808
|
-
|
809
|
-
```ruby
|
810
|
-
# Cache session store (default) - uses FlowChat::Config.cache
|
811
|
-
config.use_session_store FlowChat::Session::CacheSessionStore
|
812
|
-
|
813
|
-
# Rails session (for USSD)
|
814
|
-
config.use_session_store FlowChat::Session::RailsSessionStore
|
815
|
-
|
816
|
-
# Custom session store
|
817
|
-
class MySessionStore
|
818
|
-
def initialize(context)
|
819
|
-
@context = context
|
820
|
-
end
|
821
|
-
|
822
|
-
def get(key)
|
823
|
-
# Your storage logic
|
824
|
-
end
|
825
|
-
|
826
|
-
def set(key, value)
|
827
|
-
# Your storage logic
|
828
|
-
end
|
829
|
-
end
|
830
|
-
|
831
|
-
config.use_session_store MySessionStore
|
832
|
-
```
|
833
|
-
|
834
|
-
## Development
|
835
|
-
|
836
|
-
### Running Tests
|
837
|
-
|
838
|
-
FlowChat uses Minitest for testing:
|
839
|
-
|
840
|
-
```bash
|
841
|
-
# Run all tests
|
842
|
-
bundle exec rake test
|
843
|
-
|
844
|
-
# Run specific test file
|
845
|
-
bundle exec rake test TEST=test/unit/flow_test.rb
|
846
|
-
|
847
|
-
# Run specific test
|
848
|
-
bundle exec rake test TESTOPTS="--name=test_flow_initialization"
|
849
|
-
```
|
850
|
-
|
851
|
-
### Contributing
|
852
|
-
|
853
|
-
1. Fork the repository
|
854
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
855
|
-
3. Add tests for your changes
|
856
|
-
4. Ensure all tests pass (`bundle exec rake test`)
|
857
|
-
5. Commit your changes (`git commit -am 'Add amazing feature'`)
|
858
|
-
6. Push to the branch (`git push origin feature/amazing-feature`)
|
859
|
-
7. Open a Pull Request
|
860
|
-
|
861
|
-
## Roadmap
|
862
|
-
|
863
|
-
- ๐ฌ **Telegram Bot Support** - Native Telegram bot integration
|
864
|
-
- ๐ **Sub-flows** - Reusable conversation components and flow composition
|
865
|
-
- ๐ **Analytics Integration** - Built-in conversation analytics and user journey tracking
|
866
|
-
- ๐ **Multi-language Support** - Internationalization and localization features
|
867
|
-
- โก **Performance Optimizations** - Improved middleware performance and caching
|
868
|
-
- ๐ฏ **Advanced Validation** - More validation helpers and custom validators
|
869
|
-
- ๐ **Enhanced Security** - Rate limiting, input sanitization, and fraud detection
|
870
|
-
|
871
|
-
## License
|
1174
|
+
# config/initializers/flowchat.rb
|
872
1175
|
|
873
|
-
|
1176
|
+
# Development/Testing - use simulator mode
|
1177
|
+
FlowChat::Config.whatsapp.message_handling_mode = :simulator
|
874
1178
|
|
875
|
-
|
1179
|
+
# Low-volume Applications - use inline mode
|
1180
|
+
FlowChat::Config.whatsapp.message_handling_mode = :inline
|
876
1181
|
|
877
|
-
-
|
878
|
-
|
879
|
-
|
1182
|
+
# High-volume Production - use background mode (sync processing + async sending)
|
1183
|
+
FlowChat::Config.whatsapp.message_handling_mode = :background
|
1184
|
+
FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
|
1185
|
+
```
|
data/examples/initializer.rb
CHANGED
@@ -28,4 +28,4 @@ FlowChat::Config.ussd.pagination_next_text = "More"
|
|
28
28
|
|
29
29
|
# Configure resumable sessions (optional)
|
30
30
|
FlowChat::Config.ussd.resumable_sessions_enabled = true
|
31
|
-
FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
|
31
|
+
FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Media Prompts Examples
|
2
|
+
# This file demonstrates how to attach media to prompts in FlowChat
|
3
|
+
|
4
|
+
# ============================================================================
|
5
|
+
# BASIC MEDIA PROMPTS
|
6
|
+
# ============================================================================
|
7
|
+
|
8
|
+
class MediaPromptFlow < FlowChat::Flow
|
9
|
+
def main_page
|
10
|
+
# โ
Simple text input with attached image
|
11
|
+
# The prompt text becomes the image caption
|
12
|
+
app.screen(:feedback) do |prompt|
|
13
|
+
prompt.ask "What do you think of our new product?",
|
14
|
+
media: {
|
15
|
+
type: :image,
|
16
|
+
url: "https://cdn.example.com/products/new_product.jpg"
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
# โ
Send media message with say
|
21
|
+
app.say "Thank you for your feedback! Here's what's coming next:",
|
22
|
+
media: {
|
23
|
+
type: :video,
|
24
|
+
url: "https://videos.example.com/roadmap.mp4"
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|