Fred808 commited on
Commit
5c9423b
·
verified ·
1 Parent(s): 9570725

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -14
app.py CHANGED
@@ -54,6 +54,7 @@ class UserProfile(Base):
54
  __tablename__ = "user_profiles"
55
  id = Column(Integer, primary_key=True, index=True)
56
  user_id = Column(String, unique=True, index=True)
 
57
  name = Column(String, default="Valued Customer")
58
  email = Column(String, default="unknown@example.com")
59
  preferences = Column(Text, default="") # e.g., favorite dishes, dietary restrictions
@@ -241,8 +242,8 @@ def process_order_flow(user_id: str, message: str) -> str:
241
  asyncio.create_task(save_order())
242
  # Clear conversation state for order flow.
243
  del user_state[user_id]
244
- # For personalization, try retrieving the user's email.
245
- email = "customer@example.com" # In a real system, use UserProfile info.
246
  payment_data = create_paystack_payment_link(email, total_price * 100, order_id)
247
  if payment_data.get("status"):
248
  payment_link = payment_data["data"]["authorization_url"]
@@ -257,15 +258,19 @@ def process_order_flow(user_id: str, message: str) -> str:
257
  return ""
258
 
259
  # --- User Profile Functions ---
260
- async def get_or_create_user_profile(user_id: str) -> UserProfile:
261
- """Retrieve an existing profile or create a new one."""
262
  async with async_session() as session:
263
  result = await session.execute(
264
  UserProfile.__table__.select().where(UserProfile.user_id == user_id)
265
  )
266
  profile = result.scalar_one_or_none()
267
  if profile is None:
268
- profile = UserProfile(user_id=user_id, last_interaction=datetime.utcnow())
 
 
 
 
269
  session.add(profile)
270
  await session.commit()
271
  return profile
@@ -284,8 +289,6 @@ async def update_user_last_interaction(user_id: str):
284
  # --- Proactive Engagement: Warm Greetings ---
285
  async def send_proactive_greeting(user_id: str):
286
  """Simulate sending a proactive greeting if the user has been inactive."""
287
- # In a real system, you might schedule this using a job scheduler.
288
- # Here we just simulate a warm greeting message.
289
  greeting = "Hi again! We miss you. Would you like to see our new menu items or get personalized recommendations?"
290
  await log_chat_to_db(user_id, "outbound", greeting)
291
  return greeting
@@ -305,11 +308,13 @@ async def chatbot_response(request: Request, background_tasks: BackgroundTasks):
305
  Supports text queries, image queries, and advanced logic.
306
  Expects JSON payload with:
307
  - 'user_id'
 
308
  - 'message'
309
  - Optionally, 'is_image': true and 'image_base64'
310
  """
311
  data = await request.json()
312
  user_id = data.get("user_id")
 
313
  user_message = data.get("message", "").strip()
314
  is_image = data.get("is_image", False)
315
  image_b64 = data.get("image_base64", None)
@@ -319,11 +324,11 @@ async def chatbot_response(request: Request, background_tasks: BackgroundTasks):
319
 
320
  # Log inbound message
321
  background_tasks.add_task(log_chat_to_db, user_id, "inbound", user_message)
322
- # Update user last interaction and profile
323
  await update_user_last_interaction(user_id)
324
- await get_or_create_user_profile(user_id)
325
 
326
- # Handle voice/image queries if applicable
327
  if is_image and image_b64:
328
  if len(image_b64) >= 180_000:
329
  raise HTTPException(status_code=400, detail="Image too large.")
@@ -334,7 +339,7 @@ async def chatbot_response(request: Request, background_tasks: BackgroundTasks):
334
  sentiment_score = analyze_sentiment(user_message)
335
  background_tasks.add_task(log_sentiment, user_id, user_message, sentiment_score)
336
 
337
- # Adjust response tone based on sentiment (for demonstration)
338
  sentiment_modifier = ""
339
  if sentiment_score < -0.3:
340
  sentiment_modifier = "I'm sorry if you're having a tough time. "
@@ -426,6 +431,7 @@ async def get_user_profile(user_id: str):
426
  profile = await get_or_create_user_profile(user_id)
427
  return {
428
  "user_id": profile.user_id,
 
429
  "name": profile.name,
430
  "email": profile.email,
431
  "preferences": profile.preferences,
@@ -465,9 +471,8 @@ async def process_voice(file: UploadFile = File(...)):
465
  Accept a voice file upload, perform speech-to-text (simulated), and process the resulting text.
466
  In production, integrate with a real STT service.
467
  """
468
- # Simulated Speech-to-Text: read file bytes and decode (for demo, just return a fixed string)
469
  contents = await file.read()
470
- # In real implementation, send `contents` to an STT service.
471
  simulated_text = "Simulated speech-to-text conversion result."
