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.
@@ -63,19 +63,19 @@ class MediaSupportFlow < FlowChat::Flow
63
63
  private
64
64
 
65
65
  def handle_received_media
66
- media_type = app.media['type']
67
- media_id = app.media['id']
68
-
66
+ media_type = app.media["type"]
67
+ media_id = app.media["id"]
68
+
69
69
  Rails.logger.info "Received #{media_type} from #{app.phone_number}: #{media_id}"
70
-
70
+
71
71
  case media_type
72
- when 'image'
72
+ when "image"
73
73
  app.say "Thanks for the image! I can see it's a #{media_type} file. Let me process it for you."
74
- when 'document'
74
+ when "document"
75
75
  app.say "I've received your document. I'll review it and get back to you shortly."
76
- when 'audio'
76
+ when "audio"
77
77
  app.say "Got your voice message! I'll listen to it and respond appropriately."
78
- when 'video'
78
+ when "video"
79
79
  app.say "Thanks for the video! I'll analyze it and provide feedback."
80
80
  end
81
81
  end
@@ -83,32 +83,32 @@ class MediaSupportFlow < FlowChat::Flow
83
83
  def send_product_catalog
84
84
  # Send multiple product images from URLs
85
85
  client = get_whatsapp_client
86
-
86
+
87
87
  app.say "Here's our latest product catalog:"
88
-
88
+
89
89
  # Product images stored in cloud storage (CDN, S3, etc.)
90
90
  product_images = [
91
91
  "https://cdn.example.com/products/product1.jpg",
92
- "https://cdn.example.com/products/product2.jpg",
92
+ "https://cdn.example.com/products/product2.jpg",
93
93
  "https://cdn.example.com/products/product3.jpg"
94
94
  ]
95
-
95
+
96
96
  product_images.each_with_index do |image_url, index|
97
97
  client.send_image(app.phone_number, image_url, "Product #{index + 1}")
98
98
  sleep(0.5) # Small delay to avoid rate limiting
99
99
  end
100
-
100
+
101
101
  app.say "Which product interests you the most?"
102
102
  end
103
103
 
104
104
  def send_report
105
105
  # Send a PDF report from cloud storage
106
106
  report_url = generate_report_url # Your method to generate/get report URL
107
-
107
+
108
108
  if report_url
109
109
  client = get_whatsapp_client
110
110
  client.send_document(app.phone_number, report_url, "Your monthly report is ready!")
111
-
111
+
112
112
  app.say "📊 Report sent! Please check the document above."
113
113
  else
114
114
  app.say "Sorry, I couldn't generate the report right now. Please try again later."
@@ -118,10 +118,10 @@ class MediaSupportFlow < FlowChat::Flow
118
118
  def send_voice_message
119
119
  # Send a pre-recorded voice message from cloud storage
120
120
  audio_url = "https://cdn.example.com/audio/support_greeting.mp3"
121
-
121
+
122
122
  client = get_whatsapp_client
123
123
  client.send_audio(app.phone_number, audio_url)
124
-
124
+
125
125
  app.say "🎵 Please listen to the voice message above. You can also send me a voice message with your question!"
126
126
  end
127
127
 
@@ -129,15 +129,15 @@ class MediaSupportFlow < FlowChat::Flow
129
129
  feedback = app.screen(:feedback_text) do |prompt|
130
130
  prompt.ask "Please share your feedback. You can also send images or documents if needed:"
131
131
  end
132
-
132
+
133
133
  # Save feedback to database
134
134
  save_feedback(feedback, app.phone_number)
135
-
135
+
136
136
  # Send a thank you sticker from cloud storage
137
137
  sticker_url = "https://cdn.example.com/stickers/thanks.webp"
138
138
  client = get_whatsapp_client
139
139
  client.send_sticker(app.phone_number, sticker_url)
140
-
140
+
141
141
  app.say "Thank you for your feedback! We really appreciate it. 🙏"
142
142
  end
143
143
 
@@ -149,7 +149,7 @@ class MediaSupportFlow < FlowChat::Flow
149
149
  def generate_report_url
150
150
  # Your report generation logic here
