Files
PecHub/worker/app/notifications/whatsapp.py
T
2026-03-27 15:13:14 +01:00

74 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
WhatsApp sender (worker) Meta Cloud API v18.
Copia del sender backend: i due container sono separati.
"""
import httpx
META_GRAPH_API_URL = "https://graph.facebook.com/v18.0"
DEFAULT_TIMEOUT = 10.0
class WhatsAppError(Exception):
def __init__(self, message: str, http_status: int | None = None, api_code: int | None = None):
super().__init__(message)
self.http_status = http_status
self.api_code = api_code
async def send_whatsapp_message(
phone_number_id: str,
to_phone: str,
text: str,
access_token: str,
timeout: float = DEFAULT_TIMEOUT,
) -> dict:
"""
Invia un messaggio di testo WhatsApp via Meta Cloud API.
Raises:
WhatsAppError: in caso di errore HTTP o risposta API non-ok
"""
url = f"{META_GRAPH_API_URL}/{phone_number_id}/messages"
payload = {
"messaging_product": "whatsapp",
"to": to_phone.replace(" ", "").replace("-", ""),
"type": "text",
"text": {"body": text},
}
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
}
async with httpx.AsyncClient(timeout=timeout) as client:
try:
response = await client.post(url, json=payload, headers=headers)
except httpx.TimeoutException as exc:
raise WhatsAppError(f"Timeout WhatsApp API dopo {timeout}s") from exc
except httpx.RequestError as exc:
raise WhatsAppError(f"Errore di rete WhatsApp: {exc}") from exc
if response.status_code == 401:
raise WhatsAppError("Token Meta non valido o scaduto", http_status=401)
if response.status_code >= 400:
try:
err_data = response.json()
err_msg = err_data.get("error", {}).get("message", response.text[:200])
err_code = err_data.get("error", {}).get("code")
except Exception:
err_msg = response.text[:200]
err_code = None
raise WhatsAppError(
f"Meta API errore HTTP {response.status_code}: {err_msg}",
http_status=response.status_code,
api_code=err_code,
)
data = response.json()
messages = data.get("messages", [])
message_id = messages[0].get("id") if messages else None
return {"message_id": message_id, "http_status": response.status_code}