Spaces:
Runtime error
Runtime error
| """OpenWA Python SDK β client core. | |
| The :class:`OpenWAClient` is the single entry point. It owns an | |
| :class:`HttpExecutor` (which wraps :class:`httpx.Client` with an injectable | |
| transport) and exposes domain resources as properties:: | |
| from openwa import OpenWAClient | |
| client = OpenWAClient( | |
| base_url="http://localhost:2785", | |
| api_key="owa_k1_β¦", | |
| ) | |
| client.sessions.start("my-session") | |
| client.messages.send_text("my-session", { | |
| "chatId": "628123456789@c.us", | |
| "text": "Hello from the OpenWA SDK!", | |
| }) | |
| Pass ``transport=httpx.MockTransport(handler)`` for testability β no global | |
| monkey-patching required. | |
| """ | |
| from __future__ import annotations | |
| import warnings | |
| from types import TracebackType | |
| from typing import Any, Mapping | |
| from urllib.parse import urlparse | |
| import httpx | |
| from ._http import HttpExecutor, HttpMethod | |
| from .resources import ( | |
| CallsResource, | |
| CatalogResource, | |
| ChannelsResource, | |
| ChatsResource, | |
| ContactsResource, | |
| GroupsResource, | |
| HealthResource, | |
| LabelsResource, | |
| MessagesResource, | |
| ProfileResource, | |
| SearchResource, | |
| SessionsResource, | |
| StatusResource, | |
| TemplatesResource, | |
| WebhooksResource, | |
| ) | |
| from .types import AuthValidateResponse | |
| _LOCALHOST_HOSTS = {"localhost", "127.0.0.1", "::1"} | |
| def _warn_if_insecure_http(url: str) -> None: | |
| """Warn (not raise) when base_url is http:// and the host is not localhost. | |
| The API key is sent as an X-API-Key header on every request β over plaintext http | |
| to a non-local host that's cleartext on the wire. Warning (not refusing) keeps local | |
| dev and TLS-terminating-proxy topologies working. | |
| """ | |
| try: | |
| parsed = urlparse(url) | |
| host = (parsed.hostname or "").strip("[]") | |
| if parsed.scheme == "http" and host not in _LOCALHOST_HOSTS: | |
| warnings.warn( | |
| f"OpenWAClient: base_url uses an insecure http:// URL (host: {host}). " | |
| "The API key will be sent in cleartext. Use https:// in production.", | |
| stacklevel=3, | |
| ) | |
| except Exception: | |
| pass | |
| class OpenWAClient: | |
| def __init__( | |
| self, | |
| base_url: str, | |
| api_key: str, | |
| *, | |
| timeout: float = 30.0, | |
| default_headers: Mapping[str, str] | None = None, | |
| transport: httpx.BaseTransport | None = None, | |
| ) -> None: | |
| if not base_url: | |
| raise ValueError("OpenWAClient: base_url is required") | |
| if not api_key: | |
| raise ValueError("OpenWAClient: api_key is required") | |
| _warn_if_insecure_http(base_url) | |
| self._http = HttpExecutor( | |
| base_url=base_url, | |
| api_key=api_key, | |
| timeout=timeout, | |
| default_headers=default_headers, | |
| transport=transport, | |
| ) | |
| # ββ Resources ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def sessions(self) -> SessionsResource: | |
| return SessionsResource(self._http) | |
| def messages(self) -> MessagesResource: | |
| return MessagesResource(self._http) | |
| def contacts(self) -> ContactsResource: | |
| return ContactsResource(self._http) | |
| def groups(self) -> GroupsResource: | |
| return GroupsResource(self._http) | |
| def webhooks(self) -> WebhooksResource: | |
| return WebhooksResource(self._http) | |
| def chats(self) -> ChatsResource: | |
| return ChatsResource(self._http) | |
| def status(self) -> StatusResource: | |
| return StatusResource(self._http) | |
| def health(self) -> HealthResource: | |
| return HealthResource(self._http) | |
| def labels(self) -> LabelsResource: | |
| return LabelsResource(self._http) | |
| def channels(self) -> ChannelsResource: | |
| return ChannelsResource(self._http) | |
| def catalog(self) -> CatalogResource: | |
| return CatalogResource(self._http) | |
| def templates(self) -> TemplatesResource: | |
| return TemplatesResource(self._http) | |
| def search(self) -> SearchResource: | |
| return SearchResource(self._http) | |
| def profile(self) -> ProfileResource: | |
| return ProfileResource(self._http) | |
| def calls(self) -> CallsResource: | |
| return CallsResource(self._http) | |
| # ββ Auth βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def auth(self) -> AuthValidateResponse: | |
| return self._http.request("POST", "/api/auth/validate") | |
| # ββ Raw request escape hatch βββββββββββββββββββββββββββββββββββββ | |
| def request( | |
| self, | |
| method: str, | |
| path: str, | |
| *, | |
| query: Mapping[str, Any] | None = None, | |
| body: Any = None, | |
| ) -> Any: | |
| """Issue a raw request against the API (advanced use). ``path`` begins with ``/``.""" | |
| return self._http.request(method, path, query=query, body=body) | |
| # ββ Lifecycle ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def close(self) -> None: | |
| self._http.close() | |
| def __enter__(self) -> "OpenWAClient": | |
| return self | |
| def __exit__(self, *exc: Any) -> None: | |
| self.close() | |