| import httpx |
|
|
| from app.config import Settings |
|
|
|
|
| class WhatsAppClientError(RuntimeError): |
| pass |
|
|
|
|
| class WhatsAppClient: |
| def __init__(self, settings: Settings, client: httpx.AsyncClient | None = None) -> None: |
| self._settings = settings |
| self._client = client |
|
|
| @property |
| def _messages_url(self) -> str: |
| base = self._settings.whatsapp_graph_url.rstrip("/") |
| version = self._settings.whatsapp_api_version.strip("/") |
| phone_number_id = self._settings.whatsapp_phone_number_id |
| print(base) |
| return f"{base}/{version}/{phone_number_id}/messages" |
|
|
| async def send_text(self, remoteJid: str, text: str) -> dict: |
| payload = { |
| "messaging_product": "whatsapp", |
| "recipient_type": "individual", |
| "to": remoteJid, |
| "type": "text", |
| "text": {"preview_url": False, "body": text}, |
| } |
| headers = { |
| "Authorization": f"Bearer {self._settings.whatsapp_access_token}", |
| "Content-Type": "application/json", |
| } |
|
|
| if self._client is not None: |
| response = await self._client.post(self._messages_url, json=payload, headers=headers) |
| else: |
| async with httpx.AsyncClient(timeout=self._settings.request_timeout_seconds) as client: |
| response = await client.post(self._messages_url, json=payload, headers=headers) |
|
|
| if response.status_code >= 400: |
| raise WhatsAppClientError( |
| f"WhatsApp API failed with {response.status_code}: {response.text}" |
| ) |
|
|
| return response.json() |
|
|
| async def send_interactive_list( |
| self, |
| remoteJid: str, |
| interactive: dict[str, Any], |
| ) -> dict: |
| payload = { |
| "messaging_product": "whatsapp", |
| "recipient_type": "individual", |
| "to": remoteJid, |
| "type": "interactive", |
| "interactive": interactive, |
| } |
| headers = { |
| "Authorization": f"Bearer {self._settings.whatsapp_access_token}", |
| "Content-Type": "application/json", |
| } |
|
|
| if self._client is not None: |
| response = await self._client.post(self._messages_url, json=payload, headers=headers) |
| else: |
| async with httpx.AsyncClient(timeout=self._settings.request_timeout_seconds) as client: |
| response = await client.post(self._messages_url, json=payload, headers=headers) |
|
|
| if response.status_code >= 400: |
| raise WhatsAppClientError( |
| f"WhatsApp API failed with {response.status_code}: {response.text}" |
| ) |
|
|
| return response.json() |
|
|