waapi 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
waapi/__init__.py ADDED
@@ -0,0 +1,33 @@
1
+ """Official Python SDK for the WaAPI REST API.
2
+
3
+ from waapi import WaAPI
4
+
5
+ client = WaAPI(token="YOUR_TOKEN", instance_id=123)
6
+ client.send_message(chat_id="4915112345678@c.us", message="Hello")
7
+ """
8
+
9
+ __version__ = "0.1.0"
10
+
11
+ from .client import AsyncWaAPI, WaAPI
12
+ from .exceptions import (
13
+ AuthenticationError,
14
+ FailedActionError,
15
+ NotFoundError,
16
+ RateLimitError,
17
+ ServerError,
18
+ ValidationError,
19
+ WaAPIError,
20
+ )
21
+
22
+ __all__ = [
23
+ "AsyncWaAPI",
24
+ "AuthenticationError",
25
+ "FailedActionError",
26
+ "NotFoundError",
27
+ "RateLimitError",
28
+ "ServerError",
29
+ "ValidationError",
30
+ "WaAPI",
31
+ "WaAPIError",
32
+ "__version__",
33
+ ]
waapi/_actions.py ADDED
@@ -0,0 +1,152 @@
1
+ """Hand-written client methods.
2
+
3
+ Everything under ``/client/action/`` is generated into :mod:`waapi._generated`
4
+ from the OpenAPI specification and composed in below. This module holds only
5
+ what the generator does not cover: the instance endpoints, which are ordinary
6
+ REST routes rather than actions, and the generic escape hatch every generated
7
+ method is built on.
8
+
9
+ Add a method here only if it cannot come from the spec. Anything added here by
10
+ hand is one more place a future API change has to reach.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import TYPE_CHECKING, Any
16
+
17
+ from ._generated import GeneratedActions, GeneratedAsyncActions
18
+ from ._http import prune
19
+
20
+
21
+ class _Shared:
22
+ """Path construction, and the client contract the mixins rely on.
23
+
24
+ ``request`` and ``_resolve_instance`` live on the client. Declaring them
25
+ under TYPE_CHECKING states the contract for the type checker without
26
+ creating runtime attributes that could shadow the real ones through the
27
+ MRO.
28
+ """
29
+
30
+ if TYPE_CHECKING:
31
+
32
+ def _resolve_instance(self, instance_id: int | str | None) -> int | str: ...
33
+
34
+ @staticmethod
35
+ def _action_path(instance_id: int | str, name: str) -> str:
36
+ return f"/instances/{instance_id}/client/action/{name}"
37
+
38
+
39
+ class ActionsMixin(_Shared, GeneratedActions):
40
+ if TYPE_CHECKING:
41
+
42
+ def request(
43
+ self,
44
+ method: str,
45
+ path: str,
46
+ *,
47
+ json: Any = None,
48
+ params: Any = None,
49
+ check_body_status: bool = True,
50
+ ) -> Any: ...
51
+
52
+ # -- the call every generated method goes through -------------------------
53
+
54
+ def action(
55
+ self,
56
+ name: str,
57
+ payload: dict[str, Any] | None = None,
58
+ *,
59
+ instance_id: int | str | None = None,
60
+ ) -> Any:
61
+ """Call any client action by its API name.
62
+
63
+ Every generated method is a typed wrapper around this. Use it directly
64
+ for an action added to the API since the last release:
65
+
66
+ >>> client.action("send-seen", {"chatId": "4915112345678@c.us"})
67
+ """
68
+ target = self._resolve_instance(instance_id)
69
+ return self.request("POST", self._action_path(target, name), json=prune(payload or {}))
70
+
71
+ # -- instances (REST routes, not actions) ---------------------------------
72
+
73
+ def get_instances(self) -> Any:
74
+ """List the instances on your account."""
75
+ return self.request("GET", "/instances")
76
+
77
+ def create_instance(self) -> Any:
78
+ """Create a new instance."""
79
+ return self.request("POST", "/instances")
80
+
81
+ def get_instance(self, instance_id: int | str | None = None) -> Any:
82
+ """Retrieve one instance."""
83
+ return self.request("GET", f"/instances/{self._resolve_instance(instance_id)}")
84
+
85
+ def delete_instance(self, instance_id: int | str | None = None) -> Any:
86
+ """Delete an instance."""
87
+ return self.request("DELETE", f"/instances/{self._resolve_instance(instance_id)}")
88
+
89
+ def get_status(self, instance_id: int | str | None = None) -> Any:
90
+ """Connection status of the instance's client."""
91
+ return self.request("GET", f"/instances/{self._resolve_instance(instance_id)}/client/status")
92
+
93
+ def get_qr_code(self, instance_id: int | str | None = None) -> Any:
94
+ """QR code to connect a number to the instance."""
95
+ return self.request("GET", f"/instances/{self._resolve_instance(instance_id)}/client/qr")
96
+
97
+
98
+ class AsyncActionsMixin(_Shared, GeneratedAsyncActions):
99
+ """The same surface, awaited."""
100
+
101
+ if TYPE_CHECKING:
102
+
103
+ async def request(
104
+ self,
105
+ method: str,
106
+ path: str,
107
+ *,
108
+ json: Any = None,
109
+ params: Any = None,
110
+ check_body_status: bool = True,
111
+ ) -> Any: ...
112
+
113
+ async def action(
114
+ self,
115
+ name: str,
116
+ payload: dict[str, Any] | None = None,
117
+ *,
118
+ instance_id: int | str | None = None,
119
+ ) -> Any:
120
+ """Call any client action by its API name."""
121
+ target = self._resolve_instance(instance_id)
122
+ return await self.request(
123
+ "POST", self._action_path(target, name), json=prune(payload or {})
124
+ )
125
+
126
+ async def get_instances(self) -> Any:
127
+ """List the instances on your account."""
128
+ return await self.request("GET", "/instances")
129
+
130
+ async def create_instance(self) -> Any:
131
+ """Create a new instance."""
132
+ return await self.request("POST", "/instances")
133
+
134
+ async def get_instance(self, instance_id: int | str | None = None) -> Any:
135
+ """Retrieve one instance."""
136
+ return await self.request("GET", f"/instances/{self._resolve_instance(instance_id)}")
137
+
138
+ async def delete_instance(self, instance_id: int | str | None = None) -> Any:
139
+ """Delete an instance."""
140
+ return await self.request("DELETE", f"/instances/{self._resolve_instance(instance_id)}")
141
+
142
+ async def get_status(self, instance_id: int | str | None = None) -> Any:
143
+ """Connection status of the instance's client."""
144
+ return await self.request(
145
+ "GET", f"/instances/{self._resolve_instance(instance_id)}/client/status"
146
+ )
147
+
148
+ async def get_qr_code(self, instance_id: int | str | None = None) -> Any:
149
+ """QR code to connect a number to the instance."""
150
+ return await self.request(
151
+ "GET", f"/instances/{self._resolve_instance(instance_id)}/client/qr"
152
+ )