whatsapp-cloud-api-client 0.2.0__tar.gz

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.
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.4
2
+ Name: whatsapp-cloud-api-client
3
+ Version: 0.2.0
4
+ Summary: Biblioteca Python para integração com a API Oficial do WhatsApp (Cloud API).
5
+ Author: Seu Nome
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/seu-usuario/whatsapp-cloud-api-client
8
+ Project-URL: Documentation, https://github.com/seu-usuario/whatsapp-cloud-api-client#readme
9
+ Project-URL: Issues, https://github.com/seu-usuario/whatsapp-cloud-api-client/issues
10
+ Keywords: whatsapp,whatsapp cloud api,meta,messaging,python
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: httpx<1.0.0,>=0.27.0
23
+ Requires-Dist: pydantic<3.0.0,>=2.7.0
24
+ Requires-Dist: eval-type-backport>=0.2.0; python_version < "3.10"
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest<9.0.0,>=8.2.0; extra == "dev"
27
+ Requires-Dist: pytest-asyncio<1.0.0,>=0.23.7; extra == "dev"
28
+
29
+ # WhatsApp Cloud API Client (Python)
30
+
31
+ Biblioteca Python para integracao com a API Oficial do WhatsApp (Cloud API), com foco em simplicidade de uso em apps.
32
+
33
+ ## Instalacao
34
+
35
+ ```bash
36
+ pip install whatsapp-cloud-api-client
37
+ ```
38
+
39
+ Para desenvolvimento local:
40
+
41
+ ```bash
42
+ pip install -e ".[dev]"
43
+ ```
44
+
45
+ ## Uso rapido (sync)
46
+
47
+ ```python
48
+ from whatsapp_cloud_api import WhatsAppClient
49
+
50
+ client = WhatsAppClient(
51
+ access_token="SEU_TOKEN",
52
+ phone_number_id="SEU_PHONE_NUMBER_ID",
53
+ )
54
+
55
+ resp = client.send_text(
56
+ to="5511999999999",
57
+ body="Ola! Mensagem enviada via Cloud API.",
58
+ )
59
+ print(resp.model_dump())
60
+ ```
61
+
62
+ ## Uso rapido (async)
63
+
64
+ ```python
65
+ import asyncio
66
+ from whatsapp_cloud_api import AsyncWhatsAppClient
67
+
68
+
69
+ async def main() -> None:
70
+ async with AsyncWhatsAppClient(
71
+ access_token="SEU_TOKEN",
72
+ phone_number_id="SEU_PHONE_NUMBER_ID",
73
+ ) as client:
74
+ resp = await client.send_text(
75
+ to="5511999999999",
76
+ body="Mensagem async",
77
+ )
78
+ print(resp.model_dump())
79
+
80
+
81
+ asyncio.run(main())
82
+ ```
83
+
84
+ ## Modelos tipados (Pydantic)
85
+
86
+ Os metodos retornam modelos Pydantic:
87
+
88
+ - `SendMessageResponse`
89
+ - `MediaUploadResponse`
90
+ - `MediaInfoResponse`
91
+ - `MarkAsReadResponse`
92
+
93
+ ## Retry, backoff e rate limit
94
+
95
+ O cliente possui retry configuravel para erros transientes (`429`, `500`, `502`, `503`, `504`).
96
+
97
+ Por padrao, retry roda apenas para `GET` para evitar duplicidade em envio de mensagem (`POST`).
98
+
99
+ ```python
100
+ from whatsapp_cloud_api import WhatsAppClient
101
+
102
+ client = WhatsAppClient(
103
+ access_token="SEU_TOKEN",
104
+ phone_number_id="SEU_PHONE_NUMBER_ID",
105
+ max_retries=3,
106
+ backoff_factor=0.5,
107
+ max_backoff=8.0,
108
+ retry_methods={"GET", "POST"}, # habilite POST se quiser retry em envio
109
+ )
110
+ ```
111
+
112
+ Se a API retornar `Retry-After`, esse valor sera respeitado.
113
+
114
+ ## Funcionalidades implementadas
115
+
116
+ - Envio de mensagem de texto
117
+ - Envio de mensagem template
118
+ - Envio de midia por `media_id` ou `link` (imagem, documento, video, audio, sticker)
119
+ - Upload de midia
120
+ - Marcar mensagem como lida
121
+ - Busca de informacoes de midia
122
+ - Validacao de assinatura de webhook (`X-Hub-Signature-256`)
123
+ - Cliente sincrono e assincrono
124
+
125
+ ## Exemplo com Flask (webhook)
126
+
127
+ ```python
128
+ from flask import Flask, request, jsonify
129
+ from whatsapp_cloud_api import verify_webhook_signature, verify_webhook_challenge
130
+
131
+ app = Flask(__name__)
132
+ APP_SECRET = "SEU_APP_SECRET"
133
+ VERIFY_TOKEN = "SEU_VERIFY_TOKEN"
134
+
135
+
136
+ @app.get("/webhook")
137
+ def webhook_verify():
138
+ ok, challenge = verify_webhook_challenge(
139
+ mode=request.args.get("hub.mode"),
140
+ token=request.args.get("hub.verify_token"),
141
+ challenge=request.args.get("hub.challenge"),
142
+ verify_token=VERIFY_TOKEN,
143
+ )
144
+ if not ok:
145
+ return "forbidden", 403
146
+ return challenge, 200
147
+
148
+
149
+ @app.post("/webhook")
150
+ def webhook_receive():
151
+ if not verify_webhook_signature(
152
+ app_secret=APP_SECRET,
153
+ raw_body=request.get_data(),
154
+ x_hub_signature_256=request.headers.get("X-Hub-Signature-256", ""),
155
+ ):
156
+ return "invalid signature", 401
157
+
158
+ data = request.get_json(silent=True) or {}
159
+ return jsonify({"ok": True, "received": bool(data)}), 200
160
+ ```
161
+
162
+ ## Rodar testes
163
+
164
+ ```bash
165
+ pytest
166
+ ```
167
+
168
+ ## CI e publicacao
169
+
170
+ - CI: `.github/workflows/ci.yml`
171
+ - Criacao de tag/release: `.github/workflows/release.yml`
172
+ - Publicacao PyPI: `.github/workflows/publish.yml`
173
+
174
+ Fluxo recomendado:
175
+
176
+ 1. Execute o workflow `Create Release` e informe a tag (ex: `v0.2.0`).
177
+ 2. O release publicado dispara `Publish to PyPI`.
178
+ 3. Configure Trusted Publisher no PyPI para este repositorio (OIDC), sem token manual.
179
+
180
+ Opcional: se preferir token, adapte o workflow para usar `PYPI_API_TOKEN`.
181
+
182
+ ## Licenca
183
+
184
+ MIT
@@ -0,0 +1,156 @@
1
+ # WhatsApp Cloud API Client (Python)
2
+
3
+ Biblioteca Python para integracao com a API Oficial do WhatsApp (Cloud API), com foco em simplicidade de uso em apps.
4
+
5
+ ## Instalacao
6
+
7
+ ```bash
8
+ pip install whatsapp-cloud-api-client
9
+ ```
10
+
11
+ Para desenvolvimento local:
12
+
13
+ ```bash
14
+ pip install -e ".[dev]"
15
+ ```
16
+
17
+ ## Uso rapido (sync)
18
+
19
+ ```python
20
+ from whatsapp_cloud_api import WhatsAppClient
21
+
22
+ client = WhatsAppClient(
23
+ access_token="SEU_TOKEN",
24
+ phone_number_id="SEU_PHONE_NUMBER_ID",
25
+ )
26
+
27
+ resp = client.send_text(
28
+ to="5511999999999",
29
+ body="Ola! Mensagem enviada via Cloud API.",
30
+ )
31
+ print(resp.model_dump())
32
+ ```
33
+
34
+ ## Uso rapido (async)
35
+
36
+ ```python
37
+ import asyncio
38
+ from whatsapp_cloud_api import AsyncWhatsAppClient
39
+
40
+
41
+ async def main() -> None:
42
+ async with AsyncWhatsAppClient(
43
+ access_token="SEU_TOKEN",
44
+ phone_number_id="SEU_PHONE_NUMBER_ID",
45
+ ) as client:
46
+ resp = await client.send_text(
47
+ to="5511999999999",
48
+ body="Mensagem async",
49
+ )
50
+ print(resp.model_dump())
51
+
52
+
53
+ asyncio.run(main())
54
+ ```
55
+
56
+ ## Modelos tipados (Pydantic)
57
+
58
+ Os metodos retornam modelos Pydantic:
59
+
60
+ - `SendMessageResponse`
61
+ - `MediaUploadResponse`
62
+ - `MediaInfoResponse`
63
+ - `MarkAsReadResponse`
64
+
65
+ ## Retry, backoff e rate limit
66
+
67
+ O cliente possui retry configuravel para erros transientes (`429`, `500`, `502`, `503`, `504`).
68
+
69
+ Por padrao, retry roda apenas para `GET` para evitar duplicidade em envio de mensagem (`POST`).
70
+
71
+ ```python
72
+ from whatsapp_cloud_api import WhatsAppClient
73
+
74
+ client = WhatsAppClient(
75
+ access_token="SEU_TOKEN",
76
+ phone_number_id="SEU_PHONE_NUMBER_ID",
77
+ max_retries=3,
78
+ backoff_factor=0.5,
79
+ max_backoff=8.0,
80
+ retry_methods={"GET", "POST"}, # habilite POST se quiser retry em envio
81
+ )
82
+ ```
83
+
84
+ Se a API retornar `Retry-After`, esse valor sera respeitado.
85
+
86
+ ## Funcionalidades implementadas
87
+
88
+ - Envio de mensagem de texto
89
+ - Envio de mensagem template
90
+ - Envio de midia por `media_id` ou `link` (imagem, documento, video, audio, sticker)
91
+ - Upload de midia
92
+ - Marcar mensagem como lida
93
+ - Busca de informacoes de midia
94
+ - Validacao de assinatura de webhook (`X-Hub-Signature-256`)
95
+ - Cliente sincrono e assincrono
96
+
97
+ ## Exemplo com Flask (webhook)
98
+
99
+ ```python
100
+ from flask import Flask, request, jsonify
101
+ from whatsapp_cloud_api import verify_webhook_signature, verify_webhook_challenge
102
+
103
+ app = Flask(__name__)
104
+ APP_SECRET = "SEU_APP_SECRET"
105
+ VERIFY_TOKEN = "SEU_VERIFY_TOKEN"
106
+
107
+
108
+ @app.get("/webhook")
109
+ def webhook_verify():
110
+ ok, challenge = verify_webhook_challenge(
111
+ mode=request.args.get("hub.mode"),
112
+ token=request.args.get("hub.verify_token"),
113
+ challenge=request.args.get("hub.challenge"),
114
+ verify_token=VERIFY_TOKEN,
115
+ )
116
+ if not ok:
117
+ return "forbidden", 403
118
+ return challenge, 200
119
+
120
+
121
+ @app.post("/webhook")
122
+ def webhook_receive():
123
+ if not verify_webhook_signature(
124
+ app_secret=APP_SECRET,
125
+ raw_body=request.get_data(),
126
+ x_hub_signature_256=request.headers.get("X-Hub-Signature-256", ""),
127
+ ):
128
+ return "invalid signature", 401
129
+
130
+ data = request.get_json(silent=True) or {}
131
+ return jsonify({"ok": True, "received": bool(data)}), 200
132
+ ```
133
+
134
+ ## Rodar testes
135
+
136
+ ```bash
137
+ pytest
138
+ ```
139
+
140
+ ## CI e publicacao
141
+
142
+ - CI: `.github/workflows/ci.yml`
143
+ - Criacao de tag/release: `.github/workflows/release.yml`
144
+ - Publicacao PyPI: `.github/workflows/publish.yml`
145
+
146
+ Fluxo recomendado:
147
+
148
+ 1. Execute o workflow `Create Release` e informe a tag (ex: `v0.2.0`).
149
+ 2. O release publicado dispara `Publish to PyPI`.
150
+ 3. Configure Trusted Publisher no PyPI para este repositorio (OIDC), sem token manual.
151
+
152
+ Opcional: se preferir token, adapte o workflow para usar `PYPI_API_TOKEN`.
153
+
154
+ ## Licenca
155
+
156
+ MIT
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69.5.1", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "whatsapp-cloud-api-client"
7
+ version = "0.2.0"
8
+ description = "Biblioteca Python para integração com a API Oficial do WhatsApp (Cloud API)."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.9"
12
+ authors = [
13
+ { name = "Seu Nome" }
14
+ ]
15
+ keywords = ["whatsapp", "whatsapp cloud api", "meta", "messaging", "python"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ ]
27
+ dependencies = [
28
+ "httpx>=0.27.0,<1.0.0",
29
+ "pydantic>=2.7.0,<3.0.0",
30
+ "eval-type-backport>=0.2.0; python_version < '3.10'",
31
+ ]
32
+
33
+ [project.urls]
34
+ Homepage = "https://github.com/seu-usuario/whatsapp-cloud-api-client"
35
+ Documentation = "https://github.com/seu-usuario/whatsapp-cloud-api-client#readme"
36
+ Issues = "https://github.com/seu-usuario/whatsapp-cloud-api-client/issues"
37
+
38
+ [project.optional-dependencies]
39
+ dev = [
40
+ "pytest>=8.2.0,<9.0.0",
41
+ "pytest-asyncio>=0.23.7,<1.0.0",
42
+ ]
43
+
44
+ [tool.setuptools]
45
+ package-dir = {"" = "src"}
46
+
47
+ [tool.setuptools.packages.find]
48
+ where = ["src"]
49
+
50
+ [tool.pytest.ini_options]
51
+ testpaths = ["tests"]
52
+ asyncio_default_fixture_loop_scope = "function"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,21 @@
1
+ from .client import AsyncWhatsAppClient, WhatsAppClient
2
+ from .exceptions import WhatsAppAPIError
3
+ from .models import (
4
+ MarkAsReadResponse,
5
+ MediaInfoResponse,
6
+ MediaUploadResponse,
7
+ SendMessageResponse,
8
+ )
9
+ from .webhook import verify_webhook_challenge, verify_webhook_signature
10
+
11
+ __all__ = [
12
+ "AsyncWhatsAppClient",
13
+ "WhatsAppClient",
14
+ "WhatsAppAPIError",
15
+ "SendMessageResponse",
16
+ "MediaUploadResponse",
17
+ "MediaInfoResponse",
18
+ "MarkAsReadResponse",
19
+ "verify_webhook_challenge",
20
+ "verify_webhook_signature",
21
+ ]