151
151
  # This could return a signed URL from S3, Google Cloud Storage, etc.
152
- "https://storage.example.com/reports/monthly_report_#{Time.current.strftime('%Y%m')}.pdf"
152
+ "https://storage.example.com/reports/monthly_report_#{Time.current.strftime("%Y%m")}.pdf"
153
153
  end
154
154
 
155
155
  def save_feedback(feedback, phone_number)
@@ -187,8 +187,8 @@ class WhatsAppMediaService
187
187
  def send_order_confirmation(phone_number, order_id, invoice_url)
188
188
  # Send invoice document from cloud storage
189
189
  @client.send_document(
190
- phone_number,
191
- invoice_url,
190
+ phone_number,
191
+ invoice_url,
192
192
  "Order ##{order_id} confirmed! Here's your invoice.",
193
193
  "Invoice_#{order_id}.pdf"
194
194
  )
@@ -198,9 +198,9 @@ class WhatsAppMediaService
198
198
  phone_number,
199
199
  "Your order has been confirmed! 🛍️",
200
200
  [
201
- { id: 'track_order', title: '📦 Track Order' },
202
- { id: 'modify_order', title: '✏️ Modify Order' },
203
- { id: 'support', title: '💬 Contact Support' }
201
+ {id: "track_order", title: "📦 Track Order"},
202
+ {id: "modify_order", title: "✏️ Modify Order"},
203
+ {id: "support", title: "💬 Contact Support"}
204
204
  ]
205
205
  )
206
206
  end
@@ -220,54 +220,52 @@ class WhatsAppMediaService
220
220
  phone_number,
221
221
  "Don't miss out on this amazing deal!",
222
222
  [
223
- { id: 'buy_now', title: '🛒 Buy Now' },
224
- { id: 'more_info', title: 'ℹ️ More Info' },
225
- { id: 'remind_later', title: '⏰ Remind Later' }
223
+ {id: "buy_now", title: "🛒 Buy Now"},
224
+ {id: "more_info", title: "ℹ️ More Info"},
225
+ {id: "remind_later", title: "⏰ Remind Later"}
226
226
  ]
227
227
  )
228
228
  end
229
229
 
230
230
  # Handle media uploads with processing
231
231
  def process_uploaded_media(media_id, media_type, user_phone)
232
- begin
233
- # Download the media from WhatsApp
234
- media_url = @client.get_media_url(media_id)
235
- media_content = @client.download_media(media_id) if media_url
236
-
237
- if media_content
238
- # Upload to your cloud storage (S3, Google Cloud, etc.)
239
- cloud_url = upload_to_cloud_storage(media_content, media_type, media_id)
240
-
241
- # Process based on media type
242
- case media_type
243
- when 'image'
244
- process_image(cloud_url, user_phone)
245
- when 'document'
246
- process_document(cloud_url, user_phone)
247
- when 'audio'
248
- process_audio(cloud_url, user_phone)
249
- when 'video'
250
- process_video(cloud_url, user_phone)
251
- end
252
-
253
- Rails.logger.info "Successfully processed #{media_type} from #{user_phone}"
232
+ # Download the media from WhatsApp
233
+ media_url = @client.get_media_url(media_id)
234
+ media_content = @client.download_media(media_id) if media_url
235
+
236
+ if media_content
237
+ # Upload to your cloud storage (S3, Google Cloud, etc.)
238
+ cloud_url = upload_to_cloud_storage(media_content, media_type, media_id)
239
+
240
+ # Process based on media type
241
+ case media_type
242
+ when "image"
243
+ process_image(cloud_url, user_phone)
244
+ when "document"
245
+ process_document(cloud_url, user_phone)
246
+ when "audio"
247
+ process_audio(cloud_url, user_phone)
248
+ when "video"
249
+ process_video(cloud_url, user_phone)
254
250
  end
255
- rescue => e
256
- Rails.logger.error "Error processing media: #{e.message}"
257
- @client.send_text(user_phone, "Sorry, I couldn't process your file. Please try again.")
251
+
252
+ Rails.logger.info "Successfully processed #{media_type} from #{user_phone}"
258
253
  end