472
  return {"transcription": simulated_text}
473
 
@@ -480,7 +485,7 @@ async def payment_callback(request: Request):
480
  """
481
  data = await request.json()
482
  # Extract order reference and update order status accordingly.
483
- # This is a stub – in production, verify callback signature, extract data, and update DB.
484
  order_id = data.get("reference")
485
  new_status = data.get("status", "Paid")
486
  async with async_session() as session:
 
54
  __tablename__ = "user_profiles"
55
  id = Column(Integer, primary_key=True, index=True)
56
  user_id = Column(String, unique=True, index=True)
57
+ phone_number = Column(String, unique=True, index=True, nullable=True) # New field for phone numbers
58
  name = Column(String, default="Valued Customer")
59
  email = Column(String, default="unknown@example.com")
60
  preferences = Column(Text, default="") # e.g., favorite dishes, dietary restrictions
 
242
  asyncio.create_task(save_order())
243
  # Clear conversation state for order flow.
244
  del user_state[user_id]
245
+ # Retrieve email from user profile if available (here using a placeholder)
246
+ email = "customer@example.com"
247
  payment_data = create_paystack_payment_link(email, total_price * 100, order_id)
248
  if payment_data.get("status"):
249
  payment_link = payment_data["data"]["authorization_url"]
 
258
  return ""
259
 
260
  # --- User Profile Functions ---
261
+ async def get_or_create_user_profile(user_id: str, phone_number: str = None) -> UserProfile:
262
+ """Retrieve an existing profile or create a new one with user_id and phone_number."""
263
  async with async_session() as session:
264
  result = await session.execute(
265
  UserProfile.__table__.select().where(UserProfile.user_id == user_id)
266
  )
267
  profile = result.scalar_one_or_none()
268
  if profile is None:
269
+ profile = UserProfile(
270
+ user_id=user_id,
271
+ phone_number=phone_number,
272
+ last_interaction=datetime.utcnow()
273
+ )
274
  session.add(profile)
275
  await session.commit()
276
  return profile
 
289
  # --- Proactive Engagement: Warm Greetings ---
290
  async def send_proactive_greeting(user_id: str):
291
  """Simulate sending a proactive greeting if the user has been inactive."""
 
 
292
  greeting = "Hi again! We miss you. Would you like to see our new menu items or get personalized recommendations?"
293
  await log_chat_to_db(user_id, "outbound", greeting)
294
  return greeting
 
308
  Supports text queries, image queries, and advanced logic.
309
  Expects JSON payload with:
310
  - 'user_id'
311
+ - 'phone_number'
312
  - 'message'
313
  - Optionally, 'is_image': true and 'image_base64'
314
  """
315
  data = await request.json()
316
  user_id = data.get("user_id")
317
+ phone_number = data.get("phone_number") # New field for phone number
318
  user_message = data.get("message", "").strip()
319
  is_image = data.get("is_image", False)
320
  image_b64 = data.get("image_base64", None)
 
324
 
325
  # Log inbound message
326
  background_tasks.add_task(log_chat_to_db, user_id, "inbound", user_message)
327
+ # Update user last interaction and create profile with phone number
328
  await update_user_last_interaction(user_id)
329
+ await get_or_create_user_profile(user_id, phone_number)
330
 
331
+ # Handle image queries
332
  if is_image and image_b64:
333
  if len(image_b64) >= 180_000:
334
  raise HTTPException(status_code=400, detail="Image too large.")
 
339
  sentiment_score = analyze_sentiment(user_message)
340
  background_tasks.add_task(log_sentiment, user_id, user_message, sentiment_score)
341
 
342
+ # Adjust response tone based on sentiment
343
  sentiment_modifier = ""
344
  if sentiment_score < -0.3:
345
  sentiment_modifier = "I'm sorry if you're having a tough time. "
 
431
  profile = await get_or_create_user_profile(user_id)
432
  return {
433
  "user_id": profile.user_id,
434
+ "phone_number": profile.phone_number,
435
  "name": profile.name,
436
  "email": profile.email,
437
  "preferences": profile.preferences,
 
471
  Accept a voice file upload, perform speech-to-text (simulated), and process the resulting text.
472
  In production, integrate with a real STT service.
473
  """
 
474
  contents = await file.read()
475
+ # Simulated Speech-to-Text: In real implementation, send `contents` to an STT service.
476
  simulated_text = "Simulated speech-to-text conversion result."
477
  return {"transcription": simulated_text}
478
 
 
485
  """
486
  data = await request.json()
487
  # Extract order reference and update order status accordingly.
488
+ # In production, verify callback signature and extract data.
489
  order_id = data.get("reference")
490
  new_status = data.get("status", "Paid")
491
  async with async_session() as session: