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.
@@ -7,13 +7,12 @@ 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
- config.use_whatsapp_config(whatsapp_config)
16
- config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
15
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, whatsapp_config
17
16
  config.use_session_store FlowChat::Session::CacheSessionStore
18
17
  end
19
18
 
@@ -27,41 +26,41 @@ class MultiTenantWhatsappController < ApplicationController
27
26
  def determine_tenant(request)
28
27
  # Option 1: From subdomain
29
28
  return request.subdomain if request.subdomain.present?
30
-
29
+
31
30
  # Option 2: From path
32
31
  tenant_from_path = request.path.match(%r{^/whatsapp/(\w+)/})&.captures&.first
33
32
  return tenant_from_path if tenant_from_path
34
-
33
+
35
34
  # Option 3: From custom header
36
- return request.headers['X-Tenant-ID'] if request.headers['X-Tenant-ID']
37
-
35
+ return request.headers["X-Tenant-ID"] if request.headers["X-Tenant-ID"]
36
+
38
37
  # Fallback to default
39
- 'default'
38
+ "default"
40
39
  end
41
40
 
42
41
  def get_whatsapp_config_for_tenant(tenant)
43
42
  case tenant
44
- when 'acme_corp'
43
+ when "acme_corp"
45
44
  FlowChat::Whatsapp::Configuration.new.tap do |config|
46
- config.access_token = ENV['ACME_WHATSAPP_ACCESS_TOKEN']
47
- config.phone_number_id = ENV['ACME_WHATSAPP_PHONE_NUMBER_ID']
48
- config.verify_token = ENV['ACME_WHATSAPP_VERIFY_TOKEN']
49
- config.app_id = ENV['ACME_WHATSAPP_APP_ID']
50
- config.app_secret = ENV['ACME_WHATSAPP_APP_SECRET']
51
- 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"]
52
51
  end
53
-
54
- when 'tech_startup'
52
+
53
+ when "tech_startup"
55
54
  FlowChat::Whatsapp::Configuration.new.tap do |config|
56
- config.access_token = ENV['TECHSTARTUP_WHATSAPP_ACCESS_TOKEN']
57
- config.phone_number_id = ENV['TECHSTARTUP_WHATSAPP_PHONE_NUMBER_ID']
58
- config.verify_token = ENV['TECHSTARTUP_WHATSAPP_VERIFY_TOKEN']
59
- config.app_id = ENV['TECHSTARTUP_WHATSAPP_APP_ID']
60
- config.app_secret = ENV['TECHSTARTUP_WHATSAPP_APP_SECRET']
61
- 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"]
62
61
  end
63
-
64
- when 'retail_store'
62
+
63
+ when "retail_store"
65
64
  # Load from database
66
65
  tenant_config = WhatsappConfiguration.find_by(tenant: tenant)
67
66
  FlowChat::Whatsapp::Configuration.new.tap do |config|
@@ -72,7 +71,7 @@ class MultiTenantWhatsappController < ApplicationController
72
71
  config.app_secret = tenant_config.app_secret
73
72
  config.business_account_id = tenant_config.business_account_id
74
73
  end
75
-
74
+
76
75
  else
77
76
  # Use default/global configuration
78
77
  FlowChat::Whatsapp::Configuration.from_credentials
@@ -81,11 +80,11 @@ class MultiTenantWhatsappController < ApplicationController
81
80
 
82
81
  def get_flow_for_tenant(tenant)
83
82
  case tenant
84
- when 'acme_corp'
83
+ when "acme_corp"
85
84
  AcmeCorpFlow
86
- when 'tech_startup'
85
+ when "tech_startup"
87
86
  TechStartupFlow
88
- when 'retail_store'
87
+ when "retail_store"
89
88
  RetailStoreFlow
90
89
  else
91
90
  WelcomeFlow # Default flow
@@ -100,7 +99,7 @@ class DatabaseWhatsappController < ApplicationController
100
99
  def webhook
101
100
  # Get account from business phone number or other identifier
102
101
  business_account = find_business_account(params)
103
-
102
+
104
103
  if business_account.nil?
105
104
  return head :not_found
106
105
  end
@@ -116,8 +115,7 @@ class DatabaseWhatsappController < ApplicationController
116
115
  end
117
116
 
118
117
  processor = FlowChat::Whatsapp::Processor.new(self) do |config|
119
- config.use_whatsapp_config(whatsapp_config)
120
- config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
118
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, whatsapp_config
121
119
  config.use_session_store FlowChat::Session::CacheSessionStore
122
120
  end
123
121
 
@@ -131,7 +129,7 @@ class DatabaseWhatsappController < ApplicationController
131
129
  # 1. Phone number ID from webhook
132
130
  # 2. Business account ID from webhook
133
131
  # 3. Custom routing parameter
134
-
132
+
135
133
  # Example: Find by phone number ID in webhook
136
134
  phone_number_id = extract_phone_number_id_from_webhook(params)
137
135
  BusinessAccount.find_by(whatsapp_phone_number_id: phone_number_id)
@@ -151,19 +149,18 @@ class EnvironmentWhatsappController < ApplicationController
151
149
  def webhook
152
150
  # Different configurations for different environments
153
151
  whatsapp_config = case Rails.env
154
- when 'production'
152
+ when "production"
155
153
  production_whatsapp_config
156
- when 'staging'
154
+ when "staging"
157
155
  staging_whatsapp_config
158
- when 'development'
156
+ when "development"
159
157
  development_whatsapp_config
160
158
  else
161
159
  FlowChat::Whatsapp::Configuration.from_credentials
162
160
  end
163
161
 
