flow_chat 0.4.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb9a192cee58e0f9f9fd857e0783d098a21922b83185d6978a8d45f225045f4b
4
- data.tar.gz: 2901ac304c89aa5f4e4a40a6c9f64a9c4b9fa26b2841d1e5bce34694d6b61cff
3
+ metadata.gz: 004e0d3a8a9c9da83dfd6386b6e7684b7fea2b69daab7645e28d9a4767e80819
4
+ data.tar.gz: 85cf51f944ebb00aa7498106f88d60bfbdf060dcfe62762e3ab5a83784cff9f7
5
5
  SHA512:
6
- metadata.gz: e540ad0ca5341dc7b3e50b3276e81e37f87513e17dfcc7f8104a8346f758c8bf8962672d92b027d96292a31e9bdf2b721bf3a51392250101475bd73980456280
7
- data.tar.gz: 3995faacc87bfb01e26a38530eedab34ba67fdf1252f7dda0119c56a735b17c551094f88c85ed2a5a53661a0e983fe3467f13dfb1714bde91ec70e8b05f31ab1
6
+ metadata.gz: c5a716d3345118c334899299367e1b7ef082e54651d75d7d92a24f01f03ea36a1e55df916aa14b6ddd0e75b353a0a37be08b0ce2681082df4f0d9768dc10a525
7
+ data.tar.gz: d533c33058573554f5c340460999c6d3b08332800ef33b521a0111ca44e8b4d10d4aa559e5d4f23f6575cffc86e8fa10d0e0850cefec5e18f075397ccb3d449d
@@ -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
@@ -9,7 +9,7 @@ class MediaPromptFlow < FlowChat::Flow
9
9
  def main_page
10
10
  # ✅ Simple text input with attached image
11
11
  # The prompt text becomes the image caption
12
- feedback = app.screen(:feedback) do |prompt|
12
+ app.screen(:feedback) do |prompt|
13
13
  prompt.ask "What do you think of our new product?",
14
14
  media: {
15
15
  type: :image,
@@ -25,4 +25,3 @@ class MediaPromptFlow < FlowChat::Flow
25
25
  }
26
26
  end
27
27
  end
28
-
@@ -7,10 +7,10 @@ class MultiTenantWhatsappController < ApplicationController
7
7
  def webhook
8
8
  # Determine tenant from subdomain, path, or other logic
9
9
  tenant = determine_tenant(request)
10
-
10
+
11
11
  # Get tenant-specific WhatsApp configuration
12
12
  whatsapp_config = get_whatsapp_config_for_tenant(tenant)
13
-
13
+
14
14
  processor = FlowChat::Whatsapp::Processor.new(self) do |config|
15
15
  config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, whatsapp_config
16
16
  config.use_session_store FlowChat::Session::CacheSessionStore
@@ -26,41 +26,41 @@ class MultiTenantWhatsappController < ApplicationController
26
26
  def determine_tenant(request)
27
27
  # Option 1: From subdomain
28
28
  return request.subdomain if request.subdomain.present?
29
-
29
+
30
30
  # Option 2: From path
31
31
  tenant_from_path = request.path.match(%r{^/whatsapp/(\w+)/})&.captures&.first
32
32
  return tenant_from_path if tenant_from_path
33
-
33
+
34
34
  # Option 3: From custom header
35
- return request.headers['X-Tenant-ID'] if request.headers['X-Tenant-ID']
36
-
35
+ return request.headers["X-Tenant-ID"] if request.headers["X-Tenant-ID"]
36
+
37
37
  # Fallback to default
38
- 'default'
38
+ "default"
39
39
  end
40
40
 
41
41
  def get_whatsapp_config_for_tenant(tenant)
42
42
  case tenant
43
- when 'acme_corp'
43
+ when "acme_corp"
44
44
  FlowChat::Whatsapp::Configuration.new.tap do |config|
45
- config.access_token = ENV['ACME_WHATSAPP_ACCESS_TOKEN']
46
- config.phone_number_id = ENV['ACME_WHATSAPP_PHONE_NUMBER_ID']
47
- config.verify_token = ENV['ACME_WHATSAPP_VERIFY_TOKEN']
48
- config.app_id = ENV['ACME_WHATSAPP_APP_ID']
49
- config.app_secret = ENV['ACME_WHATSAPP_APP_SECRET']
50
- config.business_account_id = ENV['ACME_WHATSAPP_BUSINESS_ACCOUNT_ID']
45
+ config.access_token = ENV["ACME_WHATSAPP_ACCESS_TOKEN"]
46
+ config.phone_number_id = ENV["ACME_WHATSAPP_PHONE_NUMBER_ID"]
47
+ config.verify_token = ENV["ACME_WHATSAPP_VERIFY_TOKEN"]
48
+ config.app_id = ENV["ACME_WHATSAPP_APP_ID"]
49
+ config.app_secret = ENV["ACME_WHATSAPP_APP_SECRET"]
50
+ config.business_account_id = ENV["ACME_WHATSAPP_BUSINESS_ACCOUNT_ID"]
51
51
  end
