multiwa 1.0.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.
- multiwa-1.0.0/.gitignore +81 -0
- multiwa-1.0.0/LICENSE +21 -0
- multiwa-1.0.0/PKG-INFO +177 -0
- multiwa-1.0.0/README.md +142 -0
- multiwa-1.0.0/multiwa/__init__.py +31 -0
- multiwa-1.0.0/multiwa/broadcasts.py +147 -0
- multiwa-1.0.0/multiwa/client.py +173 -0
- multiwa-1.0.0/multiwa/contacts.py +172 -0
- multiwa-1.0.0/multiwa/messages.py +322 -0
- multiwa-1.0.0/multiwa/profiles.py +161 -0
- multiwa-1.0.0/multiwa/py.typed +0 -0
- multiwa-1.0.0/multiwa/types.py +159 -0
- multiwa-1.0.0/multiwa/webhooks.py +162 -0
- multiwa-1.0.0/pyproject.toml +69 -0
multiwa-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
.pnpm-store/
|
|
4
|
+
|
|
5
|
+
# Build outputs
|
|
6
|
+
dist/
|
|
7
|
+
.next/
|
|
8
|
+
.turbo/
|
|
9
|
+
*.tsbuildinfo
|
|
10
|
+
|
|
11
|
+
# TypeScript compiled output in src directories
|
|
12
|
+
apps/*/src/**/*.js
|
|
13
|
+
apps/*/src/**/*.d.ts
|
|
14
|
+
apps/*/src/**/*.d.ts.map
|
|
15
|
+
apps/*/src/**/*.js.map
|
|
16
|
+
packages/*/src/**/*.js
|
|
17
|
+
packages/*/src/**/*.d.ts
|
|
18
|
+
packages/*/src/**/*.d.ts.map
|
|
19
|
+
packages/*/src/**/*.js.map
|
|
20
|
+
|
|
21
|
+
# Environment
|
|
22
|
+
.env
|
|
23
|
+
.env.local
|
|
24
|
+
.env.*.local
|
|
25
|
+
.env.production
|
|
26
|
+
.env.staging
|
|
27
|
+
packages/database/.env
|
|
28
|
+
|
|
29
|
+
# SSL Certificates
|
|
30
|
+
*.pem
|
|
31
|
+
*.key
|
|
32
|
+
*.crt
|
|
33
|
+
docker/nginx/ssl/
|
|
34
|
+
|
|
35
|
+
# IDE
|
|
36
|
+
.vscode/
|
|
37
|
+
.idea/
|
|
38
|
+
*.swp
|
|
39
|
+
*.swo
|
|
40
|
+
|
|
41
|
+
# OS
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
44
|
+
|
|
45
|
+
# Logs
|
|
46
|
+
logs/
|
|
47
|
+
*.log
|
|
48
|
+
npm-debug.log*
|
|
49
|
+
pnpm-debug.log*
|
|
50
|
+
|
|
51
|
+
# Testing
|
|
52
|
+
coverage/
|
|
53
|
+
|
|
54
|
+
# Python cache
|
|
55
|
+
__pycache__/
|
|
56
|
+
*.pyc
|
|
57
|
+
|
|
58
|
+
# WhatsApp sessions
|
|
59
|
+
sessions/
|
|
60
|
+
.wwebjs_auth/
|
|
61
|
+
.wwebjs_cache/
|
|
62
|
+
|
|
63
|
+
# Plugins runtime data
|
|
64
|
+
plugins/*/node_modules/
|
|
65
|
+
|
|
66
|
+
# Temporary
|
|
67
|
+
.tmp/
|
|
68
|
+
tmp/
|
|
69
|
+
temp/
|
|
70
|
+
|
|
71
|
+
# Local-only working notes (never public)
|
|
72
|
+
/findings.md
|
|
73
|
+
/progress.md
|
|
74
|
+
/task_plan.md
|
|
75
|
+
/docs/superpowers/
|
|
76
|
+
|
|
77
|
+
# Internal-only operational notes and SOPs (never public)
|
|
78
|
+
/architecture/
|
|
79
|
+
|
|
80
|
+
# Docusaurus
|
|
81
|
+
docs-site/.docusaurus/
|
multiwa-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MultiWA
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
multiwa-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: multiwa
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for the MultiWA WhatsApp Business API Gateway.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ribato22/MultiWA/tree/main/packages/sdk-python#readme
|
|
6
|
+
Project-URL: Repository, https://github.com/ribato22/MultiWA
|
|
7
|
+
Project-URL: Issues, https://github.com/ribato22/MultiWA/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/ribato22/MultiWA/blob/main/CHANGELOG.md
|
|
9
|
+
Author: MultiWA Team
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: api,automation,gateway,messaging,multiwa,whatsapp,whatsapp-api
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Communications :: Chat
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Requires-Dist: httpx>=0.24.0
|
|
27
|
+
Requires-Dist: pydantic>=2.0.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# MultiWA Python SDK
|
|
37
|
+
|
|
38
|
+
Official Python SDK for [MultiWA](https://github.com/ribato22/multiwa) - WhatsApp Business API Gateway.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
The SDK is available in this repository today. Public registry publishing
|
|
43
|
+
(`multiwa` on PyPI) is tracked as a release follow-up and is **not yet
|
|
44
|
+
verified**, so do not assume `pip install multiwa` resolves to this package
|
|
45
|
+
on the registry.
|
|
46
|
+
|
|
47
|
+
Until the registry release is verified, install from this repository:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# From the MultiWA monorepo (recommended for contributors)
|
|
51
|
+
pip install -e packages/sdk-python
|
|
52
|
+
|
|
53
|
+
# From a git ref
|
|
54
|
+
pip install "multiwa @ git+https://github.com/ribato22/MultiWA.git#subdirectory=packages/sdk-python"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from multiwa import MultiWA
|
|
61
|
+
|
|
62
|
+
# Initialize the client. base_url must include the API prefix /api/v1.
|
|
63
|
+
# Local dev: http://localhost:3000/api/v1
|
|
64
|
+
# Docker: http://localhost:3333/api/v1
|
|
65
|
+
# Prod: https://your-multiwa-instance.com/api/v1
|
|
66
|
+
client = MultiWA(
|
|
67
|
+
base_url="https://your-multiwa-instance.com/api/v1",
|
|
68
|
+
api_key="your-api-key",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Send a text message
|
|
72
|
+
result = client.messages.send_text(
|
|
73
|
+
profile_id="your-profile-id",
|
|
74
|
+
to="6281234567890",
|
|
75
|
+
text="Hello from MultiWA Python SDK!"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
print(result)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Features
|
|
82
|
+
|
|
83
|
+
### Messages
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
# Send text
|
|
87
|
+
client.messages.send_text(profile_id, to, text)
|
|
88
|
+
|
|
89
|
+
# Send image
|
|
90
|
+
client.messages.send_image(profile_id, to, url="https://...", caption="Check this!")
|
|
91
|
+
|
|
92
|
+
# Send video
|
|
93
|
+
client.messages.send_video(profile_id, to, url="https://...", caption="Watch this!")
|
|
94
|
+
|
|
95
|
+
# Send document
|
|
96
|
+
client.messages.send_document(profile_id, to, url="https://...", filename="report.pdf")
|
|
97
|
+
|
|
98
|
+
# Send location
|
|
99
|
+
client.messages.send_location(profile_id, to, latitude=-6.2088, longitude=106.8456)
|
|
100
|
+
|
|
101
|
+
# Send contact
|
|
102
|
+
client.messages.send_contact(profile_id, to, name="John Doe", phone="+6281234567890")
|
|
103
|
+
|
|
104
|
+
# Send poll
|
|
105
|
+
client.messages.send_poll(
|
|
106
|
+
profile_id, to,
|
|
107
|
+
question="What's your favorite color?",
|
|
108
|
+
options=["Red", "Green", "Blue"]
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Broadcasts
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
# Create broadcast
|
|
116
|
+
client.broadcasts.create(
|
|
117
|
+
profile_id="...",
|
|
118
|
+
name="Promo Campaign",
|
|
119
|
+
recipients=["6281234567890", "6281234567891"],
|
|
120
|
+
template_id="template-uuid"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# List broadcasts
|
|
124
|
+
broadcasts = client.broadcasts.list(profile_id)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Contacts
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
# Create contact
|
|
131
|
+
client.contacts.create(
|
|
132
|
+
profile_id="...",
|
|
133
|
+
phone="6281234567890",
|
|
134
|
+
name="John Doe",
|
|
135
|
+
tags=["customer", "vip"]
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# List contacts
|
|
139
|
+
contacts = client.contacts.list(profile_id)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Webhooks
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# Create webhook
|
|
146
|
+
client.webhooks.create(
|
|
147
|
+
profile_id="...",
|
|
148
|
+
url="https://your-webhook.com/whatsapp",
|
|
149
|
+
events=["message.received", "message.sent"]
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Async Support
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
import asyncio
|
|
157
|
+
from multiwa import AsyncMultiWA
|
|
158
|
+
|
|
159
|
+
async def main():
|
|
160
|
+
client = AsyncMultiWA(
|
|
161
|
+
base_url="https://your-multiwa-instance.com/api",
|
|
162
|
+
api_key="your-api-key"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
result = await client.messages.send_text(
|
|
166
|
+
profile_id="...",
|
|
167
|
+
to="6281234567890",
|
|
168
|
+
text="Hello async!"
|
|
169
|
+
)
|
|
170
|
+
print(result)
|
|
171
|
+
|
|
172
|
+
asyncio.run(main())
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT - See [LICENSE](LICENSE) for details.
|
multiwa-1.0.0/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# MultiWA Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [MultiWA](https://github.com/ribato22/multiwa) - WhatsApp Business API Gateway.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The SDK is available in this repository today. Public registry publishing
|
|
8
|
+
(`multiwa` on PyPI) is tracked as a release follow-up and is **not yet
|
|
9
|
+
verified**, so do not assume `pip install multiwa` resolves to this package
|
|
10
|
+
on the registry.
|
|
11
|
+
|
|
12
|
+
Until the registry release is verified, install from this repository:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# From the MultiWA monorepo (recommended for contributors)
|
|
16
|
+
pip install -e packages/sdk-python
|
|
17
|
+
|
|
18
|
+
# From a git ref
|
|
19
|
+
pip install "multiwa @ git+https://github.com/ribato22/MultiWA.git#subdirectory=packages/sdk-python"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from multiwa import MultiWA
|
|
26
|
+
|
|
27
|
+
# Initialize the client. base_url must include the API prefix /api/v1.
|
|
28
|
+
# Local dev: http://localhost:3000/api/v1
|
|
29
|
+
# Docker: http://localhost:3333/api/v1
|
|
30
|
+
# Prod: https://your-multiwa-instance.com/api/v1
|
|
31
|
+
client = MultiWA(
|
|
32
|
+
base_url="https://your-multiwa-instance.com/api/v1",
|
|
33
|
+
api_key="your-api-key",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Send a text message
|
|
37
|
+
result = client.messages.send_text(
|
|
38
|
+
profile_id="your-profile-id",
|
|
39
|
+
to="6281234567890",
|
|
40
|
+
text="Hello from MultiWA Python SDK!"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
print(result)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
### Messages
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
# Send text
|
|
52
|
+
client.messages.send_text(profile_id, to, text)
|
|
53
|
+
|
|
54
|
+
# Send image
|
|
55
|
+
client.messages.send_image(profile_id, to, url="https://...", caption="Check this!")
|
|
56
|
+
|
|
57
|
+
# Send video
|
|
58
|
+
client.messages.send_video(profile_id, to, url="https://...", caption="Watch this!")
|
|
59
|
+
|
|
60
|
+
# Send document
|
|
61
|
+
client.messages.send_document(profile_id, to, url="https://...", filename="report.pdf")
|
|
62
|
+
|
|
63
|
+
# Send location
|
|
64
|
+
client.messages.send_location(profile_id, to, latitude=-6.2088, longitude=106.8456)
|
|
65
|
+
|
|
66
|
+
# Send contact
|
|
67
|
+
client.messages.send_contact(profile_id, to, name="John Doe", phone="+6281234567890")
|
|
68
|
+
|
|
69
|
+
# Send poll
|
|
70
|
+
client.messages.send_poll(
|
|
71
|
+
profile_id, to,
|
|
72
|
+
question="What's your favorite color?",
|
|
73
|
+
options=["Red", "Green", "Blue"]
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Broadcasts
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
# Create broadcast
|
|
81
|
+
client.broadcasts.create(
|
|
82
|
+
profile_id="...",
|
|
83
|
+
name="Promo Campaign",
|
|
84
|
+
recipients=["6281234567890", "6281234567891"],
|
|
85
|
+
template_id="template-uuid"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# List broadcasts
|
|
89
|
+
broadcasts = client.broadcasts.list(profile_id)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Contacts
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
# Create contact
|
|
96
|
+
client.contacts.create(
|
|
97
|
+
profile_id="...",
|
|
98
|
+
phone="6281234567890",
|
|
99
|
+
name="John Doe",
|
|
100
|
+
tags=["customer", "vip"]
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# List contacts
|
|
104
|
+
contacts = client.contacts.list(profile_id)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Webhooks
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
# Create webhook
|
|
111
|
+
client.webhooks.create(
|
|
112
|
+
profile_id="...",
|
|
113
|
+
url="https://your-webhook.com/whatsapp",
|
|
114
|
+
events=["message.received", "message.sent"]
|
|
115
|
+
)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Async Support
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
import asyncio
|
|
122
|
+
from multiwa import AsyncMultiWA
|
|
123
|
+
|
|
124
|
+
async def main():
|
|
125
|
+
client = AsyncMultiWA(
|
|
126
|
+
base_url="https://your-multiwa-instance.com/api",
|
|
127
|
+
api_key="your-api-key"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
result = await client.messages.send_text(
|
|
131
|
+
profile_id="...",
|
|
132
|
+
to="6281234567890",
|
|
133
|
+
text="Hello async!"
|
|
134
|
+
)
|
|
135
|
+
print(result)
|
|
136
|
+
|
|
137
|
+
asyncio.run(main())
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT - See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MultiWA Python SDK
|
|
3
|
+
|
|
4
|
+
Official Python SDK for MultiWA - WhatsApp Business API Gateway.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .client import MultiWA, AsyncMultiWA
|
|
8
|
+
from .webhooks import verify_webhook_signature
|
|
9
|
+
from .types import (
|
|
10
|
+
Message,
|
|
11
|
+
MessageResult,
|
|
12
|
+
Contact,
|
|
13
|
+
Broadcast,
|
|
14
|
+
Template,
|
|
15
|
+
Profile,
|
|
16
|
+
Webhook,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__version__ = "1.0.0"
|
|
20
|
+
__all__ = [
|
|
21
|
+
"MultiWA",
|
|
22
|
+
"AsyncMultiWA",
|
|
23
|
+
"Message",
|
|
24
|
+
"MessageResult",
|
|
25
|
+
"Contact",
|
|
26
|
+
"Broadcast",
|
|
27
|
+
"Template",
|
|
28
|
+
"Profile",
|
|
29
|
+
"Webhook",
|
|
30
|
+
"verify_webhook_signature",
|
|
31
|
+
]
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MultiWA Python SDK - Broadcasts Client
|
|
3
|
+
|
|
4
|
+
Client for managing broadcast campaigns.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional, List, Dict, Any
|
|
8
|
+
import httpx
|
|
9
|
+
|
|
10
|
+
from .types import Broadcast
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BroadcastsClient:
|
|
14
|
+
"""Synchronous Broadcasts API client"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, http: httpx.Client):
|
|
17
|
+
self._http = http
|
|
18
|
+
|
|
19
|
+
def create(
|
|
20
|
+
self,
|
|
21
|
+
profile_id: str,
|
|
22
|
+
name: str,
|
|
23
|
+
recipients: List[str],
|
|
24
|
+
template_id: Optional[str] = None,
|
|
25
|
+
message: Optional[str] = None,
|
|
26
|
+
schedule_at: Optional[str] = None,
|
|
27
|
+
) -> Broadcast:
|
|
28
|
+
"""Create a new broadcast campaign"""
|
|
29
|
+
response = self._http.post("/broadcasts", json={
|
|
30
|
+
"profileId": profile_id,
|
|
31
|
+
"name": name,
|
|
32
|
+
"recipients": recipients,
|
|
33
|
+
"templateId": template_id,
|
|
34
|
+
"message": message,
|
|
35
|
+
"scheduleAt": schedule_at,
|
|
36
|
+
})
|
|
37
|
+
response.raise_for_status()
|
|
38
|
+
return Broadcast(**response.json())
|
|
39
|
+
|
|
40
|
+
def get(self, broadcast_id: str) -> Broadcast:
|
|
41
|
+
"""Get a broadcast by ID"""
|
|
42
|
+
response = self._http.get(f"/broadcasts/{broadcast_id}")
|
|
43
|
+
response.raise_for_status()
|
|
44
|
+
return Broadcast(**response.json())
|
|
45
|
+
|
|
46
|
+
def list(
|
|
47
|
+
self,
|
|
48
|
+
profile_id: str,
|
|
49
|
+
limit: int = 50,
|
|
50
|
+
offset: int = 0,
|
|
51
|
+
status: Optional[str] = None,
|
|
52
|
+
) -> List[Broadcast]:
|
|
53
|
+
"""List broadcasts for a profile"""
|
|
54
|
+
params: Dict[str, Any] = {
|
|
55
|
+
"limit": limit,
|
|
56
|
+
"offset": offset,
|
|
57
|
+
}
|
|
58
|
+
if status:
|
|
59
|
+
params["status"] = status
|
|
60
|
+
|
|
61
|
+
response = self._http.get(f"/broadcasts/profile/{profile_id}", params=params)
|
|
62
|
+
response.raise_for_status()
|
|
63
|
+
return [Broadcast(**b) for b in response.json()]
|
|
64
|
+
|
|
65
|
+
def start(self, broadcast_id: str) -> Broadcast:
|
|
66
|
+
"""Start a broadcast"""
|
|
67
|
+
response = self._http.post(f"/broadcasts/{broadcast_id}/start")
|
|
68
|
+
response.raise_for_status()
|
|
69
|
+
return Broadcast(**response.json())
|
|
70
|
+
|
|
71
|
+
def pause(self, broadcast_id: str) -> Broadcast:
|
|
72
|
+
"""Pause a broadcast"""
|
|
73
|
+
response = self._http.post(f"/broadcasts/{broadcast_id}/pause")
|
|
74
|
+
response.raise_for_status()
|
|
75
|
+
return Broadcast(**response.json())
|
|
76
|
+
|
|
77
|
+
def cancel(self, broadcast_id: str) -> Broadcast:
|
|
78
|
+
"""Cancel a broadcast"""
|
|
79
|
+
response = self._http.post(f"/broadcasts/{broadcast_id}/cancel")
|
|
80
|
+
response.raise_for_status()
|
|
81
|
+
return Broadcast(**response.json())
|
|
82
|
+
|
|
83
|
+
def delete(self, broadcast_id: str) -> Dict[str, bool]:
|
|
84
|
+
"""Delete a broadcast"""
|
|
85
|
+
response = self._http.delete(f"/broadcasts/{broadcast_id}")
|
|
86
|
+
response.raise_for_status()
|
|
87
|
+
return response.json()
|
|
88
|
+
|
|
89
|
+
def stats(self, broadcast_id: str) -> Dict[str, Any]:
|
|
90
|
+
"""Get broadcast statistics"""
|
|
91
|
+
response = self._http.get(f"/broadcasts/{broadcast_id}/stats")
|
|
92
|
+
response.raise_for_status()
|
|
93
|
+
return response.json()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class AsyncBroadcastsClient:
|
|
97
|
+
"""Asynchronous Broadcasts API client"""
|
|
98
|
+
|
|
99
|
+
def __init__(self, http: httpx.AsyncClient):
|
|
100
|
+
self._http = http
|
|
101
|
+
|
|
102
|
+
async def create(
|
|
103
|
+
self,
|
|
104
|
+
profile_id: str,
|
|
105
|
+
name: str,
|
|
106
|
+
recipients: List[str],
|
|
107
|
+
template_id: Optional[str] = None,
|
|
108
|
+
message: Optional[str] = None,
|
|
109
|
+
schedule_at: Optional[str] = None,
|
|
110
|
+
) -> Broadcast:
|
|
111
|
+
"""Create a new broadcast campaign"""
|
|
112
|
+
response = await self._http.post("/broadcasts", json={
|
|
113
|
+
"profileId": profile_id,
|
|
114
|
+
"name": name,
|
|
115
|
+
"recipients": recipients,
|
|
116
|
+
"templateId": template_id,
|
|
117
|
+
"message": message,
|
|
118
|
+
"scheduleAt": schedule_at,
|
|
119
|
+
})
|
|
120
|
+
response.raise_for_status()
|
|
121
|
+
return Broadcast(**response.json())
|
|
122
|
+
|
|
123
|
+
async def get(self, broadcast_id: str) -> Broadcast:
|
|
124
|
+
"""Get a broadcast by ID"""
|
|
125
|
+
response = await self._http.get(f"/broadcasts/{broadcast_id}")
|
|
126
|
+
response.raise_for_status()
|
|
127
|
+
return Broadcast(**response.json())
|
|
128
|
+
|
|
129
|
+
async def list(
|
|
130
|
+
self,
|
|
131
|
+
profile_id: str,
|
|
132
|
+
limit: int = 50,
|
|
133
|
+
offset: int = 0,
|
|
134
|
+
) -> List[Broadcast]:
|
|
135
|
+
"""List broadcasts for a profile"""
|
|
136
|
+
response = await self._http.get(
|
|
137
|
+
f"/broadcasts/profile/{profile_id}",
|
|
138
|
+
params={"limit": limit, "offset": offset}
|
|
139
|
+
)
|
|
140
|
+
response.raise_for_status()
|
|
141
|
+
return [Broadcast(**b) for b in response.json()]
|
|
142
|
+
|
|
143
|
+
async def start(self, broadcast_id: str) -> Broadcast:
|
|
144
|
+
"""Start a broadcast"""
|
|
145
|
+
response = await self._http.post(f"/broadcasts/{broadcast_id}/start")
|
|
146
|
+
response.raise_for_status()
|
|
147
|
+
return Broadcast(**response.json())
|