import logging from typing import Any from sqlalchemy.orm import Session from .models import WhatsAppWebhookEvent logger = logging.getLogger(__name__) def _extract_events(payload: dict[str, Any]) -> list[dict[str, Any]]: events: list[dict[str, Any]] = [] if payload.get("object") != "whatsapp_business_account": return events for entry in payload.get("entry", []): waba_id = entry.get("id") for change in entry.get("changes", []): field = change.get("field", "unknown") value = change.get("value", {}) phone_number_id = (value.get("metadata") or {}).get("phone_number_id") if field == "messages": for message in value.get("messages", []): events.append( { "waba_id": waba_id, "phone_number_id": phone_number_id, "field": field, "event_type": "message", "from_wa_id": message.get("from"), "message_id": message.get("id"), "status": message.get("type"), "payload": change, } ) for status in value.get("statuses", []): events.append( { "waba_id": waba_id, "phone_number_id": phone_number_id, "field": field, "event_type": "status", "from_wa_id": status.get("recipient_id"), "message_id": status.get("id"), "status": status.get("status"), "payload": change, } ) else: events.append( { "waba_id": waba_id, "phone_number_id": phone_number_id, "field": field, "event_type": field, "from_wa_id": None, "message_id": None, "status": None, "payload": change, } ) return events def persist_webhook_payload(db: Session, payload: dict[str, Any]) -> int: events = _extract_events(payload) if not events: events = [ { "waba_id": None, "phone_number_id": None, "field": "unknown", "event_type": "raw", "from_wa_id": None, "message_id": None, "status": None, "payload": payload, } ] for event in events: db.add( WhatsAppWebhookEvent( waba_id=event.get("waba_id"), phone_number_id=event.get("phone_number_id"), field=event["field"], event_type=event["event_type"], from_wa_id=event.get("from_wa_id"), message_id=event.get("message_id"), status=event.get("status"), payload=event["payload"], ) ) db.commit() logger.info("Stored %s WhatsApp webhook event(s)", len(events)) return len(events)