52
-
53
- when 'tech_startup'
52
+
53
+ when "tech_startup"
54
54
  FlowChat::Whatsapp::Configuration.new.tap do |config|
55
- config.access_token = ENV['TECHSTARTUP_WHATSAPP_ACCESS_TOKEN']
56
- config.phone_number_id = ENV['TECHSTARTUP_WHATSAPP_PHONE_NUMBER_ID']
57
- config.verify_token = ENV['TECHSTARTUP_WHATSAPP_VERIFY_TOKEN']
58
- config.app_id = ENV['TECHSTARTUP_WHATSAPP_APP_ID']
59
- config.app_secret = ENV['TECHSTARTUP_WHATSAPP_APP_SECRET']
60
- config.business_account_id = ENV['TECHSTARTUP_WHATSAPP_BUSINESS_ACCOUNT_ID']
55
+ config.access_token = ENV["TECHSTARTUP_WHATSAPP_ACCESS_TOKEN"]
56
+ config.phone_number_id = ENV["TECHSTARTUP_WHATSAPP_PHONE_NUMBER_ID"]
57
+ config.verify_token = ENV["TECHSTARTUP_WHATSAPP_VERIFY_TOKEN"]
58
+ config.app_id = ENV["TECHSTARTUP_WHATSAPP_APP_ID"]
59
+ config.app_secret = ENV["TECHSTARTUP_WHATSAPP_APP_SECRET"]
60
+ config.business_account_id = ENV["TECHSTARTUP_WHATSAPP_BUSINESS_ACCOUNT_ID"]
61
61
  end
62
-
63
- when 'retail_store'
62
+
63
+ when "retail_store"
64
64
  # Load from database
65
65
  tenant_config = WhatsappConfiguration.find_by(tenant: tenant)
66
66
  FlowChat::Whatsapp::Configuration.new.tap do |config|
@@ -71,7 +71,7 @@ class MultiTenantWhatsappController < ApplicationController
71
71
  config.app_secret = tenant_config.app_secret
72
72
  config.business_account_id = tenant_config.business_account_id
73
73
  end
74
-
74
+
75
75
  else
76
76
  # Use default/global configuration
77
77
  FlowChat::Whatsapp::Configuration.from_credentials
@@ -80,11 +80,11 @@ class MultiTenantWhatsappController < ApplicationController
80
80
 
81
81
  def get_flow_for_tenant(tenant)
82
82
  case tenant
83
- when 'acme_corp'
83
+ when "acme_corp"
84
84
  AcmeCorpFlow
85
- when 'tech_startup'
85
+ when "tech_startup"
86
86
  TechStartupFlow
87
- when 'retail_store'
87
+ when "retail_store"
88
88
  RetailStoreFlow
89
89
  else
90
90
  WelcomeFlow # Default flow
@@ -99,7 +99,7 @@ class DatabaseWhatsappController < ApplicationController
99
99
  def webhook
100
100
  # Get account from business phone number or other identifier
101
101
  business_account = find_business_account(params)
102
-
102
+
103
103
  if business_account.nil?
104
104
  return head :not_found
105
105
  end
@@ -129,7 +129,7 @@ class DatabaseWhatsappController < ApplicationController
129
129
  # 1. Phone number ID from webhook
130
130
  # 2. Business account ID from webhook
131
131
  # 3. Custom routing parameter
132
-
132
+
133
133
  # Example: Find by phone number ID in webhook
134
134
  phone_number_id = extract_phone_number_id_from_webhook(params)
135
135
  BusinessAccount.find_by(whatsapp_phone_number_id: phone_number_id)
@@ -149,11 +149,11 @@ class EnvironmentWhatsappController < ApplicationController
149
149
  def webhook
150
150
  # Different configurations for different environments
151
151
  whatsapp_config = case Rails.env
152
- when 'production'
152
+ when "production"
153
153
  production_whatsapp_config
154
- when 'staging'
154
+ when "staging"
155
155
  staging_whatsapp_config