164
162
  processor = FlowChat::Whatsapp::Processor.new(self) do |config|
165
- config.use_whatsapp_config(whatsapp_config)
166
- config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
163
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, whatsapp_config
167
164
  config.use_session_store FlowChat::Session::CacheSessionStore
168
165
  end
169
166
 
@@ -174,34 +171,34 @@ class EnvironmentWhatsappController < ApplicationController
174
171
 
175
172
  def production_whatsapp_config
176
173
  FlowChat::Whatsapp::Configuration.new.tap do |config|
177
- config.access_token = ENV['PROD_WHATSAPP_ACCESS_TOKEN']
178
- config.phone_number_id = ENV['PROD_WHATSAPP_PHONE_NUMBER_ID']
179
- config.verify_token = ENV['PROD_WHATSAPP_VERIFY_TOKEN']
180
- config.app_id = ENV['PROD_WHATSAPP_APP_ID']
181
- config.app_secret = ENV['PROD_WHATSAPP_APP_SECRET']
182
- 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"]
183
180
  end
184
181
  end
185
182
 
186
183
  def staging_whatsapp_config
187
184
  FlowChat::Whatsapp::Configuration.new.tap do |config|
188
- config.access_token = ENV['STAGING_WHATSAPP_ACCESS_TOKEN']
189
- config.phone_number_id = ENV['STAGING_WHATSAPP_PHONE_NUMBER_ID']
190
- config.verify_token = ENV['STAGING_WHATSAPP_VERIFY_TOKEN']
191
- config.app_id = ENV['STAGING_WHATSAPP_APP_ID']
192
- config.app_secret = ENV['STAGING_WHATSAPP_APP_SECRET']
193
- 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"]
194
191
  end
195
192
  end
196
193
 
197
194
  def development_whatsapp_config
198
195
  FlowChat::Whatsapp::Configuration.new.tap do |config|
199
- config.access_token = ENV['DEV_WHATSAPP_ACCESS_TOKEN']
200
- config.phone_number_id = ENV['DEV_WHATSAPP_PHONE_NUMBER_ID']
201
- config.verify_token = ENV['DEV_WHATSAPP_VERIFY_TOKEN']
202
- config.app_id = ENV['DEV_WHATSAPP_APP_ID']
203
- config.app_secret = ENV['DEV_WHATSAPP_APP_SECRET']
204
- 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"]
205
202
  end
206
203
  end
207
204
  end
@@ -221,8 +218,7 @@ class CustomWhatsappController < ApplicationController
221
218
  my_config.business_account_id = "your_business_account_id"
222
219
 
223
220
  processor = FlowChat::Whatsapp::Processor.new(self) do |config|
224
- config.use_whatsapp_config(my_config)
225
- config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
221
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, my_config
226
222
  config.use_session_store FlowChat::Session::CacheSessionStore
227
223
  end
228
224
 
@@ -236,13 +232,13 @@ end
236
232
  # constraints subdomain: /\w+/ do
237
233
  # post '/whatsapp/webhook', to: 'multi_tenant_whatsapp#webhook'
238
234
  # end
239
- #
240
- # # Path-based routing
235
+ #
236
+ # # Path-based routing
241
237
  # post '/whatsapp/:tenant/webhook', to: 'multi_tenant_whatsapp#webhook'
242
- #
238
+ #
243
239
  # # Environment-specific
244
240
  # post '/whatsapp/env/webhook', to: 'environment_whatsapp#webhook'
245
- #
241
+ #
246
242
  # # Custom endpoint
247
243
  # post '/whatsapp/custom/webhook', to: 'custom_whatsapp#webhook'
248
- # 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,16 +22,15 @@ 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
- config.use_whatsapp_config(custom_config) # Use custom config
34
- config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
33
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, custom_config
35
34
  config.use_session_store FlowChat::Session::CacheSessionStore
36
35
  end
37
36
 
@@ -54,7 +53,7 @@ class WelcomeFlow < FlowChat::Flow
54
53
  choice = app.screen(:main_menu) do |prompt|
55
54
  prompt.select "Hi #{name}! What can I help you with today?", {
56
55
  "info" => "📋 Get Information",
57
- "support" => "🆘 Contact Support",
56
+ "support" => "🆘 Contact Support",
58
57
  "feedback" => "💬 Give Feedback"
59
58
  }
60
59
  end
@@ -95,7 +94,7 @@ class WelcomeFlow < FlowChat::Flow
95
94
  contact_method = app.screen(:contact_method) do |prompt|
96
95
  prompt.select "How would you like to contact support?", {
97
96
  "call" => "📞 Call Us",
98
- "email" => "📧 Email Us",
97
+ "email" => "📧 Email Us",
99
98
  "chat" => "💬 Live Chat"
100
99
  }
101
100
  end
@@ -114,7 +113,7 @@ class WelcomeFlow < FlowChat::Flow
114
113
  rating = app.screen(:rating) do |prompt|
115
114
  prompt.select "How would you rate our service?", {
116
115
  "5" => "⭐⭐⭐⭐⭐ Excellent",
117
- "4" => "⭐⭐⭐⭐ Good",
116
+ "4" => "⭐⭐⭐⭐ Good",
118
117
  "3" => "⭐⭐⭐ Average",
119
118
  "2" => "⭐⭐ Poor",
120
119
  "1" => "⭐ Very Poor"
@@ -138,4 +137,4 @@ class WelcomeFlow < FlowChat::Flow
138
137
  end
139
138
 
140
139
  # Add this route to your config/routes.rb:
141
- # post '/whatsapp/webhook', to: 'whatsapp#webhook'
140
+ # post '/whatsapp/webhook', to: 'whatsapp#webhook'