254
+ rescue => e
255
+ Rails.logger.error "Error processing media: #{e.message}"
256
+ @client.send_text(user_phone, "Sorry, I couldn't process your file. Please try again.")
259
257
  end
260
258
 
261
259
  # Send personalized content based on user data
262
260
  def send_personalized_content(phone_number, user_id)
263
261
  # Get user's preferred content from your system
264
262
  user_content = fetch_user_content(user_id)
265
-
263
+
266
264
  # Send personalized image
267
265
  if user_content[:image_url]
268
266
  @client.send_image(phone_number, user_content[:image_url], user_content[:image_caption])
269
267
  end
270
-
268
+
271
269
  # Send personalized document
272
270
  if user_content[:document_url]
273
271
  @client.send_document(phone_number, user_content[:document_url], user_content[:document_description])
@@ -278,7 +276,7 @@ class WhatsAppMediaService
278
276
  def send_qr_code(phone_number, data)
279
277
  # Generate QR code and get URL (using your QR service)
280
278
  qr_url = generate_qr_code_url(data)
281
-
279
+
282
280
  @client.send_image(phone_number, qr_url, "Here's your QR code!")
283
281
  end
284
282
 
@@ -286,7 +284,7 @@ class WhatsAppMediaService
286
284
  def send_analytics_chart(phone_number, chart_type, period)
287
285
  # Generate chart URL from your analytics service
288
286
  chart_url = generate_analytics_chart_url(chart_type, period)
289
-
287
+
290
288
  @client.send_image(phone_number, chart_url, "#{chart_type.humanize} for #{period}")
291
289
  end
292
290
 
@@ -340,11 +338,11 @@ class WhatsAppMediaService
340
338
 
341
339
  def get_file_extension(media_type)
342
340
  case media_type
343
- when 'image' then 'jpg'
344
- when 'document' then 'pdf'
345
- when 'audio' then 'mp3'
346
- when 'video' then 'mp4'
347
- else 'bin'
341
+ when "image" then "jpg"
342
+ when "document" then "pdf"
343
+ when "audio" then "mp3"
344
+ when "video" then "mp4"
345
+ else "bin"
348
346
  end
349
347
  end
350
348
  end
@@ -356,45 +354,45 @@ end
356
354
  class NotificationController < ApplicationController
357
355
  def send_media_notification
358
356
  service = WhatsAppMediaService.new
359
-
357
+
360
358
  # Send welcome package to new users
361
359
  service.send_welcome_package(params[:phone_number], params[:user_name])
362
-
363
- render json: { status: 'sent' }
360
+
361
+ render json: {status: "sent"}
364
362
  end
365
-
363
+
366
364
  def send_order_confirmation
367
365
  service = WhatsAppMediaService.new
368
-
366
+
369
367
  # Get invoice URL from your system (could be from S3, Google Cloud, etc.)
370
368
  invoice_url = get_invoice_url(params[:order_id])
371
-
369
+
372
370
  service.send_order_confirmation(
373
- params[:phone_number],
374
- params[:order_id],
371
+ params[:phone_number],
372
+ params[:order_id],
375
373
  invoice_url
376
374
  )
377
-
378
- render json: { status: 'sent' }
375
+
376
+ render json: {status: "sent"}
379
377
  end
380
378
 
381
379
  def send_promo
382
380
  service = WhatsAppMediaService.new
383
-
381
+
384
382
  # Promotional content from CDN
385
383
  promo_image = "https://cdn.example.com/promos/#{params[:promo_id]}/banner.jpg"
386
384
  promo_video = "https://cdn.example.com/promos/#{params[:promo_id]}/video.mp4"
387
-
385
+
388
386
  service.send_promotion(params[:phone_number], promo_image, promo_video)
389
-
390
- render json: { status: 'sent' }
387
+
388
+ render json: {status: "sent"}
391
389
  end
392
390
 
393
391
  def send_qr_code
394
392
  service = WhatsAppMediaService.new
395
393
  service.send_qr_code(params[:phone_number], params[:qr_data])