156
- when 'development'
156
+ when "development"
157
157
  development_whatsapp_config
158
158
  else
159
159
  FlowChat::Whatsapp::Configuration.from_credentials
@@ -171,34 +171,34 @@ class EnvironmentWhatsappController < ApplicationController
171
171
 
172
172
  def production_whatsapp_config
173
173
  FlowChat::Whatsapp::Configuration.new.tap do |config|
174
- config.access_token = ENV['PROD_WHATSAPP_ACCESS_TOKEN']
175
- config.phone_number_id = ENV['PROD_WHATSAPP_PHONE_NUMBER_ID']
176
- config.verify_token = ENV['PROD_WHATSAPP_VERIFY_TOKEN']
177
- config.app_id = ENV['PROD_WHATSAPP_APP_ID']
178
- config.app_secret = ENV['PROD_WHATSAPP_APP_SECRET']
179
- config.business_account_id = ENV['PROD_WHATSAPP_BUSINESS_ACCOUNT_ID']
174
+ config.access_token = ENV["PROD_WHATSAPP_ACCESS_TOKEN"]
175
+ config.phone_number_id = ENV["PROD_WHATSAPP_PHONE_NUMBER_ID"]
176
+ config.verify_token = ENV["PROD_WHATSAPP_VERIFY_TOKEN"]
177
+ config.app_id = ENV["PROD_WHATSAPP_APP_ID"]
178
+ config.app_secret = ENV["PROD_WHATSAPP_APP_SECRET"]
179
+ config.business_account_id = ENV["PROD_WHATSAPP_BUSINESS_ACCOUNT_ID"]
180
180
  end
181
181
  end
182
182
 
183
183
  def staging_whatsapp_config
184
184
  FlowChat::Whatsapp::Configuration.new.tap do |config|
185
- config.access_token = ENV['STAGING_WHATSAPP_ACCESS_TOKEN']
186
- config.phone_number_id = ENV['STAGING_WHATSAPP_PHONE_NUMBER_ID']
187
- config.verify_token = ENV['STAGING_WHATSAPP_VERIFY_TOKEN']
188
- config.app_id = ENV['STAGING_WHATSAPP_APP_ID']
189
- config.app_secret = ENV['STAGING_WHATSAPP_APP_SECRET']
190
- config.business_account_id = ENV['STAGING_WHATSAPP_BUSINESS_ACCOUNT_ID']
185
+ config.access_token = ENV["STAGING_WHATSAPP_ACCESS_TOKEN"]
186
+ config.phone_number_id = ENV["STAGING_WHATSAPP_PHONE_NUMBER_ID"]
187
+ config.verify_token = ENV["STAGING_WHATSAPP_VERIFY_TOKEN"]
188
+ config.app_id = ENV["STAGING_WHATSAPP_APP_ID"]
189
+ config.app_secret = ENV["STAGING_WHATSAPP_APP_SECRET"]
190
+ config.business_account_id = ENV["STAGING_WHATSAPP_BUSINESS_ACCOUNT_ID"]
191
191
  end
192
192
  end
193
193
 
194
194
  def development_whatsapp_config
195
195
  FlowChat::Whatsapp::Configuration.new.tap do |config|
196
- config.access_token = ENV['DEV_WHATSAPP_ACCESS_TOKEN']
197
- config.phone_number_id = ENV['DEV_WHATSAPP_PHONE_NUMBER_ID']
198
- config.verify_token = ENV['DEV_WHATSAPP_VERIFY_TOKEN']
199
- config.app_id = ENV['DEV_WHATSAPP_APP_ID']
200
- config.app_secret = ENV['DEV_WHATSAPP_APP_SECRET']
201
- config.business_account_id = ENV['DEV_WHATSAPP_BUSINESS_ACCOUNT_ID']
196
+ config.access_token = ENV["DEV_WHATSAPP_ACCESS_TOKEN"]
197
+ config.phone_number_id = ENV["DEV_WHATSAPP_PHONE_NUMBER_ID"]
198
+ config.verify_token = ENV["DEV_WHATSAPP_VERIFY_TOKEN"]
199
+ config.app_id = ENV["DEV_WHATSAPP_APP_ID"]
200
+ config.app_secret = ENV["DEV_WHATSAPP_APP_SECRET"]
201
+ config.business_account_id = ENV["DEV_WHATSAPP_BUSINESS_ACCOUNT_ID"]
202
202
  end
203
203
  end
204
204
  end
@@ -232,13 +232,13 @@ end
232
232
  # constraints subdomain: /\w+/ do
