Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -43,6 +43,7 @@ import httpx
|
|
| 43 |
import langdetect
|
| 44 |
from langdetect import detect
|
| 45 |
import threading
|
|
|
|
| 46 |
|
| 47 |
# Configure advanced logging
|
| 48 |
logging.basicConfig(
|
|
@@ -2018,7 +2019,7 @@ async def handle_all_products_selection(from_number: str, selection: str, user_c
|
|
| 2018 |
send_helpful_guidance(from_number, 'all_products_menu')
|
| 2019 |
|
| 2020 |
async def handle_intelligent_product_inquiry(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
|
| 2021 |
-
"""Handle product inquiry with OpenAI intelligence"""
|
| 2022 |
try:
|
| 2023 |
# First try direct product search
|
| 2024 |
products = get_veterinary_product_matches(query)
|
|
@@ -2141,7 +2142,7 @@ Format your response professionally with emojis and clear structure. Keep it con
|
|
| 2141 |
context_manager.add_to_history(from_number, query, message)
|
| 2142 |
|
| 2143 |
else:
|
| 2144 |
-
# Single product found - show detailed information
|
| 2145 |
selected_product = products[0]
|
| 2146 |
context_manager.update_context(
|
| 2147 |
from_number,
|
|
@@ -2153,21 +2154,15 @@ Format your response professionally with emojis and clear structure. Keep it con
|
|
| 2153 |
|
| 2154 |
# Get updated context with last message
|
| 2155 |
context = context_manager.get_context(from_number)
|
| 2156 |
-
response = generate_veterinary_product_response(selected_product, context)
|
| 2157 |
|
| 2158 |
-
#
|
| 2159 |
-
|
| 2160 |
-
|
| 2161 |
-
|
| 2162 |
-
|
| 2163 |
-
except Exception as e:
|
| 2164 |
-
logger.error(f"[AI] Translation error: {e}")
|
| 2165 |
-
send_whatsjet_message(from_number, response)
|
| 2166 |
-
else:
|
| 2167 |
-
send_whatsjet_message(from_number, response)
|
| 2168 |
|
| 2169 |
# Add to conversation history
|
| 2170 |
-
context_manager.add_to_history(from_number, query,
|
| 2171 |
|
| 2172 |
else:
|
| 2173 |
# Enhanced "not found" response with veterinary suggestions
|
|
@@ -3564,6 +3559,107 @@ def generate_veterinary_product_response_with_media(product_info: Dict[str, Any]
|
|
| 3564 |
'product_name': product_name
|
| 3565 |
}
|
| 3566 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3567 |
if __name__ == "__main__":
|
| 3568 |
# Launch FastAPI app
|
| 3569 |
import uvicorn
|
|
|
|
| 43 |
import langdetect
|
| 44 |
from langdetect import detect
|
| 45 |
import threading
|
| 46 |
+
import shutil
|
| 47 |
|
| 48 |
# Configure advanced logging
|
| 49 |
logging.basicConfig(
|
|
|
|
| 2019 |
send_helpful_guidance(from_number, 'all_products_menu')
|
| 2020 |
|
| 2021 |
async def handle_intelligent_product_inquiry(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
|
| 2022 |
+
"""Handle product inquiry with OpenAI intelligence and media support"""
|
| 2023 |
try:
|
| 2024 |
# First try direct product search
|
| 2025 |
products = get_veterinary_product_matches(query)
|
|
|
|
| 2142 |
context_manager.add_to_history(from_number, query, message)
|
| 2143 |
|
| 2144 |
else:
|
| 2145 |
+
# Single product found - show detailed information with media support
|
| 2146 |
selected_product = products[0]
|
| 2147 |
context_manager.update_context(
|
| 2148 |
from_number,
|
|
|
|
| 2154 |
|
| 2155 |
# Get updated context with last message
|
| 2156 |
context = context_manager.get_context(from_number)
|
|
|
|
| 2157 |
|
| 2158 |
+
# Use enhanced response with media support
|
| 2159 |
+
response_with_media = generate_veterinary_product_response_with_media(selected_product, context)
|
| 2160 |
+
|
| 2161 |
+
# Send the response
|
| 2162 |
+
send_whatsjet_message(from_number, response_with_media['text'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2163 |
|
| 2164 |
# Add to conversation history
|
| 2165 |
+
context_manager.add_to_history(from_number, query, response_with_media['text'])
|
| 2166 |
|
| 2167 |
else:
|
| 2168 |
# Enhanced "not found" response with veterinary suggestions
|
|
|
|
| 3559 |
'product_name': product_name
|
| 3560 |
}
|
| 3561 |
|
| 3562 |
+
# Ensure static/images directory exists for product images
|
| 3563 |
+
def ensure_images_dir():
|
| 3564 |
+
images_dir = os.path.join('static', 'images')
|
| 3565 |
+
os.makedirs(images_dir, exist_ok=True)
|
| 3566 |
+
return images_dir
|
| 3567 |
+
|
| 3568 |
+
# New feature: Send product image with caption (product details)
|
| 3569 |
+
async def send_product_image_with_caption(from_number: str, product: Dict[str, Any], user_context: Dict[str, Any]):
|
| 3570 |
+
"""
|
| 3571 |
+
Send product image (if available) with product details as caption in a single WhatsApp message.
|
| 3572 |
+
If image is not available, send only the product details as text.
|
| 3573 |
+
Now supports 'Images' column in CSV (Google Drive or direct links).
|
| 3574 |
+
"""
|
| 3575 |
+
ensure_images_dir()
|
| 3576 |
+
product_name = product.get('Product Name', 'Unknown Product')
|
| 3577 |
+
details = generate_veterinary_product_response(product, user_context)
|
| 3578 |
+
image_url = product.get('Images', '').strip() if 'Images' in product else ''
|
| 3579 |
+
temp_file_path = None
|
| 3580 |
+
try:
|
| 3581 |
+
if image_url:
|
| 3582 |
+
# Convert Google Drive link to direct download if needed
|
| 3583 |
+
if 'drive.google.com' in image_url:
|
| 3584 |
+
if '/d/' in image_url:
|
| 3585 |
+
file_id = image_url.split('/d/')[1].split('/')[0]
|
| 3586 |
+
elif 'id=' in image_url:
|
| 3587 |
+
file_id = image_url.split('id=')[1].split('&')[0]
|
| 3588 |
+
else:
|
| 3589 |
+
file_id = ''
|
| 3590 |
+
if file_id:
|
| 3591 |
+
image_url = f"https://drive.google.com/uc?export=download&id={file_id}"
|
| 3592 |
+
# Download the image to a temp file
|
| 3593 |
+
response = requests.get(image_url, stream=True, timeout=10)
|
| 3594 |
+
if response.status_code == 200:
|
| 3595 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as tmp:
|
| 3596 |
+
for chunk in response.iter_content(1024):
|
| 3597 |
+
tmp.write(chunk)
|
| 3598 |
+
temp_file_path = tmp.name
|
| 3599 |
+
media_type = 'image/jpeg'
|
| 3600 |
+
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 3601 |
+
success = send_whatsjet_message(
|
| 3602 |
+
from_number,
|
| 3603 |
+
details,
|
| 3604 |
+
media_type=media_type,
|
| 3605 |
+
media_path=temp_file_path,
|
| 3606 |
+
filename=filename
|
| 3607 |
+
)
|
| 3608 |
+
if success:
|
| 3609 |
+
logger.info(f"[Product] Sent image from CSV link with caption for product: {product_name}")
|
| 3610 |
+
return
|
| 3611 |
+
else:
|
| 3612 |
+
logger.warning(f"[Product] Failed to send image from CSV link, sending text only: {product_name}")
|
| 3613 |
+
else:
|
| 3614 |
+
logger.warning(f"[Product] Could not download image from CSV link: {image_url}")
|
| 3615 |
+
# Fallback to local static/images
|
| 3616 |
+
image_path = get_product_image_path(product_name)
|
| 3617 |
+
if image_path and os.path.exists(image_path):
|
| 3618 |
+
media_type = get_product_image_media_type(image_path)
|
| 3619 |
+
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 3620 |
+
success = send_whatsjet_message(
|
| 3621 |
+
from_number,
|
| 3622 |
+
details,
|
| 3623 |
+
media_type=media_type,
|
| 3624 |
+
media_path=image_path,
|
| 3625 |
+
filename=filename
|
| 3626 |
+
)
|
| 3627 |
+
if success:
|
| 3628 |
+
logger.info(f"[Product] Sent image with caption for product: {product_name}")
|
| 3629 |
+
else:
|
| 3630 |
+
logger.warning(f"[Product] Failed to send image, sending text only: {product_name}")
|
| 3631 |
+
send_whatsjet_message(from_number, details)
|
| 3632 |
+
else:
|
| 3633 |
+
send_whatsjet_message(from_number, details)
|
| 3634 |
+
logger.info(f"[Product] Sent product info without image: {product_name}")
|
| 3635 |
+
except Exception as e:
|
| 3636 |
+
logger.error(f"[Product] Error sending product image with caption: {e}")
|
| 3637 |
+
send_whatsjet_message(from_number, details)
|
| 3638 |
+
finally:
|
| 3639 |
+
if temp_file_path and os.path.exists(temp_file_path):
|
| 3640 |
+
try:
|
| 3641 |
+
os.remove(temp_file_path)
|
| 3642 |
+
except Exception:
|
| 3643 |
+
pass
|
| 3644 |
+
|
| 3645 |
+
@app.get("/test-product-image-with-caption")
|
| 3646 |
+
async def test_product_image_with_caption(phone: str):
|
| 3647 |
+
"""
|
| 3648 |
+
Test endpoint to send Heposel product image and details as caption to the given phone number.
|
| 3649 |
+
"""
|
| 3650 |
+
# Load Heposel product from CSV
|
| 3651 |
+
try:
|
| 3652 |
+
df = pd.read_csv('Veterinary.csv')
|
| 3653 |
+
row = df[df['Product Name'].str.lower() == 'heposel']
|
| 3654 |
+
if row.empty:
|
| 3655 |
+
return {"error": "Heposel not found in CSV"}
|
| 3656 |
+
product = row.iloc[0].to_dict()
|
| 3657 |
+
user_context = context_manager.get_context(phone)
|
| 3658 |
+
await send_product_image_with_caption(phone, product, user_context)
|
| 3659 |
+
return {"status": "sent", "phone": phone}
|
| 3660 |
+
except Exception as e:
|
| 3661 |
+
return {"error": str(e)}
|
| 3662 |
+
|
| 3663 |
if __name__ == "__main__":
|
| 3664 |
# Launch FastAPI app
|
| 3665 |
import uvicorn
|