mehfooz-backend / backend /src /utils /notifications.py
krishbaresha's picture
Final attempt to fix Meta timeout with headers
423ffd6
import httpx
import resend
from src.config.settings import settings
from loguru import logger
if settings.RESEND_API_KEY:
resend.api_key = settings.RESEND_API_KEY.get_secret_value()
else:
logger.warning("RESEND_API_KEY not configured. Email notifications will be disabled.")
from twilio.rest import Client
def _meta_configured() -> bool:
"""Check if Meta API credentials are properly set."""
return bool(
settings.META_ACCESS_TOKEN
and settings.META_PHONE_NUMBER_ID
and settings.META_ACCESS_TOKEN.get_secret_value() != "placeholder"
)
def _twilio_configured() -> bool:
"""Check if Twilio credentials are properly set."""
return bool(
settings.TWILIO_ACCOUNT_SID
and settings.TWILIO_AUTH_TOKEN
and settings.TWILIO_WHATSAPP_NUMBER
)
async def send_whatsapp_reply(to_number: str, message: str):
"""
Send a WhatsApp reply via Meta Cloud API.
"""
if _meta_configured():
clean_number = to_number.replace("whatsapp:", "").replace("+", "")
# Mask the token for logs but check if it's there
token_preview = f"{settings.META_ACCESS_TOKEN.get_secret_value()[:10]}..." if settings.META_ACCESS_TOKEN else "MISSING"
url = f"https://graph.facebook.com/v21.0/{settings.META_PHONE_NUMBER_ID}/messages"
logger.info(f"πŸ”— Meta Request: URL={url} | Phone={clean_number} | Token={token_preview}")
headers = {
"Authorization": f"Bearer {settings.META_ACCESS_TOKEN.get_secret_value()}",
"Content-Type": "application/json",
"User-Agent": "MehfoozAI/1.0",
"Accept": "application/json"
}
data = {
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": clean_number,
"type": "text",
"text": {"body": message}
}
import requests
session = requests.Session()
for attempt in range(1, 4): # Try 3 times
try:
logger.info(f"πŸ“€ [Attempt {attempt}] Sending to {clean_number}...")
response = session.post(url, headers=headers, json=data, timeout=15)
if response.status_code in (200, 201, 202):
logger.info(f"βœ… WhatsApp reply SUCCESS for {clean_number}")
return
logger.error(f"❌ Meta API Error {response.status_code}: {response.text}")
if response.status_code in (401, 403):
logger.error("πŸ›‘ Auth Error. Check Token/Permissions.")
return
# On 500 or 429, we might want to retry
except requests.exceptions.Timeout:
logger.warning(f"⏳ Timeout on attempt {attempt} (15s). Retrying...")
except Exception as e:
logger.error(f"πŸ’₯ Connection Error on attempt {attempt}: {type(e).__name__} - {str(e)}")
import time
time.sleep(1) # Small gap between retries
else:
logger.error("❌ Meta API not configured. Check META_ACCESS_TOKEN and META_PHONE_NUMBER_ID in .env")
def send_case_confirmation(to_number: str, case_id: str, routing: dict) -> str:
"""Returns formatted case confirmation text (used as TwiML body)."""
authority = routing.get("primary_authority", "Nearest Police Station")
support = routing.get("secondary_support", "Madadgaar 15")
return (
f"πŸ›‘οΈ *MehfoozAI* β€” Report Received Anonymously\n\n"
f"πŸ“‹ *Case ID:* `{case_id}`\n"
f"_(Save this to track your case)_\n\n"
f"βœ… *FIR drafted* with relevant PPC sections\n"
f"πŸš” *Routed to:* {authority}\n"
f"πŸ’™ *Support:* {support}\n\n"
f"πŸ’¬ To check status, reply: *STATUS {case_id}*\n\n"
f"_Her awaz suni jaayegi β€” anonymously, safely._"
)