233
233
  # post '/whatsapp/webhook', to: 'multi_tenant_whatsapp#webhook'
234
234
  # end
235
- #
236
- # # Path-based routing
235
+ #
236
+ # # Path-based routing
237
237
  # post '/whatsapp/:tenant/webhook', to: 'multi_tenant_whatsapp#webhook'
238
- #
238
+ #
239
239
  # # Environment-specific
240
240
  # post '/whatsapp/env/webhook', to: 'environment_whatsapp#webhook'
241
- #
241
+ #
242
242
  # # Custom endpoint
243
243
  # post '/whatsapp/custom/webhook', to: 'custom_whatsapp#webhook'
244
- # end
244
+ # end
@@ -9,7 +9,7 @@ class UssdController < ApplicationController
9
9
  config.use_gateway FlowChat::Ussd::Gateway::Nalo
10
10
  # Use Rails session for USSD (shorter sessions)
11
11
  config.use_session_store FlowChat::Session::RailsSessionStore
12
-
12
+
13
13
  # Enable resumable sessions (optional)
14
14
  config.use_resumable_sessions
15
15
  end
@@ -33,7 +33,7 @@ class WelcomeFlow < FlowChat::Flow
33
33
  choice = app.screen(:main_menu) do |prompt|
34
34
  prompt.select "Hi #{name}! Choose an option:", {
35
35
  "1" => "Account Info",
36
- "2" => "Make Payment",
36
+ "2" => "Make Payment",
37
37
  "3" => "Get Balance",
38
38
  "4" => "Customer Support"
39
39
  }
@@ -118,7 +118,7 @@ class WelcomeFlow < FlowChat::Flow
118
118
  support_choice = app.screen(:support_menu) do |prompt|