396
-
397
- render json: { status: 'sent' }
394
+
395
+ render json: {status: "sent"}
398
396
  end
399
397
 
400
398
  private
@@ -403,4 +401,4 @@ class NotificationController < ApplicationController
403
401
  # Your logic to get invoice URL from cloud storage
404
402
  "https://storage.example.com/invoices/#{order_id}.pdf"
405
403
  end
406
- end
404
+ end
@@ -54,7 +54,7 @@ class UrgentWhatsappSendJob < ApplicationJob
54
54
  error: error.message,
55
55
  user: send_data[:msisdn]
56
56
  )
57
-
57
+
58
58
  # Still send user notification
59
59
  super
60
60
  end
@@ -96,7 +96,7 @@ class MultiTenantWhatsappSendJob < ApplicationJob
96
96
  end
97
97
 
98
98
  # Usage in Rails configuration
99
- #
99
+ #
100
100
  # Add to config/application.rb:
101
101
  # config.active_job.queue_adapter = :sidekiq
102
102
  #
@@ -108,4 +108,4 @@ end
108
108
  # 1. Controller receives WhatsApp webhook
109
109
  # 2. Flow is processed synchronously (maintains controller context)
110
110
  # 3. Response is queued for async delivery via background job
111
- # 4. Job only handles sending the response, not processing flows
111
+ # 4. Job only handles sending the response, not processing flows
@@ -64,4 +64,4 @@ module FlowChat
64
64
  raise NotImplementedError, "Subclasses must implement configure_middleware_stack"
65
65
  end
66
66
  end
67
- end
67
+ end
@@ -32,18 +32,19 @@ module FlowChat
32
32
  end
33
33
 
34
34
  class WhatsappConfig
35
- attr_accessor :message_handling_mode, :background_job_class
35
+ attr_accessor :background_job_class
36
+ attr_reader :message_handling_mode
36
37
 
37
38
  def initialize
38
39
  @message_handling_mode = :inline
39
- @background_job_class = 'WhatsappMessageJob'
40
+ @background_job_class = "WhatsappMessageJob"
40
41
  end
41
42
 
42
43
  # Validate message handling mode
43
44
  def message_handling_mode=(mode)
44
45
  valid_modes = [:inline, :background, :simulator]
45
46
  unless valid_modes.include?(mode.to_sym)
46
- raise ArgumentError, "Invalid message handling mode: #{mode}. Valid modes: #{valid_modes.join(', ')}"
47
+ raise ArgumentError, "Invalid message handling mode: #{mode}. Valid modes: #{valid_modes.join(", ")}"
47
48
  end
48
49
  @message_handling_mode = mode.to_sym
49
50
  end
@@ -4,7 +4,7 @@ module FlowChat
4
4
  def initialize(context, cache = nil)
5
5
  @context = context
6
6
  @cache = cache || FlowChat::Config.cache
7
-
7
+
8
8
  raise ArgumentError, "Cache is required. Set FlowChat::Config.cache or pass a cache instance." unless @cache
9
9
  end
10
10
 
@@ -22,7 +22,7 @@ module FlowChat
22
22
 
23
23
  data = @cache.read(session_key) || {}
24
24
  data[key.to_s] = value
25
-
25
+
26
26
  @cache.write(session_key, data, expires_in: session_ttl)
27
27
  value
28
28
  end
@@ -55,7 +55,7 @@ module FlowChat
55
55
  def session_key
56
56
  gateway = @context["request.gateway"]
57
57
  msisdn = @context["request.msisdn"]
58
-
58
+
59
59
  case gateway
60
60
  when :whatsapp_cloud_api
61
61
  "flow_chat:session:whatsapp:#{msisdn}"
@@ -69,7 +69,7 @@ module FlowChat
69
69
 
70
70
  def session_ttl
71
71
  gateway = @context["request.gateway"]
72
-
72
+
73
73
  case gateway
74
74
  when :whatsapp_cloud_api
75
75
  7.days # WhatsApp conversations can be long-lived
@@ -81,4 +81,4 @@ module FlowChat
81
81
  end
82
82
  end
83
83
  end
84
- end
84
+ end