Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2760,144 +2760,33 @@ async def send_product_image_with_caption(from_number: str, product: Dict[str, A
|
|
| 2760 |
"""
|
| 2761 |
Send product image (if available) with product details as caption in a single WhatsApp message.
|
| 2762 |
If image is not available, send only the product details as text.
|
| 2763 |
-
Now supports 'Images' column in CSV (Google Drive or direct links).
|
| 2764 |
"""
|
| 2765 |
ensure_images_dir()
|
| 2766 |
product_name = product.get('Product Name', 'Unknown Product')
|
| 2767 |
details = generate_veterinary_product_response(product, user_context)
|
| 2768 |
-
|
| 2769 |
-
|
| 2770 |
-
|
| 2771 |
-
|
| 2772 |
-
image_url = "https://amgocus.com/uploads/images/Respira%20Aid%20Plus.jpg"
|
| 2773 |
-
|
| 2774 |
-
logger.info(f"[Product] Processing image for product: {product_name}")
|
| 2775 |
-
logger.info(f"[Product] Image URL from CSV: {image_url}")
|
| 2776 |
-
|
| 2777 |
-
try:
|
| 2778 |
-
# First, check if we have an image URL from CSV
|
| 2779 |
-
if image_url:
|
| 2780 |
-
# Convert Google Drive link to direct download if needed
|
| 2781 |
-
if 'drive.google.com' in image_url:
|
| 2782 |
-
logger.info(f"[Product] Converting Google Drive link: {image_url}")
|
| 2783 |
-
if '/d/' in image_url:
|
| 2784 |
-
file_id = image_url.split('/d/')[1].split('/')[0]
|
| 2785 |
-
elif 'id=' in image_url:
|
| 2786 |
-
file_id = image_url.split('id=')[1].split('&')[0]
|
| 2787 |
-
else:
|
| 2788 |
-
file_id = ''
|
| 2789 |
-
if file_id:
|
| 2790 |
-
image_url = f"https://drive.google.com/uc?export=download&id={file_id}"
|
| 2791 |
-
logger.info(f"[Product] Converted to direct download URL: {image_url}")
|
| 2792 |
-
media_type = 'image/jpeg'
|
| 2793 |
-
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 2794 |
-
try:
|
| 2795 |
-
logger.info(f"[Product] Testing image URL accessibility: {image_url}")
|
| 2796 |
-
headers = {
|
| 2797 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
| 2798 |
-
'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
|
| 2799 |
-
'Accept-Language': 'en-US,en;q=0.9',
|
| 2800 |
-
'Accept-Encoding': 'gzip, deflate, br',
|
| 2801 |
-
'Connection': 'keep-alive',
|
| 2802 |
-
'Upgrade-Insecure-Requests': '1'
|
| 2803 |
-
}
|
| 2804 |
-
test_response = requests.get(image_url, headers=headers, timeout=10, stream=True, allow_redirects=True)
|
| 2805 |
-
if test_response.status_code != 200:
|
| 2806 |
-
logger.warning(f"[Product] Image URL not accessible (status {test_response.status_code}): {image_url}")
|
| 2807 |
-
raise Exception(f"Image URL not accessible: {test_response.status_code}")
|
| 2808 |
-
logger.info(f"[Product] Image URL is accessible")
|
| 2809 |
-
except Exception as e:
|
| 2810 |
-
logger.warning(f"[Product] Failed to test image URL {image_url}: {e}")
|
| 2811 |
-
image_url = None
|
| 2812 |
-
# If image_url is public, send image+caption in a single message
|
| 2813 |
-
if image_url and image_url.startswith('http'):
|
| 2814 |
-
logger.info(f"[Product] Sending public image URL with caption using send_whatsjet_message: {image_url}")
|
| 2815 |
-
send_whatsjet_message(
|
| 2816 |
-
from_number,
|
| 2817 |
-
details,
|
| 2818 |
-
media_type=media_type,
|
| 2819 |
-
media_path=image_url,
|
| 2820 |
-
filename=filename
|
| 2821 |
-
)
|
| 2822 |
-
return
|
| 2823 |
-
# Otherwise, fallback to local file logic
|
| 2824 |
-
# Send using public URL (not local file)
|
| 2825 |
-
if image_url:
|
| 2826 |
-
logger.info(f"[Product] Attempting to send image from CSV URL for: {product_name}")
|
| 2827 |
-
success = send_whatsjet_message(
|
| 2828 |
-
from_number,
|
| 2829 |
-
details,
|
| 2830 |
-
media_type=media_type,
|
| 2831 |
-
media_path=image_url, # Use public URL directly
|
| 2832 |
-
filename=filename
|
| 2833 |
-
)
|
| 2834 |
-
|
| 2835 |
-
if success:
|
| 2836 |
-
logger.info(f"[Product] Successfully sent image from CSV link with caption for product: {product_name}")
|
| 2837 |
-
return
|
| 2838 |
-
else:
|
| 2839 |
-
logger.warning(f"[Product] Failed to send image from CSV link, trying fallback: {product_name}")
|
| 2840 |
-
|
| 2841 |
-
# Fallback 1: Try with a known public test image
|
| 2842 |
-
logger.info(f"[Product] Trying public test image for: {product_name}")
|
| 2843 |
-
test_image_url = "https://www.w3schools.com/w3images/lights.jpg"
|
| 2844 |
-
media_type = 'image/jpeg'
|
| 2845 |
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 2846 |
-
|
| 2847 |
success = send_whatsjet_message(
|
| 2848 |
from_number,
|
| 2849 |
details,
|
| 2850 |
media_type=media_type,
|
| 2851 |
-
media_path=
|
| 2852 |
filename=filename
|
| 2853 |
)
|
| 2854 |
-
|
| 2855 |
if success:
|
| 2856 |
-
logger.info(f"[Product] Successfully sent
|
| 2857 |
return
|
| 2858 |
-
|
| 2859 |
-
|
| 2860 |
-
|
| 2861 |
-
|
| 2862 |
-
|
| 2863 |
-
|
| 2864 |
-
|
| 2865 |
-
# If it's a public URL, send as image+caption
|
| 2866 |
-
if image_path.startswith('http'):
|
| 2867 |
-
logger.info(f"[Product] Sending normalized cPanel public URL with caption: {image_path}")
|
| 2868 |
-
# Send image first using the correct method for URLs
|
| 2869 |
-
image_success = send_whatsjet_media_image_only(
|
| 2870 |
-
from_number,
|
| 2871 |
-
image_path,
|
| 2872 |
-
filename=filename
|
| 2873 |
-
)
|
| 2874 |
-
if image_success:
|
| 2875 |
-
logger.info(f"[Product] Image sent successfully, now sending product details")
|
| 2876 |
-
# Send product details as text
|
| 2877 |
-
send_whatsjet_message(from_number, details)
|
| 2878 |
-
return
|
| 2879 |
-
else:
|
| 2880 |
-
logger.warning(f"[Product] Failed to send image, sending text only")
|
| 2881 |
-
send_whatsjet_message(from_number, details)
|
| 2882 |
-
return
|
| 2883 |
-
# Otherwise, treat as local file
|
| 2884 |
-
elif os.path.exists(image_path):
|
| 2885 |
-
logger.info(f"[Product] Sending local file with caption: {image_path}")
|
| 2886 |
-
send_whatsjet_message(
|
| 2887 |
-
from_number,
|
| 2888 |
-
details,
|
| 2889 |
-
media_type=media_type,
|
| 2890 |
-
media_path=image_path,
|
| 2891 |
-
filename=filename
|
| 2892 |
-
)
|
| 2893 |
-
return
|
| 2894 |
-
# No image available, send text only
|
| 2895 |
-
logger.info(f"[Product] No image available, sending text only for: {product_name}")
|
| 2896 |
-
send_whatsjet_message(from_number, details)
|
| 2897 |
-
except Exception as e:
|
| 2898 |
-
logger.error(f"[Product] Error sending product image with caption: {e}")
|
| 2899 |
-
logger.info(f"[Product] Falling back to text-only message for: {product_name}")
|
| 2900 |
-
send_whatsjet_message(from_number, details)
|
| 2901 |
|
| 2902 |
# Test endpoint for product image with caption
|
| 2903 |
@app.get("/test-product-image-with-caption")
|
|
@@ -3496,135 +3385,6 @@ async def handle_voice_message_complete(from_number: str, msg: dict):
|
|
| 3496 |
send_whatsjet_message(from_number,
|
| 3497 |
"❌ Error processing voice message. Please try a text message.")
|
| 3498 |
|
| 3499 |
-
# --- Update send_product_image_with_caption to latest version ---
|
| 3500 |
-
async def send_product_image_with_caption(from_number: str, product: Dict[str, Any], user_context: Dict[str, Any]):
|
| 3501 |
-
logger.info(f"[Product] send_product_image_with_caption called for: {product.get('Product Name', '')}")
|
| 3502 |
-
"""
|
| 3503 |
-
Send product image (if available) with product details as caption in a single WhatsApp message.
|
| 3504 |
-
If image is not available, send only the product details as text.
|
| 3505 |
-
Now supports 'Images' column in CSV (Google Drive or direct links).
|
| 3506 |
-
"""
|
| 3507 |
-
ensure_images_dir()
|
| 3508 |
-
product_name = product.get('Product Name', 'Unknown Product')
|
| 3509 |
-
details = generate_veterinary_product_response(product, user_context)
|
| 3510 |
-
image_url = product.get('Images', '').strip() if 'Images' in product else ''
|
| 3511 |
-
|
| 3512 |
-
# Force image URL for Respira Aid Plus (use cPanel public URL)
|
| 3513 |
-
if product_name.lower().strip() == "respira aid plus":
|
| 3514 |
-
image_url = "https://amgocus.com/uploads/images/Respira%20Aid%20Plus.jpg"
|
| 3515 |
-
|
| 3516 |
-
logger.info(f"[Product] Processing image for product: {product_name}")
|
| 3517 |
-
logger.info(f"[Product] Image URL from CSV: {image_url}")
|
| 3518 |
-
try:
|
| 3519 |
-
# First, check if we have an image URL from CSV
|
| 3520 |
-
if image_url:
|
| 3521 |
-
# Convert Google Drive link to direct download if needed
|
| 3522 |
-
if 'drive.google.com' in image_url:
|
| 3523 |
-
logger.info(f"[Product] Converting Google Drive link: {image_url}")
|
| 3524 |
-
if '/d/' in image_url:
|
| 3525 |
-
file_id = image_url.split('/d/')[1].split('/')[0]
|
| 3526 |
-
elif 'id=' in image_url:
|
| 3527 |
-
file_id = image_url.split('id=')[1].split('&')[0]
|
| 3528 |
-
else:
|
| 3529 |
-
file_id = ''
|
| 3530 |
-
if file_id:
|
| 3531 |
-
image_url = f"https://drive.google.com/uc?export=download&id={file_id}"
|
| 3532 |
-
logger.info(f"[Product] Converted to direct download URL: {image_url}")
|
| 3533 |
-
# Use the public URL directly for WhatsApp API
|
| 3534 |
-
media_type = 'image/jpeg'
|
| 3535 |
-
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 3536 |
-
# Test the image URL first
|
| 3537 |
-
try:
|
| 3538 |
-
logger.info(f"[Product] Testing image URL accessibility: {image_url}")
|
| 3539 |
-
headers = {
|
| 3540 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
| 3541 |
-
'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
|
| 3542 |
-
'Accept-Language': 'en-US,en;q=0.9',
|
| 3543 |
-
'Accept-Encoding': 'gzip, deflate, br',
|
| 3544 |
-
'Connection': 'keep-alive',
|
| 3545 |
-
'Upgrade-Insecure-Requests': '1'
|
| 3546 |
-
}
|
| 3547 |
-
test_response = requests.get(image_url, headers=headers, timeout=10, stream=True, allow_redirects=True)
|
| 3548 |
-
if test_response.status_code != 200:
|
| 3549 |
-
logger.warning(f"[Product] Image URL not accessible (status {test_response.status_code}): {image_url}")
|
| 3550 |
-
raise Exception(f"Image URL not accessible: {test_response.status_code}")
|
| 3551 |
-
logger.info(f"[Product] Image URL is accessible")
|
| 3552 |
-
except Exception as e:
|
| 3553 |
-
logger.warning(f"[Product] Failed to test image URL {image_url}: {e}")
|
| 3554 |
-
image_url = None
|
| 3555 |
-
# Send using public URL (not local file)
|
| 3556 |
-
if image_url:
|
| 3557 |
-
logger.info(f"[Product] Attempting to send image from CSV URL for: {product_name}")
|
| 3558 |
-
success = send_whatsjet_message(
|
| 3559 |
-
from_number,
|
| 3560 |
-
details,
|
| 3561 |
-
media_type=media_type,
|
| 3562 |
-
media_path=image_url, # Use public URL directly
|
| 3563 |
-
filename=filename
|
| 3564 |
-
)
|
| 3565 |
-
if success:
|
| 3566 |
-
logger.info(f"[Product] Successfully sent image from CSV link with caption for product: {product_name}")
|
| 3567 |
-
return
|
| 3568 |
-
else:
|
| 3569 |
-
logger.warning(f"[Product] Failed to send image from CSV link, trying fallback: {product_name}")
|
| 3570 |
-
# Fallback 1: Try with a known public test image
|
| 3571 |
-
logger.info(f"[Product] Trying public test image for: {product_name}")
|
| 3572 |
-
test_image_url = "https://www.w3schools.com/w3images/lights.jpg"
|
| 3573 |
-
media_type = 'image/jpeg'
|
| 3574 |
-
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 3575 |
-
success = send_whatsjet_message(
|
| 3576 |
-
from_number,
|
| 3577 |
-
details,
|
| 3578 |
-
media_type=media_type,
|
| 3579 |
-
media_path=test_image_url,
|
| 3580 |
-
filename=filename
|
| 3581 |
-
)
|
| 3582 |
-
if success:
|
| 3583 |
-
logger.info(f"[Product] Successfully sent test image with caption for product: {product_name}")
|
| 3584 |
-
return
|
| 3585 |
-
# Fallback 2: Try local uploads directory (public URL)
|
| 3586 |
-
logger.info(f"[Product] Trying local uploads directory for: {product_name}")
|
| 3587 |
-
image_path = get_product_image_path(product_name)
|
| 3588 |
-
if image_path:
|
| 3589 |
-
media_type = get_product_image_media_type(image_path)
|
| 3590 |
-
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 3591 |
-
# If it's a public URL, send as image+caption
|
| 3592 |
-
if image_path.startswith('http'):
|
| 3593 |
-
logger.info(f"[Product] Sending normalized cPanel public URL with caption: {image_path}")
|
| 3594 |
-
# Send image first using the correct method for URLs
|
| 3595 |
-
image_success = send_whatsjet_media_image_only(
|
| 3596 |
-
from_number,
|
| 3597 |
-
image_path,
|
| 3598 |
-
filename=filename
|
| 3599 |
-
)
|
| 3600 |
-
if image_success:
|
| 3601 |
-
logger.info(f"[Product] Image sent successfully, now sending product details")
|
| 3602 |
-
# Send product details as text
|
| 3603 |
-
send_whatsjet_message(from_number, details)
|
| 3604 |
-
return
|
| 3605 |
-
else:
|
| 3606 |
-
logger.warning(f"[Product] Failed to send image, sending text only")
|
| 3607 |
-
send_whatsjet_message(from_number, details)
|
| 3608 |
-
return
|
| 3609 |
-
# Otherwise, treat as local file
|
| 3610 |
-
elif os.path.exists(image_path):
|
| 3611 |
-
logger.info(f"[Product] Sending local file with caption: {image_path}")
|
| 3612 |
-
send_whatsjet_message(
|
| 3613 |
-
from_number,
|
| 3614 |
-
details,
|
| 3615 |
-
media_type=media_type,
|
| 3616 |
-
media_path=image_path,
|
| 3617 |
-
filename=filename
|
| 3618 |
-
)
|
| 3619 |
-
return
|
| 3620 |
-
# No image available, send text only
|
| 3621 |
-
logger.info(f"[Product] No image available, sending text only for: {product_name}")
|
| 3622 |
-
send_whatsjet_message(from_number, details)
|
| 3623 |
-
except Exception as e:
|
| 3624 |
-
logger.error(f"[Product] Error sending product image with caption: {e}")
|
| 3625 |
-
logger.info(f"[Product] Falling back to text-only message for: {product_name}")
|
| 3626 |
-
send_whatsjet_message(from_number, details)
|
| 3627 |
-
|
| 3628 |
if __name__ == "__main__":
|
| 3629 |
# Load products data on startup
|
| 3630 |
load_products_data()
|
|
|
|
| 2760 |
"""
|
| 2761 |
Send product image (if available) with product details as caption in a single WhatsApp message.
|
| 2762 |
If image is not available, send only the product details as text.
|
|
|
|
| 2763 |
"""
|
| 2764 |
ensure_images_dir()
|
| 2765 |
product_name = product.get('Product Name', 'Unknown Product')
|
| 2766 |
details = generate_veterinary_product_response(product, user_context)
|
| 2767 |
+
logger.info(f"[DEBUG] About to look up image for product: {product_name}")
|
| 2768 |
+
image_path = get_product_image_path(product_name)
|
| 2769 |
+
if image_path and image_path.startswith('http'):
|
| 2770 |
+
media_type = get_product_image_media_type(image_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2771 |
filename = f"{product_name.replace(' ', '_')}.jpg"
|
| 2772 |
+
logger.info(f"[Product] Sending public image URL with caption: {image_path}")
|
| 2773 |
success = send_whatsjet_message(
|
| 2774 |
from_number,
|
| 2775 |
details,
|
| 2776 |
media_type=media_type,
|
| 2777 |
+
media_path=image_path,
|
| 2778 |
filename=filename
|
| 2779 |
)
|
|
|
|
| 2780 |
if success:
|
| 2781 |
+
logger.info(f"[Product] Successfully sent image+caption for product: {product_name}")
|
| 2782 |
return
|
| 2783 |
+
else:
|
| 2784 |
+
logger.warning(f"[Product] Failed to send image+caption, sending text only: {product_name}")
|
| 2785 |
+
send_whatsjet_message(from_number, details)
|
| 2786 |
+
return
|
| 2787 |
+
# No image available, send text only
|
| 2788 |
+
logger.info(f"[Product] No image available, sending text only for: {product_name}")
|
| 2789 |
+
send_whatsjet_message(from_number, details)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2790 |
|
| 2791 |
# Test endpoint for product image with caption
|
| 2792 |
@app.get("/test-product-image-with-caption")
|
|
|
|
| 3385 |
send_whatsjet_message(from_number,
|
| 3386 |
"❌ Error processing voice message. Please try a text message.")
|
| 3387 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3388 |
if __name__ == "__main__":
|
| 3389 |
# Load products data on startup
|
| 3390 |
load_products_data()
|