119
119
  prompt.select "Customer Support:", {
120
120
  "1" => "Report an Issue",
121
- "2" => "Account Questions",
121
+ "2" => "Account Questions",
122
122
  "3" => "Technical Support",
123
123
  "4" => "Speak to Agent",
124
124
  "0" => "Main Menu"
@@ -159,12 +159,12 @@ class WelcomeFlow < FlowChat::Flow
159
159
 
160
160
  # Save the issue (your business logic here)
161
161
  ticket_id = create_support_ticket(issue_type, description, app.phone_number)
162
-
162
+
163
163
  app.say "Issue reported successfully!\\n\\nTicket ID: #{ticket_id}\\nWe'll contact you within 24 hours.\\n\\nThank you!"
164
164
  end
165
165
 
166
166
  # Helper methods (implement your business logic)
167
-
167
+
168
168
  def process_payment(amount, recipient)
169
169
  # Your payment processing logic here
170
170
  # Return transaction ID
@@ -175,7 +175,7 @@ class WelcomeFlow < FlowChat::Flow
175
175
  # Your balance checking logic here
176
176
  {
177
177
  available: "150.75",
178
- pending: "25.00",
178
+ pending: "25.00",
179
179
  total: "175.75"
180
180
  }
181
181
  end
@@ -190,6 +190,7 @@ end
190
190
  # Configuration Examples:
191
191
 
192
192
  # 1. Basic configuration with custom pagination
193
+ # rubocop:disable Lint/DuplicateMethods
193
194
  class UssdController < ApplicationController
194
195
  skip_forgery_protection
195
196
 
@@ -207,6 +208,7 @@ class UssdController < ApplicationController
207
208
  processor.run WelcomeFlow, :main_page
208
209
  end
209
210
  end
211
+ # rubocop:enable Lint/DuplicateMethods
210
212
 
211
213
  # 2. Configuration with custom middleware
212
214
  class LoggingMiddleware
@@ -215,18 +217,19 @@ class LoggingMiddleware
215
217
  end
216
218
 
217
219
  def call(context)
218
- Rails.logger.info "USSD Request from #{context['request.msisdn']}: #{context.input}"
220
+ Rails.logger.info "USSD Request from #{context["request.msisdn"]}: #{context.input}"
219
221
  start_time = Time.current
220
-
222
+
221
223
  result = @app.call(context)
222
-
224
+
223
225
  duration = Time.current - start_time
224
226
  Rails.logger.info "USSD Response (#{duration.round(3)}s): #{result[1]}"
225
-
227
+
226
228
  result
227
229
  end
228
230
  end
229
231
 
232
+ # rubocop:disable Lint/DuplicateMethods
230
233
  class UssdController < ApplicationController
231
234
  skip_forgery_protection
232
235
 
@@ -241,8 +244,10 @@ class UssdController < ApplicationController
241
244
  processor.run WelcomeFlow, :main_page
242
245
  end
243
246
  end
247
+ # rubocop:enable Lint/DuplicateMethods
244
248
 
245
249
  # 3. Configuration with cache-based sessions for longer persistence
250
+ # rubocop:disable Lint/DuplicateMethods
246
251
  class UssdController < ApplicationController
247
252
  skip_forgery_protection
248
253
 
@@ -256,9 +261,10 @@ class UssdController < ApplicationController
256
261
  processor.run WelcomeFlow, :main_page
257
262
  end
258
263
  end
264
+ # rubocop:enable Lint/DuplicateMethods
259
265
 
260
266
  # Add this route to your config/routes.rb:
261
267
  # post '/ussd', to: 'ussd#process_request'
262
268
 
263
269
  # For Nsano gateway, use:
264
- # config.use_gateway FlowChat::Ussd::Gateway::Nsano
270
+ # config.use_gateway FlowChat::Ussd::Gateway::Nsano
@@ -22,12 +22,12 @@ class CustomWhatsappController < ApplicationController
22
22
  def webhook
23
23
  # Create custom WhatsApp configuration for this endpoint
24
24
  custom_config = FlowChat::Whatsapp::Configuration.new
25
- custom_config.access_token = ENV['MY_WHATSAPP_ACCESS_TOKEN']
26
- custom_config.phone_number_id = ENV['MY_WHATSAPP_PHONE_NUMBER_ID']
27
- custom_config.verify_token = ENV['MY_WHATSAPP_VERIFY_TOKEN']
28
- custom_config.app_id = ENV['MY_WHATSAPP_APP_ID']
29
- custom_config.app_secret = ENV['MY_WHATSAPP_APP_SECRET']
30
- custom_config.business_account_id = ENV['MY_WHATSAPP_BUSINESS_ACCOUNT_ID']
25
+ custom_config.access_token = ENV["MY_WHATSAPP_ACCESS_TOKEN"]
26
+ custom_config.phone_number_id = ENV["MY_WHATSAPP_PHONE_NUMBER_ID"]
27
+ custom_config.verify_token = ENV["MY_WHATSAPP_VERIFY_TOKEN"]
28
+ custom_config.app_id = ENV["MY_WHATSAPP_APP_ID"]
29
+ custom_config.app_secret = ENV["MY_WHATSAPP_APP_SECRET"]
30
+ custom_config.business_account_id = ENV["MY_WHATSAPP_BUSINESS_ACCOUNT_ID"]
31
31
 
32
32
  processor = FlowChat::Whatsapp::Processor.new(self) do |config|
33
33
  config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, custom_config
@@ -53,7 +53,7 @@ class WelcomeFlow < FlowChat::Flow
53
53
  choice = app.screen(:main_menu) do |prompt|
54
54
  prompt.select "Hi #{name}! What can I help you with today?", {
55
55
  "info" => "📋 Get Information",
56
- "support" => "🆘 Contact Support",
56
+ "support" => "🆘 Contact Support",
57
57
  "feedback" => "💬 Give Feedback"
58
58
  }
59
59
  end
@@ -94,7 +94,7 @@ class WelcomeFlow < FlowChat::Flow
94
94
  contact_method = app.screen(:contact_method) do |prompt|
95
95
  prompt.select "How would you like to contact support?", {
96
96
  "call" => "📞 Call Us",
97
- "email" => "📧 Email Us",
97
+ "email" => "📧 Email Us",
98
98
  "chat" => "💬 Live Chat"
99
99
  }
100
100
  end
@@ -113,7 +113,7 @@ class WelcomeFlow < FlowChat::Flow
113
113
  rating = app.screen(:rating) do |prompt|
114
114
  prompt.select "How would you rate our service?", {
115
115
  "5" => "⭐⭐⭐⭐⭐ Excellent",
116
- "4" => "⭐⭐⭐⭐ Good",
116
+ "4" => "⭐⭐⭐⭐ Good",
117
117
  "3" => "⭐⭐⭐ Average",
118
118
  "2" => "⭐⭐ Poor",
119
119
  "1" => "⭐ Very Poor"
@@ -137,4 +137,4 @@ class WelcomeFlow < FlowChat::Flow
137
137
  end
138
138
 
139
139
  # Add this route to your config/routes.rb:
140
- # post '/whatsapp/webhook', to: 'whatsapp#webhook'
140
+ # post '/whatsapp/webhook', to: 'whatsapp#webhook'