""" Evolution API (https://github.com/EvolutionAPI/evolution-api) adapter. """ import httpx from typing import Any, Dict, List, Optional from .comms_provider import CommsProvider class EvolutionProvider(CommsProvider): def _headers(self) -> Dict[str, str]: return {"Content-Type": "application/json", "apikey": self.api_key} async def _request(self, method: str, path: str, json_data: Optional[Dict] = None) -> Dict[str, Any]: url = f"{self.base_url}{path}" async with httpx.AsyncClient(timeout=30.0) as client: resp = await client.request(method, url, headers=self._headers(), json=json_data) resp.raise_for_status() return resp.json() async def send_message(self, phone: str, message: str, message_type: str = "text", **kwargs) -> Dict[str, Any]: instance = self.instance_id or "default" payload = { "number": phone, "text": message, "options": {"delay": 1200, "presence": "composing"}, } result = await self._request("POST", f"/message/sendText/{instance}", payload) ext_id = result.get("key", {}).get("id") if isinstance(result, dict) else None return { "success": True, "provider": "evolution", "external_message_id": ext_id, "status": "sent", "raw": result, } async def normalize_webhook(self, payload: Dict[str, Any]) -> Dict[str, Any]: """ Evolution webhook v2 shape: { "event": "messages.upsert", "instance": "default", "data": { "key": {"remoteJid": "123@s.whatsapp.net", "fromMe": false, "id": "..."}, "message": {"conversation": "Hello"}, "messageTimestamp": 1710000000, ... } } """ event = payload.get("event", "") data = payload.get("data", {}) key = data.get("key", {}) remote_jid = key.get("remoteJid", "") phone = remote_jid.replace("@s.whatsapp.net", "").replace("@g.us", "") msg_content = data.get("message", {}) body = msg_content.get("conversation", "") or msg_content.get("extendedTextMessage", {}).get("text", "") direction = "outbound" if key.get("fromMe") else "inbound" return { "provider": "evolution", "external_message_id": key.get("id"), "phone_e164": phone, "direction": direction, "message_type": "text", "body": body, "media_url": None, "raw": payload, "timestamp": data.get("messageTimestamp"), } async def test_connection(self) -> Dict[str, Any]: try: instance = self.instance_id or "default" info = await self._request("GET", f"/instance/connectionState/{instance}") return { "success": True, "message": f"Evolution instance '{instance}' state retrieved.", "account_info": info, } except Exception as exc: return { "success": False, "message": f"Evolution connection failed: {exc}", } async def fetch_templates(self) -> List[Dict[str, Any]]: return []